def bind(self, expr, name): """ Generates code for binding a name to a value in the rule's locals dict. """ return ast.Stmt([ ast.Assign([ast.Subscript(ast.Name('__locals'), 'OP_ASSIGN', [ast.Const(name)])], expr), ast.Subscript(ast.Name('__locals'), 'OP_APPLY', [ast.Const(name)])])
def compileSlice(doc): assertResult(doc[0], "slice") assertResult(doc[1], "slice from") assertResult(doc[2], "slice to") assertResult(doc[3], "slice with step") return ast.Subscript(topy(doc[0]), 'OP_APPLY', [ast.Sliceobj([topy(x) for x in doc[1:4]])])
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 compileGetOp(op): lang = op.__language__ opmodname = op.__language__.__module__ if opmodname == modulename: langexpr = GlobalName(lang.__impl__.name) else: langexpr = ast.Getattr(ast.Subscript(logixglobal('lmodules'), 'OP_APPLY', [ast.Const(opmodname)]), lang.__impl__.name) return ast.Subscript( ast.Getattr(ast.Getattr(langexpr, '__impl__'), 'operators'), 'OP_APPLY', [ast.Const(op.__syntax__.token)])
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)))])
def _do_IndexExpression(self, node, context): expr = self.transform(node.Target) index = node.Index if isinstance(index, SliceExpression) and index.SliceStep is None: lower = self.transform(index.SliceStart) upper = self.transform(index.SliceStop) return ast.Slice(expr, context, lower, upper) sub = self.transform(index) return ast.Subscript(expr, context, [sub])
def continuationOp(self, expr, parts): "__continue__" assertResult(expr, "call or subscript") res = topy(expr) for part in parts: kind = part[-1] args = part[:-1] if kind == 'call': funcArgs = [] funcKws = {} for a in args: if isinstance(a, rootops.PyOp) and a.__syntax__.token == '=': if isinstance(a[0], Symbol): funcKws[str(a[0])] = a[1] else: raise CompileError("invalid keyword arg %r" % a[0]) else: funcArgs.append(a) star = part.get('star', None) dstar = part.get('dstar', None) res = compileFunctionCall(res, funcArgs, funcKws, star, dstar) elif kind == 'subscript': for key in args: assertResult(key, "subscript with") res = ast.Subscript(res, 'OP_APPLY', map(topy, args)) elif kind == 'slice': start, end, step = args assertResult(start, "slice from") assertResult(end, "slice to") assertResult(step, "slice with step") res = ast.Subscript(res, 'OP_APPLY', [ast.Sliceobj(map(topy, (start, end, step)))]) return res
def continuationOp(self, expr, *parts): "" # The language knows it as the blank operator assertResult(expr, "call or subscript") res = topy(expr) for part in parts: kind = part[-1] args = part[:-1] if kind == 'call': funcArgs = [] funcKws = {} for a in args: if isPyOp(a, "="): if isinstance(a[0], Symbol) and a[0].namespace == "": funcKws[a[0].name] = a[1] else: raise CompileError("invalid keyword arg %r" % a[0]) else: funcArgs.append(a) star = part.get('star') dstar = part.get('dstar') res = compileFunctionCall(res, funcArgs, funcKws, star, dstar) elif kind == 'subscript': for key in args: assertResult(key, "subscript with") res = ast.Subscript(res, 'OP_APPLY', map(topy, args)) elif kind == 'slice': start, end, step = args assertResult(start, "slice from") assertResult(end, "slice to") assertResult(step, "slice with step") res = ast.Subscript(res, 'OP_APPLY', [ast.Sliceobj(map(topy, (start, end, step)))]) return res
def compileGetOp(symbol): lang = language.getLanguage(symbol.namespace) if lang is None: debug() raise CompileError, "not an operator symbol: %s" % symbol opmodname = lang.__module__ if opmodname == modulename: langexpr = GlobalName(lang.__impl__.name) else: langexpr = ast.Getattr(ast.Subscript(logixglobal('lmodules'), 'OP_APPLY', [ast.Const(opmodname)]), lang.__impl__.name) return ast.Subscript( ast.Getattr(ast.Getattr(langexpr, '__impl__'), 'operators'), 'OP_APPLY', [ast.Const(symbol.name)])
def visitAugAssign(self, node): if isinstance(node.node, ast.Name) and ( not self.locals or node.node.name not in flatten(self.locals)): name = node.node.name node.node = ast.Subscript(ast.Name('data'), 'OP_APPLY', [ast.Const(name)]) node.expr = self.visit(node.expr) return ast.If( [(ast.Compare(ast.Const(name), [('in', ast.Name('data'))]), ast.Stmt([node]))], ast.Stmt([ ast.Raise( ast.CallFunc(ast.Name('UndefinedError'), [ast.Const(name)]), None, None) ])) else: return ASTTransformer.visitAugAssign(self, node)
def compileGetops(self, fromlang, *ops, **kw): targetlang = kw.get("lang") if targetlang is None: raise CompileError("No target language for getops" "(getops in non-exec parse?)") assertResult(fromlang, "get operators from") lineno = getmeta(self, 'lineno') lastdot = targetlang.rfind('.') if lastdot == -1: targetlangexpr = GlobalName(targetlang) else: assert 0, ("PROBE: Why are we getting ops into an imported language?") langname = targetlang[lastdot+1:] langmod = targetlang[:lastdot] targetlangexpr = ast.Getattr(ast.Subscript(logixglobal('lmodules'), 'OP_APPLY', [ast.Const(langmod)]), langname) if len(ops) == 0: # get all operators res = ast.CallFunc(ast.Getattr(ast.Getattr(targetlangexpr, '__impl__'), 'addAllOperators'), [topy(fromlang)]) else: stmts = [ast.CallFunc(ast.Getattr(ast.Getattr(targetlangexpr, '__impl__'), 'addOp'), [compileGetOp(op)]) for op in ops] for s in stmts: s.lineno = lineno res = ast.Stmt(stmts) res.lineno = lineno return res
def function(self, name, expr): """ Create a function of one argument with the given name returning the given expr. @param name: The function name. @param expr: The AST to insert into the function. """ fexpr = ast.Stmt([ast.Assign([ast.AssName('__locals', 'OP_ASSIGN')], ast.Dict([(ast.Const('self'), ast.Name('self'))])), ast.Assign([ast.Subscript(ast.Getattr( ast.Name('self'), 'locals'), 'OP_ASSIGN', [ast.Const( name.split('_',1)[1])])], ast.Name('__locals')), expr]) f = ast.Lambda(['self'], [], 0, fexpr) f.filename = self.name return f
def compileDefop(doc): binding = doc['binding'] ruledef = doc['ruledef'] smartspace = doc.get('smartspace') assoc = doc.get('assoc', 'left') imp = doc.get('imp') lang = doc.get('lang') if lang is None: raise CompileError("invalid defop") assertResult(ruledef, "use in defop") assertResult(binding, "use in defop") lineno = getattr(doc, "lineno", None) # {{{ token = extract from ruledef def islit(x): return x[0][0] == 'LiteralRule' if islit(ruledef): token = ruledef[1] elif ruledef[0][0] == 'SequenceRule': rules = ruledef[1:] if len(rules) > 1 and islit(rules[0]): token = rules[0][1] elif len(rules) > 1 and islit(rules[1]): token = rules[1][1] else: raise CompileError("invalid ruledef") else: raise CompileError("invalid ruledef") # }}} if imp: if imp['kind'] == 'm': impkind = 'macro' elif imp['kind'] == 'f': impkind = 'func' else: assert 0, "invalid implementation kind: %s" % imp.kind impfuncname = 'operator[%s]' % token # {{{ impfunc = argflags, argnames, argdefaults = funcArgs(imp.get('args')) impfunc = astFunction(impfuncname, argnames, argdefaults, argflags, None, #docstring ast.Return(block(imp['body'], True))) impfunc.lineno = lineno # }}} impArgs = [ast.Const(impkind), ast.Name(impfuncname)] else: impArgs = [] lastdot = lang.rfind('.') if lastdot == -1: langexpr = GlobalName(lang) else: assert 0, "PROBE: Why are we adding an op to an imported language?" langname = lang[lastdot+1:] langmod = lang[:lastdot] langexpr = ast.Getattr(ast.Subscript(logixglobal('lmodules'), 'OP_APPLY', [ast.Const(langmod)]), langname) # If unmarshallable objects get into the code-object, you get a # blanket error message, so check these before they go in. assert isinstance(token, str) assert isinstance(smartspace, str) or smartspace == None assert isinstance(assoc, str) newOpCall = ast.CallFunc( ast.Getattr(ast.Getattr(langexpr, '__impl__'), 'newOp'), [ast.Const(token), topy(binding), topy(ruledef), ast.Const(smartspace), ast.Const(assoc)] + impArgs) if impArgs != []: return ast.Stmt([impfunc, newOpCall]) else: return newOpCall
def compileDefop(self, binding, ruledef, smartspace=None, assoc='left', imp=None, lang=None): if lang is None: raise CompileError("invalid defop") assertResult(ruledef, "use in defop") assertResult(binding, "use in defop") lineno = getmeta(self, 'lineno') # {{{ token = extract from ruledef def islit(x): return x[0][0] == 'LiteralRule' if islit(ruledef): token = ruledef[1] elif ruledef[0][0] == 'SequenceRule': rules = ruledef[1:] if len(rules) > 1 and islit(rules[0]): token = rules[0][1] elif len(rules) > 1 and islit(rules[1]): token = rules[1][1] else: raise CompileError("invalid ruledef") else: raise CompileError("invalid ruledef") # }}} if imp: if imp['kind'] == 'm': funcname = 'macro' elif imp['kind'] == 'f': funcname = 'func' else: assert 0, "invalid implementation kind: %s" % imp.kind impfuncname = 'operator[%s]' % token # {{{ impfunc = argflags, argnames, argdefaults = funcArgs(imp.get('args')) impfunc = astFunction(impfuncname, argnames, argdefaults, argflags, None, #docstring ast.Return(block(imp['body'], True))) impfunc.lineno = lineno # }}} else: funcname = None impfuncname = "None" impfunc = None lastdot = lang.rfind('.') if lastdot == -1: langexpr = GlobalName(lang) else: assert 0, "PROBE: Why are we adding an op to an imported language?" langname = lang[lastdot+1:] langmod = lang[:lastdot] langexpr = ast.Getattr(ast.Subscript(logixglobal('lmodules'), 'OP_APPLY', [ast.Const(langmod)]), langname) newOpCall = ast.CallFunc( ast.Getattr(ast.Getattr(langexpr, '__impl__'), 'newOp'), [ast.Const(token), topy(binding), topy(ruledef), ast.Const(smartspace), ast.Const(assoc), ast.Const(funcname), ast.Name(impfuncname) ]) if impfunc: return ast.Stmt([impfunc, newOpCall]) else: return newOpCall
def compileGetlmodule(doc): return ast.Subscript(logixglobal("lmodules"),'OP_APPLY', [topy(doc[0])])
def compilePlace(place, opname='OP_ASSIGN'): if isinstance(place, Symbol): return ast.AssName(str(place), opname) elif isinstance(place, rootops.PyOp): token = place.__syntax__.token if token == ".": # {{{ assign to field expr = topy(place[0]) field = place[1] if isinstance(field, Symbol): return ast.AssAttr(expr, str(field), opname) else: raise CompileError("Cannot assign to %s" % place) # }}} elif token == "__continue__": # {{{ assign to slice or subscript last = place[1][-1] # expr = the continuationOp not including the last part if len(place[1]) == 1: expr = place[0] else: expr = basel.getContinuationOp()(place[0], place[1][:-1]) kind = last[-1] if kind == 'subscript': # {{{ assign to subscript assertResult(expr, "subscript") keys = last[:-1] for key in keys: assertResult(key, "subscript with") return ast.Subscript(topy(expr), opname, map(topy, keys)) # }}} elif kind == "slice": # {{{ assign to slice assertResult(expr, "slice") start,end,step = last[:-1] assertResult(start, "slice from ") assertResult(end, "slice to") assertResult(step, "slice with step") return ast.Subscript(topy(expr), opname, [ast.Sliceobj(map(topy, (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.elems]) elif token == "(": return compilePlace(place[1], opname) else: raise CompileError("Cannot asign to %s " % place) else: raise CompileError("Cannot assign to %s" % place)
def compileSubscript(doc): assertResult(doc[0], "subscript") for x in doc[1:]: assertResult(x, "subscript with") return ast.Subscript(topy(doc[0]), 'OP_APPLY', [topy(x) for x in doc[1:]])
def BINARY_SUBSCR(decompiler): oper2 = decompiler.stack.pop() oper1 = decompiler.stack.pop() if isinstance(oper2, ast.Tuple): return ast.Subscript(oper1, 'OP_APPLY', list(oper2.nodes)) else: return ast.Subscript(oper1, 'OP_APPLY', [ oper2 ])
def visitSlice(self, node): n = ast.Subscript(node.expr, compiler.consts.OP_APPLY, [ast.Sliceobj(node.asList()[2:])]) self.visit(n)
def targetlangexpr(): return ast.Getattr(ast.Subscript(logixglobal('lmodules'), 'OP_APPLY', [ast.Const(langmod)]), langname)