Mercurial > genshi > genshi-test
comparison markup/eval.py @ 88:9ecae580dd93
Add support for list comprehension in expressions (see #12).
author | cmlenz |
---|---|
date | Mon, 17 Jul 2006 17:33:14 +0000 |
parents | c6f07b7cd3ea |
children | 242610137d1f |
comparison
equal
deleted
inserted
replaced
87:c6f07b7cd3ea | 88:9ecae580dd93 |
---|---|
98 if lineno >= 0: | 98 if lineno >= 0: |
99 gen.emit('SET_LINENO', lineno) | 99 gen.emit('SET_LINENO', lineno) |
100 | 100 |
101 return gen.getCode() | 101 return gen.getCode() |
102 | 102 |
103 def _lookup_name(self, data, name): | 103 def _lookup_name(self, data, name, locals=None): |
104 val = data.get(name) | 104 val = data.get(name) |
105 if val is None and locals: | |
106 val = locals.get(name) | |
105 if val is None: | 107 if val is None: |
106 val = getattr(__builtin__, name, None) | 108 val = getattr(__builtin__, name, None) |
107 return val | 109 return val |
108 | 110 |
109 def _lookup_attribute(self, data, obj, key): | 111 def _lookup_attribute(self, data, obj, key): |
134 Every visitor method can be overridden to return an AST node that has been | 136 Every visitor method can be overridden to return an AST node that has been |
135 altered or replaced in some way. | 137 altered or replaced in some way. |
136 """ | 138 """ |
137 _visitors = {} | 139 _visitors = {} |
138 | 140 |
139 def visit(self, node): | 141 def visit(self, node, *args, **kwargs): |
140 v = self._visitors.get(node.__class__) | 142 v = self._visitors.get(node.__class__) |
141 if not v: | 143 if not v: |
142 v = getattr(self, 'visit%s' % node.__class__.__name__) | 144 v = getattr(self, 'visit%s' % node.__class__.__name__) |
143 self._visitors[node.__class__] = v | 145 self._visitors[node.__class__] = v |
144 return v(node) | 146 return v(node, *args, **kwargs) |
145 | 147 |
146 def visitExpression(self, node): | 148 def visitExpression(self, node, *args, **kwargs): |
147 node.node = self.visit(node.node) | 149 node.node = self.visit(node.node, *args, **kwargs) |
148 return node | 150 return node |
149 | 151 |
150 # Functions & Accessors | 152 # Functions & Accessors |
151 | 153 |
152 def visitCallFunc(self, node): | 154 def visitCallFunc(self, node, *args, **kwargs): |
153 node.node = self.visit(node.node) | 155 node.node = self.visit(node.node, *args, **kwargs) |
154 node.args = map(self.visit, node.args) | 156 node.args = map(lambda x: self.visit(x, *args, **kwargs), node.args) |
155 if node.star_args: | 157 if node.star_args: |
156 node.star_args = map(self.visit, node.star_args) | 158 node.star_args = map(lambda x: self.visit(x, *args, **kwargs), |
159 node.star_args) | |
157 if node.dstar_args: | 160 if node.dstar_args: |
158 node.dstart_args = map(self.visit, node.dstar_args) | 161 node.dstart_args = map(lambda x: self.visit(x, *args, **kwargs), |
159 return node | 162 node.dstar_args) |
160 | 163 return node |
161 def visitGetattr(self, node): | 164 |
162 node.expr = self.visit(node.expr) | 165 def visitGetattr(self, node, *args, **kwargs): |
163 return node | 166 node.expr = self.visit(node.expr, *args, **kwargs) |
164 | 167 return node |
165 def visitSubscript(self, node): | 168 |
166 node.expr = self.visit(node.expr) | 169 def visitSubscript(self, node, *args, **kwargs): |
167 node.subs = map(self.visit, node.subs) | 170 node.expr = self.visit(node.expr, *args, **kwargs) |
171 node.subs = map(lambda x: self.visit(x, *args, **kwargs), node.subs) | |
168 return node | 172 return node |
169 | 173 |
170 # Operators | 174 # Operators |
171 | 175 |
172 def _visitBoolOp(self, node): | 176 def _visitBoolOp(self, node, *args, **kwargs): |
173 node.nodes = map(self.visit, node.nodes) | 177 node.nodes = map(lambda x: self.visit(x, *args, **kwargs), node.nodes) |
174 return node | 178 return node |
175 visitAnd = visitOr = visitBitand = visitBitor = _visitBoolOp | 179 visitAnd = visitOr = visitBitand = visitBitor = _visitBoolOp |
176 | 180 |
177 def _visitBinOp(self, node): | 181 def _visitBinOp(self, node, *args, **kwargs): |
178 node.left = self.visit(node.left) | 182 node.left = self.visit(node.left, *args, **kwargs) |
179 node.right = self.visit(node.right) | 183 node.right = self.visit(node.right, *args, **kwargs) |
180 return node | 184 return node |
181 visitAdd = visitSub = _visitBinOp | 185 visitAdd = visitSub = _visitBinOp |
182 visitDiv = visitFloorDiv = visitMod = visitMul = visitPower = _visitBinOp | 186 visitDiv = visitFloorDiv = visitMod = visitMul = visitPower = _visitBinOp |
183 visitLeftShift = visitRightShift = _visitBinOp | 187 visitLeftShift = visitRightShift = _visitBinOp |
184 | 188 |
185 def visitCompare(self, node): | 189 def visitCompare(self, node, *args, **kwargs): |
186 node.expr = self.visit(node.expr) | 190 node.expr = self.visit(node.expr, *args, **kwargs) |
187 node.ops = map(lambda (op, expr): (op, self.visit(expr)), | 191 node.ops = map(lambda (op, n): (op, self.visit(n, *args, **kwargs)), |
188 node.ops) | 192 node.ops) |
189 return node | 193 return node |
190 | 194 |
191 def _visitUnaryOp(self, node): | 195 def _visitUnaryOp(self, node, *args, **kwargs): |
192 node.expr = self.visit(node.expr) | 196 node.expr = self.visit(node.expr, *args, **kwargs) |
193 return node | 197 return node |
194 visitUnaryAdd = visitUnarySub = visitNot = visitInvert = _visitUnaryOp | 198 visitUnaryAdd = visitUnarySub = visitNot = visitInvert = _visitUnaryOp |
195 | 199 |
196 # Identifiers & Literals | 200 # Identifiers, Literals and Comprehensions |
197 | 201 |
198 def _visitDefault(self, node): | 202 def _visitDefault(self, node, *args, **kwargs): |
199 return node | 203 return node |
204 visitAssName = visitAssTuple = _visitDefault | |
200 visitConst = visitKeyword = visitName = _visitDefault | 205 visitConst = visitKeyword = visitName = _visitDefault |
201 | 206 |
202 def visitDict(self, node): | 207 def visitDict(self, node, *args, **kwargs): |
203 node.items = map(lambda (k, v): (self.visit(k), self.visit(v)), | 208 node.items = map(lambda (k, v): (self.visit(k, *args, **kwargs), |
209 self.visit(v, *args, **kwargs)), | |
204 node.items) | 210 node.items) |
205 return node | 211 return node |
206 | 212 |
207 def visitTuple(self, node): | 213 def visitTuple(self, node, *args, **kwargs): |
208 node.nodes = map(lambda n: self.visit(n), node.nodes) | 214 node.nodes = map(lambda n: self.visit(n, *args, **kwargs), node.nodes) |
209 return node | 215 return node |
210 | 216 |
211 def visitList(self, node): | 217 def visitList(self, node, *args, **kwargs): |
212 node.nodes = map(lambda n: self.visit(n), node.nodes) | 218 node.nodes = map(lambda n: self.visit(n, *args, **kwargs), node.nodes) |
219 return node | |
220 | |
221 def visitListComp(self, node, *args, **kwargs): | |
222 node.expr = self.visit(node.expr, *args, **kwargs) | |
223 node.quals = map(lambda x: self.visit(x, *args, **kwargs), node.quals) | |
224 return node | |
225 | |
226 def visitListCompFor(self, node, *args, **kwargs): | |
227 node.assign = self.visit(node.assign, *args, **kwargs) | |
228 node.list = self.visit(node.list, *args, **kwargs) | |
229 node.ifs = map(lambda x: self.visit(x, *args, **kwargs), node.ifs) | |
230 return node | |
231 | |
232 def visitListCompIf(self, node, *args, **kwargs): | |
233 node.test = self.visit(node.test, *args, **kwargs) | |
213 return node | 234 return node |
214 | 235 |
215 | 236 |
216 class ExpressionASTTransformer(ASTTransformer): | 237 class ExpressionASTTransformer(ASTTransformer): |
217 """Concrete AST transformer that implementations the AST transformations | 238 """Concrete AST transformer that implementations the AST transformations |
218 needed for template expressions. | 239 needed for template expressions. |
219 """ | 240 """ |
220 | 241 |
221 def visitGetattr(self, node): | 242 def visitGetattr(self, node, *args, **kwargs): |
222 return ast.CallFunc( | 243 return ast.CallFunc( |
223 ast.Getattr(ast.Name('self'), '_lookup_attribute'), | 244 ast.Getattr(ast.Name('self'), '_lookup_attribute'), |
224 [ast.Name('data'), self.visit(node.expr), ast.Const(node.attrname)] | 245 [ast.Name('data'), self.visit(node.expr, *args, **kwargs), |
246 ast.Const(node.attrname)] | |
225 ) | 247 ) |
226 | 248 |
227 def visitName(self, node): | 249 def visitListComp(self, node, *args, **kwargs): |
250 old_lookup_locals = kwargs.get('lookup_locals', False) | |
251 kwargs['lookup_locals'] = True | |
252 node.expr = self.visit(node.expr, *args, **kwargs) | |
253 node.quals = map(lambda x: self.visit(x, *args, **kwargs), node.quals) | |
254 kwargs['lookup_locals'] = old_lookup_locals | |
255 return node | |
256 | |
257 def visitName(self, node, *args, **kwargs): | |
258 func_args = [ast.Name('data'), ast.Const(node.name)] | |
259 if kwargs.get('lookup_locals'): | |
260 func_args.append(ast.CallFunc(ast.Name('locals'), [])) | |
228 return ast.CallFunc( | 261 return ast.CallFunc( |
229 ast.Getattr(ast.Name('self'), '_lookup_name'), | 262 ast.Getattr(ast.Name('self'), '_lookup_name'), func_args |
230 [ast.Name('data'), ast.Const(node.name)] | |
231 ) | 263 ) |
232 return node | 264 return node |
233 | 265 |
234 def visitSubscript(self, node): | 266 def visitSubscript(self, node, *args, **kwargs): |
235 return ast.CallFunc( | 267 return ast.CallFunc( |
236 ast.Getattr(ast.Name('self'), '_lookup_item'), | 268 ast.Getattr(ast.Name('self'), '_lookup_item'), |
237 [ast.Name('data'), self.visit(node.expr), | 269 [ast.Name('data'), self.visit(node.expr, *args, **kwargs), |
238 ast.Tuple(map(self.visit, node.subs))] | 270 ast.Tuple(map(self.visit, node.subs, *args, **kwargs))] |
239 ) | 271 ) |