@@ -311,13 +311,17 @@ namespace Pome {
311311 if (oper == " =" ) {
312312 // Assignment Expression
313313 if (auto ident = dynamic_cast <IdentifierExpr*>(expr.getLeft ())) {
314- // Compile RHS
314+ // Optimized LHS lookup for assignment
315+ int localReg = resolveLocal (ident->getName ());
316+
317+ // Evaluate RHS first
315318 expr.getRight ()->accept (*this );
316319 int valReg = lastResultReg;
317320
318- int localReg = resolveLocal (ident->getName ());
319321 if (localReg != -1 ) {
320- emit (Chunk::makeABC (OpCode::MOVE, localReg, valReg, 0 ), expr.getLine ());
322+ if (valReg != localReg) {
323+ emit (Chunk::makeABC (OpCode::MOVE, localReg, valReg, 0 ), expr.getLine ());
324+ }
321325 lastResultReg = localReg;
322326 } else if ((localReg = resolveUpvalue (ident->getName ())) != -1 ) {
323327 emit (Chunk::makeABC (OpCode::SETUPVAL, valReg, localReg, 0 ), expr.getLine ());
@@ -372,12 +376,35 @@ namespace Pome {
372376 return ;
373377 }
374378
375- expr.getLeft ()->accept (*this );
376- int leftReg = allocReg ();
377- emit (Chunk::makeABC (OpCode::MOVE, leftReg, lastResultReg, 0 ), expr.getLine ());
378-
379- expr.getRight ()->accept (*this );
380- int rightReg = lastResultReg;
379+ // Optimization: Check if left/right are local variables
380+ int leftReg = -1 ;
381+ bool leftIsLocal = false ;
382+ if (auto ident = dynamic_cast <IdentifierExpr*>(expr.getLeft ())) {
383+ leftReg = resolveLocal (ident->getName ());
384+ if (leftReg != -1 ) leftIsLocal = true ;
385+ }
386+
387+ if (leftIsLocal) {
388+ // No MOVE needed, use its register directly.
389+ } else {
390+ expr.getLeft ()->accept (*this );
391+ leftReg = lastResultReg;
392+ // The left operand's result is at leftReg (>= previous freeReg).
393+ }
394+
395+ int rightReg = -1 ;
396+ bool rightIsLocal = false ;
397+ if (auto ident = dynamic_cast <IdentifierExpr*>(expr.getRight ())) {
398+ rightReg = resolveLocal (ident->getName ());
399+ if (rightReg != -1 ) rightIsLocal = true ;
400+ }
401+
402+ if (rightIsLocal) {
403+ // No MOVE needed.
404+ } else {
405+ expr.getRight ()->accept (*this );
406+ rightReg = lastResultReg;
407+ }
381408
382409 OpCode op = OpCode::ADD;
383410 bool invert = false ;
@@ -452,11 +479,23 @@ namespace Pome {
452479
453480 // 2. Resolve target and potentially fetch current value for compound ops
454481 if (auto ident = dynamic_cast <IdentifierExpr*>(stmt.getTarget ())) {
455- // Evaluate RHS first for identifiers
456- stmt.getValue ()->accept (*this );
457- int rhsReg = lastResultReg;
458-
459482 int localReg = resolveLocal (ident->getName ());
483+
484+ // Optimization: If RHS is a local, avoid calling accept() which would MOVE it to a temporary.
485+ int rhsReg = -1 ;
486+ bool rhsIsLocal = false ;
487+ if (op.empty ()) {
488+ if (auto rhsIdent = dynamic_cast <IdentifierExpr*>(stmt.getValue ())) {
489+ rhsReg = resolveLocal (rhsIdent->getName ());
490+ if (rhsReg != -1 ) rhsIsLocal = true ;
491+ }
492+ }
493+
494+ if (!rhsIsLocal) {
495+ stmt.getValue ()->accept (*this );
496+ rhsReg = lastResultReg;
497+ }
498+
460499 int upvalIdx = -1 ;
461500
462501 if (localReg != -1 ) {
@@ -470,7 +509,9 @@ namespace Pome {
470509 else if (op == " %" ) opcode = OpCode::MOD;
471510 emit (Chunk::makeABC (opcode, localReg, localReg, rhsReg), stmt.getLine ());
472511 } else {
473- emit (Chunk::makeABC (OpCode::MOVE, localReg, rhsReg, 0 ), stmt.getLine ());
512+ if (localReg != rhsReg) {
513+ emit (Chunk::makeABC (OpCode::MOVE, localReg, rhsReg, 0 ), stmt.getLine ());
514+ }
474515 }
475516 lastResultReg = localReg;
476517 } else if ((upvalIdx = resolveUpvalue (ident->getName ())) != -1 ) {
0 commit comments