public LuaFile Compile(Ast.Chunk c, string name) { file = new LuaFile(); block = new Block(); block.Chunk.Name = name; block.Chunk.ArgumentCount = 0; block.Chunk.Vararg = 2; DoChunk(c); file.Main = block.Chunk; file.Main.ArgumentCount = 0; file.Main.Vararg = 2; file.Main.UpvalueCount = file.Main.Upvalues.Count; bool addRet = file.Main.Instructions.Count == 0; if (addRet == false) addRet = file.Main.Instructions[file.Main.Instructions.Count - 1].Opcode != Instruction.LuaOpcode.RETURN; if (addRet) { Instruction ret = new Instruction("RETURN"); ret.A = 0; ret.B = 1; ret.C = 0; file.Main.Instructions.Add(ret); } return file; }
public Block(Block parent) { K = new K2Reg(this); //parent.PreviousBlock = this; this.PreviousBlock = parent; V = new Var2Reg(parent.V); Chunk = parent.Chunk; }
void DoStatement(Statement s) { line = s.LineNumber; if (s is AssignmentStatement && !(s is AugmentedAssignmentStatement)) { AssignmentStatement a = s as AssignmentStatement; if (a.IsLocal == false) { for (int i = a.Rhs.Count; i > 0; i--) DoExpr(a.Rhs[i - 1], false, a.Lhs.Count); for (int i = a.Lhs.Count; i > 0; i--) DoExpr(a.Lhs[i - 1], true); return; } else { for (int i = a.Rhs.Count; i > 0; i--) DoExpr(a.Rhs[i - 1], false, a.Lhs.Count); for (int i = a.Lhs.Count; i > 0; i--) DoExpr(a.Lhs[i - 1], true); return; } } else if (s is AugmentedAssignmentStatement) { AugmentedAssignmentStatement aas = s as AugmentedAssignmentStatement; StringBuilder sb = new StringBuilder(); //sb.Append(DoExpr(a.Lhs[0])); if (aas.IsLocal) throw new LuaSourceException(s.LineNumber, 0, "Local assignment cannot have augmented operators"); DoExpr(aas.Rhs[0], true, 1); DoExpr(aas.Lhs[0], true, 1); return; } else if (s is BreakStatement) { bool hadLoop = false; while (block != null) { if (block.IsLoop) { hadLoop = true; break; } block = block.PreviousBlock; } if (!hadLoop) throw new LuaSourceException(s.LineNumber, 0, "No loop to break"); Instruction i = new Instruction("JMP"); i.A = 0; i.sBx = -1; // Infinite loop ;) emit(i); patchSbx.Push(i); return; } else if (s is ContinueStatement) { } else if (s is CallStatement) { CallStatement cs = s as CallStatement; DoExpr(cs.Expression); return; } else if (s is DoStatement) { } else if (s is GenericForStatement) { } else if (s is NumericForStatement) { } else if (s is FunctionStatement) { } else if (s is GotoStatement) ; else if (s is IfStmt) { } else if (s is LabelStatement) ; else if (s is RepeatStatement) { } else if (s is ReturnStatement) { } else if (s is UsingStatement) { } else if (s is WhileStatement) { WhileStatement ws = s as WhileStatement; int start = block.Chunk.Instructions.Count; DoExpr(ws.Condition); Instruction t = new Instruction("TEST"); t.A = block.regnum; t.C = 0; emit(t); DoChunk(ws.Body, true); Instruction i = new Instruction("JMP"); i.A = 0; i.sBx = -(block.Chunk.Instructions.Count - start) - 1; emit(i); while (patchSbx.Count > 0) patchSbx.Pop().sBx = Math.Abs(block.Chunk.Instructions.Count + i.sBx - 1); //return; } throw new NotImplementedException(s.GetType().Name + " is not implemented"); }
void DoChunk(List<Statement> ss, bool isLoop = false) { block = new Block(block) { IsLoop = isLoop }; foreach (Statement s in ss) { DoStatement(s); block.regnum = 0; } block = block.PreviousBlock; }
public K2Reg(Block b) { this.b = b; }