private void CGTableConstructorExp(FuncInfo funcInfo, TableConstructorExpNode node, int a) { int nArray = 0; foreach (var key in node.KeyExpList) { var nilNode = key as ConstExpNode; if (nilNode != null && nilNode.ExpType == ConstExpNode.ConstExpType.NilExp) { nArray++; } } int nExps = node.KeyExpList.Count; funcInfo.EmitNewTable(a, nArray, nExps - nArray); int i = 0; foreach (var key in node.KeyExpList) { var nilNode = key as ConstExpNode; var valNode = node.ValExpList[i]; if (nilNode.ExpType == ConstExpNode.ConstExpType.NilExp) { } int b = funcInfo.AllocReg(); CGExp(funcInfo, key, b, 1); int c = funcInfo.AllocReg(); CGExp(funcInfo, valNode, c, 1); funcInfo.FreeRegs(2); funcInfo.EmitSetTable(a, b, c); i++; } }
private void CGTableAccessExp(FuncInfo funcInfo, TableAccessExpNode node, int a) { int b = funcInfo.AllocReg(); CGExp(funcInfo, node.PreExp, b, 1); int c = funcInfo.AllocReg(); CGExp(funcInfo, node.Exp, c, 1); funcInfo.EmitGetTable(a, b, c); funcInfo.FreeRegs(2); }
private void CGUnaryExp(FuncInfo funcInfo, UnaryExpNode node, int a) { int b = funcInfo.AllocReg(); CGExp(funcInfo, node.Exp, b, 1); funcInfo.EmitUnaryOp(a, b, node.OpType); funcInfo.FreeReg(); }
private void CGFuncCallStat(FuncInfo funcInfo, FuncCallStatNode node) { var r = funcInfo.AllocReg(); FuncCallExpNode funcCall = new FuncCallExpNode(); funcCall.Args = node.Args; funcCall.NameExp = node.NameExp; funcCall.PreExp = node.PreExp; CGFuncCallExp(funcInfo, funcCall, r, 0); }
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; } } }
private void CGConcatExp(FuncInfo funcInfo, ConcatExpNode node, int a) { foreach (var exp in node.ExpList) { int r = funcInfo.AllocReg(); CGExp(funcInfo, exp, r, 1); } int c = funcInfo.UsedReg - 1; int b = node.ExpList.Count - 1; funcInfo.FreeRegs(c - b + 1); funcInfo.EmitABC(a, b, c, OP.OP_CONCAT); }
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 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 int PrepFuncCall(FuncInfo funcInfo, FuncCallExpNode node, int a) { int nArgs = node.Args.Count; bool lastVarIsVarargOrFuncCall = false; CGExp(funcInfo, node.PreExp, a, 1); if (node.NameExp.ExpType != ConstExpNode.ConstExpType.NilExp) { int c = 0x100 + funcInfo.IndexOfConstVar(node.NameExp.name); funcInfo.EmitSelf(a, a, c); } int i = 0; foreach (var arg in node.Args) { int r = funcInfo.AllocReg(); if (i == nArgs - 1 && IsVarargOrFuncCall(arg)) { lastVarIsVarargOrFuncCall = true; CGExp(funcInfo, arg, r, -1); } else { CGExp(funcInfo, arg, r, 1); } i++; } funcInfo.FreeRegs(nArgs); if (node.NameExp.ExpType != ConstExpNode.ConstExpType.NilExp) { nArgs++; } if (lastVarIsVarargOrFuncCall) { nArgs--; } return(nArgs); }
private void CGReturnStat(FuncInfo funcInfo, List <ExpNode> returneExps) { if (returneExps == null) { funcInfo.EmitReturn(0, 0); return; } bool muleRet = IsVarargOrFuncCall(returneExps.Last()); foreach (var exp in returneExps) { int r = funcInfo.AllocReg(); if (r == returneExps.Count - 1 && muleRet) { CGExp(funcInfo, exp, r, -1); } else { CGExp(funcInfo, exp, r, 1); } } funcInfo.FreeRegs(returneExps.Count); }
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 CGAssignStat(FuncInfo funcInfo, AssignStatNode node) { int nExps = node.ExpList.Count; int nVars = node.VarList.Count; int oldRegs = funcInfo.UsedReg; var tRegs = new int[nVars]; var kRegs = new int[nVars]; var vRegs = new int[nVars]; int i = 0; foreach (var exp in node.VarList) { TableAccessExpNode taExp = null; ConstExpNode constExp = null; if ((taExp = exp as TableAccessExpNode) != null) { tRegs[i] = funcInfo.AllocReg(); CGExp(funcInfo, taExp.PreExp, tRegs[i], 1); kRegs[i] = funcInfo.AllocReg(); CGExp(funcInfo, taExp.Exp, kRegs[i], 1); } i++; } for (int j = 0; j < nVars; j++) { vRegs[j] = funcInfo.UsedReg + j; } if (nExps >= nVars) { i = 0; foreach (var exp in node.ExpList) { int a = funcInfo.AllocReg(); if (i > nVars && i == nExps - 1 && IsVarargOrFuncCall(exp)) { CGExp(funcInfo, exp, a, 0); } else { CGExp(funcInfo, exp, a, 1); } i++; } } else { bool multRet = false; i = 0; foreach (var exp in node.ExpList) { int a = funcInfo.AllocReg(); if (i == nExps - 1 && IsVarargOrFuncCall(exp)) { multRet = true; int n = nVars - nExps + 1; CGExp(funcInfo, exp, a, n); funcInfo.AllocRegs(n - 1); } else { CGExp(funcInfo, exp, a, 1); } i++; } if (!multRet) { int n = nVars - nExps; int a = funcInfo.AllocRegs(n); funcInfo.EmitLoadNil(a, n); } } i = 0; foreach (var exp in node.VarList) { ConstExpNode varNode = null; int r = 0; if ((varNode = exp as ConstExpNode) != null) { var name = varNode.name; LocalVarInfo info = null; if (funcInfo.VarDic1.TryGetValue(name, out info)) { funcInfo.EmitMove(info.RegIndex, vRegs[i]); } else if (funcInfo.UpValOfIndex(name) >= 0) { int b = funcInfo.UpValOfIndex(name); funcInfo.EmitSetUpval(vRegs[i], b); } else if (funcInfo.ConstDic.TryGetValue(varNode.name, out r)) { funcInfo.EmitLoadK(vRegs[i], varNode.name); } else //ć šć±ćé { int a = funcInfo.UpValOfIndex("_ENV"); if (kRegs[i] <= 0) { int b = 0x100 + funcInfo.IndexOfConstVar(name); funcInfo.EmitSetTabUp(a, b, vRegs[i]); } else { funcInfo.EmitSetTabUp(a, kRegs[i], vRegs[i]); } } } else { funcInfo.EmitSetTable(tRegs[i], kRegs[i], vRegs[i]); } i++; } funcInfo.UsedReg = oldRegs; }
private void CGLocalVarDefStat(FuncInfo funcInfo, LocalVarDecStatNode node) { int nExps = node.ExpList.Count; int nNames = node.NameList.Count; int oldReg = funcInfo.UsedReg; if (nExps == nNames) { foreach (var exp in node.ExpList) { int a = funcInfo.AllocReg(); CGExp(funcInfo, exp, a, 1); } } else if (nExps > nNames) { int i = 0; foreach (var exp in node.ExpList) { int a = funcInfo.AllocReg(); if (i == nExps - 1 && IsVarargOrFuncCall(exp)) { CGExp(funcInfo, exp, a, 0); } else { CGExp(funcInfo, exp, a, 1); } i++; } } else { bool multRet = false; int i = 0; foreach (var exp in node.ExpList) { int a = funcInfo.AllocReg(); if (i == nExps - 1 && IsVarargOrFuncCall(exp)) { multRet = true; int n = nNames - nExps - 1; CGExp(funcInfo, exp, a, n); funcInfo.AllocRegs(n - 1); } else { CGExp(funcInfo, exp, a, 1); } i++; } if (!multRet) { int n = nNames - nExps; int a = funcInfo.AllocRegs(n); funcInfo.EmitLoadNil(a, n); } } funcInfo.UsedReg = oldReg; foreach (var nameNode in node.NameList) { funcInfo.AddLocalVar(nameNode.name); } }