private void CGForInStat(FuncInfo funcInfo, ForInStatNode node) { funcInfo.EnterScope(true); LocalVarDecStatNode varDecStatNode = new LocalVarDecStatNode(); varDecStatNode.ExpList = node.ExpList; varDecStatNode.NameList = new List <ConstExpNode>() { new ConstExpNode(new Token(TokenType.Identifier, "for_generator", -1)), new ConstExpNode(new Token(TokenType.Identifier, "for_state", -1)), new ConstExpNode(new Token(TokenType.Identifier, "for_control", -1)) }; foreach (var name in node.NameList.NameList) { funcInfo.AddLocalVar(name.name); } int jmpToTFCPC = funcInfo.EmitJMP(0, 0); CGBlock(funcInfo, node.DoBlock.Block); funcInfo.FixSBX(jmpToTFCPC, funcInfo.PC() - jmpToTFCPC); var geneartor = funcInfo.VarDic1["for_generator"]; funcInfo.EmitTForCall(geneartor.RegIndex, node.NameList.NameList.Count); funcInfo.EmitTForLoop(geneartor.RegIndex + 2, jmpToTFCPC - funcInfo.PC() - 1); funcInfo.ExitScope(); }
private void CGWhileStat(FuncInfo funcInfo, WhileStatNode node) { int beforePc = funcInfo.PC(); int r = funcInfo.AllocReg(); CGExp(funcInfo, node.Exp, r, 1); funcInfo.FreeReg(); funcInfo.EmitTest(r, 0); int jumPC = funcInfo.EmitJMP(0, 0); funcInfo.EnterScope(true); CGBlock(funcInfo, node.DoStatNode.Block); funcInfo.EmitJMP(0, beforePc - funcInfo.PC()); funcInfo.ExitScope(); funcInfo.FixSBX(jumPC, funcInfo.PC() - jumPC); }
private void CGStat(FuncInfo funcInfo, StatNode node) { switch (node.Type) { case GrammarNodeType.FunctionCallStat: CGFuncCallStat(funcInfo, node as FuncCallStatNode); break; case GrammarNodeType.BreakStat: int pc = funcInfo.EmitJMP(0, 0); funcInfo.AddBreakJmp(pc); break; case GrammarNodeType.DoStat: CGDoStat(funcInfo, node as DoStatNode); break; case GrammarNodeType.RepeatStat: CGRepeatStat(funcInfo, node as RepeatStatNode); break; case GrammarNodeType.WhileStat: CGWhileStat(funcInfo, node as WhileStatNode); break; case GrammarNodeType.ForInStat: CGWhileStat(funcInfo, node as WhileStatNode); break; case GrammarNodeType.IfStat: CGIfStat(funcInfo, node as IfStatNode); break; case GrammarNodeType.ForNumStat: CGForNumStat(funcInfo, node as ForNumStatNode); break; case GrammarNodeType.LocalVarDecStat: CGLocalVarDefStat(funcInfo, node as LocalVarDecStatNode); break; case GrammarNodeType.LocalFuncDefStat: CGLocalFuncDefStat(funcInfo, node as LoacalFuncDefStatNode); break; case GrammarNodeType.AssignStat: CGAssignStat(funcInfo, node as AssignStatNode); break; } }
private void CGIfStat(FuncInfo funcInfo, IfStatNode node) { var jmpToEndsPC = new int[node.Exp.Count]; int jmpToNextExpPc = -1; int i = 0; foreach (var exp in node.Exp) { if (jmpToNextExpPc > 0) { funcInfo.FixSBX(jmpToNextExpPc, funcInfo.PC() - jmpToNextExpPc); } int r = funcInfo.AllocReg(); CGExp(funcInfo, exp, r, 1); funcInfo.FreeReg(); funcInfo.EmitTest(r, 0); jmpToNextExpPc = funcInfo.EmitJMP(0, 0); funcInfo.EnterScope(false); CGBlock(funcInfo, node.Block); funcInfo.ExitScope(); if (i < node.Exp.Count - 1) { jmpToEndsPC[i] = funcInfo.EmitJMP(0, 0); } else { jmpToEndsPC[i] = jmpToNextExpPc; } i++; } foreach (int j in jmpToEndsPC) { funcInfo.FixSBX(j, funcInfo.PC() - j); } }
private void CGRepeatStat(FuncInfo funcInfo, RepeatStatNode node) { funcInfo.EnterScope(true); int blockPC = funcInfo.PC(); CGBlock(funcInfo, node.Block); int r = funcInfo.AllocReg(); CGExp(funcInfo, node.Exp, r, 1); funcInfo.FreeReg(); funcInfo.EmitTest(r, 0); funcInfo.EmitJMP(0, blockPC - funcInfo.PC() - 1); funcInfo.ExitScope(); }
private void CGBinOpExp(FuncInfo funcInfo, DoubleOperationExpNode node, int a) { switch (node.OpType) { case TokenType.And: case TokenType.Or: { int b = funcInfo.AllocReg(); CGExp(funcInfo, node.Exp1, b, 1); funcInfo.FreeReg(); if (node.OpType == TokenType.And) { funcInfo.EmitTestSet(a, b, 0); } else { funcInfo.EmitTestSet(a, b, 1); } int jmpPC = funcInfo.EmitJMP(0, 0); int c = funcInfo.AllocReg(); CGExp(funcInfo, node.Exp2, c, 1); funcInfo.FreeReg(); funcInfo.EmitMove(a, c); funcInfo.FixSBX(jmpPC, funcInfo.PC() - jmpPC); break; } default: { int b = funcInfo.AllocReg(); CGExp(funcInfo, node.Exp1, b, 1); int c = funcInfo.AllocReg(); CGExp(funcInfo, node.Exp2, c, 1); funcInfo.EmitDoubleOperator(a, b, c, node.OpType); funcInfo.FreeRegs(2); break; } } }