Beispiel #1
0
        public void Visit(ASTWhile whileStatement, Function function)
        {
            // do condition
            int condition = function.Code.Count;

            whileStatement.Condition.Accept(this, function);

            // branch out if condition evaluates to false
            function.Code.Write(OpCodeFactory.BranchIfFalse(0));
            int conditionBranch = function.Code.Count - 1;

            // compile body
            whileStatement.Body.Accept(this, function);

            // branch back to the condition
            function.Code.Write(OpCodeFactory.Branch((uint)condition));
            int end = function.Code.Count;

            // set the conditional branch offset
            function.Code[conditionBranch].As <BranchIfFalse>().Argument = (uint)end;

            // fill breaks/continues

            for (int i = condition; i < end; i++)
            {
                var instruction = function.Code[i];
                if (instruction is Branch breakBranch && breakBranch.Argument == Break) // break, jump to end
                {
                    breakBranch.Argument = (uint)end;
                }
Beispiel #2
0
        private static List <ASTNode> ParseCodeBlock()
        {
            List <ASTNode> codeBlock = new List <ASTNode>();

            if (currentToken < currentTokens.Count)
            {
                if (currentTokens[currentToken].Token == "{")
                {
                    currentToken++;

                    while (currentToken < currentTokens.Count && currentTokens[currentToken].Token != "}")
                    {
                        if (currentTokens[currentToken] is ReservedWordToken && currentTokens[currentToken].Token == "if")
                        {
                            ASTIf ifNode = ParseIf();
                            codeBlock.Add(ifNode);
                        }
                        else if (currentTokens[currentToken] is ReservedWordToken && currentTokens[currentToken].Token == "for")
                        {
                            ASTFor forNode = ParseFor();
                            codeBlock.Add(forNode);
                        }
                        else if (currentTokens[currentToken] is ReservedWordToken && currentTokens[currentToken].Token == "while")
                        {
                            ASTWhile whileNode = ParseWhile();
                            codeBlock.Add(whileNode);
                        }
                        else
                        {
                            ASTStatement statement = ParseStatement();
                            if (statement != null)
                            {
                                codeBlock.Add(statement);
                            }
                        }
                    }

                    if (currentToken == currentTokens.Count)
                    {
                        throw new ParserException("SourceCode can't end in Code Block.", -1);
                    }

                    return(codeBlock);
                }
                // No '{' means just one line of code
                else
                {
                    ASTStatement statement = ParseStatement();

                    if (statement != null)
                    {
                        codeBlock.Add(statement);
                    }

                    return(codeBlock);
                }
            }
            throw new ParserException("Expected Code Block found End of File.", -1);
        }
Beispiel #3
0
        /// <summary>
        /// Pretty simple, just ensure that the condition is a boolean.
        /// </summary>
        /// <param name="n"></param>
        public override void VisitWhile(ASTWhile n)
        {
            CFlatType condType = CheckSubTree(n.Condition);

            if (condType is TypeBool)
            {
                CheckSubTree(n.Body);
            }
            else
            {
                ReportError(n.Location, "While loop condition must be a boolean. Got type '{0}'", TypeToFriendlyName(condType));
            }
        }
        private Symbol VisitWhileStatement(ASTWhile node)
        {
            var conditionType = Visit(node.Condition);

            if (conditionType.Name != "bool")
            {
                ThrowIncompatibleTypesException(node.Token, conditionType.Name, "bool");
            }

            Logger.DebugScope($"Enter scope : while");
            var whileScope = new ScopedSymbolTable("while", _currentScope.Level + 1, _currentScope);

            _currentScope = whileScope;

            var returnType = Visit(node.Body);

            DebugPrintSymbolTable();

            _currentScope = _currentScope.EnclosingScope;
            Logger.DebugScope($"Leave scope : while");

            return(returnType);
        }
Beispiel #5
0
        public override void VisitWhile(ASTWhile n)
        {
            //define labels
            Label loop = _gen.DefineLabel();
            Label exit = _gen.DefineLabel();

            //loop label
            _gen.MarkLabel(loop);

            //check condition
            n.Condition.Visit(this);

            //break on false
            _gen.Emit(OpCodes.Brfalse, exit);

            //emit body of loop
            n.Body.Visit(this);

            //unconditional loop branch
            _gen.Emit(OpCodes.Br, loop);

            //break label
            _gen.MarkLabel(exit);
        }
        private VisitResult VisitWhileStatement(ASTWhile node)
        {
            var condition = Visit(node.Condition).Value;

            while (condition)
            {
                var result = Visit(node.Body);
                if (result != null)
                {
                    switch (result.ControlType)
                    {
                    case ControlType.Return:
                        return(result);

                    case ControlType.Break:
                        return(null);
                    }
                }

                condition = Visit(node.Condition).Value;
            }

            return(null);
        }
Beispiel #7
0
    ASTStatement ParseStatement()
    {
        if (lexer.PeekNext() == TokenType.Identifier)  // Function call
        {
            ASTFuncCall funcCall = ParseExpression() as ASTFuncCall;
            return(new ASTInlineCall(funcCall));
        }

        Token first = lexer.NextToken();

        switch (first.Type)
        {
        case TokenType.Set:
        {
            Token varNameToken            = MatchNext(TokenType.Identifier);
            List <ASTExpression> indexers = new List <ASTExpression>();

            while (lexer.PeekNext() == TokenType.SquareBraceOpen)
            {
                MatchNext(TokenType.SquareBraceOpen);

                indexers.Add(ParseExpression());

                MatchNext(TokenType.SquareBraceClose);
            }

            MatchNext(TokenType.To);

            ASTExpression expression = ParseExpression();

            return(new ASTSet(varNameToken.Source, expression, indexers));
        }

        case TokenType.If:
        {
            ASTExpression check      = ParseExpression();
            ASTStatements statements = new ASTStatements();
            ASTIf         ifStmnt    = new ASTIf(check, statements);

            MatchNext(TokenType.Do);

            while (lexer.PeekNext() != TokenType.End)
            {
                if (lexer.PeekNext() == TokenType.Else)
                {
                    lexer.NextToken();

                    statements = new ASTStatements();
                    ifStmnt.SetElse(statements);

                    MatchNext(TokenType.Do);
                }
                else if (lexer.PeekNext() == TokenType.Elif)
                {
                    lexer.NextToken();

                    statements = new ASTStatements();
                    ASTIf elseifStmnt = new ASTIf(ParseExpression(), statements);

                    ifStmnt.SetElseIf(elseifStmnt);

                    MatchNext(TokenType.Do);
                }
                statements.AddStatement(ParseStatement());
            }

            lexer.NextToken();

            return(ifStmnt);
        }

        case TokenType.While:
        {
            ASTExpression check      = ParseExpression();
            ASTStatements statements = new ASTStatements();
            ASTWhile      whileStmnt = new ASTWhile(check, statements);

            MatchNext(TokenType.Do);

            while (lexer.PeekNext() != TokenType.End)
            {
                statements.AddStatement(ParseStatement());
            }

            lexer.NextToken();

            return(whileStmnt);
        }

        case TokenType.Return:
        {
            return(new ASTReturn(ParseExpression()));
        }

        default:
            throw new Exception("Unexpected token " + first);
        }

        return(null);
    }
        private static void PrintNode(ASTNode node, int incident)
        {
            if (node == null)
            {
                return;
            }
            for (int i = 0; i < incident; i++)
            {
                sw.Write("\t");
            }
            if (node is ASTString)
            {
                sw.WriteLine("ASTString: " + ((ASTString)node).String.Replace("\n", "\\n"));
            }
            else if (node is ASTNumber)
            {
                sw.WriteLine("ASTNumber: " + ((ASTNumber)node).Number);
            }
            else if (node is ASTIdentifier)
            {
                sw.WriteLine("ASTIdentifier: " + ((ASTIdentifier)node).Identifier);
            }
            else if (node is ASTOperator)
            {
                ASTOperator op = (ASTOperator)node;
                sw.WriteLine("ASTOperator: " + op.Operator);
                PrintNode(op.Left, incident + 1);
                PrintNode(op.Right, incident + 1);
            }
            else if (node is ASTStatement)
            {
                ASTStatement stm = (ASTStatement)node;
                sw.WriteLine("ASTStatement: ");
                PrintNode(stm.Statement, incident + 1);
            }
            else if (node is ASTFunctionCall)
            {
                ASTFunctionCall call = (ASTFunctionCall)node;
                sw.WriteLine("ASTFunctionCall: " + call.Scope + "." + call.FunctionName);
                foreach (ASTNode param in call.Parameter)
                {
                    PrintNode(param, incident + 1);
                }
            }
            else if (node is ASTClassParameter)
            {
                ASTClassParameter classP = (ASTClassParameter)node;
                sw.WriteLine("ASTClassParameter: " + classP.Scope);
                PrintNode(classP.Parameter, incident + 1);
            }
            else if (node is ASTIf)
            {
                ASTIf ifNode = (ASTIf)node;
                sw.WriteLine("ASTIf:");
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tCondition:");
                PrintNode(ifNode.Condition, incident + 2);
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tCodeBlock:");
                foreach (ASTNode codeBlock in ifNode.CodeBlock)
                {
                    PrintNode(codeBlock, incident + 2);
                }
                if (ifNode.ElseCodeBlock != null)
                {
                    for (int i = 0; i < incident; i++)
                    {
                        sw.Write("\t");
                    }
                    sw.WriteLine("\tElse:");
                    foreach (ASTNode codeBlock in ifNode.ElseCodeBlock)
                    {
                        PrintNode(codeBlock, incident + 2);
                    }
                }
            }
            else if (node is ASTFor)
            {
                ASTFor forNode = (ASTFor)node;
                sw.WriteLine("ASTFor:");
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tInit:");
                PrintNode(forNode.Initialise, incident + 2);
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tCondition:");
                PrintNode(forNode.Condition, incident + 2);
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tCounter:");
                PrintNode(forNode.Count, incident + 2);
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tCodeBlock:");
                foreach (ASTNode codeBlock in forNode.CodeBlock)
                {
                    PrintNode(codeBlock, incident + 2);
                }
            }
            else if (node is ASTWhile)
            {
                ASTWhile wNode = (ASTWhile)node;
                sw.WriteLine("ASTWhile:");
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tCondition:");
                PrintNode(wNode.Condition, incident + 2);
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tCodeBlock:");
                foreach (ASTNode codeBlock in wNode.CodeBlock)
                {
                    PrintNode(codeBlock, incident + 2);
                }
            }
            else if (node is ASTFunction)
            {
                ASTFunction func = (ASTFunction)node;
                if (node is ASTConstructor)
                {
                    sw.WriteLine("ASTConstructor:");
                }
                else
                {
                    sw.WriteLine("ASTFunction: " + func.ReturnValue.ToString() + " " + func.Name);
                }
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tParameter:");
                foreach (ASTNode n in func.Parameter)
                {
                    PrintNode(n, incident + 2);
                }
                for (int i = 0; i < incident; i++)
                {
                    sw.Write("\t");
                }
                sw.WriteLine("\tCodeBlock:");
                foreach (ASTNode codeBlock in func.CodeBlock)
                {
                    PrintNode(codeBlock, incident + 2);
                }
            }
            else if (node is ASTFunctionParameter)
            {
                ASTFunctionParameter param = (ASTFunctionParameter)node;
                switch (param.Type)
                {
                case VMType.Object:
                    sw.WriteLine("Object: " + param.Name);
                    break;

                case VMType.String:
                    sw.WriteLine("String: " + param.Name);
                    break;

                case VMType.Number:
                    sw.WriteLine("Number: " + param.Name);
                    break;
                }
            }
            else if (node is ASTLocalVariable)
            {
                ASTLocalVariable param = (ASTLocalVariable)node;
                switch (param.Type)
                {
                case VMType.Object:
                    sw.WriteLine("var Object: " + param.Name);
                    break;

                case VMType.String:
                    sw.WriteLine("var String: " + param.Name);
                    break;

                case VMType.Number:
                    sw.WriteLine("var Number: " + param.Name);
                    break;
                }
            }
            else if (node is ASTReturn)
            {
                sw.WriteLine("ASTReturn:");
                PrintNode(((ASTReturn)node).Return, incident + 1);
            }
            else if (node is ASTClass)
            {
                ASTClass cNode = (ASTClass)node;
                sw.WriteLine("ASTClass: " + cNode.Name);
                sw.WriteLine("\tAttributes:");
                foreach (ASTNode n in cNode.Attributes)
                {
                    PrintNode(n, incident + 2);
                }
                sw.WriteLine("\tConstructors:");
                foreach (ASTNode n in cNode.Constructors)
                {
                    PrintNode(n, incident + 2);
                }
                sw.WriteLine("\tFunctions:");
                foreach (ASTNode n in cNode.Functions)
                {
                    PrintNode(n, incident + 2);
                }
            }
        }