def compileDeflang(self, name, parentx, body): assert isinstance(name, Symbol) if parentx: assertResult(parentx, "derive language from") parent = topy(parentx) else: parent = logixglobal('langlang') funcname = "#lang:%s" % name body = len(body) > 0 and block(body, False).nodes or [] funcbody = ast.Stmt( body + [ast.CallFunc(ast.Getattr(ast.Getattr(ast.Name(str(name)), '__impl__'), 'addDeflangLocals'), [ast.CallFunc(ast.Name('locals'), [])])]) res = ast.Stmt([ ast.Assign([compilePlace(Symbol(name))], ast.CallFunc(logixglobal('defLanguage'), [ast.Const(str(name)), parent, ast.CallFunc(GlobalName("globals"), [])])), astFunction(funcname, tuple(), tuple(), 0, None, funcbody), ast.CallFunc(ast.Name(funcname), []), ast.AssName(funcname, 'OP_DELETE')]) lineno = getmeta(self, 'lineno') for n in res.nodes: n.lineno = lineno res.lineno = lineno return res
def file_input(self, nodelist): # Add a "from IO_MODULE import IO_CLASS" statement to the # beginning of the module. doc = None # self.get_docstring(nodelist, symbol.file_input) if sys.hexversion >= 0x02050000: io_imp = ast.From(IO_MODULE, [(IO_CLASS, None)], 0) markup_imp = ast.From(MARKUP_MODULE, [(MARKUP_CLASS, None)], 0) else: io_imp = ast.From(IO_MODULE, [(IO_CLASS, None)]) markup_imp = ast.From(MARKUP_MODULE, [(MARKUP_CLASS, None)]) markup_assign = ast.Assign( [ast.AssName(MARKUP_MANGLED_CLASS, OP_ASSIGN)], ast.Name(MARKUP_CLASS)) # Add an IO_INSTANCE binding for module level expressions (like # doc strings). This instance will not be returned. io_instance = ast.CallFunc(ast.Name(IO_CLASS), []) io_assign_name = ast.AssName(IO_INSTANCE, OP_ASSIGN) io_assign = ast.Assign([io_assign_name], io_instance) stmts = [io_imp, io_assign, markup_imp, markup_assign] for node in nodelist: if node[0] != token.ENDMARKER and node[0] != token.NEWLINE: self.com_append_stmt(stmts, node) return ast.Module(doc, ast.Stmt(stmts))
def p_expression_name(self, p): """expression : NAME | NAME array_size""" if len(p) == 2: p[0] = ast.Name(p[1]) elif len(p) == 3: p[0] = ast.Name(p[1], p[2])
def visitName(self, node): # If the name refers to a local inside a lambda, list comprehension, or # generator expression, leave it alone if node.name not in flatten(self.locals): # Otherwise, translate the name ref into a context lookup func_args = [ast.Name('data'), ast.Const(node.name)] node = ast.CallFunc(ast.Name('_lookup_name'), func_args) return node
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 compilePythonExpr(self, name, expr): """ Compile an embedded Python expression. @param name: The current rule name. @param expr: The Python expression to compile. """ c = python_compile(expr, "<grammar rule %s>" % (name,), "eval") return ast.Stmt([ ast.CallFunc(ast.Name('eval'), [ast.Const(c), ast.Getattr(ast.Name("self"), "globals"), ast.Name('__locals')])])
def apply(self, ruleName, codeName='', *exprs): """ Create a call to self.apply(ruleName, *args). """ args = [self.compilePythonExpr(codeName, arg) for arg in exprs] if ruleName == "super": return ast.CallFunc(ast.Getattr(ast.Name("self"), "superApply"), [ast.Const(codeName)] + args, None, None) return ast.CallFunc(ast.Getattr(ast.Name("self"), "apply"), [ast.Const(ruleName)] + args, None, None)
def _compile_call(self, text, attribute_handlers=None): import compiler import types from compiler import ast, misc, pycodegen raise NotImplementedError('Incomplete') # TODO Make this work? def _generate(node): if node.type == node.TERM: return ast.Compare(ast.Const(node.value), [('in', ast.Name('text'))]) elif node.type == node.AND: return ast.And([_generate(node.left), _generate(node.right)]) elif node.type == node.OR: return ast.Or([_generate(node.left), _generate(node.right)]) elif node.type == node.NOT: return ast.Not(_generate(node.left)) elif node.type == node.ATTR: raise NotImplementedError qast = ast.Expression( ast.Lambda(['self', 'text', 'attribute_handlers'], [ast.Name('None')], 0, _generate(self))) misc.set_filename('<%s compiled query>' % self.__class__.__name__, qast) gen = pycodegen.ExpressionCodeGenerator(qast) self.__call__ = types.MethodType(eval(gen.getCode()), self, Query) return self.__call__(text)
def exactly(self, expr): """ Create a call to self.exactly(expr). """ return ast.CallFunc(ast.Getattr(ast.Name("self"), "exactly"), [ast.Const(expr)], None, None)
def visitPower(self, node, *args): walk(node.left, self) walk(node.right, self) cnode = ast.CallFunc(ast.Name('pow'), [node.left, node.right], None, None) node.left = cnode # Little hack: instead of trying to turn node into a CallFunc, we just do pow(left, right)**1 node.right = ast.Const(1)
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 atom_string(self, nodelist): k = '' for node in nodelist: k = k + eval(node[1]) n = ast.Const(k) if self.__template_type and self.__template_type[-1] == "html": # change "foo" to _q_htmltext("foo") n = ast.CallFunc(ast.Name(MARKUP_MANGLED_CLASS), [n]) return n
def many1(self, expr): """ Create a call to self.many((lambda: expr), expr). """ f = ast.Lambda([], [], 0, expr) f.filename = self.name return ast.CallFunc(ast.Getattr(ast.Name("self"), "many"), [f, expr], None, None)
def listpattern(self, exprs): """ Create a call to self.listpattern(lambda: exprs). """ f = ast.Lambda([], [], 0, exprs) f.filename = self.name return ast.CallFunc(ast.Getattr(ast.Name("self"), "listpattern"), [f], None, None)
def transform(node, filename): root = ast.Module(None, node, lineno=1) nodes = [root] while nodes: node = nodes.pop() node.filename = filename if node.__class__ in (ast.Printnl, ast.Print): node.dest = ast.Name('__context') nodes.extend(node.getChildNodes()) return root
def pred(self, expr): """ Create a call to self.pred(lambda: expr). """ f = ast.Lambda([], [], 0, expr) f.filename = self.name return ast.CallFunc(ast.Getattr(ast.Name("self"), "pred"), [f], None, None)
def visitLambda(self, node): assert not (node.kwargs or node.varargs),`node.kwargs, node.varargs` # parsing `lambda *args, **kwargs: ..` not supported self.start(LAMBDA) self.start(TUPLE) for n,d in zip(node.argnames, (len(node.argnames) - len(node.defaults))*[None] + list(node.defaults)): if d is None: self.visit(ast.Name(n)) else: self.visit(ast.Keyword(n, d)) self.end(tuple_head=TUPLE) self.visit(node.code) self.end()
def _generate(node): if node.type == node.TERM: return ast.Compare(ast.Const(node.value), [('in', ast.Name('text'))]) elif node.type == node.AND: return ast.And([_generate(node.left), _generate(node.right)]) elif node.type == node.OR: return ast.Or([_generate(node.left), _generate(node.right)]) elif node.type == node.NOT: return ast.Not(_generate(node.left)) elif node.type == node.ATTR: raise NotImplementedError
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 wrap_node(n): """ Replaces literal lists and dictionaries, and list comprehensions, with calls to the appropriate Ren'Py constructors. """ if isinstance(n, (ast.List, ast.ListComp)): n = ast.CallFunc( node=ast.Name('__renpy__list__'), args=[n], star_args=None, dstar_args=None, ) elif isinstance(n, ast.Dict): n = ast.CallFunc( node=ast.Name('__renpy__dict__'), args=[n], star_args=None, dstar_args=None, ) return n
def compileCodeObjects(filename, codeobjs): if len(codeobjs) == 0: stmts = [] else: stmts = [ast.For(ast.AssName('[--codeobj--]', 'OP_ASSIGN'), ast.Const(codeobjs), ast.Stmt([ast.Exec(ast.Name('[--codeobj--]'), None, None)]), None), ast.AssName('[--codeobj--]', 'OP_DELETE')] module = ast.Module(None, ast.Stmt(stmts)) compiler.misc.set_filename(filename, module) return pycodegen.ModuleCodeGenerator(module).getCode()
def _or(self, exprs): """ Create a call to self._or([lambda: expr1, lambda: expr2, ... , lambda: exprN]). """ fs = [] for expr in exprs: f = ast.Lambda([], [], 0, expr) f.filename = self.name fs.append(f) return ast.CallFunc(ast.Getattr(ast.Name("self"), "_or"), [ast.List(fs)], None, None)
def transform(node, filename): root = ast.Module(None, node, lineno=1) nodes = [root] while nodes: node = nodes.pop() node.filename = filename if node.__class__ in (ast.Printnl, ast.Print): node.dest = ast.Name('__context') elif node.__class__ is ast.Const and isinstance(node.value, str): try: node.value.decode('ascii') except UnicodeError: node.value = node.value.decode('utf-8') nodes.extend(node.getChildNodes()) return root
def run(self, frame): expr = Interpretable(self.expr) expr.eval(frame) self.result = expr.result self.explanation = '... = ' + expr.explanation # fall-back-run the rest of the assignment ass = ast.Assign(self.nodes, ast.Name('__exprinfo_expr')) mod = ast.Module(None, ast.Stmt([ass])) mod.filename = '<run>' co = pycodegen.ModuleCodeGenerator(mod).getCode() try: frame.exec_(co, __exprinfo_expr=expr.result) except passthroughex: raise except: raise Failure(self)
def Symbol(symbol): if symbol == data.true: return ast.Const(True) elif symbol == data.false: return ast.Const(False) elif symbol == data.none: return ast.Const(None) elif symbol.namespace == "": return ast.Name(symbol.name) else: debug() raise CompileError, "can't compile symbol with namespace: %s" % symbol
def _parse_Assign(self, node): for target in node.nodes: # for each assignment target, go clamber through mapping against the assignment expression # we'll only properly parse things with a direct 1:1 mapping # if, for example, the assignment relies on understanding the value being assigned, eg. (a,b) = c # then we'll silently fail assignments = self._mapAssign(target, node.expr) resolvedAssignments = [] for (target, expr) in assignments: if isinstance(expr, str): try: resolved = self.find(expr) except ValueError: resolved = UnparsedScope(ast.Name(expr), self.imports, self.localModules, self.rootScope) else: resolved = UnparsedScope(expr, self.imports, self.localModules, self.rootScope) resolvedAssignments.append((target, resolved)) for (target, expr) in resolvedAssignments: self.assign(target, expr)
def expr_stmt(self, nodelist): if not self.__template_type or not self.__template_type[-1]: return transformer.Transformer.expr_stmt(self, nodelist) # Instead of discarding objects on the stack, call # "IO_INSTANCE += obj". exprNode = self.com_node(nodelist[-1]) if len(nodelist) == 1: lval = ast.Name(IO_INSTANCE) n = ast.AugAssign(lval, '+=', exprNode) if hasattr(exprNode, 'lineno'): n.lineno = exprNode.lineno elif nodelist[1][0] == token.EQUAL: nodes = [] for i in range(0, len(nodelist) - 2, 2): nodes.append(self.com_assign(nodelist[i], OP_ASSIGN)) n = ast.Assign(nodes, exprNode) n.lineno = nodelist[1][2] else: lval = self.com_augassign(nodelist[0]) op = self.com_augassign_op(nodelist[1]) n = ast.AugAssign(lval, op[1], exprNode) n.lineno = op[2] return n
def call_stmt(func, args, lineno): return ast.CallFunc(ast.Name(func, lineno=lineno), args, lineno=lineno)
def p_atom_name(p): """atom : NAME""" p[0] = ast.Name(p[1])
def visitKeyword(self, node): self.start(KWARG) self.visit(ast.Name(node.name)) self.visit(node.expr) self.end()