public VirtualMachine.Function CompileAST(AST ast) { ChunkCompiler chunkCompiler = new ChunkCompiler(ast.Contents, new CompilerState(), null, true); chunkCompiler.State.ResolveJumps(); return new VirtualMachine.Function(chunkCompiler.State.bytecodes.ToArray(), chunkCompiler.State.constants.ToArray(), Guid.NewGuid().ToString(), chunkCompiler.State.childFunctions, chunkCompiler.State.positions, "root"); }
public void Visit(AST.RepeatStatement statement) { String afterLabel = State.getNewLabel(); String startLabel = State.getNewLabel(); String oldBreakLabel = State.currentBreakLabel; CompilerState.SavedState oldBreakState = State.currentBreakState; State.currentBreakLabel = afterLabel; State.currentBreakState = State.SaveState(); State.labels[startLabel] = State.bytecodes.Count; ChunkCompiler chunk = new ChunkCompiler(statement.Block, State, null, false); State.currentBreakLabel = oldBreakLabel; State.currentBreakState = oldBreakState; statement.Condition.Visit(new ExpressionCompiler(State, 1)); State.bytecodes.Add(VirtualMachine.OpCodes.NOT); State.bytecodes.Add(VirtualMachine.OpCodes.JMPTRUE); State.stackPosition--; State.jumps.Add(new KeyValuePair<string, int>(startLabel, State.bytecodes.Count - 1)); State.labels[afterLabel] = State.bytecodes.Count; }
public void Visit(AST.IfStatement statement) { String afterLabel = State.getNewLabel(); KeyValuePair<String, AST.TestBlock>[] branchLabels = new KeyValuePair<String, AST.TestBlock>[statement.Conditions.Count]; for (int i = 0; i < branchLabels.Length; i++) { branchLabels[i] = new KeyValuePair<string, AST.TestBlock>(State.getNewLabel(), statement.Conditions[i]); } for (int i = 0; i < branchLabels.Length; i++) { AST.TestBlock branch = branchLabels[i].Value; String branchLabel = branchLabels[i].Key; String startLabel = State.getNewLabel(); State.labels[branchLabel] = State.bytecodes.Count; branch.Cond.Visit(new ExpressionCompiler(State, 1)); State.bytecodes.Add(VirtualMachine.OpCodes.JMPTRUE); State.stackPosition--; State.jumps.Add(new KeyValuePair<string, int>(startLabel, State.bytecodes.Count - 1)); State.bytecodes.Add(VirtualMachine.OpCodes.JMP); if (i < branchLabels.Length - 1) { State.jumps.Add(new KeyValuePair<string, int>(branchLabels[i + 1].Key, State.bytecodes.Count - 1)); } else { State.jumps.Add(new KeyValuePair<string, int>(afterLabel, State.bytecodes.Count - 1)); } State.labels[startLabel] = State.bytecodes.Count; ChunkCompiler chunk = new ChunkCompiler(branch.Block, State, null, false); if (i < branchLabels.Length - 1) { State.bytecodes.Add(VirtualMachine.OpCodes.JMP); State.jumps.Add(new KeyValuePair<string, int>(afterLabel, State.bytecodes.Count - 1)); } } State.labels[afterLabel] = State.bytecodes.Count; }
public void Visit(AST.ForStatement statement) { if (statement.Clause is AST.NumForClause) { AST.NumForClause clause = (AST.NumForClause)statement.Clause; AST.Expression exp1 = clause.Expr1; AST.Expression exp2 = clause.Expr2; AST.Expression exp3 = clause.Expr3; if (exp3 == null) { exp3 = new AST.NumberExpression(1); } CompilerState.SavedState save = State.SaveState(); // Initialize the variables for the loop. int valPosition = State.stackPosition; exp1.Visit(new ExpressionCompiler(State, 1)); int maxPosition = State.stackPosition; exp2.Visit(new ExpressionCompiler(State, 1)); int stepPosition = State.stackPosition; exp3.Visit(new ExpressionCompiler(State, 1)); // Verify that the variables are all numbers foreach (int position in new int[] { valPosition, maxPosition, stepPosition }) { State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETGLOBAL(State.AddConstant("tonumber"))); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETSTACK(State.stackPosition - position)); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.MakeCALL(1)); State.stackPosition--; State.bytecodes.Add(VirtualMachine.OpCodes.MakePOPVARGS(1, true)); } String forCondLabel = State.getNewLabel(); State.bytecodes.Add(VirtualMachine.OpCodes.AND); State.stackPosition--; State.bytecodes.Add(VirtualMachine.OpCodes.AND); State.stackPosition--; State.bytecodes.Add(VirtualMachine.OpCodes.JMPTRUE); State.stackPosition--; State.jumps.Add(new KeyValuePair<string, int>(forCondLabel, State.bytecodes.Count - 1)); State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETGLOBAL(State.AddConstant("error"))); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.MakeCALL(0)); State.bytecodes.Add(VirtualMachine.OpCodes.MakePOPVARGS(0, true)); State.stackPosition--; // Condition for the loop State.labels.Add(forCondLabel, State.bytecodes.Count); State.bytecodes.Add(VirtualMachine.OpCodes.MakeLOADK(State.AddConstant(0.0))); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETSTACK(State.stackPosition - stepPosition)); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.LESS); State.stackPosition--; State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETSTACK(State.stackPosition - valPosition)); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETSTACK(State.stackPosition - maxPosition)); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.LESSEQ); State.stackPosition--; State.bytecodes.Add(VirtualMachine.OpCodes.AND); State.stackPosition--; State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETSTACK(State.stackPosition - stepPosition)); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.MakeLOADK(State.AddConstant(0.0))); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.LESSEQ); State.stackPosition--; State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETSTACK(State.stackPosition - maxPosition)); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETSTACK(State.stackPosition - valPosition)); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.LESSEQ); State.stackPosition--; State.bytecodes.Add(VirtualMachine.OpCodes.AND); State.stackPosition--; State.bytecodes.Add(VirtualMachine.OpCodes.OR); State.stackPosition--; String bodyLabel = State.getNewLabel(); String afterLabel = State.getNewLabel(); State.bytecodes.Add(VirtualMachine.OpCodes.JMPTRUE); State.stackPosition--; State.jumps.Add(new KeyValuePair<string, int>(bodyLabel, State.bytecodes.Count - 1)); State.bytecodes.Add(VirtualMachine.OpCodes.JMP); State.jumps.Add(new KeyValuePair<string, int>(afterLabel, State.bytecodes.Count - 1)); // Body CompilerState.SavedState loopSave = State.SaveState(); String oldBreakLabel = State.currentBreakLabel; CompilerState.SavedState oldBreakState = State.currentBreakState; State.currentBreakLabel = afterLabel; State.currentBreakState = State.SaveState(); State.labels.Add(bodyLabel, State.bytecodes.Count); State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETSTACK(State.stackPosition - valPosition)); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.MakeCLOSEVAR(1)); State.newClosedVars[clause.Name] = State.closureStackPosition; State.closureStackPosition++; State.stackVars[clause.Name] = State.stackPosition - 1; ChunkCompiler chunk = new ChunkCompiler(statement.Block, State, loopSave, false); State.currentBreakLabel = oldBreakLabel; State.currentBreakState = oldBreakState; State.RestoreState(loopSave); // Increment value State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETSTACK(State.stackPosition - valPosition)); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETSTACK(State.stackPosition - stepPosition)); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.ADD); State.stackPosition--; State.bytecodes.Add(VirtualMachine.OpCodes.MakePUTSTACK(State.stackPosition - valPosition)); State.stackPosition--; State.bytecodes.Add(VirtualMachine.OpCodes.JMP); State.jumps.Add(new KeyValuePair<string, int>(forCondLabel, State.bytecodes.Count - 1)); State.labels.Add(afterLabel, State.bytecodes.Count); State.RestoreState(save); } else { AST.ListForClause clause = (AST.ListForClause)statement.Clause; CompilerState.SavedState forSave = State.SaveState(); int fPosition = State.stackPosition; int sPosition = State.stackPosition + 1; int vPosition = State.stackPosition + 2; CompileExpressionList(clause.Expressions, 3); String afterLabel = State.getNewLabel(); String startLabel = State.getNewLabel(); String bodyLabel = State.getNewLabel(); State.labels.Add(startLabel, State.bytecodes.Count); CompilerState.SavedState loopSave = State.SaveState(); State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETSTACK(State.stackPosition - fPosition)); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETSTACK(State.stackPosition - sPosition)); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETSTACK(State.stackPosition - vPosition)); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.MakeCALL(2)); State.stackPosition -= 2; State.bytecodes.Add(VirtualMachine.OpCodes.MakePOPVARGS(clause.Names.Count, true)); State.stackPosition--; State.bytecodes.Add(VirtualMachine.OpCodes.MakeCLOSEVAR(clause.Names.Count)); foreach (String name in clause.Names) { State.stackVars[name] = State.stackPosition; State.stackPosition++; State.newClosedVars[name] = State.closureStackPosition; State.closureStackPosition++; } State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETSTACK(clause.Names.Count)); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.MakePUTSTACK(State.stackPosition - vPosition)); State.stackPosition--; State.bytecodes.Add(VirtualMachine.OpCodes.MakeGETSTACK(State.stackPosition - vPosition)); State.stackPosition++; State.bytecodes.Add(VirtualMachine.OpCodes.JMPTRUE); State.stackPosition--; State.jumps.Add(new KeyValuePair<string, int>(bodyLabel, State.bytecodes.Count - 1)); State.Cleanup(loopSave); State.bytecodes.Add(VirtualMachine.OpCodes.JMP); State.jumps.Add(new KeyValuePair<string, int>(afterLabel, State.bytecodes.Count - 1)); State.labels[bodyLabel] = State.bytecodes.Count; String oldBreakLabel = State.currentBreakLabel; CompilerState.SavedState oldBreakState = State.currentBreakState; State.currentBreakLabel = afterLabel; State.currentBreakState = State.SaveState(); ChunkCompiler chunk = new ChunkCompiler(statement.Block, State, loopSave, false); State.currentBreakState = oldBreakState; State.currentBreakLabel = oldBreakLabel; State.RestoreState(loopSave); State.bytecodes.Add(VirtualMachine.OpCodes.JMP); State.jumps.Add(new KeyValuePair<string, int>(startLabel, State.bytecodes.Count - 1)); State.labels.Add(afterLabel, State.bytecodes.Count); State.RestoreState(forSave); } }