ast.py (6135B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\ast.py 2 from _ast import * 3 from _ast import __version__ 4 5 def parse(expr, filename = '<unknown>', mode = 'exec'): 6 return compile(expr, filename, mode, PyCF_ONLY_AST) 7 8 9 def literal_eval(node_or_string): 10 _safe_names = {'None': None, 11 'True': True, 12 'False': False} 13 if isinstance(node_or_string, basestring): 14 node_or_string = parse(node_or_string, mode='eval') 15 if isinstance(node_or_string, Expression): 16 node_or_string = node_or_string.body 17 18 def _convert(node): 19 if isinstance(node, Str): 20 return node.s 21 if isinstance(node, Num): 22 return node.n 23 if isinstance(node, Tuple): 24 return tuple(map(_convert, node.elts)) 25 if isinstance(node, List): 26 return list(map(_convert, node.elts)) 27 if isinstance(node, Dict): 28 return dict(((_convert(k), _convert(v)) for k, v in zip(node.keys, node.values))) 29 if isinstance(node, Name): 30 if node.id in _safe_names: 31 return _safe_names[node.id] 32 elif isinstance(node, BinOp) and isinstance(node.op, (Add, Sub)) and isinstance(node.right, Num) and isinstance(node.right.n, complex) and isinstance(node.left, Num): 33 if isinstance(node.left.n, (int, long, float)): 34 left = node.left.n 35 right = node.right.n 36 if isinstance(node.op, Add): 37 return left + right 38 return left - right 39 raise ValueError('malformed string') 40 41 return _convert(node_or_string) 42 43 44 def dump(node, annotate_fields = True, include_attributes = False): 45 46 def _format(node): 47 if isinstance(node, AST): 48 fields = [ (a, _format(b)) for a, b in iter_fields(node) ] 49 rv = '%s(%s' % (node.__class__.__name__, ', '.join(('%s=%s' % field for field in fields) if annotate_fields else (b for a, b in fields))) 50 if include_attributes and node._attributes: 51 rv += fields and ', ' or ' ' 52 rv += ', '.join(('%s=%s' % (a, _format(getattr(node, a))) for a in node._attributes)) 53 return rv + ')' 54 if isinstance(node, list): 55 return '[%s]' % ', '.join((_format(x) for x in node)) 56 return repr(node) 57 58 if not isinstance(node, AST): 59 raise TypeError('expected AST, got %r' % node.__class__.__name__) 60 return _format(node) 61 62 63 def copy_location(new_node, old_node): 64 for attr in ('lineno', 'col_offset'): 65 if attr in old_node._attributes and attr in new_node._attributes and hasattr(old_node, attr): 66 setattr(new_node, attr, getattr(old_node, attr)) 67 68 return new_node 69 70 71 def fix_missing_locations(node): 72 73 def _fix(node, lineno, col_offset): 74 if 'lineno' in node._attributes: 75 if not hasattr(node, 'lineno'): 76 node.lineno = lineno 77 else: 78 lineno = node.lineno 79 if 'col_offset' in node._attributes: 80 if not hasattr(node, 'col_offset'): 81 node.col_offset = col_offset 82 else: 83 col_offset = node.col_offset 84 for child in iter_child_nodes(node): 85 _fix(child, lineno, col_offset) 86 87 _fix(node, 1, 0) 88 return node 89 90 91 def increment_lineno(node, n = 1): 92 if 'lineno' in node._attributes: 93 node.lineno = getattr(node, 'lineno', 0) + n 94 for child in walk(node): 95 if 'lineno' in child._attributes: 96 child.lineno = getattr(child, 'lineno', 0) + n 97 98 return node 99 100 101 def iter_fields(node): 102 for field in node._fields: 103 try: 104 yield (field, getattr(node, field)) 105 except AttributeError: 106 pass 107 108 109 def iter_child_nodes(node): 110 for name, field in iter_fields(node): 111 if isinstance(field, AST): 112 yield field 113 elif isinstance(field, list): 114 for item in field: 115 if isinstance(item, AST): 116 yield item 117 118 119 def get_docstring(node, clean = True): 120 if not isinstance(node, (FunctionDef, ClassDef, Module)): 121 raise TypeError("%r can't have docstrings" % node.__class__.__name__) 122 if node.body and isinstance(node.body[0], Expr) and isinstance(node.body[0].value, Str): 123 if clean: 124 import inspect 125 return inspect.cleandoc(node.body[0].value.s) 126 return node.body[0].value.s 127 128 129 def walk(node): 130 from collections import deque 131 todo = deque([node]) 132 while todo: 133 node = todo.popleft() 134 todo.extend(iter_child_nodes(node)) 135 yield node 136 137 138 class NodeVisitor(object): 139 140 def visit(self, node): 141 method = 'visit_' + node.__class__.__name__ 142 visitor = getattr(self, method, self.generic_visit) 143 return visitor(node) 144 145 def generic_visit(self, node): 146 for field, value in iter_fields(node): 147 if isinstance(value, list): 148 for item in value: 149 if isinstance(item, AST): 150 self.visit(item) 151 152 elif isinstance(value, AST): 153 self.visit(value) 154 155 156 class NodeTransformer(NodeVisitor): 157 158 def generic_visit(self, node): 159 for field, old_value in iter_fields(node): 160 old_value = getattr(node, field, None) 161 if isinstance(old_value, list): 162 new_values = [] 163 for value in old_value: 164 if isinstance(value, AST): 165 value = self.visit(value) 166 if value is None: 167 continue 168 elif not isinstance(value, AST): 169 new_values.extend(value) 170 continue 171 new_values.append(value) 172 173 old_value[:] = new_values 174 elif isinstance(old_value, AST): 175 new_node = self.visit(old_value) 176 if new_node is None: 177 delattr(node, field) 178 else: 179 setattr(node, field, new_node) 180 181 return node