public Instr Emit_Asgn(AsgnNode node) { // 先编译右值 node.cdr.Compile(this); // 然后把堆栈中的值赋给左值 return(GenAssignment(node.car, vm.CurrentScope.sp)); }
private void GenAssignment(CodeGenScope s, AstNode tree, int sp, int val) { int idx; AsgnNode asgnNode = tree.As <AsgnNode> (); Gen(s, asgnNode.cdr, VAL); Pop(s); switch (asgnNode.car.type) { case AstNodeType.GVAR: idx = NewSym(s, asgnNode.car.As <GlobalVarNode>().name); GenOp_2(s, OpCode.SetGV, sp, idx); break; case AstNodeType.ARG: case AstNodeType.LVAR: idx = s.FindLocalVarIdx(asgnNode.car.As <SymNode> ().name); if (idx != -1) { if (idx != sp) { GenMove(s, idx, sp, val == 1); if (val == 1 && s.parser.on_eval) { GenOp_0(s, OpCode.Nop); } } break; } else { int lv = 0; CodeGenScope up = s.prev; while (up != null) { idx = up.FindLocalVarIdx(asgnNode.car.As <SymNode> ().name); if (idx != -1) { GenOp_3(s, OpCode.SetUpVar, sp, idx, lv); break; } lv++; up = up.prev; } } break; case AstNodeType.IVAR: idx = NewSym(s, nsym(asgnNode.car)); GenOp_2(s, OpCode.SetIV, sp, idx); break; case AstNodeType.CVAR: idx = NewSym(s, nsym(asgnNode.car)); GenOp_2(s, OpCode.SetCV, sp, idx); break; case AstNodeType.CONST: idx = NewSym(s, nsym(asgnNode.car)); GenOp_2(s, OpCode.SetConst, sp, idx); break; case AstNodeType.COLON2: // TODO: break; case AstNodeType.CALL: case AstNodeType.SCALL: Push(s); GenCall(s, asgnNode.car, sp, NOVAL, asgnNode.car.type == AstNodeType.SCALL); Pop(s); if (val != NOVAL) { GenMove(s, s.sp, sp, false); } break; case AstNodeType.MASGN: // TODO: break; case AstNodeType.NIL: break; default: Console.WriteLine($"unknown lhs {asgnNode.car.type}\n"); break; } if (val != NOVAL) { Push(s); } }