@@ -122,10 +122,12 @@ static void concatenate(VM* pvm) {
122122 memcpy (chars + a -> length , b -> chars , b -> length );
123123 chars [length ] = '\0' ;
124124
125+ // a and b are still on stack, so they are rooted
125126 ObjString * result = takeString (chars , length );
126- pop (pvm );
127- pop (pvm );
128- push (pvm , OBJ_VAL (result ));
127+
128+ // Now we can safely replace a and b with the result
129+ pvm -> stackTop [-2 ] = OBJ_VAL (result );
130+ pvm -> stackTop -- ;
129131}
130132
131133// Helper functions moved to vm_helpers.c to avoid duplication
@@ -502,21 +504,34 @@ static InterpretResult run(VM* vm) {
502504 push (vm , NUMBER_VAL (a + b ));
503505 } else if (IS_NUMBER (peek (vm , 0 )) && IS_STRING (peek (vm , 1 ))) {
504506 // String + Number
505- Value numVal = pop (vm ); // b
506- Value strVal = pop (vm ); // a
507+ Value numVal = peek (vm , 0 ); // b
508+ Value strVal = peek (vm , 1 ); // a
507509 char buffer [32 ];
508510 snprintf (buffer , sizeof (buffer ), "%.14g" , AS_NUMBER (numVal ));
509- push (vm , strVal );
510511 push (vm , OBJ_VAL (copyString (buffer , (int )strlen (buffer ))));
512+ // Stack: [a (str), b (num), new_b (str)]
513+ // We need to move new_b to b position and pop b, then concatenate.
514+ // Or just call concatenate differently.
515+ // concatenate expects [a, b] on top.
516+ // Current stack: [..., a, b, new_str]
517+ // Swap b with new_str then pop b.
518+ vm -> stackTop [-2 ] = vm -> stackTop [-1 ];
519+ pop (vm );
511520 concatenate (vm );
512521 } else if (IS_STRING (peek (vm , 0 )) && IS_NUMBER (peek (vm , 1 ))) {
513522 // Number + String
514- Value strVal = pop (vm ); // b
515- Value numVal = pop (vm ); // a
523+ Value strVal = peek (vm , 0 ); // b
524+ Value numVal = peek (vm , 1 ); // a
516525 char buffer [32 ];
517526 snprintf (buffer , sizeof (buffer ), "%.14g" , AS_NUMBER (numVal ));
518- push (vm , OBJ_VAL (copyString (buffer , (int )strlen (buffer ))));
519- push (vm , strVal );
527+ Value newStr = OBJ_VAL (copyString (buffer , (int )strlen (buffer )));
528+ push (vm , newStr );
529+ // Stack: [..., a (num), b (str), new_a (str)]
530+ // We want [new_a, b] on top.
531+ // Current: top-2=a, top-1=b, top=new_a
532+ vm -> stackTop [-3 ] = vm -> stackTop [-1 ];
533+ // Stack: [new_a, b, new_a]
534+ pop (vm );
520535 concatenate (vm );
521536 } else {
522537 // Enhanced Error Logging
@@ -1036,20 +1051,22 @@ static InterpretResult run(VM* vm) {
10361051 double a = AS_NUMBER (pop (vm ));
10371052 push (vm , NUMBER_VAL (a + b ));
10381053 } else if (IS_NUMBER (peek (vm , 0 )) && IS_STRING (peek (vm , 1 ))) {
1039- Value numVal = pop (vm );
1040- Value strVal = pop (vm );
1054+ Value numVal = peek (vm , 0 );
10411055 char buffer [32 ];
10421056 snprintf (buffer , sizeof (buffer ), "%.14g" , AS_NUMBER (numVal ));
1043- push (vm , strVal );
1044- push (vm , OBJ_VAL (copyString (buffer , (int )strlen (buffer ))));
1057+ Value newB = OBJ_VAL (copyString (buffer , (int )strlen (buffer )));
1058+ push (vm , newB );
1059+ vm -> stackTop [-2 ] = vm -> stackTop [-1 ];
1060+ pop (vm );
10451061 concatenate (vm );
10461062 } else if (IS_STRING (peek (vm , 0 )) && IS_NUMBER (peek (vm , 1 ))) {
1047- Value strVal = pop (vm );
1048- Value numVal = pop (vm );
1063+ Value numVal = peek (vm , 1 );
10491064 char buffer [32 ];
10501065 snprintf (buffer , sizeof (buffer ), "%.14g" , AS_NUMBER (numVal ));
1051- push (vm , OBJ_VAL (copyString (buffer , (int )strlen (buffer ))));
1052- push (vm , strVal );
1066+ Value newA = OBJ_VAL (copyString (buffer , (int )strlen (buffer )));
1067+ push (vm , newA );
1068+ vm -> stackTop [-3 ] = vm -> stackTop [-1 ];
1069+ pop (vm );
10531070 concatenate (vm );
10541071 } else {
10551072 Value v1 = peek (vm , 1 ); // a
0 commit comments