diff --git a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java index 0b2a74a..cbb923e 100644 --- a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java +++ b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java @@ -68,25 +68,32 @@ public class ContextAnalysis extends KlangBaseVisitor { @Override public Node visitBraced_block(KlangParser.Braced_blockContext ctx) { - var actualStatementCount = 0; - var declaredStatementCount = ctx.statement().size(); + var statementsOrFunctionCalls = new ArrayList(); var hasReturn = false; - var statements = new Statement[declaredStatementCount]; - for (int i = 0; i < declaredStatementCount; i++) { - var currentStatement = visit(ctx.statement(i)); - statements[i] = (Statement) currentStatement; - actualStatementCount += 1; + for (var child: ctx.children) { + var statementOrFunctionCall = visit(child); - // We use the existence of a type to indicate that this statement returns - // something for which the VariableDeclaration is an exception - if (currentStatement.type != null && !(currentStatement instanceof VariableDeclaration)) { + // The children array contains more than just the statements or function calls + // but everything else evaluates to null, so we can skip it. + if (statementOrFunctionCall == null) { + continue; + } + + statementsOrFunctionCalls.add(statementOrFunctionCall); + + if ( + statementOrFunctionCall.type != null + && !(statementOrFunctionCall instanceof VariableDeclaration) + && !statementOrFunctionCall.type.equals(Type.getVoidType()) + ) { // check whether the type matches try { - currentDeclaredReturnType.combine(currentStatement.type); + currentDeclaredReturnType.combine(statementOrFunctionCall.type); } catch (Exception e) { - throw new RuntimeException( - Helper.getErrorPrefix(currentStatement.line, currentStatement.col) + e.getMessage()); + var line = statementOrFunctionCall.line; + var col = statementOrFunctionCall.col; + throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage()); } // since we have a return guaranteed, every statement @@ -96,20 +103,12 @@ public class ContextAnalysis extends KlangBaseVisitor { } } - // If there was unreachable code in this block, - // create a shorter statements array and copy the statements to there - if (actualStatementCount < declaredStatementCount) { - var newStatements = new Statement[actualStatementCount]; - System.arraycopy(statements, 0, newStatements, 0, actualStatementCount); - statements = newStatements; - } - // if this block contains at least one statement that guarantees a return value, // we indicate that this block guarantees a return value by setting result.type - var result = new Block(statements); + var result = new Block(statementsOrFunctionCalls.toArray(new Node[0])); if (hasReturn) { - result.type = this.currentDeclaredReturnType; + result.type = currentDeclaredReturnType; } result.line = ctx.start.getLine(); @@ -884,42 +883,47 @@ public class ContextAnalysis extends KlangBaseVisitor { } @Override - public Node visitFunctionCallExpression(KlangParser.FunctionCallExpressionContext ctx) { - String name = ctx.functionCall().IDENT().getText(); - int line = ctx.start.getLine(); - int col = ctx.start.getCharPositionInLine(); + public Node visitFunctionCall(KlangParser.FunctionCallContext ctx) { + var name = ctx.IDENT().getText(); + var line = ctx.start.getLine(); + var col = ctx.start.getCharPositionInLine(); - var functionDef = this.functionDefs.get(name); + var functionDef = functionDefs.get(name); if (functionDef == null) { - String error = "Function with name \"" + name + "\" not defined."; + var error = "Function with name \"" + name + "\" not defined."; throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); } // Make sure the number of arguments matches the number of parameters - int argCount = ctx.functionCall().arguments().expression().size(); - int paramCount = functionDef.parameters.length; + var argCount = ctx.arguments().expression().size(); + var paramCount = functionDef.parameters.length; if (argCount != paramCount) { - String error = "Function \"" + name + "\" expects " + paramCount + " parameters, but got " + argCount + "."; + var error = "Function \"" + name + "\" expects " + paramCount + " parameters, but got " + argCount + "."; throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); } // Evaluate every argument - Expression[] args = new Expression[argCount]; + var args = new Expression[argCount]; for (int i = 0; i < argCount; i++) { - Expression expression = (Expression) this.visit(ctx.functionCall().arguments().expression(i)); + var expression = (Expression) visit(ctx.arguments().expression(i)); if (!expression.type.equals(functionDef.parameters[i].type)) { throw new RuntimeException(Helper.getErrorPrefix(line, col) + "argument " + i + " Expected " + functionDef.parameters[i].type.getName() + " but got: " + expression.type.getName()); } args[i] = expression; } - FunctionCall result = new FunctionCall(name, args); + var result = new FunctionCall(name, args); result.type = functionDef.type; result.line = line; result.col = col; return result; } + @Override + public Node visitFunctionCallExpression(KlangParser.FunctionCallExpressionContext ctx) { + return visit(ctx.functionCall()); + } + @Override public Node visitConstructorCallExpression(KlangParser.ConstructorCallExpressionContext ctx) { String name = ctx.IDENT().getText(); diff --git a/src/main/java/de/hsrm/compiler/Klang/nodes/Block.java b/src/main/java/de/hsrm/compiler/Klang/nodes/Block.java index fe7a019..fa477b6 100644 --- a/src/main/java/de/hsrm/compiler/Klang/nodes/Block.java +++ b/src/main/java/de/hsrm/compiler/Klang/nodes/Block.java @@ -1,14 +1,13 @@ package de.hsrm.compiler.Klang.nodes; -import de.hsrm.compiler.Klang.nodes.statements.Statement; import de.hsrm.compiler.Klang.visitors.Visitor; public class Block extends Node { - public Statement[] statements; + public Node[] statementsOrFunctionCalls; - public Block(Statement[] statements) { - this.statements = statements; + public Block(Node[] statements) { + this.statementsOrFunctionCalls = statements; } @Override diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java b/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java index ee6193a..9cf28c5 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java @@ -404,7 +404,7 @@ public class EvalVisitor implements Visitor { @Override public Value visit(Block e) { - for (var stmt : e.statements) { + for (var stmt : e.statementsOrFunctionCalls) { var result = stmt.welcome(this); if (result != null) { return result; diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java b/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java index 4618c3d..b5e7e08 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java @@ -543,7 +543,7 @@ public class GenASM implements Visitor { @Override public Void visit(Block e) { - for (var statement : e.statements) { + for (var statement : e.statementsOrFunctionCalls) { statement.welcome(this); } return null; diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java b/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java deleted file mode 100644 index 45220bc..0000000 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java +++ /dev/null @@ -1,288 +0,0 @@ -package de.hsrm.compiler.Klang.visitors; - -import java.util.Map; -import java.util.Set; - -import de.hsrm.compiler.Klang.nodes.*; -import de.hsrm.compiler.Klang.nodes.expressions.*; -import de.hsrm.compiler.Klang.nodes.loops.DoWhileLoop; -import de.hsrm.compiler.Klang.nodes.loops.ForLoop; -import de.hsrm.compiler.Klang.nodes.loops.WhileLoop; -import de.hsrm.compiler.Klang.nodes.statements.*; -import de.hsrm.compiler.Klang.types.Type; - -class GetVars implements Visitor { - - public Set vars; - public Map types; - - public GetVars(Set vars, Map types) { - this.vars = vars; - this.types = types; - } - - @Override - public Void visit(IntegerExpression e) { - return null; - } - - @Override - public Void visit(FloatExpression e) { - return null; - } - - @Override - public Void visit(BooleanExpression e) { - return null; - } - - @Override - public Void visit(Variable e) { - return null; - } - - @Override - public Void visit(EqualityExpression e) { - e.lhs.welcome(this); - e.rhs.welcome(this); - return null; - } - - @Override - public Void visit(NotEqualityExpression e) { - e.lhs.welcome(this); - e.rhs.welcome(this); - return null; - } - - @Override - public Void visit(GTExpression e) { - e.lhs.welcome(this); - e.rhs.welcome(this); - return null; - } - - @Override - public Void visit(GTEExpression e) { - e.lhs.welcome(this); - e.rhs.welcome(this); - return null; - } - - @Override - public Void visit(LTExpression e) { - e.lhs.welcome(this); - e.rhs.welcome(this); - return null; - } - - @Override - public Void visit(LTEExpression e) { - e.lhs.welcome(this); - e.rhs.welcome(this); - return null; - } - - @Override - public Void visit(AdditionExpression e) { - e.lhs.welcome(this); - e.rhs.welcome(this); - return null; - } - - @Override - public Void visit(SubstractionExpression e) { - e.lhs.welcome(this); - e.rhs.welcome(this); - return null; - } - - @Override - public Void visit(MultiplicationExpression e) { - e.lhs.welcome(this); - e.rhs.welcome(this); - return null; - } - - @Override - public Void visit(DivisionExpression e) { - e.lhs.welcome(this); - e.rhs.welcome(this); - return null; - } - - @Override - public Void visit(ModuloExpression e) { - e.lhs.welcome(this); - e.rhs.welcome(this); - return null; - } - - @Override - public Void visit(NegateExpression e) { - e.lhs.welcome(this); - return null; - } - - @Override - public Void visit(OrExpression e) { - e.lhs.welcome(this); - e.rhs.welcome(this); - return null; - } - - @Override - public Void visit(AndExpression e) { - e.lhs.welcome(this); - e.rhs.welcome(this); - return null; - } - - @Override - public Void visit(NotExpression e) { - e.lhs.welcome(this); - return null; - } - - @Override - public Void visit(IfStatement e) { - e.cond.welcome(this); - e.then.welcome(this); - if (e.alt != null) { - e.alt.welcome(this); - } else if (e.elif != null) { - e.elif.welcome(this); - } - return null; - } - - @Override - public Void visit(WhileLoop e) { - e.cond.welcome(this); - e.block.welcome(this); - return null; - } - - @Override - public Void visit(DoWhileLoop e) { - e.cond.welcome(this); - e.block.welcome(this); - return null; - } - - @Override - public Void visit(ForLoop e) { - e.init.welcome(this); - e.condition.welcome(this); - e.step.welcome(this); - e.block.welcome(this); - return null; - } - - @Override - public Void visit(VariableDeclaration e) { - vars.add(e.name); - types.put(e.name, e.type); - return null; - } - - @Override - public Void visit(VariableAssignment e) { - e.expression.welcome(this); - return null; - } - - @Override - public Void visit(ReturnStatement e) { - if (e.expression != null) { - e.expression.welcome(this); - } - return null; - } - - @Override - public Void visit(Block e) { - for (var statement : e.statements) { - statement.welcome(this); - } - return null; - } - - @Override - public Void visit(FunctionDefinition e) { - e.block.welcome(this); - return null; - } - - @Override - public Void visit(FunctionCall e) { - for (var expression : e.arguments) { - expression.welcome(this); - } - return null; - } - - @Override - public Void visit(Program e) { - e.expression.welcome(this); - for (var func : e.funcs) { - func.welcome(this); - } - return null; - } - - @Override - public Void visit(Parameter e) { - return null; - } - - @Override - public Void visit(EnumDefinition e) { - return null; - } - - @Override - public Void visit(EnumValue e) { - return null; - } - - @Override - public Void visit(StructDefinition e) { - return null; - } - - @Override - public Void visit(StructField e) { - return null; - } - - @Override - public Void visit(MemberAccessExpression e) { - return null; - } - - @Override - public Void visit(EnumAccessExpression e) { - return null; - } - - @Override - public Void visit(ConstructorCall e) { - return null; - } - - @Override - public Void visit(NullExpression e) { - return null; - } - - @Override - public Void visit(DestructorCall e) { - return null; - } - - @Override - public Void visit(FieldAssignment e) { - return null; - } -} \ No newline at end of file