@@ -209,6 +209,16 @@ def visit_goto(self, op: Goto) -> None:
209
209
if op .label is not self .next_block :
210
210
self .emit_line ("goto %s;" % self .label (op .label ))
211
211
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
+
212
222
def visit_branch (self , op : Branch ) -> None :
213
223
true , false = op .true , op .false
214
224
negated = op .negated
@@ -225,15 +235,8 @@ def visit_branch(self, op: Branch) -> None:
225
235
expr_result = self .reg (op .value )
226
236
cond = f"{ neg } { expr_result } "
227
237
elif op .op == Branch .IS_ERROR :
228
- typ = op .value .type
229
238
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 )
237
240
else :
238
241
assert False , "Invalid branch"
239
242
@@ -358,8 +361,8 @@ def get_attr_expr(self, obj: str, op: GetAttr | SetAttr, decl_cl: ClassIR) -> st
358
361
return f"({ cast } { obj } )->{ self .emitter .attr (op .attr )} "
359
362
360
363
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 )
363
366
return
364
367
dest = self .reg (op )
365
368
obj = self .reg (op .obj )
@@ -429,8 +432,11 @@ def visit_get_attr(self, op: GetAttr) -> None:
429
432
elif not always_defined :
430
433
self .emitter .emit_line ("}" )
431
434
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
+ """
434
440
dest = self .reg (op )
435
441
obj = self .reg (op .obj )
436
442
rtype = op .class_type
@@ -443,7 +449,8 @@ def get_attr_with_allow_null(self, op: GetAttr) -> None:
443
449
444
450
# Only emit inc_ref if not NULL
445
451
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 } ) {{" )
447
454
self .emitter .emit_inc_ref (dest , attr_rtype )
448
455
self .emitter .emit_line ("}" )
449
456
0 commit comments