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 invoke(self, rdr, ch): if ARG_ENV.deref() is not nil: throw_syntax_error_with_data(rdr, u"Nested #()s are not allowed") try: ARG_ENV.set_value(rt.assoc(EMPTY_MAP, ARG_MAX, rt.wrap(-1))) rdr.unread() form = read_inner(rdr, True) args = EMPTY_VECTOR percent_args = ARG_ENV.deref() max_arg = rt.get(percent_args, ARG_MAX) for i in range(1, max_arg.int_val() + 1): arg = rt.get(percent_args, rt.wrap(i)) if arg is nil: arg = ArgReader.gen_arg(i) args = rt.conj(args, arg) rest_arg = rt.get(percent_args, rt.wrap(-1)) if rest_arg is not nil: args = rt.conj(args, ARG_AMP) args = rt.conj(args, rest_arg) return rt.cons(symbol(u"fn*"), rt.cons(args, rt.cons(form, nil))) finally: ARG_ENV.set_value(nil)
def maybe_oop_invoke(form): head = rt.first(form) if isinstance(rt.first(form), symbol.Symbol) and rt.name(head).startswith(".-"): postfix = rt.next(form) affirm(rt.count(postfix) == 1, u" Attribute lookups must only have one argument") subject = rt.first(postfix) kw = keyword(rt.name(head)[2:]) fn = symbol.symbol(u"pixie.stdlib/-get-attr") return create_from_list([fn, subject, kw]) elif isinstance(rt.first(form), symbol.Symbol) and rt.name(head).startswith("."): subject = rt.first(rt.next(form)) postfix = rt.next(rt.next(form)) form = cons(keyword(rt.name(head)[1:]), postfix) form = cons(subject, form) form = cons(symbol.symbol(u"pixie.stdlib/-call-method"), form) return form else: return form
def maybe_oop_invoke(form): head = rt.first(form) if isinstance(rt.first(form), symbol.Symbol) and rt.name(head).startswith(".-"): postfix = rt.next(form) affirm( rt.count(postfix) == 1, u" Attribute lookups must only have one argument") subject = rt.first(postfix) kw = keyword(rt.name(head)[2:]) fn = symbol.symbol(u"pixie.stdlib/-get-attr") return create_from_list([fn, subject, kw]) elif isinstance(rt.first(form), symbol.Symbol) and rt.name(head).startswith("."): subject = rt.first(rt.next(form)) postfix = rt.next(rt.next(form)) form = cons(keyword(rt.name(head)[1:]), postfix) form = cons(subject, form) form = cons(symbol.symbol(u"pixie.stdlib/-call-method"), form) return form else: return form
def read_symbol(rdr, ch): acc = [ch] try: while True: ch = rdr.read() if is_whitespace(ch) or is_terminating_macro(ch): rdr.unread(ch) break acc.append(ch) except EOFError: pass sym_str = u"".join(acc) if sym_str == u"true": return true if sym_str == u"false": return false if sym_str == u"nil": return nil return symbol(sym_str)
def read_symbol(rdr, ch): acc = [ch] try: while True: ch = rdr.read() if is_whitespace(ch) or is_terminating_macro(ch): rdr.unread() break acc.append(ch) except EOFError: pass sym_str = u"".join(acc) if sym_str == u"true": return true if sym_str == u"false": return false if sym_str == u"nil": return nil return symbol(sym_str)
def read_obj(rdr): tag = read_tag(rdr) if tag == INT: return Integer(intmask(read_raw_integer(rdr))) elif tag == BIGINT: return BigInteger(read_raw_bigint(rdr)) elif tag == CODE: return read_code(rdr) elif tag == NIL: return nil elif tag == VAR: return read_var(rdr) elif tag == STRING: return String(read_raw_string(rdr)) elif tag == KEYWORD: return keyword(read_raw_string(rdr)) elif tag == SYMBOL: return symbol(read_raw_string(rdr)) elif tag == LINE_PROMISE: lp = LinePromise() lp._chrs = None lp._str = read_raw_string(rdr) return lp elif tag == MAP: return read_map(rdr) elif tag == TRUE: return true elif tag == FALSE: return false elif tag == NIL: return nil elif tag == VECTOR: return read_vector(rdr) elif tag == SEQ: return read_seq(rdr) elif tag == FLOAT: return read_float(rdr) elif tag == NAMESPACE: return read_namespace(rdr) elif tag == INT_STRING: return Integer(int(read_raw_string(rdr))) elif tag == BIGINT_STRING: return BigInteger(rbigint.fromstr(str(read_raw_string(rdr)))) elif tag == NEW_CACHED_OBJ: return rdr.read_and_cache() elif tag == CACHED_OBJ: return rdr.read_cached_obj() elif tag == EOF: from pixie.vm.reader import eof return eof elif tag == CODE_INFO: return read_interpreter_code_info(rdr) elif tag == TAGGED: tp_name = read_raw_string(rdr) tp = get_type_by_name(tp_name) handler = read_handlers.get(tp, None) if handler is None: runtime_error(u"No type handler for " + tp_name) obj = read_obj(rdr) return handler.invoke([obj]) else: runtime_error(u"No dispatch for bytecode: " + unicode(tag_name[tag])) return nil
def invoke(self, rdr, ch): return rt.cons(symbol(u"-deref"), rt.cons(read(rdr, True), nil))
def invoke(self, rdr, ch): itm = read(rdr, True) return cons(symbol(u"quote"), cons(itm))
l = len(token) - 1 if l > 3: throw_syntax_error_with_data(rdr, u"Invalid octal escape sequence: \\" + token) c = read_unicode_char(rdr, token, 1, l, 8) if c > 0377: throw_syntax_error_with_data(rdr, u"Octal escape sequences must be in range [0, 377]") return Character(c) else: throw_syntax_error_with_data(rdr, u"Unsupported character: \\" + token) class DerefReader(ReaderHandler): def invoke(self, rdr, ch): return rt.cons(symbol(u"-deref"), rt.cons(read(rdr, True), nil)) QUOTE = symbol(u"quote") UNQUOTE = symbol(u"unquote") UNQUOTE_SPLICING = symbol(u"unquote-splicing") APPLY = symbol(u"apply") CONCAT = symbol(u"concat") SEQ = symbol(u"seq") LIST = symbol(u"list") def is_unquote(form): return True if rt.satisfies_QMARK_(rt.ISeq.deref(), form) \ and rt.eq(rt.first(form), UNQUOTE) \ else False def is_unquote_splicing(form): return True if rt.satisfies_QMARK_(rt.ISeq.deref(), form) \ and rt.eq(rt.first(form), UNQUOTE_SPLICING) \
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) LOOP = symbol.symbol(u"loop") def compile_fn_body(name, args, body, ctx): new_ctx = Context(rt.name(name), rt.count(args), ctx) required_args = add_args(rt.name(name), args, new_ctx) bc = 0 if name is not None: affirm(isinstance(name, symbol.Symbol), u"Function names must be symbols") #new_ctx.add_local(name._str, Self()) arg_syms = EMPTY for x in range(rt.count(args)): sym = rt.nth(args, rt.wrap(x))
def invoke(self, rdr, ch): itm = read_inner(rdr, True) return cons(symbol(u"quote"), cons(itm))
def invoke(self, rdr, ch): return rt.cons(symbol(u"-deref"), rt.cons(read_inner(rdr, True), nil))
def read_obj(rdr): tag = read_tag(rdr) if tag == INT: return Integer(intmask(read_raw_integer(rdr))) elif tag == CODE: return read_code(rdr) elif tag == NIL: return nil elif tag == VAR: return read_var(rdr) elif tag == STRING: return String(read_raw_string(rdr)) elif tag == KEYWORD: return keyword(read_raw_string(rdr)) elif tag == SYMBOL: return symbol(read_raw_string(rdr)) elif tag == LINE_PROMISE: lp = LinePromise() lp._str = read_raw_string(rdr) return lp elif tag == MAP: return read_map(rdr) elif tag == TRUE: return true elif tag == FALSE: return false elif tag == NIL: return nil elif tag == VECTOR: return read_vector(rdr) elif tag == SEQ: return read_seq(rdr) elif tag == FLOAT: return read_float(rdr) elif tag == NAMESPACE: return read_namespace(rdr) elif tag == INT_STRING: return Integer(int(read_raw_string(rdr))) elif tag == NEW_CACHED_OBJ: return rdr.read_and_cache() elif tag == CACHED_OBJ: return rdr.read_cached_obj() elif tag == EOF: from pixie.vm.reader import eof return eof elif tag == CODE_INFO: return read_interpreter_code_info(rdr) elif tag == TAGGED: tp_name = read_raw_string(rdr) tp = get_type_by_name(tp_name) handler = read_handlers.get(tp, None) if handler is None: runtime_error(u"No type handler for " + tp_name) obj = read_obj(rdr) return handler.invoke([obj]) else: runtime_error(u"No dispatch for bytecode: " + unicode(tag_name[tag])) return nil
from rpython.rlib.rsre import rsre_re as re READING_FORM_VAR = code.intern_var(u"pixie.stdlib", u"*reading-form*") READING_FORM_VAR.set_dynamic() READING_FORM_VAR.set_root(false) LINE_NUMBER_KW = keyword(u"line-number") COLUMN_NUMBER_KW = keyword(u"column-number") LINE_KW = keyword(u"line") FILE_KW = keyword(u"file") GEN_SYM_ENV = code.intern_var(u"pixie.stdlib.reader", u"*gen-sym-env*") GEN_SYM_ENV.set_dynamic() GEN_SYM_ENV.set_root(EMPTY_MAP) ARG_AMP = symbol(u"&") ARG_MAX = keyword(u"max-arg") ARG_ENV = code.intern_var(u"pixie.stdlib.reader", u"*arg-env*") ARG_ENV.set_dynamic() ARG_ENV.set_root(nil) class PlatformReader(object.Object): _type = object.Type(u"PlatformReader") def type(self): return PlatformReader._type def read(self): assert False def unread(self):
from pixie.vm.reader import read, StringReader from pixie.vm.object import Object from pixie.vm.cons import Cons from pixie.vm.numbers import Integer from pixie.vm.symbol import symbol, Symbol from pixie.vm.persistent_vector import PersistentVector import pixie.vm.rt as rt import unittest data = {u"(1 2)": (1, 2,), u"(foo)": (symbol(u"foo"),), u"foo": symbol(u"foo"), u"1": 1, u"2": 2, u"((42))": ((42,),), u"(platform+ 1 2)": (symbol(u"platform+"), 1, 2), u"[42 43 44]": [42, 43, 44]} class TestReader(unittest.TestCase): def _compare(self, frm, to): if isinstance(to, tuple): assert isinstance(frm, Cons) for x in to: self._compare(frm.first(), x) frm = frm.next() elif isinstance(to, int): assert isinstance(frm, Integer) assert frm._int_val == to
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) LOOP = symbol.symbol(u"loop") def compile_fn_body(name, args, body, ctx): new_ctx = Context(rt.name(name), rt.count(args), ctx) required_args = add_args(rt.name(name), args, new_ctx) bc = 0 affirm(isinstance(name, symbol.Symbol), u"Function names must be symbols") arg_syms = EMPTY for x in range(rt.count(args)): sym = rt.nth(args, rt.wrap(x)) if not rt.name(sym) == u"&": arg_syms = rt.conj(rt.conj(arg_syms, sym), sym) body = rt.list(rt.cons(LOOP, rt.cons(arg_syms, body)))
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) LOOP = symbol.symbol(u"loop*") def compile_fn_body(name, args, body, ctx): new_ctx = Context(rt.name(name), rt.count(args), ctx) required_args = add_args(rt.name(name), args, new_ctx) affirm(isinstance(name, symbol.Symbol), u"Function names must be symbols") arg_syms = EMPTY for x in range(rt.count(args)): sym = rt.nth(args, rt.wrap(x)) if not rt.name(sym) == u"&": arg_syms = rt.conj(rt.conj(arg_syms, sym), sym) body = rt.list(rt.cons(LOOP, rt.cons(arg_syms, body)))
from pixie.vm.reader import read, StringReader from pixie.vm.object import Object from pixie.vm.cons import Cons from pixie.vm.numbers import Integer from pixie.vm.symbol import symbol, Symbol from pixie.vm.persistent_vector import PersistentVector import pixie.vm.rt as rt import unittest data = { u"(1 2)": ( 1, 2, ), u"(foo)": (symbol(u"foo"), ), u"foo": symbol(u"foo"), u"1": 1, u"2": 2, u"((42))": ((42, ), ), u"(platform+ 1 2)": (symbol(u"platform+"), 1, 2), u"[42 43 44]": [42, 43, 44], u"(1 2 ; 7 8 9\n3)": ( 1, 2, 3, ), u"(1 2 ; 7 8 9\r\n3)": ( 1, 2, 3, )