def create_type(type_name, fields): affirm(isinstance(type_name, Keyword), u"Type name must be a keyword") field_count = rt.count(fields) acc = {} for i in range(rt.count(fields)): val = rt.nth(fields, rt.wrap(i)) affirm(isinstance(val, Keyword), u"Field names must be keywords") acc[val] = i return CustomType(rt.name(type_name), acc)
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)) 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))) #new_ctx.push_recur_point(FunctionRecurPoint()) new_ctx.disable_tail_call() if body is nil: compile_form(body, new_ctx) else: while body is not nil: if rt.next(body) is nil: new_ctx.enable_tail_call() compile_form(rt.first(body), new_ctx) body = rt.next(body) if body is not nil: new_ctx.pop() new_ctx.bytecode.append(code.RETURN) closed_overs = new_ctx.closed_overs if len(closed_overs) == 0: ctx.push_const(new_ctx.to_code(required_args)) else: ctx.push_const(new_ctx.to_code(required_args)) for x in closed_overs: x.emit(ctx) ctx.bytecode.append(code.MAKE_CLOSURE) ctx.bytecode.append(r_uint(len(closed_overs))) ctx.sub_sp(len(closed_overs)) if required_args >= 0: ctx.bytecode.append(code.MAKE_VARIADIC) ctx.bytecode.append(r_uint(required_args)) return required_args, intmask(rt.count(args))
def ffi_callback(args, ret_type): """(ffi-callback args ret-type) Creates a ffi callback type. Args is a vector of CType args. Ret-type is the CType return type of the callback. Returns a ffi callback type that can be used with ffi-prep-callback.""" args_w = [None] * rt.count(args) for x in range(rt.count(args)): arg = rt.nth(args, rt.wrap(x)) if not isinstance(arg, object.Type): runtime_error(u"Expected type, got " + rt.name(rt.str(arg))) args_w[x] = arg if not isinstance(ret_type, object.Type): runtime_error(u"Expected type, got " + rt.name(rt.str(ret_type))) return CFunctionType(args_w, ret_type)
def load_ns(filename): import pixie.vm.string as string import pixie.vm.symbol as symbol if isinstance(filename, symbol.Symbol): affirm( rt.namespace(filename) is None, u"load-file takes a un-namespaced symbol") filename_str = rt.name(filename).replace(u".", u"/") + u".pxi" loaded_ns = code._ns_registry.get(rt.name(filename), None) if loaded_ns is not None: return loaded_ns else: affirm(isinstance(filename, string.String), u"Filename must be string") filename_str = rt.name(filename) paths = rt.deref(rt.deref(rt.load_paths)) f = None for x in range(rt.count(paths)): path_x = rt.nth(paths, rt.wrap(x)) affirm(isinstance(path_x, string.String), u"Contents of load-paths must be strings") full_path = path.join(str(rt.name(path_x)), str(filename_str)) if path.isfile(full_path): f = full_path break if f is None: affirm( False, u"File '" + rt.name(filename) + u"' does not exist in any directory found in load-paths") else: rt.load_file(rt.wrap(f)) return nil
def load_lib(self): if not self._is_inited: load_paths = rt.deref(rt.deref(rt.load_paths)) for x in range(rt.count(load_paths)): s = rffi.str2charp(str(rt.name(rt.nth(load_paths, rt.wrap(x)))) + "/" + str(self._name)) try: self._dyn_lib = dynload.dlopen(s) self._is_inited = True except dynload.DLOpenError as ex: continue finally: rffi.free_charp(s) break if not self._is_inited: s = rffi.str2charp(str(self._name)) try: self._dyn_lib = dynload.dlopen(s) self._is_inited = True except dynload.DLOpenError as ex: raise object.runtime_error(u"Couldn't Load Library: " + self._name, u"pixie.stdlib/LibraryNotFoundException") finally: rffi.free_charp(s)
def load_ns(filename): import pixie.vm.string as string import pixie.vm.symbol as symbol import os.path as path if isinstance(filename, symbol.Symbol): affirm(rt.namespace(filename) is None, u"load-file takes a un-namespaced symbol") filename_str = rt.name(filename).replace(u".", u"/") + u".pxi" loaded_ns = code._ns_registry.get(rt.name(filename), None) if loaded_ns is not None: return loaded_ns else: affirm(isinstance(filename, string.String), u"Filename must be string") filename_str = rt.name(filename) paths = rt.deref(rt.deref(rt.load_paths)) f = None for x in range(rt.count(paths)): path_x = rt.nth(paths, rt.wrap(x)) affirm(isinstance(path_x, string.String), u"Contents of load-paths must be strings") full_path = path.join(str(rt.name(path_x)), str(filename_str)) if path.isfile(full_path): f = full_path break if f is None: affirm(False, u"File '" + rt.name(filename) + u"' does not exist in any directory found in load-paths") else: rt.load_file(rt.wrap(f)) return nil
def compile_let(form, ctx): form = next(form) bindings = rt.first(form) affirm(isinstance(bindings, PersistentVector), u"Bindings must be a vector") body = next(form) ctc = ctx.can_tail_call ctx.disable_tail_call() binding_count = 0 for i in range(0, rt.count(bindings).int_val(), 2): binding_count += 1 name = rt.nth(bindings, numbers.Integer(i)) affirm(isinstance(name, symbol.Symbol), u"Let locals must be symbols") bind = rt.nth(bindings, numbers.Integer(i + 1)) compile_form(bind, ctx) ctx.add_local(name._str, LetBinding(ctx.sp())) if ctc: ctx.enable_tail_call() while True: compile_form(rt.first(body), ctx) body = rt.next(body) if body is nil: break else: ctx.pop() ctx.bytecode.append(code.POP_UP_N) ctx.sub_sp(binding_count) ctx.bytecode.append(binding_count)
def load_lib(self): if not self._is_inited: load_paths = rt.deref(rt.deref(rt.load_paths)) for x in range(rt.count(load_paths)): s = rffi.str2charp( str(rt.name(rt.nth(load_paths, rt.wrap(x)))) + "/" + str(self._name)) try: self._dyn_lib = dynload.dlopen(s) self._is_inited = True except dynload.DLOpenError as ex: continue finally: rffi.free_charp(s) break if not self._is_inited: s = rffi.str2charp(str(self._name)) try: self._dyn_lib = dynload.dlopen(s) self._is_inited = True except dynload.DLOpenError as ex: raise object.runtime_error( u"Couldn't Load Library: " + self._name, u"pixie.stdlib/LibraryNotFoundException") finally: rffi.free_charp(s)
def compile_if(form, ctx): form = form.next() affirm(2 <= rt.count(form) <= 3, u"If must have either 2 or 3 forms") test = rt.first(form) form = rt.next(form) then = rt.first(form) form = rt.next(form) els = rt.first(form) ctx.disable_tail_call() compile_form(test, ctx) ctx.bytecode.append(code.COND_BR) ctx.sub_sp(1) sp1 = ctx.sp() cond_lbl = ctx.label() ctx.enable_tail_call() compile_form(then, ctx) ctx.bytecode.append(code.JMP) ctx.sub_sp(1) affirm( ctx.sp() == sp1, u"If branches stacks are unequal " + unicode(str(ctx.sp())) + u", " + unicode(str(sp1))) else_lbl = ctx.label() ctx.mark(cond_lbl) compile_form(els, ctx) ctx.mark(else_lbl)
def compile_if(form, ctx): form = form.next() affirm(2 <= rt.count(form) <= 3, u"If must have either 2 or 3 forms") test = rt.first(form) form = rt.next(form) then = rt.first(form) form = rt.next(form) els = rt.first(form) ctx.disable_tail_call() compile_form(test, ctx) ctx.bytecode.append(code.COND_BR) ctx.sub_sp(1) sp1 = ctx.sp() cond_lbl = ctx.label() ctx.enable_tail_call() compile_form(then, ctx) ctx.bytecode.append(code.JMP) ctx.sub_sp(1) affirm(ctx.sp() == sp1, u"If branches stacks are unequal " + unicode(str(ctx.sp())) + u", " + unicode(str(sp1))) else_lbl = ctx.label() ctx.mark(cond_lbl) compile_form(els, ctx) ctx.mark(else_lbl)
def _ffi_fn__args(args): affirm(len(args) >= 4, u"ffi-fn requires at least 4 arguments") lib, nm, arg_types, ret_type = args[:4] affirm(isinstance(lib, ExternalLib), u"First argument must be an ExternalLib") affirm(isinstance(ret_type, object.Type), u"Ret type must be a type") affirm(rt.namespace(nm) is None, u"Name must not be namespaced") cnt = rt.count(arg_types) new_args = [None] * cnt for x in range(cnt): t = rt.nth(arg_types, rt.wrap(x)) affirm(isinstance(t, object.Type), u"Arg defs must be types") new_args[x] = t kwargs = args[4:] affirm(len(kwargs) & 0x1 == 0, u"ffi-fn requires even number of options") is_variadic = False for i in range(0, len(kwargs)/2, 2): key = kwargs[i] val = kwargs[i+1] affirm(isinstance(key, Keyword), u"ffi-fn options should be keyword/bool pairs") affirm(val is true or val is false, u"ffi-fn options should be keyword/bool pairs") k = rt.name(key) if k == u"variadic?": is_variadic = True if val is true else False else: affirm(False, u"unknown ffi-fn option: :" + k) f = FFIFn(lib, rt.name(nm), new_args, ret_type, is_variadic) return f
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).int_val() * 2 ctx.bytecode.append(code.INVOKE) ctx.bytecode.append(r_uint(size) + 1)
def compile_form(form, ctx): if form is nil: ctx.push_const(nil) return if rt.instance_QMARK_(rt.ISeq.deref(), form) and form is not nil: return compile_cons(form, ctx) if isinstance(form, numbers.Integer): ctx.push_const(form) return if isinstance(form, symbol.Symbol): name = form._str loc = resolve_local(ctx, name) if loc is None: var = resolve_var(ctx, form) if var is None: var = NS_VAR.deref().intern_or_make(name) ctx.push_const(var) ctx.bytecode.append(code.DEREF_VAR) return loc.emit(ctx) 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).int_val() #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, numbers.Integer(x)), ctx) ctx.bytecode.append(code.INVOKE) ctx.bytecode.append(r_uint(size + 1)) ctx.sub_sp(size) return if rt.instance_QMARK_(rt.IMap.deref(), form): compile_map_literal(form, ctx) return if isinstance(form, String): ctx.push_const(form) return raise Exception("Can't compile ")
def write_seq(s, wtr): write_tag(SEQ, wtr) write_int_raw(rt.count(s), wtr) s = rt.seq(s) while s is not nil: write_object(rt.first(s), wtr) s = rt.next(s)
def call_macro(var, form, ctx): form = rt.next(form) args = [None] * rt.count(form) i = 0 while form is not nil: args[i] = rt.first(form) form = rt.next(form) i += 1 return var.invoke(args)
def compile_platform_eq(form, ctx): form = form.next() affirm(rt.count(form) == 2, u"TODO: REMOVE") while form is not nil: compile_form(form.first(), ctx) form = form.next() ctx.bytecode.append(code.EQ) ctx.sub_sp(1) return ctx
def compile_ns(form, ctx): affirm(rt.count(form).int_val() == 2, u"ns only takes one argument, a symbol") nm = rt.first(rt.next(form)) affirm(isinstance(nm, symbol.Symbol), u"Namespace name must be a symbol") str_name = rt.name(nm) NS_VAR.set_value(code._ns_registry.find_or_make(str_name)) ctx.push_const(nil)
def compile_fn_body(name, args, body, ctx): new_ctx = Context(name._str, rt.count(args).int_val(), ctx) required_args = add_args(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()) new_ctx.push_recur_point(FunctionRecurPoint()) new_ctx.disable_tail_call() if body is nil: compile_form(body, new_ctx) else: while body is not nil: if rt.next(body) is nil: new_ctx.enable_tail_call() compile_form(rt.first(body), new_ctx) if rt.next(body) is not nil: new_ctx.pop() bc += 1 body = rt.next(body) new_ctx.bytecode.append(code.RETURN) closed_overs = new_ctx.closed_overs if len(closed_overs) == 0: ctx.push_const(new_ctx.to_code(required_args)) else: ctx.push_const(new_ctx.to_code(required_args)) for x in closed_overs: x.emit(ctx) ctx.bytecode.append(code.MAKE_CLOSURE) ctx.bytecode.append(r_uint(len(closed_overs))) ctx.sub_sp(len(closed_overs)) if required_args >= 0: ctx.bytecode.append(code.MAKE_VARIADIC) ctx.bytecode.append(r_uint(required_args)) return required_args, rt.count(args).int_val()
def compile_ns(form, ctx): affirm(rt.count(form) == 2, u"ns only takes one argument, a symbol") nm = rt.first(rt.next(form)) affirm(isinstance(nm, symbol.Symbol), u"Namespace name must be a symbol") str_name = rt.name(nm) NS_VAR.set_value(code._ns_registry.find_or_make(str_name)) NS_VAR.deref().include_stdlib() ctx.push_const(nil)
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 add_args(args, ctx): required_args = -1 local_idx = 0 for x in range(rt.count(args).int_val()): arg = rt.nth(args, numbers.Integer(x)) affirm(isinstance(arg, symbol.Symbol), u"Argument names must be symbols") if arg._str == u"&": required_args = x continue ctx.add_local(arg._str, Arg(local_idx)) local_idx += 1 return required_args
def add_args(name, args, ctx): required_args = -1 local_idx = 0 ctx.add_local(name, Self()) for x in range(rt.count(args)): arg = rt.nth(args, rt.wrap(x)) affirm(isinstance(arg, symbol.Symbol), u"Argument names must be symbols") if arg._str == u"&": required_args = intmask(x) continue ctx.add_local(arg._str, Arg(local_idx)) local_idx += 1 return required_args
def _ffi_fn(lib, nm, args, ret_type): affirm(isinstance(lib, ExternalLib), u"First argument must be an ExternalLib") affirm(isinstance(ret_type, object.Type), u"Ret type must be a type") affirm(rt.namespace(nm) is None, u"Name must not be namespaced") cnt = rt.count(args) new_args = [None] * cnt for x in range(cnt): t = rt.nth(args, rt.wrap(x)) affirm(isinstance(t, object.Type), u"Arg defs must be types") new_args[x] = t f = FFIFn(lib, rt.name(nm), new_args, ret_type) return f
def c_struct(name, size, spec): d = {} for x in range(rt.count(spec)): row = rt.nth(spec, rt.wrap(x)) nm = rt.nth(row, rt.wrap(0)) tp = rt.nth(row, rt.wrap(1)) offset = rt.nth(row, rt.wrap(2)) affirm(isinstance(nm, Keyword), u"c-struct field names must be keywords") if not isinstance(tp, CType): runtime_error(u"c-struct field types must be c types, got: " + rt.name(rt.str(tp))) d[nm] = (tp, offset.int_val()) return CStructType(rt.name(name), size.int_val(), d)
def add_args(name, args, ctx): required_args = -1 local_idx = 0 ctx.add_local(name, Self()) for x in range(rt.count(args)): arg = rt.nth(args, rt.wrap(x)) affirm(isinstance(arg, symbol.Symbol), u"Argument names must be symbols") if rt.name(arg) == u"&": required_args = intmask(x) continue ctx.add_local(rt.name(arg), Arg(local_idx)) local_idx += 1 return required_args
def load_file(filename): import pixie.vm.reader as reader import pixie.vm.compiler as compiler import pixie.vm.string as string import pixie.vm.symbol as symbol import os.path as path if isinstance(filename, symbol.Symbol): affirm(rt.namespace(filename) is None, u"load-file takes a un-namespaced symbol") filename_str = rt.name(filename).replace(u".", u"/") + u".lisp" loaded_ns = code._ns_registry.get(rt.name(filename), None) if loaded_ns is not None: return loaded_ns else: affirm(isinstance(filename, string.String), u"Filename must be string") filename_str = rt.name(filename) paths = rt.deref(rt.deref(rt.load_paths)) f = None for x in range(rt.count(paths)): path_x = rt.nth(paths, rt.wrap(x)) affirm(isinstance(path_x, string.String), u"Contents of load-paths must be strings") full_path = path.join(str(rt.name(path_x)), str(filename_str)) if path.isfile(full_path): f = open(str(full_path)) break if f is None: affirm(False, u"File does not exist in any directory found in load-paths") else: data = f.read() f.close() if data.startswith("#!"): newline_pos = data.find("\n") if newline_pos > 0: data = data[newline_pos:] rdr = reader.StringReader(unicode(data)) with compiler.with_ns(u"user"): while True: form = reader.read(rdr, False) if form is reader.eof: return nil result = compiler.compile(form).invoke([]) return nil
def macroexpand(form): sym = rt.first(form) if isinstance(sym, symbol.Symbol): s = rt.name(sym) if s.startswith(".") and s != u".": if rt.count(form) < 2: raise Exception("malformed dot expression, expecting (.member obj ...)") method = rt.keyword(rt.wrap(rt.name(sym)[1:])) obj = rt.first(rt.next(form)) dot = rt.symbol(rt.wrap(u".")) call = rt.cons(dot, rt.cons(obj, rt.cons(method, rt.next(rt.next(form))))) return call return form
def macroexpand(form): sym = rt.first(form) if isinstance(sym, symbol.Symbol): s = rt.name(sym) if s.startswith(".") and s != u".": if rt.count(form) < 2: raise Exception( "malformed dot expression, expecting (.member obj ...)") method = rt.keyword(rt.wrap(rt.name(sym)[1:])) obj = rt.first(rt.next(form)) dot = rt.symbol(rt.wrap(u".")) call = rt.cons( dot, rt.cons(obj, rt.cons(method, rt.next(rt.next(form))))) return call return form
def c_struct(name, size, spec): """(c-struct name size spec) Creates a CStruct named name, of size size, with the given spec. Spec is a vector of vectors. Each row of the format [field-name type offset]""" d = {} for x in range(rt.count(spec)): row = rt.nth(spec, rt.wrap(x)) nm = rt.nth(row, rt.wrap(0)) tp = rt.nth(row, rt.wrap(1)) offset = rt.nth(row, rt.wrap(2)) affirm(isinstance(nm, Keyword), u"c-struct field names must be keywords") #if not isinstance(tp, CType): # runtime_error(u"c-struct field types must be c types, got: " + rt.name(rt.str(tp))) d[nm] = (tp, offset.int_val()) tp = CStructType(rt.name(name), size.int_val(), d) proto._dispose_BANG_.extend(tp, _dispose_cstruct) return tp
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 compile_loop(form, ctx): form = rt.next(form) bindings = rt.first(form) affirm(isinstance(bindings, PersistentVector), u"Loop bindings must be a vector") body = rt.next(form) ctx.enable_tail_call() ctc = ctx.can_tail_call ctx.disable_tail_call() binding_count = 0 for i in range(0, rt.count(bindings), 2): binding_count += 1 name = rt.nth(bindings, rt.wrap(i)) affirm(isinstance(name, symbol.Symbol), u"Loop bindings must be symbols") bind = rt.nth(bindings, rt.wrap(i + 1)) compile_form(bind, ctx) ctx.add_local(rt.name(name), LetBinding(ctx.sp())) if ctc: ctx.enable_tail_call() ctx.push_recur_point(LoopRecurPoint(binding_count, ctx)) while True: compile_form(rt.first(body), ctx) body = rt.next(body) if body is nil: break else: ctx.pop() ctx.pop_recur_point() ctx.bytecode.append(code.POP_UP_N) ctx.sub_sp(binding_count) ctx.bytecode.append(binding_count) ctx.pop_locals(binding_count)
def _ffi_fn__args(args): affirm(len(args) >= 4, u"ffi-fn requires at least 4 arguments") lib, nm, arg_types, ret_type = args[:4] affirm(isinstance(lib, ExternalLib), u"First argument must be an ExternalLib") affirm(isinstance(ret_type, object.Type), u"Ret type must be a type") affirm(rt.namespace(nm) is None, u"Name must not be namespaced") cnt = rt.count(arg_types) new_args = [None] * cnt for x in range(cnt): t = rt.nth(arg_types, rt.wrap(x)) affirm(isinstance(t, object.Type), u"Arg defs must be types") new_args[x] = t kwargs = args[4:] affirm(len(kwargs) & 0x1 == 0, u"ffi-fn requires even number of options") is_variadic = False for i in range(0, len(kwargs) / 2, 2): key = kwargs[i] val = kwargs[i + 1] affirm(isinstance(key, Keyword), u"ffi-fn options should be keyword/bool pairs") affirm(val is true or val is false, u"ffi-fn options should be keyword/bool pairs") k = rt.name(key) if k == u"variadic?": is_variadic = True if val is true else False else: affirm(False, u"unknown ffi-fn option: :" + k) tp = CFunctionType(new_args, ret_type, is_variadic) nm = rt.name(nm) f = FFIFn(nm, lib.get_fn_ptr(nm), tp) return f
def compile_loop(form, ctx): form = rt.next(form) bindings = rt.first(form) affirm(isinstance(bindings, PersistentVector), u"Loop bindings must be a vector") body = rt.next(form) ctc = ctx.can_tail_call ctx.disable_tail_call() binding_count = 0 for i in range(0, rt.count(bindings), 2): binding_count += 1 name = rt.nth(bindings, rt.wrap(i)) affirm(isinstance(name, symbol.Symbol), u"Loop must bindings must be symbols") bind = rt.nth(bindings, rt.wrap(i + 1)) compile_form(bind, ctx) ctx.add_local(rt.name(name), LetBinding(ctx.sp())) if ctc: ctx.enable_tail_call() ctx.push_recur_point(LoopRecurPoint(binding_count, ctx)) while True: compile_form(rt.first(body), ctx) body = rt.next(body) if body is nil: break else: ctx.pop() ctx.pop_recur_point() ctx.bytecode.append(code.POP_UP_N) ctx.sub_sp(binding_count) ctx.bytecode.append(binding_count) ctx.pop_locals(binding_count)
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 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 ")
def compile_in_ns(form, ctx): affirm(rt.count(form) == 2, u"in-ns requires an argument") arg = rt.first(rt.next(form)) NS_VAR.set_value(code._ns_registry.find_or_make(rt.name(arg))) NS_VAR.deref().include_stdlib() compile_fn_call(form, ctx)
def compile_yield(form, ctx): affirm(rt.count(form) == 2, u"yield takes a single argument") arg = rt.first(rt.next(form)) compile_form(arg, ctx) ctx.bytecode.append(code.YIELD)
def next(self): if self._idx < rt.count(self._w_array) - 1: return ArraySeq(self._idx + 1, self._w_array) else: return nil
def split(a, b): affirm(rt.count(b) > 0, u"separator can't be empty") v = rt.vector() for s in rstring.split(rt.name(a), rt.name(b)): v = rt.conj(v, rt.wrap(s)) return v
def _seq(self): assert isinstance(self, Array) if rt.count(self) > 0: return ArraySeq(0, self) else: return nil
def write_vector(vec, wtr): write_tag(VECTOR, wtr) write_int_raw(rt.count(vec), wtr) rt._reduce(vec, WriteItem(wtr), nil)
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 reduce(self, f, init): for x in range(self._idx, rt.count(self._w_array)): if rt.reduced_QMARK_(init): return rt.deref(init) init = f.invoke([init, rt.nth(self._w_array, rt.wrap(x))]) return init
def write_map(mp, wtr): write_tag(MAP, wtr) write_int_raw(rt.count(mp), wtr) rt._reduce(mp, WriteParirFn(wtr), nil)