Пример #1
0
        /* simpleexp -> NUMBER | STRING | NIL | true | false | ... |
                        constructor | FUNCTION body | primaryexp */
        private AST.Expression ParseSimpleExpr()
        {
            AST.Expression expr = null;

            if (Stream.IsNumber())
            {
                expr = new AST.NumberExpression(Stream.GetNumber().NumberValue.Value);
                Stream.MoveNext();
            }
            else if (Stream.IsString())
            {
                expr = new AST.StringExpression(Stream.GetString().Value);
                Stream.MoveNext();
            }
            else if (Stream.IsKeyword("nil"))
            {
                expr = new AST.NilExpression();
                Stream.MoveNext();
            }
            else if (Stream.IsKeyword("true"))
            {
                expr = new AST.BoolExpression(true);
                Stream.MoveNext();
            }
            else if (Stream.IsKeyword("false"))
            {
                expr = new AST.BoolExpression(false);
                Stream.MoveNext();
            }
            else if (Stream.IsKeyword("..."))
            {
                expr = new AST.VarArgsExpression();
                Stream.MoveNext();
            }
            else if (Stream.IsKeyword("{"))
            {
                expr = ParseConstructor();
            }
            else if (Stream.IsKeyword("function"))
            {
                Stream.MoveNext();

                return new AST.FunctionExpression(ParseBody());
            }
            else
            {
                expr = ParsePrimaryExpr();
            }

            return expr;
        }
Пример #2
0
        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);
            }
        }