def decode(stream): stream.skipspace() if stream.shift(u'{'): dct = space.Dict() if stream.shift(u'}'): return dct decode_pair(stream, dct) while stream.shift(u','): decode_pair(stream, dct) stream.skipspace() stream.skipspace() stream.expect(u'}') return dct if stream.shift(u'['): lst = [] if stream.shift(u']'): return space.List(lst) lst.append(decode(stream)) while stream.shift(u','): lst.append(decode(stream)) stream.skipspace() stream.skipspace() stream.expect(u']') return space.List(lst) if stream.get() == u'"': return decode_string(stream) if stream.shift(u'f'): stream.expect(u'a') stream.expect(u'l') stream.expect(u's') stream.expect(u'e') return space.false if stream.shift(u't'): stream.expect(u'r') stream.expect(u'u') stream.expect(u'e') return space.true if stream.shift(u'n'): stream.expect(u'u') stream.expect(u'l') stream.expect(u'l') return space.null if stream.shift(u'-'): sign = -1 else: sign = +1 num = digits(stream) if stream.shift(u'.'): num += u'.' + digits(stream) if stream.get() in u'eE': raise space.Error(u"XXX") return space.Float(float(num.encode('utf-8'))) else: if stream.get() in u'eE': raise space.Error(u"XXX") return space.Integer(sign * int(num.encode('utf-8'))) raise space.Error(u"JSON decode error at %s" % stream.get())
def from_macro(env, exp): if len(exp.exps) == 2: exp.exps.extend(env.capture(exp)) if len(exp.exps) <= 2: raise space.Error(u"%s: format: from expr symbol..." % exp.start.repr()) val = translate(env, exp.exps[1]) for attr in exp.exps[2:]: if isinstance(attr, reader.Literal) and attr.name == u'symbol': var = env.add(GetAttr(val, attr.value)) env.add(SetLocal(attr.value, var, False)) else: raise space.Error(u"%s: expected symbol" % attr.start.repr()) return val
def call(self, argv): if len(argv) != 1: raise space.Error(u"program expects module as an argument") module = argv[0] assert isinstance(module, space.Module) frame = ActivationRecord(module, None) return interpret(self.body, frame)
def call(self, argv): argc = len(self.func.args) if len(argv) < argc: raise space.Error(u"closure requires %d arguments" % argc) frame = ActivationRecord(self.frame.module, self.frame) for i in range(argc): frame.var[self.func.args[i]] = argv[i] return interpret(self.func.body, frame)
def yield_macro(env, exp): if len(exp.exps) != 2: raise space.Error(u"%s: format: yield expr" % exp.start.repr()) env.is_generator = True val = translate(env, exp.exps[1]) yield_ = env.add(Yield(val, env.new_block())) env.block = yield_.block return yield_
def call(self, argv): if len(argv) != 1: raise space.Error(u"program expects module as an argument") module = argv[0] assert isinstance(module, space.Module) entry = self.unit.functions[0] frame = Frame(entry, module, None) regv = new_register_array(entry.regc) return interpret(0, entry.block, regv, frame)
def call(self, argv): argc = self.function.argc if len(argv) < argc: raise space.Error(u"closure requires %d arguments" % argc) frame = Frame(self.function, self.frame.module, self.frame) for i in range(argc): frame.local[i] = argv[i] regv = new_register_array(self.function.regc) return interpret(0, self.function.block, regv, frame)
def translate_chain(env, chain): chain_above = env.chain exp = chain.pop(0) env.chain = chain val = translate(env, exp) if len(env.chain) > 0: raise space.Error(u"%s: chain without receiver" % exp.start.repr()) env.chain = chain_above return val
def or_macro(env, exp): if len(exp.exps) != 3: raise space.Error(u"no translation for %s with length != 3" % exp.name) val = translate(env, exp.exps[1]) cond = env.add(Cond(val)) cond.exit = env.block = env.new_block() cond.then = env.new_block() env.add(Merge(val, translate(env, exp.exps[2]))) env.add(Jump(cond.then)) env.block = cond.then return val
def func_macro(env, exp): argv = [] for i in range(1, len(exp.exps)): arg = exp.exps[i] if isinstance(arg, reader.Literal) and arg.name == u'symbol': argv.append(arg.value) else: raise space.Error(u"%s: expected symbol inside func" % arg.start.repr()) body = env.capture(exp) return env.new_function(argv, body)
def for_macro(env, exp): if len(exp.exps) != 3: raise space.Error(u"no translation for %s with length != 2" % exp.name) var = exp.exps[1] if not isinstance(var, reader.Literal): raise space.Error(u"%s: format: for variable exp" % exp.start.repr()) it = env.add(Iter(translate(env, exp.exps[2]))) current_loop = (loop, exit, _) = (env.new_block(), env.new_block(), True) env.loop_stack.append(current_loop) cond = env.add(SetBreak(exit)) env.add(Jump(loop)) env.block = loop env.add(SetLocal(var.value, env.add(Next(it)), False)) val = translate_flow(env, env.capture(exp)) env.add(Merge(cond, val)) env.add(Jump(loop)) env.block = exit loop_exit(env) return cond
def if_macro(env, exp): if len(exp.exps) != 2: raise space.Error(u"no translation for %s with length != 2" % exp.name) chain = env.pull_chain() cond = Cond(translate(env, exp.exps[1])) env.add(cond) cond.then = env.block = env.new_block() cond.exit = exit = env.new_block() val = translate_flow(env, env.capture(exp)) env.add(Merge(cond, val)) env.add(Jump(exit)) if len(chain) > 0: first = chain[0] if len(chain) > 1 and macro_name(first.exps[0]) != u'else' and len( first.exps) != 1: raise space.Error(u"%s: non-else longer chains not supported" % exp.start.repr()) env.block, exit = exit, env.new_block() val = translate_flow(env, first.capture) env.add(Merge(cond, val)) env.add(Jump(exit)) env.block = exit return cond
def while_macro(env, exp): if len(exp.exps) != 2: raise space.Error(u"no translation for %s with length != 2" % exp.name) current_loop = (loop, exit, _) = (env.new_label(), env.new_block(), False) env.loop_stack.append(current_loop) loop = env.new_label() cond = env.add(Cond(translate(env, exp.exps[1]))) cond.then = env.block = env.new_block() cond.exit = env.new_block() val = translate_flow(env, env.capture(exp)) env.add(Merge(cond, val)) env.add(Jump(loop)) env.block = cond.exit loop_exit(env) return cond
def store_value(env, lhs, value, upscope): if isinstance(lhs, reader.Literal) and lhs.name == u'symbol': return env.add(SetLocal(lhs.value, value, upscope)) elif isinstance(lhs, reader.Expr) and lhs.name == u'attr' and len( lhs.exps) == 2: obj, name = lhs.exps obj = translate(env, obj) assert isinstance(name, reader.Literal) return env.add(SetAttr(obj, name.value, value)) elif isinstance(lhs, reader.Expr) and lhs.name == u'index' and len( lhs.exps) == 2: obj, index = lhs.exps obj = translate(env, obj) index = translate(env, index) return env.add(SetItem(obj, index, value)) else: raise space.Error(u"no translation for " + lhs.name)
def escape_ch(ch): if ch == u'"': return u'"' if ch == u'\\': return u'\\' if ch == u'\/': return u'/' if ch == u'b': return u'\b' if ch == u'f': return u'\f' if ch == u'n': return u'\n' if ch == u'r': return u'\r' if ch == u't': return u'\t' raise space.Error(u"JSON decode error")
def syntax_chain(env, exp): if len(exp.exps) < 3: raise space.Error(u"no translation for %s with length < 3" % exp.name) and_ = Variable(u'and') if len(exp.exps) > 3: env.add(and_) lhs = translate(env, exp.exps[0]) op = translate(env, exp.exps[1]) rhs = translate(env, exp.exps[2]) res = env.add(Call(op, [lhs, rhs])) i = 3 while i < len(exp.exps): lhs = rhs op = translate(env, exp.exps[i]) rhs = translate(env, exp.exps[i + 1]) res = env.add(Call(and_, [res, env.add(Call(op, [lhs, rhs]))])) i += 2 return res
def store_aug_value(env, aug, lhs, value): aug = env.add(Variable(aug.value)) if isinstance(lhs, reader.Literal) and lhs.name == u'symbol': name = lhs.value value = env.add(Call(aug, [env.add(Variable(name)), value])) return env.add(SetLocal(name, value, True)) elif isinstance(lhs, reader.Expr) and lhs.name == u'attr' and len( lhs.exps) == 2: obj, name = lhs.exps assert isinstance(name, reader.Literal) obj = translate(env, obj) value = env.add(Call(aug, [env.add(GetAttr(obj, name.value)), value])) return env.add(SetAttr(obj, name.value, value)) elif isinstance(lhs, reader.Expr) and lhs.name == u'index' and len( lhs.exps) == 2: obj, index = lhs.exps obj = translate(env, obj) index = translate(env, index) value = env.add(Call(aug, [env.add(GetItem(obj, index)), value])) return env.add(SetItem(obj, index, value)) else: raise space.Error(u"no translation for " + lhs.name)
def interpret_body(block, t, cl_frame, loop_break): frame = Frame(t) pc = 0 module = jit.promote(cl_frame.module) try: while pc < len(block): try: jitdriver.jit_merge_point(pc=pc, block=block, loop_break=loop_break, module=module, cl_frame=cl_frame, frame=frame) op = block[pc] pc += 1 if isinstance(op, Call): do_call(frame, op) elif isinstance(op, Assert): if space.is_false(frame.load(op.value.i)): raise space.Error(u"Assertion error") elif isinstance(op, Cond): pc = 0 if space.is_false(frame.load(op.cond.i)): block = op.exit else: block = op.then elif isinstance(op, Jump): pc = 0 block = op.exit elif isinstance(op, Next): frame.store(op.i, frame.load(op.it.i).callattr(u'next', [])) elif isinstance(op, Yield): raise YieldIteration(op.block, loop_break, op.i, frame.load(op.value.i)) elif isinstance(op, SetBreak): loop_break = op.block elif isinstance(op, Iter): frame.store(op.i, frame.load(op.value.i).iter()) elif isinstance(op, Constant): frame.store(op.i, op.value) elif isinstance(op, Variable): frame.store(op.i, lookup(module, cl_frame, op.name)) elif isinstance(op, Merge): frame.store(op.dst.i, frame.load(op.src.i)) elif isinstance(op, Function): frame.store(op.i, Closure(cl_frame, op)) elif isinstance(op, MakeList): contents = [] for val in op.values: contents.append(frame.load(val.i)) frame.store(op.i, space.List(contents)) elif isinstance(op, GetAttr): frame.store(op.i, frame.load(op.value.i).getattr(op.name)) elif isinstance(op, GetItem): frame.store( op.i, frame.load(op.value.i).getitem(frame.load(op.index.i))) elif isinstance(op, SetAttr): frame.store( op.i, frame.load(op.obj.i).setattr(op.name, frame.load(op.value.i))) elif isinstance(op, SetItem): frame.store( op.i, frame.load(op.obj.i).setitem(frame.load(op.index.i), frame.load(op.value.i))) elif isinstance(op, SetLocal): frame.store( op.i, set_local(module, cl_frame, op.name, frame.load(op.value.i), op.upscope)) elif isinstance(op, Return): return frame.load(op.ref.i) else: raise space.Error(u"spaced out") except StopIteration as stopiter: if loop_break is not None: block = loop_break loop_break = None continue op = block[pc - 1] error = space.Error(u"stop iteration") error.stacktrace.append((cl_frame, op.start, op.stop)) raise error raise space.Error(u"crappy compiler") except space.Error as e: op = block[pc - 1] e.stacktrace.append((cl_frame, op.start, op.stop)) raise e
def interpret(pc, block, regv, frame, iterstop=LARGE_PC): module = jit.promote(frame.module) unit = jit.promote(frame.unit) try: while pc < len(block): jitdriver.jit_merge_point( pc=pc, block=block, module=module, unit=unit, iterstop=iterstop, regv=regv, frame=frame) opcode = rffi.r_ulong(block[pc])>>8 ix = pc+1 pc = ix+(rffi.r_ulong(block[pc])&255) if opcode == opcode_of('assert'): if space.is_false(regv.load(block[ix+0])): raise space.Error(u"Assertion error") elif opcode == opcode_of('constant'): regv.store(block[ix+0], unit.constants[block[ix+1]]) elif opcode == opcode_of('list'): contents = [] for i in range(ix+1, pc): contents.append(regv.load(block[i])) regv.store(block[ix], space.List(contents)) elif opcode == opcode_of('move'): regv.store(block[ix+0], regv.load(block[ix+1])) elif opcode == opcode_of('call'): op_call(regv, block, ix, pc) elif opcode == opcode_of('return'): return regv.load(block[ix+0]) elif opcode == opcode_of('jump'): pc = rffi.r_ulong(block[ix+0]) elif opcode == opcode_of('cond'): if space.is_false(regv.load(block[ix+0])): pc = rffi.r_ulong(block[ix+2]) else: pc = rffi.r_ulong(block[ix+1]) elif opcode == opcode_of('func'): regv.store(block[ix+0], Closure(frame, unit.functions[block[ix+1]])) elif opcode == opcode_of('iter'): regv.store(block[ix+0], regv.load(block[ix+1]).iter()) elif opcode == opcode_of('iterstop'): iterstop = rffi.r_ulong(block[ix+0]) elif opcode == opcode_of('next'): regv.store(block[ix+0], regv.load(block[ix+1]).callattr(u'next', [])) # this is missing. #elif isinstance(op, Yield): # raise YieldIteration(op.block, loop_break, op.i, regv.load(op.value.i)) elif opcode == opcode_of('getattr'): name = get_string(unit, block, ix+2) obj = regv.load(block[ix+1]) regv.store(block[ix+0], obj.getattr(name)) elif opcode == opcode_of('setattr'): value = regv.load(block[ix+3]) name = get_string(unit, block, ix+2) obj = regv.load(block[ix+1]) regv.store(block[ix+0], obj.setattr(name, value)) elif opcode == opcode_of('getitem'): index = regv.load(block[ix+2]) obj = regv.load(block[ix+1]) regv.store(block[ix+0], obj.getitem(index)) elif opcode == opcode_of('setitem'): item = regv.load(block[ix+3]) index = regv.load(block[ix+2]) obj = regv.load(block[ix+1]) regv.store(block[ix+0], obj.setitem(index, item)) elif opcode == opcode_of('getloc'): regv.store(block[ix+0], frame.local[block[ix+1]]) elif opcode == opcode_of('setloc'): value = regv.load(block[ix+2]) frame.local[block[ix+1]] = value regv.store(block[ix+0], value) elif opcode == opcode_of('getupv'): value = get_upframe(frame, block[ix+1]).local[block[ix+2]] regv.store(block[ix+0], value) elif opcode == opcode_of('setupv'): value = regv.load(block[ix+3]) get_upframe(frame, block[ix+1]).local[block[ix+2]] = value regv.store(block[ix+0], value) elif opcode == opcode_of('getglob'): regv.store(block[ix+0], module.getattr(get_string(unit, block, ix+1))) elif opcode == opcode_of('setglob'): regv.store(block[ix+0], module.setattr( get_string(unit, block, ix+1), regv.load(block[ix+2]))) else: raise space.Error(u"unexpected instruction: " + optable.names.get(opcode, str(opcode)).decode('utf-8')) except StopIteration as stop: if iterstop != LARGE_PC: return interpret(iterstop, block, regv, frame) else: raise space.Error(u"StopIteration") return space.null
def translate_(env, exp): if isinstance(exp, reader.Literal): if exp.name == u'string': return env.add(Constant(space.from_ustring(exp.value))) elif exp.name == u'int': return env.add( Constant(space.Integer(int(exp.value.encode('utf-8'))))) elif exp.name == u'hex': return env.add( Constant(space.Integer(int(exp.value[2:].encode('utf-8'), 16)))) elif exp.name == u'float': return env.add( Constant(space.Float(float(exp.value.encode('utf-8'))))) elif exp.name == u'symbol': return env.add(Variable(exp.value)) raise space.Error(u"no translation for " + exp.name) assert isinstance(exp, reader.Expr), exp.__class__.__name__ if exp.name == u'form' and len(exp.exps) > 0: if macro_name(exp) in macros: cc = env.capture_catch if len(exp.capture) > 0: env.capture_catch = exp.capture res = macros[macro_name(exp)](env, exp) if len(exp.capture) > 0 and len(env.capture_catch) > 0: raise space.Error(u"%s: capture without receiver" % exp.start.repr()) env.capture_catch = cc return res # callattr goes here, if it'll be needed args = translate_map(env, exp.exps) callee = args.pop(0) args.extend(translate_map(env, exp.capture)) return env.add(Call(callee, args)) elif exp.name == u'list': return env.add(MakeList(translate_map(env, exp.exps))) elif exp.name == u'attr' and len(exp.exps) == 2: lhs, name = exp.exps lhs = translate(env, lhs) if not isinstance(name, reader.Literal): raise space.Error(u"%s: bad attribute expr" % exp.repr()) return env.add(GetAttr(lhs, name.value)) sym.value elif exp.name == u'index' and len(exp.exps) == 2: lhs, rhs = exp.exps lhs = translate(env, lhs) rhs = translate(env, rhs) return env.add(GetItem(lhs, rhs)) elif exp.name == u'let' or exp.name == u'set': lhs, rhs = exp.exps rhs = translate(env, rhs) return store_value(env, lhs, rhs, exp.name == u'set') elif exp.name == u'aug' and len(exp.exps) == 3: aug, lhs, rhs = exp.exps if not isinstance(aug, reader.Literal): raise space.Error(u"%s: bad augmented expr" % exp.repr()) rhs = translate(env, rhs) return store_aug_value(env, aug, lhs, rhs) elif exp.name == u'chain': return syntax_chain(env, exp) raise space.Error(u"no translation for " + exp.name)
def continue_macro(env, exp): if len(exp.exps) != 1: raise space.Error(u"%s: format: continue" % exp.start.repr()) if len(env.loop_stack) == 0: raise space.Error(u"%s: not inside a loop" % exp.start.repr()) return env.add(Jump(env.loop_stack[-1][0]))
def capture(self, exp): if len(self.capture_catch) == 0: raise space.Error(u"%s: expecting capture" % exp.start.repr()) cap = self.capture_catch self.capture_catch = [] return cap
def expect(self, ch): if not self.shift(ch): raise space.Error(u"JSON decode expected '%s', got '%s'" % (ch, self.get()))
def return_macro(env, exp): if len(exp.exps) != 2: raise space.Error(u"no translation for %s with length != 2" % exp.name) return env.add(Return(translate(env, exp.exps[1])))
def assert_macro(env, exp): if len(exp.exps) != 2: raise space.Error(u"no translation for %s with length != 2" % exp.name) val = translate(env, exp.exps[1]) env.add(Assert(val)) return val