def find(sym): from py.clojure.lang.namespace import find as findNamespace if sym.ns is None: raise InvalidArgumentException("Symbol must be namespace-qualified") ns = findNamespace(Symbol.intern(sym.ns)) if ns is None: raise InvalidArgumentException("No such namespace " + str(sym.ns)) return ns.findInternedVar(Symbol.intern(sym.name))
def syntaxQuote(self, form): from py.clojure.lang.compiler import builtins as compilerbuiltins if form in compilerbuiltins: ret = RT.list(_QUOTE_, form) elif isinstance(form, Symbol): sym = form if sym.ns is None and sym.name.endswith("#"): gmap = GENSYM_ENV.deref() if gmap == None: raise ReaderException("Gensym literal not in syntax-quote, before", self.rdr) gs = gmap[sym] if gs is None: gs = Symbol.intern(None, sym.name[:-1] + "__" + str(RT.nextID()) + "__auto__") GENSYM_ENV.set(gmap.assoc(sym, gs)) sym = gs elif sym.ns is None and sym.name.endswith("."): ret = sym elif sym.ns is None and sym.name.startswith("."): ret = sym else: comp = currentCompiler.get(lambda: None) if comp is None: raise IllegalStateException("No Compiler found in syntax quote!") ns = comp.getNS() if ns is None: raise IllegalStateException("No ns in reader") sym = Symbol.intern(ns.__name__, sym.name) ret = RT.list(_QUOTE_, sym) else: if isUnquote(form): return form.next().first() elif isUnquoteSplicing(form): raise IllegalStateException("splice not in list") elif isinstance(form, IPersistentCollection): if isinstance(form, IPersistentMap): keyvals = flattenMap(form) ret = RT.list(_APPLY_, _HASHMAP_, RT.list(RT.cons(_CONCAT_, self.sqExpandList(keyvals.seq())))) elif isinstance(form, (IPersistentVector, IPersistentSet)): ret = RT.list(_APPLY_, _VECTOR_, RT.list(_SEQ_, RT.cons(_CONCAT_, self.sqExpandList(form.seq())))) elif isinstance(form, (ISeq, IPersistentList)): seq = form.seq() if seq is None: ret = RT.cons(_LIST_, None) else: ret = RT.list(_SEQ_, RT.cons(_CONCAT_, self.sqExpandList(seq))) else: raise IllegalStateException("Unknown collection type") elif isinstance(form, (int, float, str, Keyword)): ret = form else: ret = RT.list(_QUOTE_, form) if hasattr(form, "meta") and form.meta() is not None: newMeta = form.meta().without(LINE_KEY) if len(newMeta) > 0: return RT.list(_WITH_META_, ret, self.syntaxQuote(form.meta())) return ret
def find(self, *args): if len(args) == 1: if isinstance(args[0], Symbol): return interned.val()[args[0]]() if isinstance(args[0], str): return Keyword.find(Symbol.intern(args[0])) if len(args) == 2: return Keyword.find(Symbol.intern(*args)) raise ArityException()
def compileFNStar(comp, form): haslocalcaptures = False if len(comp.locals) > 0: # we got a closure to deal with comp.pushLocalCaptures() haslocalcaptures = True orgform = form if len(form) < 2: raise CompilerException("2 or more arguments to fn* required", form) form = form.next() name = form.first() pushed = False if not isinstance(name, Symbol): comp.pushName(name) pushed = True name = Symbol.intern("fn" + str(RT.nextID())) else: form = form.next() if isinstance(form.first(), IPersistentVector): code = compileFn(comp, name, form, orgform) else: code = compileMultiFn(comp, name, form) if pushed: comp.popName() clist = comp.closureList() fcode = [] if haslocalcaptures: comp.popLocalCaptures() if clist: for x in clist: fcode.extend(comp.compile(Symbol.intern(x))) fcode.append((STORE_DEREF, x)) fcode.append((LOAD_CLOSURE, x)) fcode.append((BUILD_TUPLE, len(clist))) fcode.extend(code) fcode.append((MAKE_CLOSURE, 0)) code = fcode return code
def compileMultiFn(comp, name, form): s = form argdefs = [] while s is not None: argdefs.append(MultiFn(comp, s.first())) s = s.next() argdefs = sorted(argdefs, lambda x, y: len(x.args) < len(y.args)) if len(filter(lambda x: x.lastisargs, argdefs)) > 1: raise CompilerException("Only one function overload may have variable number of arguments", form) code = [] args = [] for x in argdefs: code.extend(x.code) for x in x.args: if x not in args: args.append(x) code.append((LOAD_CONST, Exception)) code.append((CALL_FUNCTION, 0)) code.append((RAISE_VARARGS, 1)) c = Code(code, comp.closureList(), ["__argsv__"], True, False, True, str(Symbol.intern(comp.getNS().__name__, name.name)), "./clj/clojure/core.clj", 0, None) fn = new.function(c.to_code(), comp.ns.__dict__, name.name) return [(LOAD_CONST, fn)]
def compileVector(comp, form): code = [] code.extend(comp.compile(Symbol.intern("clojure.lang.rt.vector"))) for x in form: code.extend(comp.compile(x)) code.append((CALL_FUNCTION, len(form))) return code
def compileFn(comp, name, form, orgform): locals, args, lastisargs, argsname = unpackArgs(form.first()) for x in locals: comp.pushAlias(x, FnArgument(x)) if orgform.meta() is not None: line = orgform.meta()[LINE_KEY] else: line = 0 code = [(SetLineno,line if line is not None else 0)] recurlabel = Label("recurLabel") recur = {"label": recurlabel, "args": args} code.append((recurlabel, None)) comp.pushRecur(recur) code.extend(compileImplcitDo(comp, form.next())) comp.popRecur() code.append((RETURN_VALUE,None)) comp.popAliases(locals) clist = map(lambda x: x.sym.name, comp.closureList()) c = Code(code, clist, args, lastisargs, False, True, str(Symbol.intern(comp.getNS().__name__, name.name)), "./clj/clojure/core.clj", 0, None) if not clist: c = new.function(c.to_code(), comp.ns.__dict__, name.name) return [(LOAD_CONST, c)]
def compileMultiFn(comp, name, form): s = form argdefs = [] while s is not None: argdefs.append(MultiFn(comp, s.first())) s = s.next() argdefs = sorted(argdefs, lambda x, y: len(x.args) < len(y.args)) if len(filter(lambda x: x.lastisargs, argdefs)) > 1: raise CompilerException("Only one function overload may have variable number of arguments", form) code = [] if len(argdefs) == 1 and not argdefs[0].lastisargs: hasvararg = False argslist = argdefs[0].args code.extend(argdefs[0].bodycode) else: hasvararg = True argslist = ["__argsv__"] for x in argdefs: code.extend(x.argcode) code.extend(x.bodycode) code.append((LOAD_CONST, Exception)) code.append((CALL_FUNCTION, 0)) code.append((RAISE_VARARGS, 1)) clist = map(lambda x: x.sym.name, comp.closureList()) c = Code(code, clist, argslist, hasvararg, False, True, str(Symbol.intern(comp.getNS().__name__, name.name)), "./clj/clojure/core.clj", 0, None) if not clist: c = new.function(c.to_code(), comp.ns.__dict__, name.name) return [(LOAD_CONST, c)]
def executeCode(self, code): import sys if code == []: return None newcode = code[:] newcode.append((RETURN_VALUE, None)) c = Code(newcode, [], [], False, False, False, str(Symbol.intern(self.getNS().__name__, "<string>")), "./clj/clojure/core.clj", 0, None) retval = eval(c.to_code(), self.getNS().__dict__) return retval
def intern(*args): if len(args) == 1: if isinstance(args[0], Symbol): sym = args[0] if sym.meta() is not None: sym = sym.withMeta(None) k = Keyword(sym) interned.mutate(lambda old: old if sym in old else old.assoc(sym,k)) return interned.get()[sym] elif isinstance(args[0], str): return Keyword.intern(Symbol.intern(args[0])) else: raise InvalidArgumentException() elif len(args) == 2: return Keyword.intern(Symbol.intern(*args)) else: raise ArityException()
def compileMap(comp, form): s = form.seq() c = 0 code = [] code.extend(comp.compile(Symbol.intern("clojure.lang.rt.map"))) while s is not None: kvp = s.first() code.extend(comp.compile(kvp.getKey())) code.extend(comp.compile(kvp.getValue())) c += 2 s = s.next() code.append([CALL_FUNCTION, c]) return code
def compileFNStar(comp, form): haslocalcaptures = False aliases = [] if len(comp.aliases) > 0: # we got a closure to deal with for x in comp.aliases: comp.pushAlias(x, Closure(x)) aliases.append(x) haslocalcaptures = True orgform = form if len(form) < 2: raise CompilerException("2 or more arguments to fn* required", form) form = form.next() name = form.first() pushed = False if not isinstance(name, Symbol): comp.pushName(name) pushed = True name = Symbol.intern("fn" + str(RT.nextID())) else: form = form.next() if isinstance(form.first(), IPersistentVector): code = compileFn(comp, name, form, orgform) else: code = compileMultiFn(comp, name, form) if pushed: comp.popName() clist = comp.closureList() fcode = [] if haslocalcaptures: comp.popAliases(aliases) if clist: for x in clist: fcode.extend(comp.getAlias(x.sym).compile(comp)) # Load our local version fcode.append((STORE_DEREF, x.sym.name)) # Store it in a Closure Cell fcode.append((LOAD_CLOSURE, x.sym.name)) # Push the cell on the stack fcode.append((BUILD_TUPLE, len(clist))) fcode.extend(code) fcode.append((MAKE_CLOSURE, 0)) code = fcode return code
def executeModule(self, code): code.append((RETURN_VALUE, None)) c = Code(code, [], [], False, False, False, str(Symbol.intern(self.getNS().__name__, "<string>")), "./clj/clojure/core.clj", 0, None) import marshal import pickle import py_compile import time import dis dis.dis(c) codeobject = c.to_code() print codeobject.__class__ is compileDef.__class__ with open('output.pyc', 'wb') as fc: fc.write(py_compile.MAGIC) py_compile.wr_long(fc, long(time.time())) marshal.dump(c, fc)
def compileLoopStar(comp, form): if len(form) < 3: raise CompilerException("loop* takes at least two args") form = form.next() if not isinstance(form.first(), PersistentVector): raise CompilerException("loop* takes a vector as it's first argument") s = form.first() args = [] code = [] idx = 0 while idx < len(s): if len(s) - idx < 2: raise CompilerException("loop* takes a even number of bindings") local = s[idx] if not isinstance(local, Symbol) or local.ns is not None: raise CompilerException("bindings must be non-namespaced symbols") idx += 1 body = s[idx] if local in comp.locals: newlocal = Symbol.intern(str(local)+"_"+str(RT.nextID())) code.extend(comp.compile(body)) comp.locals[local] = comp.locals[local].cons(newlocal) args.append(local) local = newlocal else: comp.locals[local] = RT.list(local) args.append(local) code.extend(comp.compile(body)) code.append((STORE_FAST, str(local))) idx += 1 form = form.next() recurlabel = Label("recurLabel") recur = {"label": recurlabel, "args": map(lambda x: x.name, args)} code.append((recurlabel, None)) comp.pushRecur(recur) code.extend(compileImplcitDo(comp, form)) comp.popRecur() comp.popLocals(args) return code
def compileRecur(comp, form): s = form.next() idx = 0 code = [] locals = [] while s is not None: code.extend(comp.compile(s.first())) if idx >= len(comp.recurPoint.first()["args"]): raise CompilerException("to many arguments to recur", form) local = comp.recurPoint.first()["args"][idx] local = comp.locals[Symbol.intern(local)].first() locals.append(local.name) idx += 1 s = s.next() locals.reverse() code.extend(map(lambda x: (STORE_FAST, x), locals)) code.append((JUMP_ABSOLUTE, comp.recurPoint.first()["label"])) return code
def matchSymbol(s): from py.clojure.lang.symbol import Symbol from py.clojure.lang.cljkeyword import Keyword m = symbolPat.match(s) if m is not None: ns = m.group(1) name = m.group(2) if ns is not None and ns.endswith(":/") or name.endswith(":")\ or s.find("::") != -1: return None if s.startswith("::"): return "FIX" ns = ns if ns is None else ns[:-1] iskeyword = s.find(':') == 0 sym = Symbol.intern(ns, name[(1 if iskeyword else 0):]) if iskeyword: return Keyword.intern(s) else: return sym return None
def compileRecur(comp, form): s = form.next() idx = 0 code = [] locals = [] while s is not None: code.extend(comp.compile(s.first())) if idx >= len(comp.recurPoint.first()["args"]): raise CompilerException("to many arguments to recur", form) local = comp.recurPoint.first()["args"][idx] local = comp.getAlias(Symbol.intern(local)) if local is None: pass locals.append(local) idx += 1 s = s.next() locals.reverse() for x in locals: code.extend(x.compileSet(comp)) code.append((JUMP_ABSOLUTE, comp.recurPoint.first()["label"])) return code
def compileLetStar(comp, form): if len(form) < 3: raise CompilerException("let* takes at least two args") form = form.next() if not isinstance(form.first(), PersistentVector): raise CompilerException("let* takes a vector as it's first argument") s = form.first() args = [] code = [] idx = 0 while idx < len(s): if len(s) - idx < 2: raise CompilerException("let* takes a even number of bindings") local = s[idx] if not isinstance(local, Symbol) or local.ns is not None: raise CompilerException("bindings must be non-namespaced symbols") idx += 1 body = s[idx] if comp.getAlias(local) is not None: code.extend(comp.compile(body)) newlocal = Symbol.intern(str(local)+"_"+str(RT.nextID())) comp.pushAlias(local, RenamedLocal(newlocal)) args.append(local) else: code.extend(comp.compile(body)) comp.pushAlias(local, RenamedLocal(local)) args.append(local) code.extend(comp.getAlias(local).compileSet(comp)) idx += 1 form = form.next() code.extend(compileImplcitDo(comp, form)) comp.popAliases(args) return code
def compileDef(comp, form): if len(form) not in [2, 3]: raise CompilerException("Only 2 or 3 arguments allowed to def", form) sym = form.next().first() value = None if len(form) == 3: value = form.next().next().first() if sym.ns is None: ns = comp.getNS() else: ns = sym.ns code = [] code.extend(comp.compile(value)) code.append((DUP_TOP, 0)) code.append((STORE_GLOBAL, sym.name)) if sym.meta() is not None: code.extend(comp.compileAccessList(Symbol.intern("clojure.lang.rt.setMeta"))) code.append((ROT_TWO, 0)) code.append((LOAD_CONST, sym.meta())) code.append((CALL_FUNCTION, 2)) return code
def main(): requireClj("./clj/clojure/core.clj") RT.init() comp = Compiler() currentCompiler.set(comp) comp.setNS(Symbol.intern("user")) if not sys.argv[1:]: while True: try: line = raw_input(comp.getNS().__name__ + "=> ") except EOFError: break if not line: continue while unbalanced(line): try: line += raw_input('.' * len(comp.getNS().__name__) + '.. ') except EOFError: break # Propogate break from above loop. if unbalanced(line): break r = StringReader(line) s = read(r, True, None, True) try: res = comp.compile(s) print comp.executeCode(res) except Exception: import traceback; traceback.print_exc()
def garg(n): from symbol import Symbol return Symbol.intern(None, "rest" if n == -1 else ("p" + str(n)) + "__" + str(RT.nextID()) + "#")
def pushLocalCaptures(self): for x in self.locals: self.locals[x] = self.locals[x].cons(Symbol.intern("__closure__" + self.locals[x].first().name)) self.usedClosures = self.usedClosures.cons([])
def setUp(self): RT.init() self.comp = Compiler() currentCompiler.set(self.comp) self.comp.setNS(Symbol.intern('clojure.core'))
from py.clojure.lang.ipersistentvector import IPersistentVector from py.clojure.lang.ipersistentmap import IPersistentMap from py.clojure.lang.ipersistentlist import IPersistentList from py.clojure.lang.var import Var from py.clojure.util.byteplay import * from py.clojure.lang.cljkeyword import Keyword import new import py.clojure.lang.rt as RT from py.clojure.lang.lispreader import _AMP_ from py.clojure.lang.namespace import findItem from py.clojure.lang.lispreader import LINE_KEY, garg import re import new _MACRO_ = Keyword.intern(Symbol.intern(":macro")) def compileNS(comp, form): rest = form.next() if len(rest) != 1: raise CompilerException("ns only supports one item", rest) comp.setNS(rest.first()) return [] def compileDef(comp, form): if len(form) not in [2, 3]: raise CompilerException("Only 2 or 3 arguments allowed to def", form) sym = form.next().first() value = None
def intern(ns, name): if isinstance(ns, Namespace): return ns.intern(name) ns = Namespace.findOrCreate(Symbol.intern(ns)) return Var.intern(ns, name)
from py.clojure.lang.iref import IRef from py.clojure.lang.ifn import IFn from py.clojure.lang.settable import Settable from py.clojure.lang.aref import ARef from py.clojure.lang.cljexceptions import ArityException, InvalidArgumentException, IllegalStateException from py.clojure.lang.persistenthashmap import EMPTY from py.clojure.lang.threadutil import ThreadLocal, synchronized, currentThread from py.clojure.lang.symbol import Symbol from py.clojure.lang.cljkeyword import Keyword from persistentarraymap import PersistentArrayMap privateKey = Keyword.intern(Symbol.intern("private")) macrokey = Keyword.intern(Symbol.intern(":macro")) dvals = ThreadLocal() privateMeta = PersistentArrayMap.create([privateKey, True]) UKNOWN = Symbol.intern("UNKNOWN") def pushThreadBindings(bindings): f = dvals.get(lambda: Var.Frame()) bmap = f.bindings bs = bindings.seq() while bs is not None: e = bs.first() v = e.getKey() if not v.dynamic: raise IllegalStateException("Can't dynamically bind non-dynamic var: " + str(v.ns) + "/" + str(v.sym)) v.validate(v.getValidator(), e.getValue()) v.threadBound = True bmap = bmap.assoc(v, Var.TBox(currentThread(), e.getValue())) bs = bs.next() dvals.set(Var.Frame(bmap, f))
def compileSymbol(self, sym): if sym in self.locals or Symbol.intern("__closure__" + str(sym)) in self.locals: return self.compileLocal(sym) return self.compileAccessList(sym)
#from py.clojure.lang.gmp import Integer, Rational, Float import py.clojure.lang.rt as RT from py.clojure.lang.cljkeyword import LINE_KEY from py.clojure.lang.symbol import Symbol from py.clojure.lang.persistentvector import EMPTY as EMPTY_VECTOR from py.clojure.lang.globals import currentCompiler from py.clojure.lang.cljkeyword import Keyword import re def read1(rdr): rdr.next() if rdr is None: return "" return rdr.first() _AMP_ = Symbol.intern("&") _FN_ = Symbol.intern("fn") _VAR_ = Symbol.intern("var") _APPLY_ = Symbol.intern("apply") _HASHMAP_ = Symbol.intern("clojure.core", "hashmap") _CONCAT_ = Symbol.intern("clojure.core", "concat") _LIST_ = Symbol.intern("clojure.core", "list") _SEQ_ = Symbol.intern("clojure.core", "seq") _VECTOR_ = Symbol.intern("clojure.core", "vector") _QUOTE_ = Symbol.intern("quote") _SYNTAX_QUOTE_ = Symbol.intern("`") _UNQUOTE_ = Symbol.intern("~") _UNQUOTE_SPLICING_ = Symbol.intern("~@") ARG_ENV = Var.create(None).setDynamic() GENSYM_ENV = Var.create(None).setDynamic()
def internPrivate(nsName, sym): ns = Namespace.findOrCreate(Symbol.intern(nsName)) ret = Var.intern(ns, Symbol.intern(sym)) ret.setMeta(Var.privateMeta) return ret
def __init__(self, sym, rest = None): AAlias.__init__(self, rest) self.sym = sym self.newsym = Symbol.intern(sym.name + str(RT.nextID()))