@@ -209,6 +209,16 @@ def visit_goto(self, op: Goto) -> None:
209209 if op .label is not self .next_block :
210210 self .emit_line ("goto %s;" % self .label (op .label ))
211211
212+ def error_value_check (self , value : Value , compare : str ) -> str :
213+ typ = value .type
214+ if isinstance (typ , RTuple ):
215+ # TODO: What about empty tuple?
216+ return self .emitter .tuple_undefined_check_cond (
217+ typ , self .reg (value ), self .c_error_value , compare
218+ )
219+ else :
220+ return f"{ self .reg (value )} { compare } { self .c_error_value (typ )} "
221+
212222 def visit_branch (self , op : Branch ) -> None :
213223 true , false = op .true , op .false
214224 negated = op .negated
@@ -225,15 +235,8 @@ def visit_branch(self, op: Branch) -> None:
225235 expr_result = self .reg (op .value )
226236 cond = f"{ neg } { expr_result } "
227237 elif op .op == Branch .IS_ERROR :
228- typ = op .value .type
229238 compare = "!=" if negated else "=="
230- if isinstance (typ , RTuple ):
231- # TODO: What about empty tuple?
232- cond = self .emitter .tuple_undefined_check_cond (
233- typ , self .reg (op .value ), self .c_error_value , compare
234- )
235- else :
236- cond = f"{ self .reg (op .value )} { compare } { self .c_error_value (typ )} "
239+ cond = self .error_value_check (op .value , compare )
237240 else :
238241 assert False , "Invalid branch"
239242
@@ -358,8 +361,8 @@ def get_attr_expr(self, obj: str, op: GetAttr | SetAttr, decl_cl: ClassIR) -> st
358361 return f"({ cast } { obj } )->{ self .emitter .attr (op .attr )} "
359362
360363 def visit_get_attr (self , op : GetAttr ) -> None :
361- if op .allow_null :
362- self .get_attr_with_allow_null (op )
364+ if op .allow_error_value :
365+ self .get_attr_with_allow_error_value (op )
363366 return
364367 dest = self .reg (op )
365368 obj = self .reg (op .obj )
@@ -429,8 +432,11 @@ def visit_get_attr(self, op: GetAttr) -> None:
429432 elif not always_defined :
430433 self .emitter .emit_line ("}" )
431434
432- def get_attr_with_allow_null (self , op : GetAttr ) -> None :
433- """Handle GetAttr with allow_null=True which allows NULL without raising AttributeError."""
435+ def get_attr_with_allow_error_value (self , op : GetAttr ) -> None :
436+ """Handle GetAttr with allow_error_value=True.
437+
438+ This allows NULL or other error value without raising AttributeError.
439+ """
434440 dest = self .reg (op )
435441 obj = self .reg (op .obj )
436442 rtype = op .class_type
@@ -443,7 +449,8 @@ def get_attr_with_allow_null(self, op: GetAttr) -> None:
443449
444450 # Only emit inc_ref if not NULL
445451 if attr_rtype .is_refcounted and not op .is_borrowed :
446- self .emitter .emit_line (f"if ({ dest } != NULL) {{" )
452+ check = self .error_value_check (op , "!=" )
453+ self .emitter .emit_line (f"if ({ check } ) {{" )
447454 self .emitter .emit_inc_ref (dest , attr_rtype )
448455 self .emitter .emit_line ("}" )
449456
0 commit comments