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 comp.pushName(RT.name(sym)) code = [] v = internVar(comp.getNS(), sym) v.setDynamic(True) if len(form) == 3: code.append((LOAD_CONST, v)) code.append((LOAD_ATTR, "bindRoot")) compiledValue = comp.compile(value) if isinstance(value, ISeq) \ and value.first().getName() == 'fn' \ and sym.meta() is not None: try: compiledValue[0][1].__doc__ = sym.meta()[keyword('doc')] except AttributeError: pass code.extend(compiledValue) code.append((CALL_FUNCTION, 1)) else: code.append((LOAD_CONST, v)) v.setMeta(sym.meta()) comp.popName() 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 comp.pushName(RT.name(sym)) code = [] v = intern(comp.getNS(), sym) v.setDynamic(True) if len(form) == 3: code.append((LOAD_CONST, v)) code.append((LOAD_ATTR, "bindRoot")) compiledValue = comp.compile(value) if isinstance(value, ISeq) \ and value.first().getName() == 'fn' \ and sym.meta() is not None: try: compiledValue[0][1].__doc__ = sym.meta()[Keyword('doc')] except AttributeError: pass code.extend(compiledValue) code.append((CALL_FUNCTION, 1)) else: code.append((LOAD_CONST, v)) v.setMeta(sym.meta()) comp.popName() 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)] 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: RT.name(x.sym), 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 = types.FunctionType(c.to_code(), comp.ns.__dict__, name.name) return [(LOAD_CONST, c)], 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: RT.name(x.sym), 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 = types.FunctionType(c.to_code(), comp.ns.__dict__, name.name) return [(LOAD_CONST, c)], c
def extendForType(self, tp, mp): """Extends this protocol for the given type and the given map of methods mp should be a map of methodnames: functions""" for x in mp: name = RT.name(x.sym) if name not in self.protofns: raise ProtocolException("No Method found for name " + x) fn = self.protofns[name] fn.extend(tp, mp[x]) self.markImplementor(tp)
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 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 comp.pushName(RT.name(sym)) code = [] i = getAttrChain("clojure.lang.var.intern") v = tr.Call(i, tr.Const(comp.getNS().__name__), tr.Const(sym.getName())) # We just wrote some treadle code to define a var, but # the compiler won't see that yet, so let's re-define the var now # so that the compiler can pick it up internVar(comp.getNS().__name__, sym.getName()) #v.setDynamic(True) if len(form) == 3: code = tr.Call(tr.Attr(v, "bindRoot"), comp.compile(value)) else: code = v with Quoted(comp): code = tr.Call(tr.Attr(code, "setMeta"), comp.compile(sym.meta())) #v.setMeta(sym.meta()) comp.popName() 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)] 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: RT.name(x.sym), 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 = types.FunctionType(c.to_code(), comp.ns.__dict__, name.name) return [(LOAD_CONST, c)], 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: RT.name(x.sym), 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 = types.FunctionType(c.to_code(), comp.ns.__dict__, name.name) return [(LOAD_CONST, c)], c
def test_named(self): self.assertEqual(RT.name(RT.symbol(u"foo")), u"foo") self.assertEqual(RT.namespace(RT.symbol(u"foo", u"bar")), u"foo")
def compile(self, comp): self.isused = True return [(LOAD_DEREF, RT.name(self.sym))]
def compileSet(self, comp): return [(STORE_DEREF, RT.name(self.sym))]
def compileAccessList(self, sym): if sym.ns == 'py': return [(LOAD_CONST, getBuiltin(RT.name(sym)))] code = self.getAccessCode(sym) return code
def compile(self, comp): return [(LOAD_FAST, RT.name(self.newsym))]
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 __init__(self, sym, rest=None): AAlias.__init__(self, rest) self.sym = sym self.newsym = Symbol(RT.name(sym) + str(RT.nextID()))
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() + "_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 selfalias = Closure(name) comp.pushAlias(name, selfalias) # form = ([x] x) if isinstance(form.first(), IPersistentVector): code, ptr = compileFn(comp, name, form, orgform) # form = (([x] x)) elif len(form) == 1: code, ptr = compileFn(comp, name, RT.list(*form.first()), orgform) # form = (([x] x) ([x y] x)) 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, RT.name(x.sym))) # Store it in a Closure Cell fcode.append((LOAD_CLOSURE, RT.name(x.sym))) # 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 compileSet(self, comp): return [(STORE_FAST, RT.name(self.newsym))]
def __init__(self, sym, rest = None): AAlias.__init__(self, rest) self.sym = sym self.newsym = symbol(RT.name(sym) + str(RT.nextID()))
def getAccessCode(self, sym): if sym.ns is None or sym.ns == self.getNS().__name__: 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 [GlobalPtr(self.getNS(), RT.name(sym))] 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 = findNS(sym.ns) if not hasattr(module, RT.name(sym)): raise CompilerException( "{0} does not define {1}".format(module, 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: {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 compileAccessList(self, sym): if sym.ns == 'py': return getBuiltin(RT.name(sym)) code = self.getAccessCode(sym) return code
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() + "_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 selfalias = Closure(name) comp.pushAlias(name, selfalias) # form = ([x] x) if isinstance(form.first(), IPersistentVector): code, ptr = compileFn(comp, name, form, orgform) # form = (([x] x)) elif len(form) == 1: code, ptr = compileFn(comp, name, RT.list(*form.first()), orgform) # form = (([x] x) ([x y] x)) 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, RT.name(x.sym))) # Store it in a Closure Cell fcode.append( (LOAD_CLOSURE, RT.name(x.sym))) # 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 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