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 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 c_cast(frm, to): if not isinstance(to, CStructType): runtime_error(u"Expected a CStruct type to cast to, got " + rt.name(rt.str(to))) if not isinstance(frm, CStruct) and not isinstance(frm, VoidP): runtime_error(u"From must be a CVoidP or a CStruct, got " + rt.name(rt.str(frm))) return to.cast_to(frm)
def set_field(self, name, val): self._custom_type.set_mutable(name) idx = self._custom_type.get_slot_idx(name) if idx == -1: runtime_error(u"Invalid field named " + rt.name(rt.str(name)) + u" on type " + rt.name(rt.str(self.type()))) self._fields[idx] = val return self
def add_refer_symbol(self, sym, var): assert isinstance(self, Namespace) name = rt.name(sym) prev_binding = self._registry.get(name, None) if prev_binding is not None: print rt.str(rt.wrap(u"Warning: "), sym, rt.wrap(u" already refers to "), prev_binding)._str self._registry[name] = var return var
def get_field(self, name): idx = self._custom_type.get_slot_idx(name) if idx == -1: runtime_error(u"Invalid field named " + rt.name(rt.str(name)) + u" on type " + rt.name(rt.str(self.type()))) if self._custom_type.is_mutable(name): return self._fields[idx] else: return self.get_field_immutable(idx)
def c_cast(frm, to): """(cast from to) Converts a VoidP to a CStruct. From is either a VoidP or a CStruct, to is a CStruct type.""" if not isinstance(to, CStructType): runtime_error(u"Expected a CStruct type to cast to, got " + rt.name(rt.str(to))) if not isinstance(frm, CStruct) and not isinstance(frm, VoidP): runtime_error(u"From must be a CVoidP or a CStruct, got " + rt.name(rt.str(frm))) return to.cast_to(frm)
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 __repr__(self): import pixie.vm.rt as rt s = [] trace = self._trace[:] trace.reverse() for x in trace: s.append(x.__repr__()) s.append(u"\n") s.extend([u"RuntimeException: " + rt.name(rt.str(self._data)) + u" " + rt.name(rt.str(self._msg)) + u"\n"]) return u"".join(s)
def ffi_set_value(self, ptr, val): if isinstance(val, CCallback): casted = rffi.cast(rffi.VOIDPP, ptr) casted[0] = val.get_raw_closure() elif val is nil: casted = rffi.cast(rffi.VOIDPP, ptr) casted[0] = rffi.cast(rffi.VOIDP, 0) else: frm_name = rt.name(rt.str(val.type())) to_name = rt.name(rt.str(self)) affirm(False, u"Cannot encode " + frm_name + u" as " + to_name) return None
def set_field(self, name, val): idx = self._custom_type.get_slot_idx(name) if idx == -1: runtime_error(u"Invalid field named " + rt.name(rt.str(name)) + u" on type " + rt.name(rt.str(self.type()))) old_val = self._fields[idx] if isinstance(old_val, AbstractMutableCell): old_val.set_mutable_cell_value(self._custom_type, self._fields, name, idx, val) else: self._custom_type.set_mutable(name) self._fields[idx] = val return self
def get_field(self, name): idx = self._custom_type.get_slot_idx(name) if idx == -1: runtime_error(u"Invalid field named " + rt.name(rt.str(name)) + u" on type " + rt.name(rt.str(self.type()))) if self._custom_type.is_mutable(name): value = self._fields[idx] else: value = self.get_field_immutable(idx) if isinstance(value, AbstractMutableCell): return value.get_mutable_cell_value() else: return value
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 set_field(self, name, val): idx = self._custom_type.get_slot_idx(name) if idx == -1: runtime_error( u"Invalid field named " + rt.name(rt.str(name)) + u" on type " + rt.name(rt.str(self.type())), u"pixie.stdlib/InvalidFieldException") old_val = self.get_field_by_idx(idx) if isinstance(old_val, AbstractMutableCell): old_val.set_mutable_cell_value(self._custom_type, self, name, idx, val) else: self._custom_type.set_mutable(name) self.set_field_by_idx(idx, val) return self
def struct_size(tp): """(struct-size tp) Gives the size of the given CStruct type tp, in bytes.""" if not isinstance(tp, CStructType): runtime_error(u"Expected a CStruct type to get the size of, got " + rt.name(rt.str(tp))) return rt.wrap(tp.get_size())
def inner_invoke(self, args): from pixie.vm.keyword import keyword import pixie.vm.rt as rt from pixie.vm.string import String import pixie.vm.persistent_vector as vector with with_ns(u"user"): NS_VAR.deref().include_stdlib() acc = vector.EMPTY for x in self._argv: acc = rt.conj(acc, rt.wrap(x)) PROGRAM_ARGUMENTS.set_root(acc) rdr = MetaDataReader(PromptReader()) with with_ns(u"user"): while True: try: val = read(rdr, False) if val is eof: break val = interpret(compile(val)) except WrappedException as ex: print "Error: ", ex._ex.__repr__() rdr.reset_line() continue if val is keyword(u"exit-repl"): break val = rt.str(val) assert isinstance(val, String), "str should always return a string" print val._str
def load_file(filename): import pixie.vm.reader as reader import pixie.vm.compiler as compiler f = open(str(filename._str)) data = f.read() f.close() rdr = reader.StringReader(unicode(data)) result = nil while True: form = reader.read(rdr, False) print "printing" print rt.str(form)._str if form is reader.eof: return result print "compiling" result = compiler.compile(form).invoke([]) print "compiled"
def set_val(self, k, v): (tp, offset) = self._type.get_desc(k) if tp is None: runtime_error(u"Invalid field name: " + rt.name(rt.str(k))) offset = rffi.ptradd(self._buffer, offset) tp.ffi_set_value(rffi.cast(rffi.VOIDP, offset), v) return nil
def add_refer_symbol(self, sym, var): assert isinstance(self, Namespace) name = rt.name(sym) prev_binding = self._registry.get(name, None) if prev_binding is not None: print rt.name(rt.str(rt.wrap(u"Warning: "), sym, rt.wrap(u" already refers to "), prev_binding)) self._registry[name] = var return var
def ffi_set_value(self, ptr, val): pnt = rffi.cast(rffi.VOIDPP, ptr) if isinstance(val, String): pnt = rffi.cast(rffi.CCHARPP, ptr) utf8 = unicode_to_utf8(rt.name(val)) raw = rffi.str2charp(utf8) pnt[0] = raw return CCharPToken(raw) elif isinstance(val, Buffer): pnt[0] = val.buffer() elif isinstance(val, VoidP): pnt[0] = val.raw_data() elif val is nil: pnt[0] = rffi.cast(rffi.VOIDP, 0) elif isinstance(val, CStruct): pnt[0] = rffi.cast(rffi.VOIDP, val.raw_data()) else: frm_name = rt.name(rt.str(val.type())) to_name = rt.name(rt.str(self)) affirm(False, u"Cannot encode " + frm_name + u" as " + to_name)
def set_field(self, name, val): idx = self._custom_type.get_slot_idx(name) if idx == -1: runtime_error(u"Invalid field named " + rt.name(rt.str(name)) + u" on type " + rt.name(rt.str(self.type())), u"pixie.stdlib/InvalidFieldException") old_val = self.get_field_by_idx(idx) if isinstance(old_val, AbstractMutableCell): old_val.set_mutable_cell_value(self._custom_type, self, name, idx, val) else: self._custom_type.set_mutable(name) self.set_field_by_idx(idx, val) return self
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 get_field(self, name): idx = self._custom_type.get_slot_idx(name) if idx == -1: runtime_error(u"Invalid field named " + rt.name(rt.str(name)) + u" on type " + rt.name(rt.str(self.type())), u"pixie.stdlib/InvalidFieldException") if self._custom_type.is_mutable(name): value = self.get_field_by_idx(idx) else: value = self.get_field_immutable(idx) if isinstance(value, AbstractMutableCell): return value.get_mutable_cell_value() else: return value
def write_object(obj, wtr): wtr.flush() if isinstance(obj, String): write_string(rt.name(obj), wtr) elif isinstance(obj, Integer): write_int(obj.int_val(), wtr) elif isinstance(obj, BigInteger): #TODO test write_bigint(obj.bigint_val(), wtr) elif isinstance(obj, Float): write_float(obj.float_val(), wtr) elif isinstance(obj, Code): write_code(obj, wtr) elif obj is nil: wtr.write(chr(NIL)) elif isinstance(obj, Var): #wtr.write_cached_obj(obj, write_var) write_var(obj, wtr) elif rt._satisfies_QMARK_(rt.IMap.deref(), obj): write_map(obj, wtr) elif rt._satisfies_QMARK_(rt.IVector.deref(), obj): write_vector(obj, wtr) elif rt._satisfies_QMARK_(rt.ISeq.deref(), obj): write_seq(obj, wtr) elif isinstance(obj, Keyword): wtr.write_cached_obj(obj, write_keyword) elif isinstance(obj, LinePromise): wtr.write_cached_obj(obj, write_line_promise) elif obj is true: write_tag(TRUE, wtr) elif obj is false: write_tag(FALSE, wtr) elif isinstance(obj, Symbol): write_symbol(obj, wtr) elif isinstance(obj, Namespace): wtr.write_cached_obj(obj, write_namespace) elif isinstance(obj, InterpreterCodeInfo): wtr.write_cached_obj(obj, write_interpreter_code_info) else: from pixie.vm.libs.pxic.util import write_handlers handler = write_handlers.get(obj.type(), None) if handler is None: runtime_error(u"Object is not supported by pxic writer: " + rt.name(rt.str(obj.type()))) else: write_tag(TAGGED, wtr) write_string_raw(obj.type().name(), wtr) write_object(handler.invoke([obj]), wtr)
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 repl(): from pixie.vm.keyword import keyword import pixie.vm.rt as rt from pixie.vm.string import String with with_ns(u"user"): NS_VAR.deref().include_stdlib() rdr = PromptReader() while True: with with_ns(u"user"): try: val = interpret(compile(read(rdr, True))) except WrappedException as ex: print "Error: ", ex._ex.__repr__() continue if val is keyword(u"exit-repl"): break val = rt.str(val) assert isinstance(val, String), "str should always return a string" print val._str
def gensym(): rt.reset_BANG_(gensym_id, rt._add(rt.deref(gensym_id), rt.wrap(1))) i = rt.deref(gensym_id) return rt.symbol(rt.str(rt.wrap(u"gensym_"), i))
def gensym2(prefix): rt.reset_BANG_(gensym_id, rt._add(rt.deref(gensym_id), rt.wrap(1))) i = rt.deref(gensym_id) return rt.symbol(rt.str(prefix, i))