def compile_fn(form, ctx): form = rt.next(form) if isinstance(rt.first(form), symbol.Symbol): name = rt.first(form) form = rt.next(form) else: name = symbol.symbol(default_fn_name) if rt._satisfies_QMARK_(rt.ISeq.deref(), rt.first(form)): arities = [] while form is not nil: required_arity, argc = compile_fn_body(name, rt.first(rt.first(form)), rt.next(rt.first(form)), ctx) arities.append(argc if required_arity == -1 else required_arity | 256) form = rt.next(form) ctx.bytecode.append(code.MAKE_MULTI_ARITY) ctx.bytecode.append(r_uint(len(arities))) arities.reverse() for x in arities: ctx.bytecode.append(r_uint(x)) ctx.add_sp(1) # result ctx.sub_sp(len(arities)) else: res = compile_fn_body(name, rt.first(form), rt.next(form), ctx) if rt.meta(name) is not nil: compile_meta(rt.meta(name), ctx)
def load_reader(rdr): import pixie.vm.reader as reader import pixie.vm.compiler as compiler import sys if not we_are_translated(): print "Loading file while interpreted, this may take time" val = PXIC_WRITER.deref() if val is nil: pxic_writer = None else: pxic_writer = val.get_pxic_writer() with compiler.with_ns(u"user"): compiler.NS_VAR.deref().include_stdlib() while True: if not we_are_translated(): sys.stdout.write(".") sys.stdout.flush() form = reader.read(rdr, False) if form is reader.eof: return nil try: compiled = compiler.compile(form) except WrappedException as ex: meta = rt.meta(form) if meta is not nil: ci = rt.interpreter_code_info(meta) add_info(ex, ci.__repr__()) add_info(ex, u"Compiling: " + rt.name(rt.str(form))) raise ex try: if pxic_writer is not None: pxic_writer.write_object(compiled) compiled.invoke([]) except WrappedException as ex: meta = rt.meta(form) if meta is not nil: ci = rt.interpreter_code_info(meta) add_info(ex, ci.__repr__()) add_info(ex, u"Running: " + rt.name(rt.str(form))) raise ex if not we_are_translated(): print "done" return nil
def compile_cons(form, ctx): if isinstance(form.first(), symbol.Symbol) and form.first()._str in builtins: return builtins[form.first()._str](form, ctx) macro = is_macro_call(form, ctx) if macro: return compile_form(call_macro(macro, form, ctx), ctx) meta = rt.meta(form) cnt = 0 ctc = ctx.can_tail_call while form is not nil: ctx.disable_tail_call() compile_form(rt.first(form), ctx) cnt += 1 form = rt.next(form) if ctc: ctx.enable_tail_call() #if ctx.can_tail_call: # ctx.bytecode.append(code.TAIL_CALL) #else: if meta is not nil: ctx.debug_points[len(ctx.bytecode)] = meta ctx.bytecode.append(code.INVOKE) ctx.bytecode.append(cnt) ctx.sub_sp(cnt - 1)
def compile_fn_call(form, ctx): macro = is_macro_call(form, ctx) if macro: return compile_form(call_macro(macro, form, ctx), ctx) meta = rt.meta(form) cnt = 0 ctc = ctx.can_tail_call while form is not nil: ctx.disable_tail_call() compile_form(rt.first(form), ctx) cnt += 1 form = rt.next(form) if ctc: ctx.enable_tail_call() #if ctx.can_tail_call: # ctx.bytecode.append(code.TAIL_CALL) #else: if meta is not nil: ctx.debug_points[len(ctx.bytecode)] = rt.interpreter_code_info(meta) ctx.bytecode.append(code.INVOKE) ctx.bytecode.append(cnt) ctx.sub_sp(r_uint(cnt - 1))
def invoke(self, rdr, ch): meta = read(rdr, True) obj = read(rdr, True) if isinstance(meta, Keyword): meta = rt.hashmap(meta, true) if rt.satisfies_QMARK_(rt.IMeta.deref(), obj): return rt.with_meta(obj, rt.merge(meta, rt.meta(obj))) return obj
def compile_map_literal(form, ctx): ctx.push_const(code.intern_var(u"pixie.stdlib", u"hashmap")) rt.reduce(CompileMapRf(ctx), nil, form) size = rt.count(form) * 2 ctx.bytecode.append(code.INVOKE) ctx.bytecode.append(r_uint(size) + 1) ctx.sub_sp(size - 1) compile_meta(rt.meta(form), ctx)
def compile_map_literal(form, ctx): ctx.push_const(code.intern_var(u"pixie.stdlib", u"hashmap")) rt.reduce(CompileMapRf(ctx), nil, form) size = rt.count(form) * 2 ctx.bytecode.append(code.INVOKE) ctx.bytecode.append(r_uint(size) + 1) if size > 0: ctx.sub_sp(size) compile_meta(rt.meta(form), ctx)
def invoke(self, rdr, ch): meta = read_inner(rdr, True) obj = read_inner(rdr, True) if isinstance(meta, Keyword): meta = rt.hashmap(meta, true) if isinstance(meta, Symbol): meta = rt.hashmap(keyword(u"tag"), meta) if rt._satisfies_QMARK_(rt.IMeta.deref(), obj): return rt.with_meta(obj, rt.merge(meta, rt.meta(obj))) return obj
def read_inner(rdr, error_on_eof, always_return_form=True): try: eat_whitespace(rdr) except EOFError as ex: if error_on_eof: runtime_error(u"Unexpected EOF while reading", u"pixie.stdlib/EOFWhileReadingException") return eof ch = rdr.read() if isinstance(rdr, MetaDataReader): meta = rdr.get_metadata() else: meta = nil macro = handlers.get(ch, None) if macro is not None: itm = macro.invoke(rdr, ch) if always_return_form and itm == rdr: return read_inner(rdr, error_on_eof, always_return_form=always_return_form) elif is_digit(ch): itm = read_number(rdr, ch) elif ch == u"-": ch2 = rdr.read() if is_digit(ch2): rdr.unread() itm = read_number(rdr, ch) else: rdr.unread() itm = read_symbol(rdr, ch) else: itm = read_symbol(rdr, ch) if itm != rdr: if rt.has_meta_QMARK_(itm): itm = rt.with_meta(itm, rt.merge(meta, rt.meta(itm))) return itm
def compile_def(form, ctx): form = rt.next(form) name = rt.first(form) form = rt.next(form) val = rt.first(form) affirm(isinstance(name, symbol.Symbol), u"Def'd name must be a symbol") var = NS_VAR.deref().intern_or_make(rt.name(name)) if rt._val_at(rt.meta(name), DYNAMIC_KW, nil) is true: assert isinstance(var, code.Var) var.set_dynamic() ctx.push_const(var) compile_form(val, ctx) ctx.bytecode.append(code.SET_VAR) ctx.sub_sp(1)
def read(rdr, error_on_eof): try: eat_whitespace(rdr) except EOFError as ex: if error_on_eof: raise ex return eof ch = rdr.read() if isinstance(rdr, MetaDataReader): meta = rdr.get_metadata() else: meta = nil macro = handlers.get(ch, None) if macro is not None: itm = macro.invoke(rdr, ch) elif is_digit(ch): itm = read_number(rdr, ch) elif ch == u"-": ch2 = rdr.read() if is_digit(ch2): rdr.unread(ch2) itm = read_number(rdr, ch) else: rdr.unread(ch2) itm = read_symbol(rdr, ch) else: itm = read_symbol(rdr, ch) if rt.has_meta_QMARK_(itm): itm = rt.with_meta(itm, rt.merge(meta, rt.meta(itm))) return itm
def compile_cons(form, ctx): if isinstance(form, EmptyList): ctx.push_const(form) return if isinstance(rt.first(form), symbol.Symbol): special = compiler_special(rt.first(form)) if special is not None: return special(form, ctx) macro = is_macro_call(form, ctx) if macro: return compile_form(call_macro(macro, form, ctx), ctx) meta = rt.meta(form) cnt = 0 ctc = ctx.can_tail_call while form is not nil: ctx.disable_tail_call() compile_form(rt.first(form), ctx) cnt += 1 form = rt.next(form) if ctc: ctx.enable_tail_call() #if ctx.can_tail_call: # ctx.bytecode.append(code.TAIL_CALL) #else: if meta is not nil: ctx.debug_points[len(ctx.bytecode)] = rt.interpreter_code_info(meta) ctx.bytecode.append(code.INVOKE) ctx.bytecode.append(cnt) ctx.sub_sp(r_uint(cnt - 1))
def compile_quote(form, ctx): data = rt.first(rt.next(form)) ctx.push_const(data) if rt.meta(form) is not nil: compile_meta(rt.meta(form), ctx)
def compile_form(form, ctx): if form is nil: ctx.push_const(nil) return if rt._satisfies_QMARK_(rt.ISeq.deref(), form) and form is not nil: form = macroexpand(form) return compile_cons(form, ctx) if isinstance(form, numbers.Integer): ctx.push_const(form) return if isinstance(form, numbers.BigInteger): ctx.push_const(form) return if isinstance(form, numbers.Float): ctx.push_const(form) return if isinstance(form, numbers.Ratio): ctx.push_const(form) return if isinstance(form, symbol.Symbol): name = rt.name(form) ns = rt.namespace(form) loc = resolve_local(ctx, name) var = resolve_var(ctx, form) if var is None and loc: loc.emit(ctx) return if var and loc and ns is None: loc.emit(ctx) return if var is None: name = rt.name(form) var = NS_VAR.deref().intern_or_make(name) ctx.push_const(var) meta = rt.meta(form) if meta is not nil: ctx.debug_points[len(ctx.bytecode)] = rt.interpreter_code_info(meta) ctx.bytecode.append(code.DEREF_VAR) return if isinstance(form, Bool) or form is nil: ctx.push_const(form) return if isinstance(form, Keyword): ctx.push_const(form) return if isinstance(form, PersistentVector): vector_var = rt.vector() size = rt.count(form) #assert rt.count(form).int_val() == 0 ctx.push_const(code.intern_var(u"pixie.stdlib", u"vector")) for x in range(size): compile_form(rt.nth(form, rt.wrap(x)), ctx) ctx.bytecode.append(code.INVOKE) ctx.bytecode.append(r_uint(size + 1)) ctx.sub_sp(size) compile_meta(rt.meta(form), ctx) return if isinstance(form, PersistentHashSet): compile_set_literal(form, ctx) return if rt._satisfies_QMARK_(rt.IMap.deref(), form): compile_map_literal(form, ctx) return if isinstance(form, String): ctx.push_const(form) return if isinstance(form, Character): ctx.push_const(form) return raise Exception("Can't compile ")
def compile_form(form, ctx): if form is nil: ctx.push_const(nil) return if rt._satisfies_QMARK_(rt.ISeq.deref(), form) and form is not nil: form = maybe_oop_invoke(form) return compile_cons(form, ctx) if isinstance(form, numbers.Integer): ctx.push_const(form) return if isinstance(form, numbers.BigInteger): ctx.push_const(form) return if isinstance(form, numbers.Float): ctx.push_const(form) return if isinstance(form, numbers.Ratio): ctx.push_const(form) return if isinstance(form, symbol.Symbol): name = rt.name(form) ns = rt.namespace(form) loc = resolve_local(ctx, name) var = resolve_var(form) if var is None and loc: loc.emit(ctx) return if var and loc and ns is None: loc.emit(ctx) return if var is None: name = rt.name(form) var = NS_VAR.deref().intern_or_make(name) ctx.push_const(var) meta = rt.meta(form) if meta is not nil: ctx.debug_points[len( ctx.bytecode)] = rt.interpreter_code_info(meta) ctx.bytecode.append(code.DEREF_VAR) return if isinstance(form, Bool) or form is nil: ctx.push_const(form) return if isinstance(form, Keyword): ctx.push_const(form) return if isinstance(form, PersistentVector): size = rt.count(form) #assert rt.count(form).int_val() == 0 ctx.push_const(code.intern_var(u"pixie.stdlib", u"vector")) for x in range(size): compile_form(rt.nth(form, rt.wrap(x)), ctx) ctx.bytecode.append(code.INVOKE) ctx.bytecode.append(r_uint(size + 1)) ctx.sub_sp(size) compile_meta(rt.meta(form), ctx) return if isinstance(form, PersistentHashSet): compile_set_literal(form, ctx) return if rt._satisfies_QMARK_(rt.IMap.deref(), form): compile_map_literal(form, ctx) return if isinstance(form, String): ctx.push_const(form) return if isinstance(form, Character): ctx.push_const(form) return raise Exception("Can't compile ")