def atom_number(self, nodelist): n = Transformer.atom_number(self, nodelist) number, lineno = nodelist[0][1:] if _is_integer(number): n = Const(long(number), lineno) return CallFunc(Name('Integer'), [n]) if number.endswith('j'): n = Const(complex(number), lineno) return CallFunc(Name('sympify'), [n]) n = Const(number, lineno) return CallFunc(Name('Real'), [n])
def visit_FunctionCall(self, func_call, cfg, func, node): if func_call.declaration != func: return post_entry = cfg.entry.out_edges.keys()[0] # Assign parameters to temporaries, and then temporaries to arguments nodes1 = [] nodes2 = [] for i in range(len(func_call.args)): # Don't need to assign if it's variable assigned to itself if func_call.args[i].declaration == func.args[i]: continue target = Name(func.args[i]) target.type = func.args[i].type # Don't need temporary if target isn't used in remaining args if target.declaration in [ x.declaration for x in func_call.args[i + 1:] ]: op_node1, source = assign_to_temporary(cfg, func_call.args[i]) nodes1.append(op_node1) else: source = func_call.args[i] op_node2 = Operation(AssignStatement(target, source)) nodes2.append(op_node2) # Link assignments into CFG first_assign = None last_assign = None for n in nodes1 + nodes2: if last_assign is not None: cfg.connect(last_assign, n) else: first_assign = n last_assign = n if first_assign is None: first_assign = post_entry else: cfg.connect(last_assign, post_entry) # Call node is replaced from each of its predecessors with the first assignment or target cfg.replace_before(node, first_assign) # Call node is removed from its successor post_call = node.out_edges.keys()[0] cfg.disconnect(node, post_call)
def visit_FunctionCall(self, func_call, cfg, func, node): if func_call.declaration != func: return post_entry = cfg.entry.out_edges.keys()[0] # Assign parameters to temporaries, and then temporaries to arguments nodes1 = [] nodes2 = [] for i in range(len(func_call.args)): # Don't need to assign if it's variable assigned to itself if func_call.args[i].declaration == func.args[i]: continue target = Name(func.args[i]) target.type = func.args[i].type # Don't need temporary if target isn't used in remaining args if target.declaration in [x.declaration for x in func_call.args[i+1:]]: op_node1, source = assign_to_temporary(cfg, func_call.args[i]) nodes1.append(op_node1) else: source = func_call.args[i] op_node2 = Operation(AssignStatement(target, source)) nodes2.append(op_node2) # Link assignments into CFG first_assign = None last_assign = None for n in nodes1 + nodes2: if last_assign is not None: cfg.connect(last_assign, n) else: first_assign = n last_assign = n if first_assign is None: first_assign = post_entry else: cfg.connect(last_assign, post_entry) # Call node is replaced from each of its predecessors with the first assignment or target cfg.replace_before(node, first_assign) # Call node is removed from its successor post_call = node.out_edges.keys()[0] cfg.disconnect(node, post_call)
def test_ast_policy(self): 'Policy: Keep tidy ASTs' a = Discard(Name('a')) empty = Stmt([]) self.assertEqual(empty, Block('').ast) self.assertEqual(empty, Block(empty).ast) self.assertEqual(empty, Block(Module(None, empty)).ast) self.assertEqual(a, Block('a').ast) self.assertEqual(a, Block(a).ast) self.assertEqual(a, Block(Stmt([a])).ast) self.assertEqual(a, Block(Module(None, Stmt([a]))).ast) # Similar, except we don't use strings since Block does its own parsing b = Block() b.ast = empty self.assertEqual(b.ast, empty) b.ast = Module(None, empty) self.assertEqual(b.ast, empty) b.ast = a self.assertEqual(b.ast, a) b.ast = Stmt([a]) self.assertEqual(b.ast, a) b.ast = Module(None, Stmt([a])) self.assertEqual(b.ast, a)
def visitFrom(self, node): for elem in node.modname.split("."): self.popWordsUpTo(elem) for name, alias in node.names: if name == self.targetstr: if alias is not None: pretendNode = Name(alias) else: pretendNode = Name(name) if findDefinitionFromASTNode(self.scope, pretendNode) \ == self.targetMatch: self.appendMatch(name) self.popWordsUpTo(name) if alias is not None: self.popWordsUpTo(alias)
def lambdef(self, nodelist): #this is python stdlib symbol, not SymPy symbol: from sympy import stdlib_symbol if nodelist[2][0] == stdlib_symbol.varargslist: names, defaults, flags = self.com_arglist(nodelist[2][1:]) else: names = defaults = () flags = 0 lineno = nodelist[1][2] code = self.com_node(nodelist[-1]) assert not defaults, ` defaults ` # sympy.Lambda does not support optional arguments if len(names) == 0: argument = ['x'] else: argument = names def convert(x): return CallFunc(Name('sympify'), [Const(x)]) argument = [convert(arg) for arg in argument] return CallFunc(Name('Lambda'), argument + [code])
def lambdef(self, nodelist): if nodelist[2][0] == symbol.varargslist: names, defaults, flags = self.com_arglist(nodelist[2][1:]) else: names = defaults = () flags = 0 lineno = nodelist[1][2] code = self.com_node(nodelist[-1]) assert not defaults, ` defaults ` # sympy.Lambda does not support optional arguments def convert(x): return CallFunc(Name('sympify'), [Const(x)]) argument = [convert(arg) for arg in names] return CallFunc(Name('Lambda'), [CallFunc(Name('Tuple'), argument), code])
def __const(self): from compiler.ast import Discard, CallFunc, Name, Const try: n = Discard( CallFunc(Name('__write__'), [Const(self.__tokenText(strip=0))], None, None)) t = self.__tokenPop() _renumber(n, t[1] - 1) return n except: self.__error('bad constant')
def visitFrom(self, node): if self._checkModuleName(node.modname): return for name, alias in node.names: if self.checkIfNameMatchesColumn(name): assert "." not in name self.node = Name(name) return self.popWordsUpTo(name) if alias is not None: self.popWordsUpTo(alias)
def visitFunction(self, node): if self.checkIfNameMatchesColumn(node.name): self.node = node self.popWordsUpTo(node.name) for arg, default in self.zipArgs(node.argnames, node.defaults): if self.checkIfNameMatchesColumn(arg): self.node = Name(arg) self.popWordsUpTo(arg) if default is not None: self.visit(default) self.visit(node.code)
def __expr(self): from compiler.ast import Discard, CallFunc, Name t = self.__tokenText() try: n = Discard( CallFunc(Name('__swrite__'), [self._cparse(t, 'eval').getChildren()[0]], None, None)) t = self.__tokenPop() _renumber(n, t[1] - 1) return n except: self.__error('bad expression')
def visit_FunctionCall(self, func_call, cfg, func, node): if isinstance(func_call.declaration, Builtin) or func_call.declaration == func: return try: other_cfg = func_call.declaration.cfg except AttributeError: return # Embed a copy of the inlined function's CFG isomorphism = cfg.embed(other_cfg) # Copy the inlined function's symbol table, and replace subgraph's variables with copies var_isomorphism = self.copy_variables(cfg, other_cfg) for n in isomorphism.values(): self.replace_vars(n, var_isomorphism) # Assign parameters to inlined function's argument variables for i in range(len(func_call.args)): arg = func_call.args[i] orig_var = func_call.declaration.args[i] target_var = var_isomorphism[orig_var] pre_assign = Operation(AssignStatement(Name(target_var), arg)) cfg.insert_before(node, pre_assign) # Assign return value to caller's result variable, at each of the subgraph's return nodes if isinstance(node.expression, AssignStatement): target = node.expression.target for subgraph_node in isomorphism.values(): if isinstance(subgraph_node, Return): ret_assign = Operation(AssignStatement(target, subgraph_node.expression)) cfg.replace_before(subgraph_node, ret_assign) cfg.replace_after(subgraph_node, ret_assign) # Disconnect old entry and exit from inlined subgraph. first_node = isomorphism[other_cfg.entry].out_edges.keys()[0] cfg.disconnect(isomorphism[other_cfg.entry], first_node) cfg.replace_before(node, first_node) for ln in isomorphism[other_cfg.exit].in_edges.keys(): cfg.disconnect(ln, isomorphism[other_cfg.exit]) cfg.replace_after(node, ln)
def deduceImportsForNewFile(refs, scope): importModules = {} for ref in refs: match = findDefinitionFromASTNode(scope, Name(ref)) if match.filename == scope.module.filename: tgtscope = getScopeForLine(getSourceNode(match.filename), match.lineno) while tgtscope != scope and not isinstance(tgtscope, Module): tgtscope = tgtscope.getParent() if not isinstance(tgtscope, Module): continue # was defined in this function mpath = filenameToModulePath(match.filename) if mpath in importModules: importModules[mpath].append(ref) else: importModules[mpath] = [ref] return importModules
def __script(self, mode='script'): self.__tokenPop() text = dedent(self.__tokenText(strip=0)) scriptMode = 'script' == mode if text: try: stmt = self._cparse(text, scriptMode and 'exec' or 'eval').node except: self.__error() t = self.__tokenPop() end = 'end' + mode try: assert self._tokens[self._tokenX][0] == end self.__tokenPop() except: self.__error(end + ' expected') if not text: return [] _renumber(stmt, t[1] - 1) if scriptMode: return stmt.nodes from compiler.ast import Discard, CallFunc, Name, Const return Discard( CallFunc(Name('__swrite__'), [stmt.getChildren()[0]], None, None))
def convert(x): return CallFunc(Name('sympify'), [Const(x)])
def __get_ast(self): from compiler.ast import Module, Stmt, Assign, AssName, Const, Function, For, Getattr,\ TryFinally, TryExcept, If, Import, AssAttr, Name, CallFunc,\ Class, Compare, Raise, And, Mod, Tuple, Pass, Not, Exec, List,\ Discard, Keyword, Return, Dict, Break, AssTuple, Subscript,\ Printnl, From, Lambda preppyNodes = self.__parse() if self._defSeen == 1: fixargs = self._fnc_argnames defaults = list(self._fnc_defaults) if self._fnc_kwargs: spargs = [fixargs[-1]] fixargs = fixargs[:-1] else: spargs = ['__kwds__'] if self._fnc_varargs: spargs.insert(0, fixargs[-1]) fixargs = fixargs[:-1] kwargs = fixargs[-len(defaults):] fixargs = fixargs[:-len(defaults)] flags = self._fnc_flags #construct the getOutput function nodes = [ Assign([AssName('__lquoteFunc__', 'OP_ASSIGN')], CallFunc(Getattr(Name(spargs[-1]), 'setdefault'), [Const('__lquoteFunc__'), Name('str')], None, None)), Discard( CallFunc(Getattr(Name(spargs[-1]), 'pop'), [Const('__lquoteFunc__')], None, None)), Assign([AssName('__quoteFunc__', 'OP_ASSIGN')], CallFunc(Getattr(Name(spargs[-1]), 'setdefault'), [Const('__quoteFunc__'), Name('str')], None, None)), Discard( CallFunc(Getattr(Name(spargs[-1]), 'pop'), [Const('__quoteFunc__')], None, None)) ] if not self._fnc_kwargs: nodes += [ If([(Name(spargs[-1]), Stmt([ Raise( CallFunc(Name('TypeError'), [ Const('get: unexpected keyword arguments') ], None, None), None, None) ]))], None) ] nodes += [ Assign([AssName('__append__', 'OP_ASSIGN')], Getattr(List(()), 'append')), Assign([AssName('__write__', 'OP_ASSIGN')], Lambda(['x'], [], 0, CallFunc(Name('__append__'), [ CallFunc(Name('__lquoteFunc__'), [Name('x')], None, None) ], None, None))), Assign([AssName('__swrite__', 'OP_ASSIGN')], Lambda(['x'], [], 0, CallFunc(Name('__append__'), [ CallFunc(Name('__quoteFunc__'), [Name('x')], None, None) ], None, None))) ] for n in nodes: _denumber(n, self._fnc_lineno) preppyNodes = nodes + preppyNodes + [ Return( CallFunc(Getattr(Const(''), 'join'), [Getattr(Name('__append__'), '__self__')], None, None)) ] argnames = list(fixargs) + list(kwargs) + list(spargs) FA = ('get', argnames, defaults, flags | 8, None, Stmt(preppyNodes)) global _newPreambleAst if not _newPreambleAst: _newPreambleAst = self._cparse(_newPreamble).node.nodes map(_denumber, _newPreambleAst) extraAst = _newPreambleAst else: global _preambleAst, _localizer if not _preambleAst: _preambleAst = self._cparse(_preamble).node.nodes map(_denumber, _preambleAst) _localizer = [ Assign([AssName('__d__', 'OP_ASSIGN')], Name('dictionary')), Discard( CallFunc( Getattr(CallFunc(Name('globals'), [], None, None), 'update'), [Name('__d__')], None, None)) ] preppyNodes = _localizer + preppyNodes FA = ('__code__', [ 'dictionary', 'outputfile', '__write__', '__swrite__', '__save_sys_stdout__' ], (), 0, None, Stmt(preppyNodes)) extraAst = _preambleAst if sys.hexversion >= 0x2040000: FA = (None, ) + FA return Module( self.filename, Stmt([ Assign([AssName('__checksum__', 'OP_ASSIGN')], Const(getattr(self, 'sourcechecksum'))), Function(*FA), ] + extraAst))
def createGetattr(self,fqn): node = Name(fqn[0]) for name in fqn.split(".")[1:]: node = Getattr(node,name) return node
def test_attemptToConvertGetattrToFqn_returnsNoneIfFails(self): ast = Getattr(CallFunc(Name("foo"),[],[],[]),"hello") assert attemptToConvertGetattrToFqn(ast) is None
def findDefinitionFromASTNode(scope,node): assert node is not None if isinstance(node,Name) or isinstance(node,AssName): while 1: # try scope children childscope = scope.getChild(node.name) if childscope is not None: return convertNodeToMatchObject(childscope,100) if isinstance(scope,Package): scope = scope.getChild("__init__") # try arguments and assignments match = scanScopeAST(scope,node.name, AssignmentAndFnArgsSearcher(node.name)) if match is not None: return match # try imports match = searchImportedModulesForDefinition(scope,node) if match is not None: return match if not isinstance(scope,Module): # try parent scope scope = scope.getParent() else: break assert isinstance(scope,Module) elif isinstance(node,Getattr) or isinstance(node,AssAttr): exprtype = getTypeOfExpr(scope,node.expr) if not (exprtype is None or isinstance(exprtype,UnfoundType)): if isinstance(exprtype,Instance): exprtype = exprtype.getType() match = findDefinitionOfAttributeFromASTNode(exprtype, node.attrname) else: match = findDefinitionFromASTNode(exprtype, Name(node.attrname)) if match is not None: return match elif isinstance(node,compiler.ast.Function) or \ isinstance(node,compiler.ast.Class): if isAMethod(scope,node): match = findDefinitionOfAttributeFromASTNode(scope, node.name) else: match = findDefinitionFromASTNode(scope,Name(node.name)) if match is not None: return match type = getTypeOfExpr(scope,node) if type is not None and (not isinstance(type,UnfoundType)) and \ (not isinstance(type,Instance)): return convertNodeToMatchObject(type,100) else: return None
def test_attemptToConvertGetattrToFqn_works(self): ast = Getattr(Getattr(Name("foo"),"bah"),"hello") assert attemptToConvertGetattrToFqn(ast) == "foo.bah.hello"
def transform(self, node): if isinstance(node, Node) and node in name_for.keys(): return Name(name_for[node]) else: return super(C, self).transform(node)
def _manufactureASTNodeFromFQN(self, fqn): if "." in fqn: assert 0, "getattr not supported yet" else: return Name(fqn)