def syntax_quote(form): if isinstance(form, Symbol) and compiler.is_compiler_special(form): ret = rt.list(QUOTE, form) elif isinstance(form, Symbol): if rt.namespace(form) is None and rt.name(form).endswith("#"): gmap = rt.deref(GEN_SYM_ENV) affirm(gmap is not nil, u"Gensym literal used outside a syntax quote") gs = rt.get(gmap, form) if gs is nil: gs = rt.symbol(rt.str(form, rt.wrap(u"__"), rt.gensym())) GEN_SYM_ENV.set_value(rt.assoc(gmap, form, gs)) form = gs else: var = rt.resolve_in(compiler.NS_VAR.deref(), form) if var is nil: form = rt.symbol(rt.str(rt.wrap(rt.name(rt.deref(compiler.NS_VAR))), rt.wrap(u"/"), form)) else: form = rt.symbol(rt.str(rt.wrap(rt.namespace(var)), rt.wrap(u"/"), rt.str(rt.wrap(rt.name(var))))) ret = rt.list(QUOTE, form) elif is_unquote(form): ret = rt.first(rt.next(form)) elif is_unquote_splicing(form): return runtime_error(u"Unquote splicing not used inside list") elif rt.vector_QMARK_(form) is true: ret = rt.list(APPLY, CONCAT, SyntaxQuoteReader.expand_list(form)) elif rt.map_QMARK_(form) is true: mes = SyntaxQuoteReader.flatten_map(form) ret = rt.list(APPLY, HASHMAP, rt.list(APPLY, CONCAT, SyntaxQuoteReader.expand_list(mes))) elif form is not nil and rt.seq_QMARK_(form) is true: ret = rt.list(APPLY, LIST, rt.cons(CONCAT, SyntaxQuoteReader.expand_list(rt.seq(form)))) else: ret = rt.list(QUOTE, form) return ret
def syntax_quote(form): if isinstance(form, Symbol) and compiler.is_compiler_special(form): ret = rt.list(QUOTE, form) elif isinstance(form, Symbol): if rt.namespace(form) is None and rt.name(form).endswith("#"): gmap = rt.deref(GEN_SYM_ENV) affirm(gmap is not nil, u"Gensym literal used outside a syntax quote") gs = rt.get(gmap, form) if gs is nil: gs = rt.symbol(rt.str(form, rt.wrap(u"__"), rt.gensym())) GEN_SYM_ENV.set_value(rt.assoc(gmap, form, gs)) form = gs else: var = rt.resolve_in(compiler.NS_VAR.deref(), form) if var is nil: form = rt.symbol(rt.str(rt.wrap(rt.name(rt.deref(compiler.NS_VAR))), rt.wrap(u"/"), form)) else: form = rt.symbol(rt.str(rt.wrap(rt.namespace(var)), rt.wrap(u"/"), rt.str(rt.wrap(rt.name(var))))) ret = rt.list(QUOTE, form) elif is_unquote(form): ret = rt.first(rt.next(form)) elif is_unquote_splicing(form): raise Exception("Unquote splicing not used inside list") elif rt.vector_QMARK_(form) is true: ret = rt.list(APPLY, CONCAT, SyntaxQuoteReader.expand_list(form)) elif rt.seq_QMARK_(form) is true: ret = rt.list(APPLY, LIST, rt.cons(CONCAT, SyntaxQuoteReader.expand_list(rt.seq(form)))) else: ret = rt.list(QUOTE, form) return ret
def compile_var(form, ctx): form = rt.next(form) name = rt.first(form) affirm(isinstance(name, symbol.Symbol), u"var name must be a symbol") if rt.namespace(name) is not None: var = code._ns_registry.find_or_make(rt.namespace(name)) else: var = NS_VAR.deref().intern_or_make(rt.name(name)) ctx.push_const(var)
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_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 = filename._str affirm(path.isfile(str(filename_str)), u"File does not exist on path") f = open(str(filename_str)) data = f.read() f.close() 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([])
def resolve(self, s, use_refers=True): import pixie.vm.symbol as symbol affirm(isinstance(s, symbol.Symbol), u"Must resolve symbols") ns = rt.namespace(s) name = rt.name(s) if ns is not None: refer = self._refers.get(ns, None) resolved_ns = None if refer is not None: resolved_ns = refer._namespace if resolved_ns is None: resolved_ns = _ns_registry.get(ns, None) if resolved_ns is None: affirm( False, u"Unable to resolve namespace: " + ns + u" inside namespace " + self._name) else: resolved_ns = self assert isinstance(resolved_ns, Namespace) var = resolved_ns._registry.get(name, None) if var is None and use_refers: for refer_nm in self._refers: refer = self._refers[refer_nm] if name in refer._refer_syms or refer._refer_all: var = refer._namespace.resolve(symbol.Symbol(name), False) if var is not None: return var return None return var
def resolve(self, s, use_refers=True): import pixie.vm.symbol as symbol affirm(isinstance(s, symbol.Symbol), u"Must resolve symbols") ns = rt.namespace(s) name = rt.name(s) if ns is not None: refer = self._refers.get(ns, None) resolved_ns = None if refer is not None: resolved_ns = refer._namespace if resolved_ns is None: resolved_ns = _ns_registry.get(ns, None) if resolved_ns is None: affirm(False, u"Unable to resolve namespace: " + ns + u" inside namespace " + self._name) else: resolved_ns = self assert isinstance(resolved_ns, Namespace) var = resolved_ns._registry.get(name, None) if var is None and use_refers: for refer_nm in self._refers: refer = self._refers[refer_nm] if name in refer._refer_syms or refer._refer_all: var = refer._namespace.resolve(symbol.Symbol(name), False) if var is not None: return var return None return var
def invoke(self, rdr, ch): nms = u"" ch = rdr.read() if ch == u":": itm = read_inner(rdr, True) nms = rt.name(rt.ns.deref()) else: rdr.unread() itm = read_inner(rdr, True) affirm(isinstance(itm, Symbol), u"Can't keyword quote a non-symbol") if nms: affirm(rt.namespace(itm) is None, u"Kewyword cannot have two namespaces") return keyword(rt.name(itm), nms) else: return keyword(rt.name(itm), rt.namespace(itm))
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 compiler_special(s): if isinstance(s, symbol.Symbol): ns = rt.namespace(s) if ns is None or ns == u"pixie.stdlib": return builtins.get(rt.name(s), None) return None
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 invoke(self, rdr, ch): nms = u"" ch = rdr.read() if ch == u":": itm = read_inner(rdr, True) nms = rt.name(rt.ns.deref()) else: rdr.unread() itm = read_inner(rdr, True) affirm(isinstance(itm, Symbol), u"Can't keyword quote a non-symbol") if nms: affirm( rt.namespace(itm) is None, u"Kewyword cannot have two namespaces") return keyword(rt.name(itm), nms) else: return keyword(rt.name(itm), rt.namespace(itm))
def fqd(self, itm): ns_alias = rt.namespace(itm) current_nms = rt.ns.deref() if ns_alias is None: return keyword(rt.name(itm), rt.name(current_nms)) else: ns_fqd = current_nms.resolve_ns(ns_alias) return keyword(rt.name(itm), rt.name(ns_fqd))
def refer_symbol(ns, sym, var): from pixie.vm.symbol import Symbol affirm(isinstance(ns, code.Namespace), u"First argument must be a namespace") affirm(isinstance(sym, Symbol) and rt.namespace(sym) is None, u"Second argument must be a non-namespaced symbol") affirm(isinstance(var, code.Var), u"Third argument must be a var") ns.add_refer_symbol(sym, var) return nil
def invoke(self, rdr, ch): ch = rdr.read() if ch == u":": itm = read_inner(rdr, True) return self.fqd(itm) else: rdr.unread() itm = read_inner(rdr, True) return keyword(rt.name(itm), rt.namespace(itm))
def invoke(self, rdr, ch): ch = rdr.read() if ch == u":": ch = rdr.read() itm = read_symbol(rdr, ch, False) return self.fqd(itm) else: itm = read_symbol(rdr, ch, False) return keyword(rt.name(itm), rt.namespace(itm))
def refer_symbol(ns, sym, var): from pixie.vm.symbol import Symbol affirm(isinstance(ns, Namespace), u"First argument must be a namespace") affirm( isinstance(sym, Symbol) and rt.namespace(sym) is None, u"Second argument must be a non-namespaced symbol") affirm(isinstance(var, Var), u"Third argument must be a var") ns.add_refer_symbol(sym, var) return nil
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 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 _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 the_ns(ns_name): affirm(rt.namespace(ns_name) is None, u"the-ns takes a un-namespaced symbol") return code._ns_registry.get(rt.name(ns_name), nil)
def the_ns(ns_name): affirm( rt.namespace(ns_name) is None, u"the-ns takes a un-namespaced symbol") return code._ns_registry.get(rt.name(ns_name), nil)
def _var(nm): var = get_var_if_defined(rt.namespace(nm), rt.name(nm), nil) return var
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 ")