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; }
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); }
/// <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); }
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); }
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); } } }