comparison markup/eval.py @ 88:628ba9ed39ef trunk

Add support for list comprehension in expressions (see #12).
author cmlenz
date Mon, 17 Jul 2006 17:33:14 +0000
parents 1b874f032bde
children c835e81c50af
comparison
equal deleted inserted replaced
87:1b874f032bde 88:628ba9ed39ef
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 )
Copyright (C) 2012-2017 Edgewall Software