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 unquoteReader(rdr, tilde): s = read1(rdr) if s == "": raise ReaderException("EOF reading unquote", rdr) if s == "@": o = read(rdr, True, None, True) return RT.list(_UNQUOTE_SPLICING_, o) else: rdr.back() o = read(rdr, True, None, True) return RT.list(_UNQUOTE_, o)
def sqExpandList(self, seq): ret = EMPTY_VECTOR while seq is not None: item = seq.first() if isUnquote(item): ret = ret.cons(RT.list(_LIST_, item.next().first())) elif isUnquoteSplicing(item): ret = ret.cons(item.next().first()) else: ret = ret.cons(RT.list(_LIST_, self.syntaxQuote(item))) seq = seq.next() return ret.seq()
def unquoteReader(rdr, tilde): """Return one of: * (unquote-splicing next-object-read) * (unquote next-object-read)""" s = read1(rdr) if s == "": raise ReaderException("EOF reading unquote", rdr) if s == "@": o = read(rdr, True, None, True) return RT.list(_UNQUOTE_SPLICING_, o) else: rdr.back() o = read(rdr, True, None, True) return RT.list(_UNQUOTE_, o)
def __init__(self): self.recurPoint = RT.list() self.names = None self.ns = None self.lastlineno = -1 self.aliases = {} self.filename = "<unknown>"
def fnReader(rdr, lparen): """Read an anonymous function #() from reader rdr -- a read/unread-able object lparen -- ignored Return an IPersistentList""" if ARG_ENV.deref() is not None: raise IllegalStateException("Nested #()s are not allowed") with threadBindings(RT.map(ARG_ENV, EMPTY_MAP)): rdr.back() form = read(rdr, True, None, True) drefed = ARG_ENV.deref() sargs = sorted(list(filter(lambda x: x != -1, drefed))) args = [] if len(sargs): for x in range(1, int(str(sargs[-1])) + 1): if x in drefed: args.append(drefed[x]) else: args.append(garg(x)) retsym = drefed[-1] if retsym is not None: args.append(_AMP_) args.append(retsym) vargs = RT.vector(*args) return RT.list(_FN_, vargs, form)
def fnReader(rdr, lparen): from clojure.lang.persistenthashmap import EMPTY from clojure.lang.var import popThreadBindings, pushThreadBindings if ARG_ENV.deref() is not None: raise IllegalStateException("Nested #()s are not allowed") pushThreadBindings(RT.map(ARG_ENV, EMPTY)) rdr.back() form = read(rdr, True, None, True) drefed = ARG_ENV.deref() sargs = sorted(list(filter(lambda x: x != -1, drefed))) args = [] if len(sargs): for x in range(1, int(str(sargs[-1])) + 1): if x in drefed: args.append(drefed[x]) else: args.append(garg(x)) retsym = drefed[-1] if retsym is not None: args.append(_AMP_) args.append(retsym) vargs = RT.vector(*args) popThreadBindings() return RT.list(_FN_, vargs, form)
def __init__(self): self.recurPoint = RT.list() self.names = None self.ns = clojure_core = Namespace("clojure.core") self.lastlineno = -1 self.aliases = {} self.filename = "<unknown>" self._NS_ = findItem(clojure_core, _NS_)
def varQuoteReader(rdr, singlequote): """Return the list (var next-object-read) rdr -- read/unread-able object singlequote -- ignored""" line = rdr.lineCol()[0] form = read(rdr, True, None, True) return RT.list(_VAR_, form).withMeta(RT.map(LINE_KEY, line))
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 unpackArgs(form): locals = {} args = [] lastisargs = False argsname = None for x in form: if x == _AMP_: lastisargs = True continue if lastisargs and argsname is not None: raise CompilerException("variable length argument must be the last in the function") if lastisargs: argsname = x if not isinstance(x, Symbol) or x.ns is not None: raise CompilerException("fn* arguments must be non namespaced symbols " + " got " + str(form) + " instead", form) locals[x] = RT.list(x) args.append(x.name) return locals, args, lastisargs, argsname
def unpackArgs(form): locals = {} args = [] lastisargs = False argsname = None for x in form: if x == _AMP_: lastisargs = True continue if lastisargs and argsname is not None: raise CompilerException( "variable length argument must be the last in the function") if lastisargs: argsname = x if not isinstance(x, Symbol) or x.ns is not None: raise CompilerException( "fn* arguments must be non namespaced symbols " + " got " + str(form) + " instead", form) locals[x] = RT.list(x) args.append(x.name) return locals, args, lastisargs, argsname
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, 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 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 __call__(self, rdr, quote): o = read(rdr, True, None, True) return RT.list(self.sym, o)
def varQuoteReader(rdr, singlequote): line = rdr.lineCol()[0] form = read(rdr, True, None, True) return RT.list(_VAR_, form).withMeta(RT.map(LINE_KEY, line))
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