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)] if lastisargs: code.extend(cleanRest(argsname.name)) recurlabel = Label("recurLabel") recur = {"label": recurlabel, "args": map(lambda x: comp.getAlias(symbol(x)).compileSet(comp), 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()) code = expandMetas(code, comp) c = Code(code, clist, args, lastisargs, False, True, str(symbol(comp.getNS().__name__, name.name)), comp.filename, 0, None) if not clist: c = new.function(c.to_code(), comp.ns.__dict__, name.name) return [(LOAD_CONST, c)], c
def getAccessCode(self, sym): if (sym.ns is not None and sym.ns == self.getNS().__name__) \ or sym.ns is None: if self.getNS() is None: raise CompilerException("no namespace has been defined", None) if not hasattr(self.getNS(), sym.name): raise CompilerException("could not resolve '" + str(sym) + "', '" \ + sym.name + "' not found in " + self.getNS().__name__ + " reference " + str(self.getNamesString(False)), None) var = getattr(self.getNS(), sym.name) return [GlobalPtr(self.getNS(), sym.name)] if hasattr(self.getNS(), "__aliases__") and \ symbol(sym.ns) in self.getNS().__aliases__: sym = symbol(self.getNS().__aliases__[symbol(sym.ns)].__name__, sym.name) splt = [] if sym.ns is not None: module = findNamespace(sym.ns) if not hasattr(module, sym.name): raise CompilerException(str(module) + " does not define " + sym.name, None) return [GlobalPtr(module, sym.name)] code = LOAD_ATTR if sym.ns else LOAD_GLOBAL #if not sym.ns and sym.name.find(".") != -1 and sym.name != "..": raise CompilerException("unqualified dotted forms not supported: " + str(sym), sym) if len(sym.name.replace(".", "")): splt.extend((code, attr) for attr in sym.name.split(".")) else: splt.append((code, sym.name)) return splt
def getAccessCode(self, sym): if (sym.ns is not None and sym.ns == self.getNS().__name__) \ or sym.ns is None: if self.getNS() is None: raise CompilerException("no namespace has been defined", None) if not hasattr(self.getNS(), RT.name(sym)): raise CompilerException("could not resolve '" + str(sym) + "', '" \ + RT.name(sym) + "' not found in " + self.getNS().__name__ + " reference " + str(self.getNamesString(False)), None) var = getattr(self.getNS(), RT.name(sym)) return [GlobalPtr(self.getNS(), RT.name(sym))] if hasattr(self.getNS(), "__aliases__") and \ symbol(sym.ns) in self.getNS().__aliases__: sym = symbol(self.getNS().__aliases__[symbol(sym.ns)].__name__, RT.name(sym)) splt = [] if sym.ns is not None: module = findNamespace(sym.ns) if not hasattr(module, RT.name(sym)): raise CompilerException( str(module) + " does not define " + RT.name(sym), None) return [GlobalPtr(module, RT.name(sym))] code = LOAD_ATTR if sym.ns else LOAD_GLOBAL #if not sym.ns and RT.name(sym).find(".") != -1 and RT.name(sym) != "..": raise CompilerException( "unqualified dotted forms not supported: " + str(sym), sym) if len(RT.name(sym).replace(".", "")): splt.extend((code, attr) for attr in RT.name(sym).split(".")) else: splt.append((code, RT.name(sym))) return splt
def syntaxQuote(self, form): from 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(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 elif sym.ns is not None: 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(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 = self.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()))#FIXME: _WITH_META_ undefined return ret
def find(sym): from clojure.lang.namespace import find as findNamespace if sym.ns is None: raise InvalidArgumentException("Symbol must be namespace-qualified") ns = findNamespace(symbol(sym.ns)) if ns is None: raise InvalidArgumentException("No such namespace " + str(sym.ns)) return ns.findInternedVar(symbol(sym.name))
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(args[0])) if len(args) == 2: return Keyword.find(symbol(*args)) raise ArityException()
def findItem(ns, sym): if sym.ns is not None and symbol(sym.ns) in getattr(ns, "__aliases__", {}): sym = symbol(ns.__aliases__[symbol(sym.ns)].__name__, sym.name) if isinstance(sym, Symbol): if ns is None: ns = sys.modules["clojure.core"] # we need this to boostrap files if sym.ns == ns.__name__: return getattr(ns, sym.name, None) if sym.ns is not None: mod = find(sym.ns, ns) return getattr(mod, sym.name, None) return getattr(ns, str(sym), None) return getattr(ns, sym)
def matchSymbol(s): """Return a symbol or keyword. Return None if the string s does not define a legal symbol or keyword.""" m = symbolPat.match(s) if m is not None: ns = m.group(1) name = m.group(2) if name.endswith(".") and not name.startswith("."): name = name[:-1] if ns is not None and (ns.endswith(":/") or name.endswith(":")\ or s.find("::") != -1): return None ns = ns if ns is None else ns[:-1] if s.startswith("::"): return keyword(currentNSName(), s[2:]) iskeyword = s.startswith(':') if iskeyword: return keyword(s[1:]) else: return symbol(ns, name) return None
def compileVector(comp, form): code = [] code.extend(comp.compile(symbol("clojure.lang.rt", "vector"))) for x in form: code.extend(comp.compile(x)) code.append((CALL_FUNCTION, len(form))) return code
def compileDot(comp, form): from clojure.lang.persistentlist import PersistentList from clojure.lang.iseq import ISeq if len(form) != 3: raise CompilerException(". form must have two arguments", form) clss = form.next().first() member = form.next().next().first() if isinstance(member, Symbol): attr = member.name args = [] elif isinstance(member, ISeq): if not isinstance(member.first(), Symbol): raise CompilerException("Member name must be symbol") attr = member.first().name args = [] if len(member) > 1: f = member.next() while f is not None: args.append(comp.compile(f.first())) f = f.next() alias = comp.getAlias(clss) if alias: code = alias.compile(comp) code.append((LOAD_ATTR, attr)) else: code = comp.compile(symbol(clss, attr)) for x in args: code.extend(x) code.append((CALL_FUNCTION, len(args))) return code
def compileDot(comp, form): if len(form) != 3: raise CompilerException(". form must have two arguments", form) clss = form.next().first() member = form.next().next().first() if isinstance(member, Symbol): attr = member.name args = [] elif isinstance(member, ISeq): if not isinstance(member.first(), Symbol): raise CompilerException("Member name must be symbol", form) attr = member.first().name args = [] if len(member) > 1: f = member.next() while f is not None: args.append(comp.compile(f.first())) f = f.next() alias = comp.getAlias(clss) if alias: code = alias.compile(comp) code = tr.Attr(code, attr) else: code = comp.compile(symbol(clss, attr)) code = tr.Call(code, *args) return code
def intern(ns, name): from namespace import findOrCreate, intern as nsintern if isinstance(ns, types.ModuleType): return nsintern(ns, name) ns = findOrCreate(symbol(ns)) return nsintern(ns, name)
def compileDot(comp, form): if len(form) != 3: raise CompilerException(". form must have two arguments", form) clss = form.next().first() member = form.next().next().first() if isinstance(member, Symbol): attr = member.name args = [] elif isinstance(member, ISeq): if not isinstance(member.first(), Symbol): raise CompilerException("Member name must be symbol") attr = member.first().name args = [] if len(member) > 1: f = member.next() while f is not None: args.append(comp.compile(f.first())) f = f.next() alias = comp.getAlias(clss) if alias: code = alias.compile(comp) code.append((LOAD_ATTR, attr)) else: code = comp.compile(symbol(clss, attr)) for x in args: code.extend(x) code.append((CALL_FUNCTION, len(args))) 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 = [] 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()) code = expandMetas(code, comp) c = Code(code, clist, argslist, hasvararg, False, True, str(symbol(comp.getNS().__name__, name.name)), comp.filename, 0, None) if not clist: c = new.function(c.to_code(), comp.ns.__dict__, name.name) return [(LOAD_CONST, c)], c
def intern(ns, name): from namespace import findOrCreate, intern as nsintern import new if isinstance(ns, new.module): return nsintern(ns, name) ns = findOrCreate(symbol(ns)) return nsintern(ns, name)
def find(sym): from clojure.lang.namespace import find as findNamespace if sym.ns is None: raise InvalidArgumentException("Symbol must be namespace-qualified") ns = findNamespace(symbol(sym.ns)) if ns is None: raise InvalidArgumentException("No such namespace {0}".format(sym.ns)) return getattr(ns, sym.name)
def executeCode(self, code): if code == []: return None newcode = expandMetas(code, self) newcode.append((RETURN_VALUE, None)) c = Code(newcode, [], [], False, False, False, str(symbol(self.getNS().__name__, "<string>")), self.filename, 0, None) retval = eval(c.to_code(), self.getNS().__dict__) self.getNS().__file__ = self.filename return retval
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(self.getNS().__name__, "<string>")), self.filename, 0, None) retval = eval(c.to_code(), self.getNS().__dict__) return retval
def keyword(*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, unicode)): return keyword(symbol(args[0])) else: raise InvalidArgumentException() elif len(args) == 2: return keyword(symbol(*args)) else: raise ArityException()
def keyword(*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, unicode)): return keyword(symbol(args[0])) else: raise InvalidArgumentException() elif len(args) == 2: return keyword(symbol(*args)) else: raise ArityException()
def executeModule(self, code): code.append((RETURN_VALUE, None)) c = Code(code, [], [], False, False, False, str(symbol(self.getNS().__name__, "<string>")), self.filename, 0, None) dis.dis(c) codeobject = c.to_code() 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 __init__(self, comp, form): form = RT.seq(form) if len(form) < 2: raise CompilerException("FN defs must have at least two vars", form) argv = form.first() if not isinstance(argv, PersistentVector): raise CompilerException("FN arg list must be a vector", form) body = form.next() self.locals, self.args, self.lastisargs, self.argsname = unpackArgs( argv) endLabel = Label("endLabel") argcode = [(LOAD_CONST, len), (LOAD_FAST, '__argsv__'), (CALL_FUNCTION, 1), (LOAD_CONST, len(self.args) - (1 if self.lastisargs else 0)), (COMPARE_OP, ">=" if self.lastisargs else "==")] argcode.extend(emitJump(endLabel)) for x in range(len(self.args)): if self.lastisargs and x == len(self.args) - 1: offset = len(self.args) - 1 argcode.extend([(LOAD_FAST, '__argsv__'), (LOAD_CONST, offset), (SLICE_1, None), (STORE_FAST, self.argsname.name)]) argcode.extend(cleanRest(self.argsname.name)) else: argcode.extend([(LOAD_FAST, '__argsv__'), (LOAD_CONST, x), (BINARY_SUBSCR, None), (STORE_FAST, self.args[x])]) for x in self.locals: comp.pushAlias(x, FnArgument(x)) recurlabel = Label("recurLabel") recur = { "label": recurlabel, "args": map(lambda x: comp.getAlias(symbol(x)).compileSet(comp), self.args) } bodycode = [(recurlabel, None)] comp.pushRecur(recur) bodycode.extend(compileImplcitDo(comp, body)) bodycode.append((RETURN_VALUE, None)) bodycode.extend(emitLanding(endLabel)) comp.popRecur() comp.popAliases(self.locals) self.argcode = argcode self.bodycode = bodycode
def findItem(ns, sym): from clojure.lang.symbol import Symbol, symbol if sym.ns is not None and hasattr(ns, "__aliases__") and \ symbol(sym.ns) in ns.__aliases__: sym = symbol(ns.__aliases__[symbol(sym.ns)].__name__, sym.name) if isinstance(sym, Symbol): if ns is None: ns = sys.modules["clojure.core"] # we need this to boostrap files if sym.ns == ns.__name__: if not hasattr(ns, sym.name): return None return getattr(ns, sym.name) if sym.ns is not None: mod = find(sym.ns, ns) if hasattr(mod, sym.name): return getattr(mod, sym.name) return None if not hasattr(ns, str(sym)): return None return getattr(ns, str(sym)) return getattr(ns, sym)
def compileMap(comp, form): s = form.seq() c = 0 code = [] code.extend(comp.compile(symbol("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 getAccessCode(self, sym): print sym if (sym.ns is not None and sym.ns == self.nsString) \ or sym.ns is None: if self.getNS() is None: raise CompilerException("no namespace has been defined", None) if not hasattr(self.getNS(), RT.name(sym)): raise CompilerException( "could not resolve '{0}', '{1}' not found in {2} reference {3}". format(sym, RT.name(sym), self.getNS().__name__, self.getNamesString(False)), None) var = getattr(self.getNS(), RT.name(sym)) return maybeDeref(self.ns, self.nsString, RT.name(sym), self.nsString) if symbol(sym.ns) in getattr(self.getNS(), "__aliases__", {}): sym = symbol(self.getNS().__aliases__[symbol(sym.ns)].__name__, RT.name(sym)) splt = [] if sym.ns is not None: module = findNamespace(sym.ns) if not hasattr(module, RT.name(sym)): raise CompilerException( "{0} does not define {1}".format(module, RT.name(sym)), None) return getAttrChain(sym.getNamespace() + "." + sym.getName()) code = LOAD_ATTR if sym.ns else LOAD_GLOBAL #if not sym.ns and RT.name(sym).find(".") != -1 and RT.name(sym) != "..": raise CompilerException( "unqualified dotted forms not supported: {0}".format(sym), sym) if len(RT.name(sym).replace(".", "")): splt.extend((code, attr) for attr in RT.name(sym).split(".")) else: splt.append((code, RT.name(sym))) return splt
def findItem(ns, sym): from clojure.lang.symbol import Symbol, symbol if sym.ns is not None and hasattr(ns, "__aliases__") and symbol(sym.ns) in ns.__aliases__: sym = symbol(ns.__aliases__[symbol(sym.ns)].__name__, sym.name) if isinstance(sym, Symbol): if ns is None: ns = sys.modules["clojure.core"] # we need this to boostrap files if sym.ns == ns.__name__: if not hasattr(ns, sym.name): return None return getattr(ns, sym.name) if sym.ns is not None: mod = find(sym.ns, ns) if hasattr(mod, sym.name): return getattr(mod, sym.name) return None if not hasattr(ns, str(sym)): return None return getattr(ns, str(sym)) return getattr(ns, sym)
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)] if lastisargs: code.extend(cleanRest(argsname.name)) recurlabel = Label("recurLabel") recur = { "label": recurlabel, "args": map(lambda x: comp.getAlias(symbol(x)).compileSet(comp), 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(comp.getNS().__name__, name.name)), comp.filename, 0, None) if not clist: c = new.function(c.to_code(), comp.ns.__dict__, name.name) return [(LOAD_CONST, c)], c
def __init__(self, comp, form): form = RT.seq(form) if len(form) < 1: raise CompilerException("FN defs must have at least one arg", form) argv = form.first() if not isinstance(argv, PersistentVector): raise CompilerException("FN arg list must be a vector", form) body = form.next() self.locals, self.args, self.lastisargs, self.argsname = unpackArgs(argv) endLabel = Label("endLabel") argcode = [(LOAD_CONST, len), (LOAD_FAST, '__argsv__'), (CALL_FUNCTION, 1), (LOAD_CONST, len(self.args) - (1 if self.lastisargs else 0)), (COMPARE_OP, ">=" if self.lastisargs else "==")] argcode.extend(emitJump(endLabel)) for x in range(len(self.args)): if self.lastisargs and x == len(self.args) - 1: offset = len(self.args) - 1 argcode.extend([(LOAD_FAST, '__argsv__'), (LOAD_CONST, offset), (SLICE_1, None), (STORE_FAST, self.argsname.name)]) argcode.extend(cleanRest(self.argsname.name)) else: argcode.extend([(LOAD_FAST, '__argsv__'), (LOAD_CONST, x), (BINARY_SUBSCR, None), (STORE_FAST, self.args[x])]) for x in self.locals: comp.pushAlias(x, FnArgument(x)) recurlabel = Label("recurLabel") recur = {"label": recurlabel, "args": map(lambda x: comp.getAlias(symbol(x)).compileSet(comp), self.args)} bodycode = [(recurlabel, None)] comp.pushRecur(recur) bodycode.extend(compileImplcitDo(comp, body)) bodycode.append((RETURN_VALUE, None)) bodycode.extend(emitLanding(endLabel)) comp.popRecur() comp.popAliases(self.locals) self.argcode = argcode self.bodycode = bodycode
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.aliases: newlocal = symbol(str(local) + "_" + str(RT.nextID())) code.extend(comp.compile(body)) comp.pushAlias(local, RenamedLocal(newlocal)) args.append(local) else: comp.pushAlias(local, RenamedLocal(local)) args.append(local) code.extend(comp.compile(body)) code.extend(comp.getAlias(local).compileSet(comp)) idx += 1 form = form.next() recurlabel = Label("recurLabel") recur = { "label": recurlabel, "args": map(lambda x: comp.getAlias(x).compileSet(comp), args) } code.append((recurlabel, None)) comp.pushRecur(recur) code.extend(compileImplcitDo(comp, form)) comp.popRecur() comp.popAliases(args) return code
def compileLetStar(comp, form): if len(form) < 3: raise CompilerException("let* takes at least two args", form) form = form.next() if not isinstance(form.first(), IPersistentVector): raise CompilerException( "let* takes a vector as it's first argument", form) s = form.first() args = [] code = [] idx = 0 with ResolutionContext(comp): code = [] while idx < len(s): if len(s) - idx < 2: raise CompilerException( "let* takes a even number of bindings", form) local = s[idx] if not isinstance(local, Symbol) or local.ns is not None: raise CompilerException( "bindings must be non-namespaced symbols", form) idx += 1 body = s[idx] if comp.getAlias(local) is not None: cb = (comp.compile(body)) newlocal = symbol("{0}_{1}".format(local, RT.nextID())) comp.pushAlias(local, tr.Local(newlocal.getName())) args.append(local) else: cb = comp.compile(body) comp.pushAlias(local, tr.Local(local.getName())) args.append(local) code.append(tr.StoreLocal(comp.getAlias(local), cb)) idx += 1 form = form.next() code.append(compileImplcitDo(comp, form)) code = tr.Do(*code) return code
def executeCode(self, code): if code == []: return None newcode = expandMetas(code, self) newcode.append((RETURN_VALUE, None)) c = Code(newcode, [], [], False, False, False, str(symbol(self.getNS().__name__, "<string>")), self.filename, 0, None) c = c.to_code() # work on .cljs #from clojure.util.freeze import write, read #with open("foo.cljs", "wb") as fl: # f = write(c, fl) retval = eval(c, self.getNS().__dict__) self.getNS().__file__ = self.filename return retval
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.aliases: newlocal = symbol(str(local)+"_"+str(RT.nextID())) code.extend(comp.compile(body)) comp.pushAlias(local, RenamedLocal(newlocal)) args.append(local) else: comp.pushAlias(local, RenamedLocal(local)) args.append(local) code.extend(comp.compile(body)) code.extend(comp.getAlias(local).compileSet(comp)) idx += 1 form = form.next() recurlabel = Label("recurLabel") recur = {"label": recurlabel, "args": map(lambda x: comp.getAlias(x).compileSet(comp), args)} code.append((recurlabel, None)) comp.pushRecur(recur) code.extend(compileImplcitDo(comp, form)) comp.popRecur() comp.popAliases(args) return code
def compileFNStar(comp, form): with ResolutionContext(comp): if len(comp.aliases) > 0: # we might have closures to deal with for x in comp.aliases: comp.pushAlias(x, tr.Closure(comp.getAlias(x).name, comp.getAlias(x))) 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): name = comp.getNamesString() + "_auto_" else: comp.pushName(name.name) pushed = True form = form.next() name = symbol(name) # This is fun stuff here. The idea is that we want closures to be able # to call themselves. But we can't get a pointer to a closure until after # it's created, which is when we actually run this code. So, we're going to # create a tmp local that is None at first, then pass that in as a possible # closure cell. Then after we create the closure with MAKE_CLOSURE we'll # populate this var with the correct value # form = ([x] x) if isinstance(form.first(), IPersistentVector): expr = compileFn(comp, name, form, orgform) # form = (([x] x)) elif len(form) == 1: expr = compileFn(comp, name, RT.list(*form.first()), orgform) # form = (([x] x) ([x y] x)) else: expr = compileMultiFn(comp, name, form) if pushed: comp.popName() return expr
def intern(ns, sym): from clojure.lang.var import Var if isinstance(sym, str): sym = symbol(str) if sym.ns is not None: raise InvalidArgumentException("Can't intern namespace-qualified symbol") ns = find(ns) if hasattr(ns, str(sym)): v = getattr(ns, str(sym)) if not isinstance(v, Var): raise Exception("can't redefine " + str(v) + " as " + str(sym) + ": is not Var") if ns.__name__ == v.ns.__name__: return v v = Var(ns, sym) setattr(ns, sym.name, v) return v
def matchSymbol(s): from clojure.lang.symbol import Symbol from 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(ns, name[(1 if iskeyword else 0):]) if iskeyword: return keyword(s) else: return sym return None
def intern(ns, sym): from clojure.lang.var import Var if isinstance(sym, str): sym = symbol(str) if sym.ns is not None: raise InvalidArgumentException( "Can't intern namespace-qualified symbol") ns = find(ns) if hasattr(ns, str(sym)): v = getattr(ns, str(sym)) if not isinstance(v, Var): raise Exception("can't redefine " + str(v) + " as " + str(sym) + ": is not Var") if ns.__name__ == v.ns.__name__: return v v = Var(ns, sym) setattr(ns, sym.name, v) return v
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(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 main(): requireClj(os.path.dirname(__file__) + "/core.clj") RT.init() comp = Compiler() currentCompiler.set(comp) comp.setNS(symbol("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: traceback.print_exc() else: for x in sys.argv[1:]: requireClj(x)
def compileFn(comp, name, form, orgform): locals, args, lastisargs, argsname = unpackArgs(form.first()) with ResolutionContext(comp): trargs = [] for x in args: if lastisargs and x == args[-1]: arg = tr.RestArgument(x) else: arg = tr.Argument(x) comp.pushAlias(symbol(x), arg) trargs.append(arg) resolved = partial(resolveTrLocal, comp.aliases) if lastisargs: expr = tr.Do(cleanRest(comp.getAlias(argsname)), compileImplcitDo(comp, form.next())) else: expr = compileImplcitDo(comp, form.next()) return tr.Func(trargs, expr, resolved, name = str(name))
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(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 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(comp.getNS().__name__, name.name)), comp.filename, 0, None) if not clist: c = new.function(c.to_code(), comp.ns.__dict__, name.name) return [(LOAD_CONST, c)], c
def executeCode(self, code): if code == []: return None newcode = expandMetas(code, self) newcode.append((RETURN_VALUE, None)) c = Code(newcode, [], [], False, False, False, str(symbol(self.getNS().__name__, "<string>")), self.filename, 0, None) try: c = c.to_code() except: for x in newcode: print x raise # work on .cljs #from clojure.util.freeze import write, read #with open("foo.cljs", "wb") as fl: # f = write(c, fl) retval = eval(c, self.getNS().__dict__) self.getNS().__file__ = self.filename return retval
def __init__(self, sym, rest=None): AAlias.__init__(self, rest) self.sym = sym self.newsym = symbol(sym.name + str(RT.nextID()))
def inner(func): builtins[sym if isinstance(sym, Symbol) else symbol(sym)] = func return func
def compileTry(comp, form): """ Compiles the try macro. """ assert form.first() == symbol("try") form = form.next() if not form: # I don't like this, but (try) == nil return [(LOAD_CONST, None)] # Extract the thing that may raise exceptions body = form.first() form = form.next() if not form: # If there are no catch/finally/else etc statements, just # compile the budy return comp.compile(body) catch = [] els = None fin = None for subform in form: # FIXME, could also be a Cons, LazySeq, etc. #if not isinstance(subform, IPersistentList): # raise CompilerException("try arguments must be lists", form) if not len(subform): raise CompilerException("try arguments must not be empty", form) name = subform.first() if name in (symbol("catch"), symbol("except")): if len(subform) != 4: raise CompilerException( "try " + str(name) + "blocks must be 4 items long", form) # Exception is second, val is third exception = subform.next().first() if not isinstance(exception, Symbol): raise CompilerException( "exception passed to " + str(name) + "block must be a symbol", form) for ex, _, _ in catch: if ex == exception: raise CompilerException( "try cannot catch duplicate" + " exceptions", form) var = subform.next().next().first() if not isinstance(var, Symbol): raise CompilerException( "variable name for " + str(name) + "block must be a symbol", form) val = subform.next().next().next().first() catch.append((exception, var, val)) elif name == symbol("else"): if len(subform) != 2: raise CompilerException("try else blocks must be 2 items", form) elif els: raise CompilerException("try cannot have multiple els blocks", form) els = subform.next().first() elif name == symbol("finally"): if len(subform) != 2: raise CompilerException("try finally blocks must be 2 items", form) elif fin: raise CompilerException( "try cannot have multiple finally blocks", form) fin = subform.next().first() else: raise CompilerException( "try does not accept any symbols apart " + "from catch/except/else/finally, got" + str(form), form) if fin and not catch and not els: return compileTryFinally(comp.compile(body), comp.compile(fin)) elif catch and not fin and not els: return compileTryCatch(comp, comp.compile(body), catch) elif not fin and not catch and els: raise CompilerException("Try does not accept else statements on " +\ "their own", form) if fin and catch and not els: return compileTryCatchFinally(comp, comp.compile(body), catch, comp.compile(fin))
def setUp(self): RT.init() self.comp = Compiler() currentCompiler.set(self.comp) self.comp.setNS(symbol('clojure.core'))
from clojure.lang.aref import ARef from clojure.lang.cljexceptions import (ArityException, InvalidArgumentException, IllegalStateException) from clojure.lang.persistenthashmap import EMPTY from clojure.lang.threadutil import ThreadLocal, currentThread from clojure.lang.symbol import symbol from clojure.lang.cljkeyword import keyword from clojure.lang.iprintable import IPrintable from clojure.lang.atomicreference import AtomicReference import persistentarraymap import types privateKey = keyword(symbol("private")) macrokey = keyword(symbol("macro")) STATIC_KEY = keyword(symbol("static")) dvals = ThreadLocal() privateMeta = persistentarraymap.create([privateKey, True]) UKNOWN = symbol("UNKNOWN") def pushThreadBindings(bindings): f = dvals.get(lambda: Frame()) bmap = f.bindings for v in bindings: value = bindings[v] if not v.dynamic: raise IllegalStateException("Can't dynamically bind non-dynamic " "var: " + str(v.ns) + "/" + str(v.sym))
from clojure.lang.iref import IRef from clojure.lang.ifn import IFn from clojure.lang.settable import Settable from clojure.lang.aref import ARef from clojure.lang.cljexceptions import (ArityException, InvalidArgumentException, IllegalStateException) from clojure.lang.persistenthashmap import EMPTY from clojure.lang.threadutil import ThreadLocal, currentThread from clojure.lang.symbol import symbol from clojure.lang.cljkeyword import keyword import persistentarraymap privateKey = keyword(symbol("private")) macrokey = keyword(symbol(":macro")) dvals = ThreadLocal() privateMeta = persistentarraymap.create([privateKey, True]) UKNOWN = symbol("UNKNOWN") def pushThreadBindings(bindings): f = dvals.get(lambda: 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))
def compileFNStar(comp, form): haslocalcaptures = False aliases = [] if len(comp.aliases) > 0: # we might have closures 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): name = comp.getNamesString() else: comp.pushName(name.name) pushed = True form = form.next() name = symbol(name) # This is fun stuff here. The idea is that we want closures to be able # to call themselves. But we can't get a pointer to a closure until after # it's created, which is when we actually run this code. So, we're going to # create a tmp local that is None at first, then pass that in as a possible # closure cell. Then after we create the closure with MAKE_CLOSURE we'll # populate this var with the correct value selfalias = Closure(name) comp.pushAlias(name, selfalias) if isinstance(form.first(), IPersistentVector): code, ptr = compileFn(comp, name, form, orgform) else: code, ptr = compileMultiFn(comp, name, form) if pushed: comp.popName() clist = comp.closureList() fcode = [] if haslocalcaptures: comp.popAliases(aliases) if clist: for x in clist: if x is not selfalias: #we'll populate selfalias later 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 if selfalias in clist: prefix = [] prefix.append((LOAD_CONST, None)) prefix.extend(selfalias.compileSet(comp)) prefix.extend(code) code = prefix code.append((DUP_TOP, None)) code.extend(selfalias.compileSet(comp)) comp.popAlias(symbol(name)) #closure return code
def internPrivate(nsName, sym): ns = Namespace.findOrCreate(symbol(nsName)) #FIXME: undefined Namespace ret = intern(ns, symbol(sym)) ret.setMeta(Var.privateMeta) return ret
from clojure.lang.ipersistentlist import IPersistentList from clojure.lang.var import Var, define, intern as internVar, var as createVar from clojure.util.byteplay import * import clojure.util.byteplay as byteplay from clojure.lang.cljkeyword import Keyword, keyword from clojure.lang.namespace import find as findNamespace import new import clojure.lang.rt as RT from clojure.lang.lispreader import _AMP_ from clojure.lang.namespace import findItem from clojure.lang.lispreader import LINE_KEY, garg import re import new import sys _MACRO_ = keyword(symbol(":macro")) version = (sys.version_info[0] * 10) + sys.version_info[1] def emitJump(label): if version == 26: return [(JUMP_IF_FALSE, label), (POP_TOP, None)] else: return [(POP_JUMP_IF_FALSE, label)] def emitLanding(label): if version == 26: return [(label, None), (POP_TOP, None)] else: return [(label, None)]