@@ -40,20 +40,16 @@ def _expected_type(storage_kind: StorageKind) -> ValueType:
4040
4141
4242def _resolve (
43- variables : list [VariableDefinition ], name : str
44- ) -> tuple [int , VariableDefinition ]:
45- matches = [
46- (index , variable )
47- for index , variable in enumerate (variables )
48- if variable .name .casefold () == name .casefold ()
49- ]
50- if len (matches ) != 1 :
43+ variables : dict [str , VariableDefinition ], name : str
44+ ) -> tuple [str , VariableDefinition ]:
45+ key = name .casefold ()
46+ if key not in variables :
5147 raise frontend_error (
5248 "unknown_variable" ,
5349 f"Variable { name !r} is not present in the current schema." ,
5450 variable = name ,
5551 )
56- return matches [ 0 ]
52+ return key , variables [ key ]
5753
5854
5955def _validate_match (match : RecodeMatch , source : VariableDefinition ) -> None :
@@ -133,7 +129,7 @@ def _validate_recode_string_width(
133129
134130
135131def _bind_recode (
136- operation : RecodeOperation , variables : list [ VariableDefinition ]
132+ operation : RecodeOperation , variables : dict [ str , VariableDefinition ]
137133) -> None :
138134 _ , source = _resolve (variables , operation .source )
139135 if operation .target_mode == "create" :
@@ -143,10 +139,8 @@ def _bind_recode(
143139 f"Target name { operation .target !r} is reserved." ,
144140 target = operation .target ,
145141 )
146- if any (
147- variable .name .casefold () == operation .target .casefold ()
148- for variable in variables
149- ):
142+ target_key = operation .target .casefold ()
143+ if target_key in variables :
150144 raise frontend_error (
151145 "target_already_exists" ,
152146 f"Target name { operation .target !r} already exists." ,
@@ -183,16 +177,14 @@ def _bind_recode(
183177 variable = source .name ,
184178 )
185179 if operation .target_mode == "create" :
186- variables .append (
187- VariableDefinition (
188- operation .target ,
189- "numeric" if output_type == "binary64" else "string" ,
190- )
180+ variables [target_key ] = VariableDefinition (
181+ operation .target ,
182+ "numeric" if output_type == "binary64" else "string" ,
191183 )
192184
193185
194186def _operand_type (
195- operand : Operand , variables : list [ VariableDefinition ]
187+ operand : Operand , variables : dict [ str , VariableDefinition ]
196188) -> ValueType :
197189 if operand .kind == "literal" :
198190 assert operand .value is not None
@@ -204,7 +196,7 @@ def _operand_type(
204196
205197def _validate_predicate (
206198 predicate : ComparisonExpression | BooleanExpression ,
207- variables : list [ VariableDefinition ],
199+ variables : dict [ str , VariableDefinition ],
208200) -> None :
209201 if isinstance (predicate , BooleanExpression ):
210202 for item in predicate .operands :
@@ -236,7 +228,7 @@ def _validate_predicate(
236228
237229
238230def _bind_assign (
239- operation : AssignOperation , variables : list [ VariableDefinition ]
231+ operation : AssignOperation , variables : dict [ str , VariableDefinition ]
240232) -> None :
241233 output_type = _operand_type (operation .value , variables )
242234 if output_type == "string" :
@@ -253,19 +245,17 @@ def _bind_assign(
253245 f"Target name { operation .target !r} is reserved." ,
254246 target = operation .target ,
255247 )
256- if any (
257- variable .name .casefold () == operation .target .casefold ()
258- for variable in variables
259- ):
248+ target_key = operation .target .casefold ()
249+ if target_key in variables :
260250 raise frontend_error (
261251 "target_already_exists" ,
262252 f"Target name { operation .target !r} already exists." ,
263253 target = operation .target ,
264254 )
265- variables . append ( VariableDefinition (
255+ variables [ target_key ] = VariableDefinition (
266256 operation .target ,
267257 "numeric" if output_type == "binary64" else "string" ,
268- ))
258+ )
269259 return
270260 _ , target = _resolve (variables , operation .target )
271261 if target .storage_kind == "string" :
@@ -284,7 +274,7 @@ def _bind_assign(
284274
285275def _bind_conditional_assign (
286276 operation : ConditionalAssignOperation ,
287- variables : list [ VariableDefinition ],
277+ variables : dict [ str , VariableDefinition ],
288278) -> None :
289279 _validate_predicate (operation .condition , variables )
290280 _ , target = _resolve (variables , operation .target )
@@ -328,17 +318,17 @@ def bind_transformation_plan(
328318 raise TypeError ("plan must be a TransformationPlan." )
329319 if not isinstance (schema , VariableSchema ):
330320 raise TypeError ("schema must be a VariableSchema." )
331- variables = list (schema .variables )
321+ variables = {variable .name .casefold (): variable for variable in schema .variables }
322+ last_create = max (
323+ (index for index , operation in enumerate (plan .operations ) if _creates_variable (operation )),
324+ default = - 1 ,
325+ )
332326 for operation_index , operation in enumerate (plan .operations ):
333- later_create = any (
334- _creates_variable (later_operation )
335- for later_operation in plan .operations [operation_index + 1 :]
336- )
337327 if isinstance (operation , CreateVariableOperation ):
338328 _bind_create (operation , variables )
339329 continue
340330 if isinstance (operation , DeleteVariableOperation ):
341- _bind_delete (operation , variables , allow_empty = later_create )
331+ _bind_delete (operation , variables , allow_empty = operation_index < last_create )
342332 continue
343333 if isinstance (operation , RecodeOperation ):
344334 _bind_recode (operation , variables )
@@ -397,27 +387,28 @@ def bind_transformation_plan(
397387 if isinstance (operation , ExecuteOperation ):
398388 continue
399389 raise AssertionError (f"Unknown plan operation: { type (operation )!r} " )
400- return BoundTransformation (plan , VariableSchema (tuple (variables )))
390+ return BoundTransformation (plan , VariableSchema (tuple (variables . values () )))
401391def _bind_create (
402392 operation : CreateVariableOperation ,
403- variables : list [ VariableDefinition ],
393+ variables : dict [ str , VariableDefinition ],
404394) -> None :
405- if any (variable .name .casefold () == operation .variable .casefold () for variable in variables ):
395+ key = operation .variable .casefold ()
396+ if key in variables :
406397 raise frontend_error (
407398 "target_already_exists" ,
408399 f"Target name { operation .variable !r} already exists." ,
409400 target = operation .variable ,
410401 )
411- variables . append ( VariableDefinition (
402+ variables [ key ] = VariableDefinition (
412403 operation .variable ,
413404 operation .storage_kind ,
414405 declared_string_width = operation .declared_string_width ,
415- ))
406+ )
416407
417408
418409def _bind_delete (
419410 operation : DeleteVariableOperation ,
420- variables : list [ VariableDefinition ],
411+ variables : dict [ str , VariableDefinition ],
421412 * ,
422413 allow_empty : bool ,
423414) -> None :
0 commit comments