@@ -145,14 +145,19 @@ def isthisname(tree):
145145 return type (tree ) is Name and tree .id == name
146146 @Walker
147147 def splice (tree , * , stop , ** kw ):
148- # discard Expr wrapper at use site for a block substitution
148+ def subst ():
149+ # Copy just to be on the safe side. Different instances may be
150+ # edited differently by other macros expanded later.
151+ return deepcopy (value )
152+ # discard Expr wrapper (identifying a statement position) at use site
153+ # when performing a block substitution
149154 if mode == "block" and type (tree ) is Expr and isthisname (tree .value ):
150155 stop ()
151- tree = splice . recurse ( tree . value )
156+ tree = subst ( )
152157 elif isthisname (tree ):
153- # Copy just to be on the safe side. Different instances may be
154- # edited differently by other macros expanded later.
155- tree = deepcopy ( value )
158+ if mode == "block" :
159+ assert False , "cannot substitute a block into expression position"
160+ tree = subst ( )
156161 return tree
157162 return splice .recurse (tree )
158163
@@ -165,23 +170,29 @@ def _substitute_templates(templates, tree):
165170 for name , formalparams , value , mode in templates :
166171 def isthisfunc (tree ):
167172 return type (tree ) is Call and type (tree .func ) is Name and tree .func .id == name
173+ def subst (tree ):
174+ theargs = tree .args
175+ if len (theargs ) != len (formalparams ):
176+ assert False , "let_syntax template '{}' expected {} arguments, got {}" .format (name ,
177+ len (formalparams ),
178+ len (theargs ))
179+ # make a fresh deep copy of the RHS to avoid destroying the template.
180+ tree = deepcopy (value ) # expand the f itself in f(x, ...)
181+ for k , v in zip (formalparams , theargs ): # expand the x, ... in the expanded form of f
182+ # can't put statements in a Call, so always treat args as expressions.
183+ tree = _substitute_barename (k , v , tree , "expr" )
184+ return tree
168185 @Walker
169186 def splice (tree , * , stop , ** kw ):
170- # discard Expr wrapper at use site for a block substitution
187+ # discard Expr wrapper (identifying a statement position) at use site
188+ # when performing a block substitution
171189 if mode == "block" and type (tree ) is Expr and isthisfunc (tree .value ):
172190 stop ()
173- tree = splice . recurse (tree .value )
191+ tree = subst (tree .value )
174192 elif isthisfunc (tree ):
175- theargs = tree .args
176- if len (theargs ) != len (formalparams ):
177- assert False , "let_syntax template '{}' expected {} arguments, got {}" .format (name ,
178- len (formalparams ),
179- len (theargs ))
180- # make a fresh deep copy of the RHS to avoid destroying the template.
181- tree = deepcopy (value ) # expand the f itself in f(x, ...)
182- for k , v in zip (formalparams , theargs ): # expand the x, ... in the expanded form of f
183- # can't put statements in a Call, so always treat args as expressions.
184- tree = _substitute_barename (k , v , tree , "expr" )
193+ if mode == "block" :
194+ assert False , "cannot substitute a block into expression position"
195+ tree = subst (tree )
185196 return tree
186197 tree = splice .recurse (tree )
187198 return tree
0 commit comments