6666from mypyc .ir .ops import (
6767 NAMESPACE_MODULE ,
6868 NAMESPACE_TYPE_VAR ,
69+ NO_TRACEBACK_LINE_NO ,
6970 Assign ,
7071 BasicBlock ,
7172 Branch ,
@@ -288,7 +289,7 @@ def accept(self, node: Statement | Expression, *, can_borrow: bool = False) -> V
288289 res = Register (self .node_type (node ))
289290 self .can_borrow = old_can_borrow
290291 if not can_borrow :
291- self .flush_keep_alives ()
292+ self .flush_keep_alives (node . line )
292293 return res
293294 else :
294295 try :
@@ -297,8 +298,8 @@ def accept(self, node: Statement | Expression, *, can_borrow: bool = False) -> V
297298 pass
298299 return None
299300
300- def flush_keep_alives (self ) -> None :
301- self .builder .flush_keep_alives ()
301+ def flush_keep_alives (self , line : int ) -> None :
302+ self .builder .flush_keep_alives (line )
302303
303304 # Pass through methods for the most common low-level builder ops, for convenience.
304305
@@ -320,23 +321,23 @@ def self(self) -> Register:
320321 def py_get_attr (self , obj : Value , attr : str , line : int ) -> Value :
321322 return self .builder .py_get_attr (obj , attr , line )
322323
323- def load_str (self , value : str ) -> Value :
324- return self .builder .load_str (value )
324+ def load_str (self , value : str , line : int = - 1 ) -> Value :
325+ return self .builder .load_str (value , line )
325326
326- def load_bytes_from_str_literal (self , value : str ) -> Value :
327+ def load_bytes_from_str_literal (self , value : str , line : int = - 1 ) -> Value :
327328 """Load bytes object from a string literal.
328329
329330 The literal characters of BytesExpr (the characters inside b'')
330331 are stored in BytesExpr.value, whose type is 'str' not 'bytes'.
331332 Thus we perform a special conversion here.
332333 """
333- return self .builder .load_bytes (bytes_from_str (value ))
334+ return self .builder .load_bytes (bytes_from_str (value ), line )
334335
335- def load_int (self , value : int ) -> Value :
336- return self .builder .load_int (value )
336+ def load_int (self , value : int , line : int = - 1 ) -> Value :
337+ return self .builder .load_int (value , line )
337338
338- def load_float (self , value : float ) -> Value :
339- return self .builder .load_float (value )
339+ def load_float (self , value : float , line : int = - 1 ) -> Value :
340+ return self .builder .load_float (value , line )
340341
341342 def unary_op (self , lreg : Value , expr_op : str , line : int ) -> Value :
342343 return self .builder .unary_op (lreg , expr_op , line )
@@ -347,17 +348,17 @@ def binary_op(self, lreg: Value, rreg: Value, expr_op: str, line: int) -> Value:
347348 def coerce (self , src : Value , target_type : RType , line : int , force : bool = False ) -> Value :
348349 return self .builder .coerce (src , target_type , line , force , can_borrow = self .can_borrow )
349350
350- def none_object (self ) -> Value :
351- return self .builder .none_object ()
351+ def none_object (self , line : int = - 1 ) -> Value :
352+ return self .builder .none_object (line )
352353
353- def none (self ) -> Value :
354- return self .builder .none ()
354+ def none (self , line : int = - 1 ) -> Value :
355+ return self .builder .none (line )
355356
356- def true (self ) -> Value :
357- return self .builder .true ()
357+ def true (self , line : int = - 1 ) -> Value :
358+ return self .builder .true (line )
358359
359- def false (self ) -> Value :
360- return self .builder .false ()
360+ def false (self , line : int = - 1 ) -> Value :
361+ return self .builder .false (line )
361362
362363 def new_list_op (self , values : list [Value ], line : int ) -> Value :
363364 return self .builder .new_list_op (values , line )
@@ -438,7 +439,7 @@ def add_to_non_ext_dict(
438439 self , non_ext : NonExtClassInfo , key : str , val : Value , line : int
439440 ) -> None :
440441 # Add an attribute entry into the class dict of a non-extension class.
441- key_unicode = self .load_str (key )
442+ key_unicode = self .load_str (key , line )
442443 self .primitive_op (dict_set_item_op , [non_ext .dict , key_unicode , val ], line )
443444
444445 # It's important that accessing class dictionary items from multiple threads
@@ -452,7 +453,7 @@ def gen_import(self, id: str, line: int) -> None:
452453 self .check_if_module_loaded (id , line , needs_import , out )
453454
454455 self .activate_block (needs_import )
455- value = self .call_c (import_op , [self .load_str (id )], line )
456+ value = self .call_c (import_op , [self .load_str (id , line )], line )
456457 self .add (InitStatic (value , id , namespace = NAMESPACE_MODULE ))
457458 self .goto_and_activate (out )
458459
@@ -467,14 +468,14 @@ def check_if_module_loaded(
467468 needs_import: the BasicBlock that is run if the module has not been loaded yet
468469 out: the BasicBlock that is run if the module has already been loaded"""
469470 first_load = self .load_module (id )
470- comparison = self .translate_is_op (first_load , self .none_object (), "is not" , line )
471+ comparison = self .translate_is_op (first_load , self .none_object (line ), "is not" , line )
471472 self .add_bool_branch (comparison , out , needs_import )
472473
473474 def get_module (self , module : str , line : int ) -> Value :
474475 # Python 3.7 has a nice 'PyImport_GetModule' function that we can't use :(
475476 mod_dict = self .call_c (get_module_dict_op , [], line )
476477 # Get module object from modules dict.
477- return self .primitive_op (dict_get_item_op , [mod_dict , self .load_str (module )], line )
478+ return self .primitive_op (dict_get_item_op , [mod_dict , self .load_str (module , line )], line )
478479
479480 def get_module_attr (self , module : str , attr : str , line : int ) -> Value :
480481 """Look up an attribute of a module without storing it in the local namespace.
@@ -491,9 +492,9 @@ def get_module_attr(self, module: str, attr: str, line: int) -> Value:
491492 def assign_if_null (self , target : Register , get_val : Callable [[], Value ], line : int ) -> None :
492493 """If target is NULL, assign value produced by get_val to it."""
493494 error_block , body_block = BasicBlock (), BasicBlock ()
494- self .add (Branch (target , error_block , body_block , Branch .IS_ERROR ))
495+ self .add (Branch (target , error_block , body_block , Branch .IS_ERROR , line ))
495496 self .activate_block (error_block )
496- self .add (Assign (target , self .coerce (get_val (), target .type , line )))
497+ self .add (Assign (target , self .coerce (get_val (), target .type , line ), line ))
497498 self .goto (body_block )
498499 self .activate_block (body_block )
499500
@@ -508,7 +509,7 @@ def assign_if_bitmap_unset(
508509 IntOp .AND ,
509510 line ,
510511 )
511- b = self .add (ComparisonOp (o , Integer (0 , bitmap_rprimitive ), ComparisonOp .EQ ))
512+ b = self .add (ComparisonOp (o , Integer (0 , bitmap_rprimitive ), ComparisonOp .EQ , line ))
512513 self .add (Branch (b , error_block , body_block , Branch .BOOL ))
513514 self .activate_block (error_block )
514515 self .add (Assign (target , self .coerce (get_val (), target .type , line )))
@@ -524,8 +525,9 @@ def maybe_add_implicit_return(self) -> None:
524525 def add_implicit_return (self ) -> None :
525526 block = self .builder .blocks [- 1 ]
526527 if not block .terminated :
527- retval = self .coerce (self .builder .none (), self .ret_types [- 1 ], - 1 )
528- self .nonlocal_control [- 1 ].gen_return (self , retval , self .fn_info .fitem .line )
528+ line = self .fn_info .fitem .line
529+ retval = self .coerce (self .builder .none (), self .ret_types [- 1 ], line )
530+ self .nonlocal_control [- 1 ].gen_return (self , retval , line )
529531
530532 def add_implicit_unreachable (self ) -> None :
531533 block = self .builder .blocks [- 1 ]
@@ -605,13 +607,15 @@ def load_type_var(self, name: str, line: int) -> Value:
605607 )
606608 )
607609
608- def load_literal_value (self , val : int | str | bytes | float | complex | bool ) -> Value :
610+ def load_literal_value (
611+ self , val : int | str | bytes | float | complex | bool , line : int = - 1
612+ ) -> Value :
609613 """Load value of a final name, class-level attribute, or constant folded expression."""
610614 if isinstance (val , bool ):
611615 if val :
612- return self .true ()
616+ return self .true (line )
613617 else :
614- return self .false ()
618+ return self .false (line )
615619 elif isinstance (val , int ):
616620 return self .builder .load_int (val )
617621 elif isinstance (val , float ):
@@ -669,7 +673,7 @@ def get_assignment_target(
669673 return self .lookup (symbol )
670674 elif lvalue .kind == GDEF :
671675 globals_dict = self .load_globals_dict ()
672- name = self .load_str (lvalue .name )
676+ name = self .load_str (lvalue .name , line )
673677 return AssignmentTargetIndex (globals_dict , name )
674678 else :
675679 assert False , lvalue .kind
@@ -745,23 +749,23 @@ def read_nullable_attr(self, obj: Value, attr: str, line: int = -1) -> Value:
745749
746750 def assign (self , target : Register | AssignmentTarget , rvalue_reg : Value , line : int ) -> None :
747751 if isinstance (target , Register ):
748- self .add (Assign (target , self .coerce_rvalue (rvalue_reg , target .type , line )))
752+ self .add (Assign (target , self .coerce_rvalue (rvalue_reg , target .type , line ), line ))
749753 elif isinstance (target , AssignmentTargetRegister ):
750754 rvalue_reg = self .coerce_rvalue (rvalue_reg , target .type , line )
751- self .add (Assign (target .register , rvalue_reg ))
755+ self .add (Assign (target .register , rvalue_reg , line ))
752756 elif isinstance (target , AssignmentTargetAttr ):
753757 if isinstance (target .obj_type , RInstance ):
754758 setattr = target .obj_type .class_ir .get_method ("__setattr__" )
755759 if setattr :
756- key = self .load_str (target .attr )
760+ key = self .load_str (target .attr , line )
757761 boxed_reg = self .builder .box (rvalue_reg )
758762 call = MethodCall (target .obj , setattr .name , [key , boxed_reg ], line )
759763 self .add (call )
760764 else :
761765 rvalue_reg = self .coerce_rvalue (rvalue_reg , target .type , line )
762766 self .add (SetAttr (target .obj , target .attr , rvalue_reg , line ))
763767 else :
764- key = self .load_str (target .attr )
768+ key = self .load_str (target .attr , line )
765769 boxed_reg = self .builder .box (rvalue_reg )
766770 self .primitive_op (py_setattr_op , [target .obj , key , boxed_reg ], line )
767771 elif isinstance (target , AssignmentTargetIndex ):
@@ -931,8 +935,8 @@ def make_spill_target(self, type: RType) -> AssignmentTarget:
931935 def spill (self , value : Value ) -> AssignmentTarget :
932936 """Moves a given Value instance into the generator class' environment class."""
933937 target = self .make_spill_target (value .type )
934- # Shouldn't be able to fail, so -1 for line
935- self .assign (target , value , - 1 )
938+ # Shouldn't be able to fail
939+ self .assign (target , value , NO_TRACEBACK_LINE_NO )
936940 return target
937941
938942 def maybe_spill (self , value : Value ) -> Value | AssignmentTarget :
@@ -963,7 +967,7 @@ def maybe_spill_assignable(self, value: Value) -> Register | AssignmentTarget:
963967
964968 # Allocate a temporary register for the assignable value.
965969 reg = Register (value .type )
966- self .assign (reg , value , - 1 )
970+ self .assign (reg , value , NO_TRACEBACK_LINE_NO )
967971 return reg
968972
969973 def extract_int (self , e : Expression ) -> int | None :
@@ -1132,7 +1136,7 @@ def emit_load_final(
11321136 line: line number where loading occurs
11331137 """
11341138 if final_var .final_value is not None : # this is safe even for non-native names
1135- return self .load_literal_value (final_var .final_value )
1139+ return self .load_literal_value (final_var .final_value , line )
11361140 elif native and module_prefix (self .graph , fullname ):
11371141 return self .load_final_static (fullname , self .mapper .type_to_rtype (typ ), line , name )
11381142 else :
@@ -1409,7 +1413,7 @@ def load_global(self, expr: NameExpr) -> Value:
14091413
14101414 def load_global_str (self , name : str , line : int ) -> Value :
14111415 _globals = self .load_globals_dict ()
1412- reg = self .load_str (name )
1416+ reg = self .load_str (name , line )
14131417 return self .primitive_op (dict_get_item_op , [_globals , reg ], line )
14141418
14151419 def load_globals_dict (self ) -> Value :
@@ -1473,7 +1477,7 @@ def add_coroutine_setup_call(self, class_name: str, obj: Value) -> Value:
14731477 FuncSignature ([RuntimeArg ("type" , object_rprimitive )], bool_rprimitive ),
14741478 ),
14751479 [obj ],
1476- - 1 ,
1480+ obj . line ,
14771481 )
14781482 )
14791483
@@ -1571,13 +1575,13 @@ def create_type_params(
15711575 # To match runtime semantics, pass infer_variance=True
15721576 tv = builder .py_call (
15731577 tvt ,
1574- [builder .load_str (type_param .name ), builder .true ()],
1578+ [builder .load_str (type_param .name , line ), builder .true (line )],
15751579 line ,
15761580 arg_kinds = [ARG_POS , ARG_NAMED ],
15771581 arg_names = [None , "infer_variance" ],
15781582 )
15791583 else :
1580- tv = builder .py_call (tvt , [builder .load_str (type_param .name )], line )
1584+ tv = builder .py_call (tvt , [builder .load_str (type_param .name , line )], line )
15811585 builder .init_type_var (tv , type_param .name , line )
15821586 tvs .append (tv )
15831587 return tvs
0 commit comments