def quote(obj, depth=1): assert depth > 0 if isDoc(obj, rootops.quote): depth += 1 elif isDoc(obj, rootops.escape): escapelevel = 1 + len(obj.get('extra', [])) if escapelevel > depth: raise CompileError("more quote escapes than quotes") elif escapelevel == depth: if obj.hasProperty('splice'): raise CompileError("Can't splice here") elif obj.hasProperty("localmodule"): return topy(localModuleQuote()) else: assertResult(obj[0], "insert into quote") return topy(obj[0]) if isinstance(obj, Doc): return quotedDoc(obj, depth) elif isinstance(obj, Symbol): return compileSymbol(obj) else: return topy(obj)
def interactiveCompile(expr, env, filename, mode): modname = env['__name__'] if data.isDoc(expr, rootops.setlang): newlang = language.tmpLanguage(language.eval(expr, env), modname) env['__currentlang__'] = newlang env[newlang.__impl__.name] = newlang return compile("None", "", "eval") if data.isDoc(expr, (rootops.defop, rootops.getops)): expr['lang'] = '__currentlang__' language.eval(expr, env) return compile("None", "", "eval") else: return logixcompiler.compile([expr], filename, mode, module=modname)
def assign(self, place, val): "=" if isDoc(val, self.symbol): # chained assign (a = b = blah) res = topy(val) res.nodes.append(compilePlace(place)) return res else: assertResult(val, "assign from") res = ast.Assign([compilePlace(place)], topy(val)) if lineno: res.lineno = lineno return res
def quotedDoc(doc, depth): """ Generate code to build a Doc like `doc` with quote-escapes replaced by runtime values. """ # Each element of contentParts is either: # an AST - meaning a spliced value - the resulting content # should be `extend`ed by that value # a list of ASTs - a list of regular elements, the resulting # content should be `extend`ed by an ast.List # with these elements # {{{ contentParts = contentParts = [[]] for x in doc.content(): if isDoc(x, rootops.escape): escapelevel = 1 + len(x.get('extra', [])) if escapelevel > depth: raise CompileError("more quote escapes than quotes") escape = escapelevel == depth else: escape = False if escape: if x.hasProperty("splice"): assertResult(x[0], "insert into quote") contentParts.append(topy(x[0])) contentParts.append([]) elif x.hasProperty("localmodule"): contentParts[-1].append(topy(localModuleQuote())) else: assertResult(x[0], "insert into quote") contentParts[-1].append(topy(x[0])) else: contentParts[-1].append(quote(x, depth)) # }}} # These properties are added to the result doc *after* # any spliced in docs, so they overwrite any spliced properties for v in doc.propertyValues(): assertResult(v, "use as operand") properties = ast.Dict([(compileSymbol(n), quote(v, depth)) for n, v in doc.properties()]) # assert isinstance(contentParts[0], list) if contentParts == [[]]: return ast.CallFunc(logixglobal("Doc"), [compileSymbol(doc.tag), properties]) else: if len(contentParts[0]) > 0: docArg = ast.List(contentParts[0]) rest = contentParts[1:] elif len(contentParts) > 0: docArg = contentParts[1] rest = contentParts[2:] if len(rest) == 0: return ast.CallFunc(logixglobal("Doc"), [compileSymbol(doc.tag), docArg, properties]) else: val = macros.gensym("val") stmts = [ast.Assign([compilePlace(val)], ast.CallFunc(logixglobal("Doc"), [compileSymbol(doc.tag), docArg]))] for part in rest: if isinstance(part, list): if len(part) == 0: continue ext = ast.List(part) else: ext = part stmts.append(ast.Discard(ast.CallFunc(ast.Getattr(topy(val), "extend"), [ext]))) stmts.append(ast.Discard(ast.CallFunc(ast.Getattr(topy(val), "extend"), [properties]))) stmts.append(topy(val)) return ast.Stmt(stmts)
def compilePlace(place, opname='OP_ASSIGN'): # {{{ def compileSubscriptPlace(objx, keyxs): def compileSubscriptPlace(objx, keyxs): assertResult(objx, "subscript") for key in keyxs: assertResult(key, "subscript with") return ast.Subscript(topy(objx), opname, map(topy, keyxs)) # }}} # {{{ def compileSlicePlace(objx, fromx, tox, stepx): def compileSlicePlace(objx, fromx, tox, stepx): assertResult(objx, "slice") assertResult(fromx, "slice from ") assertResult(tox, "slice to") assertResult(stepx, "slice with step") return ast.Subscript(topy(objx), opname, [ast.Sliceobj(map(topy, (fromx, tox, stepx)))]) # }}} if isinstance(place, Symbol): if place.namespace != "": raise CompileError, "cannot assign to symbol with namespace: %s" % place return ast.AssName(place.name, opname) elif isDoc(place, rootops.sliceOp): return compileSlicePlace(place[0], place[1], place[2], place[3]) elif isDoc(place, rootops.subscriptOp): return compileSubscriptPlace(place[0], place[1:]) elif isPyOp(place): token = place.tag.name if token == ".": # {{{ assign to field expr = topy(place[0]) field = place[1] if isinstance(field, Symbol) and field.namespace == "": return ast.AssAttr(expr, field.name, opname) else: raise CompileError("Cannot assign to %s" % place) # }}} elif token == "": # continuation op # {{{ assign to slice or subscript last = place[-1] # expr = the continuationOp not including the last part if len(place) == 2: expr = place[0] else: expr = Doc(Symbol(rootops.base_ns, ""), place[:-1]) kind = last[-1] if kind == 'subscript': return compileSubscriptPlace(expr, last[:-1]) elif kind == "slice": start,end,step = last[:-1] return compileSlicePlace(expr, start, end, step) else: raise CompileError("Cannot asign to %s " % place) # }}} elif token == ",": return ast.AssTuple([compilePlace(p, opname) for p in list(place)]) elif token == "[" and place[1] == 'list': return ast.AssList([compilePlace(p, opname) for p in place]) elif token == "(": return compilePlace(place[1], opname) else: raise CompileError("Cannot asign to %s " % place) else: raise CompileError("Cannot assign to %s" % place)