def compileLetStar(comp, form): if len(form) < 2: 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) bindings = RT.seq(form.first()) args = [] code = [] if bindings and len(bindings) % 2: raise CompilerException("let* takes a even number of bindings", form) while bindings: local, bindings = bindings.first(), bindings.next() body, bindings = bindings.first(), bindings.next() if not isinstance(local, Symbol) or local.ns is not None: raise CompilerException("bindings must be non-namespaced symbols", form) code.extend(comp.compile(body)) alias = RenamedLocal( Symbol("{0}_{1}".format(local, RT.nextID())) if comp. getAlias(local) else local) comp.pushAlias(local, alias) args.append(local) code.extend(alias.compileSet(comp)) form = form.next() code.extend(compileImplcitDo(comp, form)) comp.popAliases(args) return code
def getNamesString(self, markused=True): if self.names is None: return "fn_{0}".format(RT.nextID()) s = str(self.names) if markused and self.names is not None: self.names.isused = True return s
def getNamesString(self, markused=True): if self.names is None: return "fn_"+str(RT.nextID()) s = str(self.names) if markused and self.names is not None: self.names.isused = True return s
def compileLetStar(comp, form): if len(form) < 2: 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) bindings = RT.seq(form.first()) args = [] code = [] if bindings and len(bindings) % 2: raise CompilerException("let* takes a even number of bindings", form) while bindings: local, bindings = bindings.first(), bindings.next() body, bindings = bindings.first(), bindings.next() if not isinstance(local, Symbol) or local.ns is not None: raise CompilerException( "bindings must be non-namespaced symbols", form) code.extend(comp.compile(body)) alias = RenamedLocal(Symbol("{0}_{1}".format(local, RT.nextID())) if comp.getAlias(local) else local) comp.pushAlias(local, alias) args.append(local) code.extend(alias.compileSet(comp)) form = form.next() code.extend(compileImplcitDo(comp, form)) comp.popAliases(args) return code
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 compileTryCatch(comp, body, catches): """ Compiles the try/catch/catch... form. Takes the body of the try statement, and a list of (exception, exception_var, except_body) tuples for each exception. The order of the list is important. """ assert len(catches), "Calling compileTryCatch with empty catches list" catch_labels = [Label("TryCatch_{0}".format(ex)) for ex, _, _ in catches] endLabel = Label("TryCatchEnd") endFinallyLabel = Label("TryCatchEndFinally") firstExceptLabel = Label("TryFirstExcept") ret_val = "__ret_val_{0}".format(RT.nextID()) code = [(SETUP_EXCEPT, firstExceptLabel)] # First catch label code.extend(body) code.append((STORE_FAST, ret_val)) # Because I give up with # keeping track of what's in the stack code.append((POP_BLOCK, None)) code.append((JUMP_FORWARD, endLabel)) # if all went fine, goto end n = len(catches) for i, (exception, var, val) in enumerate(catches): comp.pushAlias(var, FnArgument(var)) # FnArgument will do last = i == n - 1 # except Exception code.extend(emitLanding(catch_labels[i])) if i == 0: # first time only code.append((firstExceptLabel, None)) code.append((DUP_TOP, None)) code.extend(comp.compile(exception)) code.append((COMPARE_OP, "exception match")) code.extend( emitJump(catch_labels[i + 1] if not last else endFinallyLabel)) # as e code.append((POP_TOP, None)) code.append((STORE_FAST, var.name)) code.append((POP_TOP, None)) # body code.extend(comp.compile(val)) code.append((STORE_FAST, ret_val)) code.append((JUMP_FORWARD, endLabel)) comp.popAlias(var) code.extend(emitLanding(endFinallyLabel)) code.append((END_FINALLY, None)) code.append((endLabel, None)) code.append((LOAD_FAST, ret_val)) return code
def compileTryCatch(comp, body, catches): """ Compiles the try/catch/catch... form. Takes the body of the try statement, and a list of (exception, exception_var, except_body) tuples for each exception. The order of the list is important. """ assert len(catches), "Calling compileTryCatch with empty catches list" catch_labels = [Label("TryCatch_{0}".format(ex)) for ex, _, _ in catches] endLabel = Label("TryCatchEnd") endFinallyLabel = Label("TryCatchEndFinally") firstExceptLabel = Label("TryFirstExcept") ret_val = "__ret_val_{0}".format(RT.nextID()) code = [(SETUP_EXCEPT, firstExceptLabel)] # First catch label code.extend(body) code.append((STORE_FAST, ret_val)) # Because I give up with # keeping track of what's in the stack code.append((POP_BLOCK, None)) code.append((JUMP_FORWARD, endLabel)) # if all went fine, goto end n = len(catches) for i, (exception, var, val) in enumerate(catches): comp.pushAlias(var, FnArgument(var)) # FnArgument will do last = i == n - 1 # except Exception code.extend(emitLanding(catch_labels[i])) if i == 0: # first time only code.append((firstExceptLabel, None)) code.append((DUP_TOP, None)) code.extend(comp.compile(exception)) code.append((COMPARE_OP, "exception match")) code.extend(emitJump(catch_labels[i + 1] if not last else endFinallyLabel)) # as e code.append((POP_TOP, None)) code.append((STORE_FAST, var.name)) code.append((POP_TOP, None)) # body code.extend(comp.compile(val)) code.append((STORE_FAST, ret_val)) code.append((JUMP_FORWARD, endLabel)) comp.popAlias(var) code.extend(emitLanding(endFinallyLabel)) code.append((END_FINALLY, None)) code.append((endLabel, None)) code.append((LOAD_FAST, ret_val)) return code
def __str__(self): v = [] r = self while r is not None: v.append(r.name) r = r.rest v.reverse() s = "_".join(v) if self.isused: s = s + str(RT.nextID()) return s
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 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 compileTryFinally(body, fin): """ Compiles the try/finally form. Takes the body of the try statement, and the finally statement. They must be compiled bytecode (i.e. comp.compile(body)). """ finallyLabel = Label("TryFinally") ret_val = "__ret_val_{0}".format(RT.nextID()) code = [(SETUP_FINALLY, finallyLabel)] code.extend(body) code.append((STORE_FAST, ret_val)) code.append((POP_BLOCK, None)) code.append((LOAD_CONST, None)) code.append((finallyLabel, None)) code.extend(fin) code.extend([(POP_TOP, None), (END_FINALLY, None), (LOAD_FAST, ret_val)]) 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(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 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 compileLoopStar(comp, form): with ResolutionContext(comp): if len(form) < 3: raise CompilerException("loop* takes at least two args", form) form = form.next() if not isinstance(form.first(), PersistentVector): raise CompilerException( "loop* takes a vector as it's first argument", form) s = form.first() args = [] vars = [] code = [] idx = 0 while idx < len(s): if len(s) - idx < 2: raise CompilerException( "loop* 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 local in comp.aliases: newlocal = symbol("{0}_{1}".format(local, RT.nextID())) comp.pushAlias(local, tr.Local(newlocal.getName())) else: comp.pushAlias(local, tr.Local(local.getName())) args.append(comp.compile(body)) vars.append(comp.getAlias(local)) idx += 1 return compileImplcitDo(comp, form.next()).Loop(vars, args)
def compileTryCatchFinally(comp, body, catches, fin): """ Compiles the try/catch/finally form. """ assert len(catches), "Calling compileTryCatch with empty catches list" catch_labels = [Label("TryCatch_{0}".format(ex)) for ex, _, _ in catches] finallyLabel = Label("TryCatchFinally") notCaughtLabel = Label("TryCatchFinally2") firstExceptLabel = Label("TryFirstExcept") normalEndLabel = Label("NoExceptionLabel") ret_val = "__ret_val_{0}".format(RT.nextID()) code = [(SETUP_FINALLY, finallyLabel), (SETUP_EXCEPT, firstExceptLabel)] # First catch label code.extend(body) code.append((STORE_FAST, ret_val)) # Because I give up with # keeping track of what's in the stack code.append((POP_BLOCK, None)) code.append((JUMP_FORWARD, normalEndLabel)) # if all went fine, goto finally n = len(catches) for i, (exception, var, val) in enumerate(catches): comp.pushAlias(var, FnArgument(var)) # FnArgument will do last = i == n - 1 first = i == 0 # except Exception code.extend(emitLanding(catch_labels[i])) if first: # After the emitLanding, so as to split the label code.append((firstExceptLabel, None)) code.append((DUP_TOP, None)) code.extend(comp.compile(exception)) code.append((COMPARE_OP, "exception match")) code.extend( emitJump(catch_labels[i + 1] if not last else notCaughtLabel)) # as e code.append((POP_TOP, None)) code.append((STORE_FAST, var.name)) code.append((POP_TOP, None)) # body code.extend(comp.compile(val)) code.append((STORE_FAST, ret_val)) code.append((JUMP_FORWARD, normalEndLabel)) comp.popAlias(var) code.extend(emitLanding(notCaughtLabel)) code.append((END_FINALLY, None)) code.append((normalEndLabel, None)) code.append((POP_BLOCK, None)) code.append((LOAD_CONST, None)) code.append((finallyLabel, None)) code.extend(fin) code.append((POP_TOP, None)) code.append((END_FINALLY, None)) code.append((LOAD_FAST, ret_val)) return code
def __init__(self, sym, rest=None): AAlias.__init__(self, rest) self.sym = sym self.newsym = Symbol(RT.name(sym) + str(RT.nextID()))
def garg(n): from symbol import Symbol return symbol(None, "rest" if n == -1 else ("p" + str(n)) + "__" + str(RT.nextID()) + "#")
def garg(n): return symbol(None, "rest" if n == -1 else ("p" + str(n)) + "__" + str(RT.nextID()) + "#")
def compileTryCatchFinally(comp, body, catches, fin): """ Compiles the try/catch/finally form. """ assert len(catches), "Calling compileTryCatch with empty catches list" catch_labels = [Label("TryCatch_{0}".format(ex)) for ex, _, _ in catches] finallyLabel = Label("TryCatchFinally") notCaughtLabel = Label("TryCatchFinally2") firstExceptLabel = Label("TryFirstExcept") normalEndLabel = Label("NoExceptionLabel") ret_val = "__ret_val_{0}".format(RT.nextID()) code = [ (SETUP_FINALLY, finallyLabel), (SETUP_EXCEPT, firstExceptLabel)] # First catch label code.extend(body) code.append((STORE_FAST, ret_val)) # Because I give up with # keeping track of what's in the stack code.append((POP_BLOCK, None)) code.append((JUMP_FORWARD, normalEndLabel)) # if all went fine, goto finally n = len(catches) for i, (exception, var, val) in enumerate(catches): comp.pushAlias(var, FnArgument(var)) # FnArgument will do last = i == n - 1 first = i == 0 # except Exception code.extend(emitLanding(catch_labels[i])) if first: # After the emitLanding, so as to split the label code.append((firstExceptLabel, None)) code.append((DUP_TOP, None)) code.extend(comp.compile(exception)) code.append((COMPARE_OP, "exception match")) code.extend(emitJump(catch_labels[i + 1] if not last else notCaughtLabel)) # as e code.append((POP_TOP, None)) code.append((STORE_FAST, var.name)) code.append((POP_TOP, None)) # body code.extend(comp.compile(val)) code.append((STORE_FAST, ret_val)) code.append((JUMP_FORWARD, normalEndLabel)) comp.popAlias(var) code.extend(emitLanding(notCaughtLabel)) code.append((END_FINALLY, None)) code.append((normalEndLabel, None)) code.append((POP_BLOCK, None)) code.append((LOAD_CONST, None)) code.append((finallyLabel, None)) code.extend(fin) code.append((POP_TOP, None)) code.append((END_FINALLY, None)) code.append((LOAD_FAST, ret_val)) return code
def syntaxQuote(self, form): # compiler uses this module, so import it lazily 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, "{0}__{1}__auto__".format(sym.name[:-1], RT.nextID())) 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.deref() 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") item = namespace.findItem(ns, sym) if item is None: sym = Symbol(ns.__name__, sym.name) else: sym = Symbol(item.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 getattr(form, "meta", lambda: None)() 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 __init__(self, sym, rest = None): AAlias.__init__(self, rest) self.sym = sym self.newsym = symbol(sym.name + str(RT.nextID()))
def garg(n): return symbol( None, "rest" if n == -1 else ("p" + str(n)) + "__" + str(RT.nextID()) + "#")
def garg(n): return Symbol("rest" if n == -1 else "p{0}__{1}#".format(n, RT.nextID()))