def fn(self, ctx: ExecutionContext) -> FollowUp: if ctx.nip: a = [ctx.thread.update(ip=ctx.nip)] else: a = [] return FollowUp.new(a)
def fn(self, ctx: ExecutionContext) -> FollowUp: if len(ctx.stack) == 0: raise ExecutionError( f'`{ctx.thread.id}:{ctx.thread.ip}` Stack underflow') push_pop(ctx.stack[0], ctx) return FollowUp.new([ctx.thread.update(ip=ctx.nip)], update_stacks=[ctx.stack[0]])
def fn(self, ctx: ExecutionContext) -> FollowUp: a, b, jmp_if_true = ctx.resolve_arg(0), ctx.resolve_arg( 1), ctx.resolve_arg(2) nip = ctx.nip if a != b: nip = jmp_if_true return FollowUp.new([ctx.thread.update(ip=nip)])
def fn(self, ctx: ExecutionContext) -> FollowUp: if len(ctx.args) != 1: raise ExecutionError( f'(j) `{ctx.thread.id}:{ctx.thread.ip}` too many args: {ctx.args}' ) jmp = ctx.resolve_arg(0) return FollowUp.new([ctx.thread.update(ip=jmp)])
def fn(self, ctx: ExecutionContext) -> FollowUp: # how do we know which stacks have been changed ? csf = StackFrame.load_exists(ctx.singleton.db, ctx.resolve_arg(0)) push_pop(csf, ctx, ctx.args[1:]) return FollowUp.new(create_threads=[ ctx.thread.update(ip=ctx.nip, sp=[csf.id] + ctx.thread.sp) ], create_stacks=[csf])
def fn(self, ctx: ExecutionContext) -> FollowUp: # how do we know which stacks have been changed ? csf = StackFrame.new(uuid4().hex) push_pop(csf, ctx) return FollowUp.new(create_threads=[ ctx.thread.update(ip=ctx.nip, sp=[csf.id] + ctx.thread.sp) ], create_stacks=[csf])
def fn(self, ctx: ExecutionContext) -> FollowUp: if len(ctx.args) != 2: raise ExecutionError( f'(fork) `{ctx.thread.id}:{ctx.thread.ip}` not enough args: {ctx.args}' ) fork_id = ctx.resolve_arg(0) jmp = ctx.resolve_arg(1) return FollowUp.new([ ctx.thread.update(ip=ctx.nip), ThreadContext.new(fork_id, jmp, ctx.thread.sp), ])
def fn(self, ctx: ExecutionContext): frz_id = ctx.resolve_arg(0) cmp, succ = FrozenThreadContext.load_exists(ctx.singleton.db, frz_id) ok, items = ctx.singleton.db.transaction(compare=[cmp], success=[succ]) if not ok: raise ExecutionError(f'Could not find `{frz_id}`') frz = FrozenThreadContext.deserialize_range(items) ctx.thread.update(ip=frz.ctx.ip, sp=ctx.thread.sp + frz.ctx.sp) return FollowUp.new([ctx])
def __call__(self, ctx: ExecutionContext) -> FollowUp: def map_args(args: OpcodeArgs): pos = [] kw = {} for i, arg in enumerate(args): if isinstance(arg, Identifier) or isinstance(arg, Constant): pos.append(OpArg.map(ctx, arg)) elif isinstance(arg, Map): kw[arg.identifier.name] = OpArg.map(ctx, arg.to) else: raise NotImplementedError(f'{args}') return pos, kw args, kwargs = map_args(ctx.args) self.fn(ctx, *args, **kwargs) return FollowUp.new( create_threads=[ctx.thread.update(ip=ctx.nip)], update_stacks=[ctx.stack[x] for x in ctx.stacks_updated] )
def fn(self, ctx: ExecutionContext) -> FollowUp: # so a stack frame needs to load the parent stack frame # then update it # rtn = ctx.stack_get('psp') # # x = StackFrame.load(ctx.singleton.db, rtn) if len(ctx.stack) == 0: raise ExecutionError( f'`{ctx.thread.id}:{ctx.thread.ip}` Stack underflow') if len(ctx.args) and len(ctx.stack) < 2: raise ExecutionError( f'`{ctx.thread.id}:{ctx.thread.ip}` Stack underflow') elif len(ctx.args): push_pop(ctx.stack[-2], ctx) return FollowUp.new( [ctx.thread.update(ip=ctx.nip, sp=ctx.thread.sp[1:])], update_stacks=[ctx.stack[1]])
def fn(self, ctx: ExecutionContext) -> FollowUp: # if we had access to the meta-info, then we could easily remove it ourselves if len(ctx.stack) == 0: raise ExecutionError( f'`{ctx.thread.id}:{ctx.thread.ip}` Stack underflow') if len(ctx.args) and len(ctx.stack) < 2: raise ExecutionError( f'`{ctx.thread.id}:{ctx.thread.ip}` Stack underflow') elif len(ctx.args): push_pop(ctx.stack[-2], ctx) upd = [] if len(ctx.stack) > 1: upd = [ctx.stack[1]] return FollowUp.new( [ctx.thread.update(ip=ctx.nip, sp=ctx.thread.sp[1:])], update_stacks=upd, delete_stacks=[ctx.stack[0]])
def fn(self, ctx: ExecutionContext) -> FollowUp: return FollowUp.new()