@@ -3092,33 +3092,55 @@ static Value builtin_cdiv(Interpreter* interp, Value* args, int argc, Expr** arg
30923092}
30933093
30943094static Value builtin_mod (Interpreter * interp , Value * args , int argc , Expr * * arg_nodes , Env * env , int line , int col ) {
3095- (void )arg_nodes ; ( void ) env ;
3095+ (void )env ;
30963096 EXPECT_NUM (args [0 ], "MOD" , interp , line , col );
30973097 EXPECT_NUM (args [1 ], "MOD" , interp , line , col );
3098-
3098+
30993099 if (args [0 ].type != args [1 ].type ) {
31003100 RUNTIME_ERROR (interp , "MOD cannot mix INT and FLT" , line , col );
31013101 }
3102-
3102+
31033103 int out_base = result_base_from_values (args [0 ], args [1 ]);
31043104 if (args [0 ].type == VAL_INT ) {
31053105 if (args [1 ].as .i == 0 ) {
31063106 RUNTIME_ERROR (interp , "Division by zero" , line , col );
31073107 }
31083108 int64_t b = args [1 ].as .i < 0 ? - args [1 ].as .i : args [1 ].as .i ;
31093109 Value result = value_int_base (args [0 ].as .i % b , out_base );
3110- if (!writeback_ptr_range (interp , arg_nodes , env , 0 , 2 , result , "MOD" , line , col )) {
3110+
3111+ bool ok = true;
3112+ if (arg_nodes && arg_nodes [0 ] && arg_nodes [0 ]-> type == EXPR_PTR ) {
3113+ if (!writeback_ptr_node (interp , arg_nodes [0 ], env , result , "MOD" , line , col )) ok = false;
3114+ }
3115+ /* Only write back into the divisor (arg_nodes[1]) when the dividend
3116+ (arg_nodes[0]) is also a pointer literal — matching the spec and
3117+ tests that expect MOD(a2, @b2) to NOT overwrite b2. */
3118+ if (ok && arg_nodes && arg_nodes [1 ] && arg_nodes [1 ]-> type == EXPR_PTR && arg_nodes [0 ] && arg_nodes [0 ]-> type == EXPR_PTR ) {
3119+ if (!writeback_ptr_node (interp , arg_nodes [1 ], env , result , "MOD" , line , col )) ok = false;
3120+ }
3121+
3122+ if (!ok ) {
31113123 value_free (result );
31123124 return value_null ();
31133125 }
31143126 return result ;
31153127 }
3128+
31163129 if (args [1 ].as .f == 0.0 ) {
31173130 RUNTIME_ERROR (interp , "Division by zero" , line , col );
31183131 }
31193132 double b = args [1 ].as .f < 0 ? - args [1 ].as .f : args [1 ].as .f ;
31203133 Value result = value_flt_base (fmod (args [0 ].as .f , b ), out_base );
3121- if (!writeback_ptr_range (interp , arg_nodes , env , 0 , 2 , result , "MOD" , line , col )) {
3134+
3135+ bool ok = true;
3136+ if (arg_nodes && arg_nodes [0 ] && arg_nodes [0 ]-> type == EXPR_PTR ) {
3137+ if (!writeback_ptr_node (interp , arg_nodes [0 ], env , result , "MOD" , line , col )) ok = false;
3138+ }
3139+ if (ok && arg_nodes && arg_nodes [1 ] && arg_nodes [1 ]-> type == EXPR_PTR && arg_nodes [0 ] && arg_nodes [0 ]-> type == EXPR_PTR ) {
3140+ if (!writeback_ptr_node (interp , arg_nodes [1 ], env , result , "MOD" , line , col )) ok = false;
3141+ }
3142+
3143+ if (!ok ) {
31223144 value_free (result );
31233145 return value_null ();
31243146 }
0 commit comments