15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# TreeFragments - parsing of strings to trees 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import re 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from StringIO import StringIO 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Scanning import PyrexScanner, StringSourceDescriptor 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Symtab import ModuleScope 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import PyrexTypes 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Visitor import VisitorTransform 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Nodes import Node, StatListNode 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from ExprNodes import NameNode 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import Parsing 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import Main 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import UtilNodes 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)""" 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Support for parsing strings into code trees. 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)""" 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class StringParseContext(Main.Context): 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __init__(self, name, include_directories=None): 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if include_directories is None: include_directories = [] 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Main.Context.__init__(self, include_directories, {}, 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) create_testscope=False) 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.module_name = name 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def find_module(self, module_name, relative_to = None, pos = None, need_pxd = 1): 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if module_name not in (self.module_name, 'cython'): 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise AssertionError("Not yet supporting any cimports/includes from string code snippets") 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ModuleScope(module_name, parent_module = None, context = self) 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def parse_from_strings(name, code, pxds={}, level=None, initial_pos=None, 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) context=None, allow_struct_enum_decorator=False): 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Utility method to parse a (unicode) string of code. This is mostly 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) used for internal Cython compiler purposes (creating code snippets 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) that transforms should emit, as well as unit testing). 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) code - a unicode string containing Cython (module-level) code 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name - a descriptive name for the code source (to use in error messages etc.) 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) RETURNS 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) The tree, i.e. a ModuleNode. The ModuleNode's scope attribute is 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) set to the scope used when parsing. 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if context is None: 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) context = StringParseContext(name) 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # Since source files carry an encoding, it makes sense in this context 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # to use a unicode string so that code fragments don't have to bother 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # with encoding. This means that test code passed in should not have an 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # encoding header. 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assert isinstance(code, unicode), "unicode code snippets only please" 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) encoding = "UTF-8" 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) module_name = name 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if initial_pos is None: 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) initial_pos = (name, 1, 0) 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) code_source = StringSourceDescriptor(name, code) 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scope = context.find_module(module_name, pos = initial_pos, need_pxd = 0) 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) buf = StringIO(code) 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scanner = PyrexScanner(buf, code_source, source_encoding = encoding, 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scope = scope, context = context, initial_pos = initial_pos) 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ctx = Parsing.Ctx(allow_struct_enum_decorator=allow_struct_enum_decorator) 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if level is None: 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tree = Parsing.p_module(scanner, 0, module_name, ctx=ctx) 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tree.scope = scope 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tree.is_pxd = False 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tree = Parsing.p_code(scanner, level=level, ctx=ctx) 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tree.scope = scope 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return tree 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class TreeCopier(VisitorTransform): 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_Node(self, node): 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node is None: 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) c = node.clone_node() 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(c) 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return c 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ApplyPositionAndCopy(TreeCopier): 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __init__(self, pos): 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) super(ApplyPositionAndCopy, self).__init__() 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.pos = pos 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_Node(self, node): 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) copy = super(ApplyPositionAndCopy, self).visit_Node(node) 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) copy.pos = self.pos 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return copy 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class TemplateTransform(VisitorTransform): 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Makes a copy of a template tree while doing substitutions. 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) A dictionary "substitutions" should be passed in when calling 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) the transform; mapping names to replacement nodes. Then replacement 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) happens like this: 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) - If an ExprStatNode contains a single NameNode, whose name is 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) a key in the substitutions dictionary, the ExprStatNode is 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) replaced with a copy of the tree given in the dictionary. 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) It is the responsibility of the caller that the replacement 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node is a valid statement. 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) - If a single NameNode is otherwise encountered, it is replaced 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if its name is listed in the substitutions dictionary in the 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) same way. It is the responsibility of the caller to make sure 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) that the replacement nodes is a valid expression. 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Also a list "temps" should be passed. Any names listed will 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) be transformed into anonymous, temporary names. 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Currently supported for tempnames is: 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NameNode 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (various function and class definition nodes etc. should be added to this) 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Each replacement node gets the position of the substituted node 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) recursively applied to every member node. 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temp_name_counter = 0 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __call__(self, node, substitutions, temps, pos): 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.substitutions = substitutions 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.pos = pos 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tempmap = {} 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temphandles = [] 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for temp in temps: 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TemplateTransform.temp_name_counter += 1 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) handle = UtilNodes.TempHandle(PyrexTypes.py_object_type) 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tempmap[temp] = handle 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temphandles.append(handle) 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.tempmap = tempmap 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result = super(TemplateTransform, self).__call__(node) 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if temps: 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result = UtilNodes.TempsBlockNode(self.get_pos(node), 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temps=temphandles, 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body=result) 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return result 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def get_pos(self, node): 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if self.pos: 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.pos 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node.pos 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_Node(self, node): 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node is None: 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) c = node.clone_node() 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if self.pos is not None: 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) c.pos = self.pos 1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(c) 1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return c 1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def try_substitution(self, node, key): 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sub = self.substitutions.get(key) 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if sub is not None: 1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos = self.pos 1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if pos is None: pos = node.pos 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ApplyPositionAndCopy(pos)(sub) 1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.visit_Node(node) # make copy as usual 1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_NameNode(self, node): 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temphandle = self.tempmap.get(node.name) 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if temphandle: 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # Replace name with temporary 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return temphandle.ref(self.get_pos(node)) 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.try_substitution(node, node.name) 1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_ExprStatNode(self, node): 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # If an expression-as-statement consists of only a replaceable 1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # NameNode, we replace the entire statement, not only the NameNode 1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(node.expr, NameNode): 1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.try_substitution(node, node.expr.name) 1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.visit_Node(node) 1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def copy_code_tree(node): 1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return TreeCopier()(node) 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)INDENT_RE = re.compile(ur"^ *") 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def strip_common_indent(lines): 1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Strips empty lines and common indentation from the list of strings given in lines" 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # TODO: Facilitate textwrap.indent instead 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lines = [x for x in lines if x.strip() != u""] 1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) minindent = min([len(INDENT_RE.match(x).group(0)) for x in lines]) 1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lines = [x[minindent:] for x in lines] 1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return lines 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class TreeFragment(object): 2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __init__(self, code, name="(tree fragment)", pxds={}, temps=[], pipeline=[], level=None, initial_pos=None): 2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(code, unicode): 2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def fmt(x): return u"\n".join(strip_common_indent(x.split(u"\n"))) 2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fmt_code = fmt(code) 2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fmt_pxds = {} 2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for key, value in pxds.iteritems(): 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fmt_pxds[key] = fmt(value) 2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mod = t = parse_from_strings(name, fmt_code, fmt_pxds, level=level, initial_pos=initial_pos) 2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if level is None: 2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) t = t.body # Make sure a StatListNode is at the top 2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(t, StatListNode): 2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) t = StatListNode(pos=mod.pos, stats=[t]) 2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for transform in pipeline: 2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if transform is None: 2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue 2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) t = transform(t) 2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.root = t 2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(code, Node): 2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if pxds != {}: raise NotImplementedError() 2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.root = code 2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise ValueError("Unrecognized code format (accepts unicode and Node)") 2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.temps = temps 2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def copy(self): 2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return copy_code_tree(self.root) 2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def substitute(self, nodes={}, temps=[], pos = None): 2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return TemplateTransform()(self.root, 2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) substitutions = nodes, 2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temps = self.temps + temps, pos = pos) 2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class SetPosTransform(VisitorTransform): 2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __init__(self, pos): 2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) super(SetPosTransform, self).__init__() 2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.pos = pos 2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_Node(self, node): 2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos = self.pos 2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 243