diff --git a/src/tile/AntlrToExpression.java b/src/tile/AntlrToExpression.java index 8bf233b..ad1044c 100644 --- a/src/tile/AntlrToExpression.java +++ b/src/tile/AntlrToExpression.java @@ -276,6 +276,7 @@ public Expression visitFuncCallExpression(FuncCallExpressionContext ctx) { is_native = true; } catch (Exception e) { Log.error(line + ":" + col + ": function " + funcId + " is not defined before called."); + return null; // FIXME: find a better way and consider func overloading as well for the future! } } @@ -357,8 +358,31 @@ public Expression visitLogicalAndExpression(LogicalAndExpressionContext ctx) { @Override public Expression visitLogicalOrExpression(LogicalOrExpressionContext ctx) { - // TODO Auto-generated method stub - return super.visitLogicalOrExpression(ctx); + if (ctx.logicalAndExpression().size() == 1) { + return visit(ctx.logicalAndExpression(0)); + } + + // Otherwise, process the operator and operands. + Expression left = visit(ctx.logicalAndExpression(0)); // The first operand. + for (int i = 1; i < ctx.logicalAndExpression().size(); i++) { + // Get the operator (* or /). + String operator = ctx.getChild((i * 2) - 1).getText(); // Operators are at odd indices. + + // Visit the right operand. + Expression right = visit(ctx.logicalAndExpression(i)); + + String lhs_type = left.getType(); + String rhs_type = right.getType(); + + if (!lhs_type.equals("bool") || !rhs_type.equals("bool")) { + int line = ctx.stop.getLine(); + int col = ctx.stop.getCharPositionInLine(); + Log.warning(line + ":" + col + ": logical expressions type should be a bool type!"); + } + TypeInfoLogicalBinop type = TypeResolver.resolveBinopLogicalType(lhs_type, rhs_type); + left = new LogicalExpression(left, operator, right, type); + } + return left; } @Override @@ -523,7 +547,12 @@ public Expression visitArrayIndexAccessor(ArrayIndexAccessorContext ctx) { int reducedDim = exprs.size(); typeInfo = TypeResolver.resolveArrayIndexAccessor(varType.toString(), reducedDim); - return new ArrayIndexAccessor(typeInfo, tasmIdx, exprs); + ArrayIndexAccessor aia = new ArrayIndexAccessor(typeInfo, tasmIdx, exprs); + if (isGlobal.get() == true) { + aia.setAsGlobal(); + } + + return aia; } @Override diff --git a/src/tile/AntlrToStatement.java b/src/tile/AntlrToStatement.java index fd52ab9..68e16e1 100644 --- a/src/tile/AntlrToStatement.java +++ b/src/tile/AntlrToStatement.java @@ -24,11 +24,13 @@ import gen.antlr.tile.tileParser.ProgramContext; import gen.antlr.tile.tileParser.ReturnStmtContext; import gen.antlr.tile.tileParser.SelectionStmtContext; +import gen.antlr.tile.tileParser.StructDefinitionContext; import gen.antlr.tile.tileParser.VariableAssignmentContext; import gen.antlr.tile.tileParser.VariableDeclerationContext; import gen.antlr.tile.tileParser.VariableDefinitionContext; import gen.antlr.tile.tileParser.VariableStmtContext; import gen.antlr.tile.tileParser.TasmBlockContext; +import gen.antlr.tile.tileParser.TypeDefinitionContext; import gen.antlr.tile.tileParser.WhileStmtContext; import gen.antlr.tile.tileParser.ForInitialContext; import gen.antlr.tile.tileParserBaseVisitor; @@ -45,6 +47,19 @@ public class AntlrToStatement extends tileParserBaseVisitor { + public static boolean staticReturnAnalysis(BlockStmt blck) { + for (Statement stmt : blck.statements) { + if (stmt instanceof ReturnStmt) { + return true; + } else if (stmt instanceof BlockStmt) { + if (staticReturnAnalysis((BlockStmt)stmt)) { + return true; + } + } + } + return false; + } + @Override public Statement visitBlockStmt(BlockStmtContext ctx) { BlockStmt blockStmt = null; @@ -156,6 +171,20 @@ public Statement visitBlockStmt(BlockStmtContext ctx) { if (Program.parentStack.isEmpty() || !(Program.parentStack.peek() instanceof ForStmt)) { Program.blockStack.remove(Program.blockStack.size() - 1); } + + // static analysis if func returns the correct thing + if (parent instanceof FuncDefStmtContext) { + if (!(func.getReturn_type().result_type.equals("void"))) { + boolean isReturned = staticReturnAnalysis(blockStmt); + if (!isReturned) { + int line = ((FuncDefStmtContext)parentFunc).IDENTIFIER().getSymbol().getLine(); + int col = ((FuncDefStmtContext)parentFunc).IDENTIFIER().getSymbol().getCharPositionInLine(); + Log.error(line + ":" + col + ": function should return!"); + } + } + } + + return blockStmt; } @@ -180,7 +209,18 @@ public Statement visitBlockStmt(BlockStmtContext ctx) { } blockStmt.addStatement(stmt); } - + + // static analysis if func returns the correct thing + if (parent instanceof FuncDefStmtContext) { + if (!(func.getReturn_type().result_type.equals("void"))) { + boolean isReturned = staticReturnAnalysis(blockStmt); + if (!isReturned) { + int line = ((FuncDefStmtContext)parentFunc).IDENTIFIER().getSymbol().getLine(); + int col = ((FuncDefStmtContext)parentFunc).IDENTIFIER().getSymbol().getCharPositionInLine(); + Log.error(line + ":" + col + ": function should return!"); + } + } + } if (Program.parentStack.isEmpty() || !(Program.parentStack.peek() instanceof ForStmt)) { Program.blockStack.remove(Program.blockStack.size() - 1); @@ -263,38 +303,26 @@ else if (ctx.variableStmt() != null) { return result; } - // @Override - // public Statement visitTypeDefinition(TypeDefinitionContext ctx) { - // String name = ctx.IDENTIFIER().getText(); - - // if (ctx.structDefinition() != null) { - // TypeDefinition def = new TypeDefinition(name, TypeDefinition.Kind.STRUCT); - // List fields = new ArrayList<>(); - - // for (var fieldCtx : ctx.structDefinition().fieldDefinition()) { - // String fieldName = fieldCtx.IDENTIFIER().getText(); - // String fieldType = fieldCtx.typeName().getText(); - // fields.add(new String(fieldName, fieldType)); - // } - - // def.fields = fields; - // TypeResolver.userTypeDefs.put(name, def); - - // } else if (ctx.typeUnion() != null) { - // TypeDefinition def = new TypeDefinition(name, TypeDefinition.Kind.UNION); - - // List variants = ctx.typeUnion().IDENTIFIER() - // .stream() - // .map(ParseTree::getText) - // .toList(); - - // def.variants = variants; - // TypeResolver.userTypeDefs.put(name, def); - // } + @Override + public Statement visitTypeDefinition(TypeDefinitionContext ctx) { + String typeName = ctx.IDENTIFIER().getText(); + List fields = null; + TypeDefinition.Kind kind = null; + if (ctx.structDefinition() != null) { + fields = new ArrayList<>(); + kind = TypeDefinition.Kind.STRUCT; + for (int i = 0; i < ctx.structDefinition().fieldDefinition().size(); i++) { + String id = ctx.structDefinition().fieldDefinition(i).IDENTIFIER().getText(); + String type = ctx.structDefinition().fieldDefinition(i).typeName().getText(); + TypeDefinition.Field field = new TypeDefinition.Field(id, type); + fields.add(field); + } + } - // return new ExpressionStmt(null, false); - // return super.visitTypeDefinition(ctx); - // } + TypeDefinition td = new TypeDefinition(typeName, kind, fields); + TypeResolver.userTypeDefs.put(typeName, td); + return td; + } @Override public Statement visitFuncDefStmt(FuncDefStmtContext ctx) { diff --git a/src/tile/ast/expr/ArrayIndexAccessor.java b/src/tile/ast/expr/ArrayIndexAccessor.java index 05e4047..d5040a2 100644 --- a/src/tile/ast/expr/ArrayIndexAccessor.java +++ b/src/tile/ast/expr/ArrayIndexAccessor.java @@ -10,29 +10,47 @@ public class ArrayIndexAccessor implements Expression { TypeInfoArray typeInfo; private int identifierTasmIdx; List indicies; + boolean isGlobal; public ArrayIndexAccessor(TypeInfoArray typeInfo, int identifierTasmIdx, List indicies) { this.typeInfo = typeInfo; this.identifierTasmIdx = identifierTasmIdx; this.indicies = indicies; + isGlobal = false; + } + + private String genLoadCode(String generatedCode) { + if (isGlobal) { + generatedCode += " gload " + identifierTasmIdx + "\n"; + } else { + generatedCode += " load " + identifierTasmIdx + "\n"; + } + return generatedCode; } @Override public String generateTasm(String generatedCode) { - generatedCode += " load " + identifierTasmIdx + "\n"; + generatedCode = genLoadCode(generatedCode); generatedCode += " deref ; dereferance\n"; - // FIXME: + generatedCode += " derefb " + typeInfo.element_size + " ; dereferance\n"; generatedCode = indicies.get(0).generateTasm(generatedCode); generatedCode += " push " + typeInfo.element_size + "\n"; generatedCode += " mult\n"; generatedCode += " add\n"; - generatedCode += " deref ; dereferance\n"; return generatedCode; + + + // generatedCode += " derefb " + typeInfo.element_size + " ; dereferance\n"; + // generatedCode += " deref ; dereferance\n"; } @Override public String getType() { return typeInfo.type; } + + public void setAsGlobal() { + isGlobal = true; + } } diff --git a/src/tile/ast/expr/LogicalExpression.java b/src/tile/ast/expr/LogicalExpression.java index 440ad33..55d3288 100644 --- a/src/tile/ast/expr/LogicalExpression.java +++ b/src/tile/ast/expr/LogicalExpression.java @@ -28,6 +28,8 @@ public String generateTasm(String generatedCode) { if (operator.equals("&&")) { generatedCode += " and\n"; + } else if (operator.equals("||")) { + generatedCode += " or\n"; } return generatedCode; diff --git a/src/tile/ast/stmt/TypeDefinition.java b/src/tile/ast/stmt/TypeDefinition.java index 9021d3d..c795070 100644 --- a/src/tile/ast/stmt/TypeDefinition.java +++ b/src/tile/ast/stmt/TypeDefinition.java @@ -10,25 +10,26 @@ public enum Kind { UNION } - public String name; + public String typeName; public Kind kind; public static class Field { - public String name; + public String id; public String type; - public Field(String name, String type) { - this.name = name; + public Field(String id, String type) { + this.id = id; this.type = type; } } - public List fields; // for struct - public List variants; // for union + private List fields; // for struct + private List variants; // for union - public TypeDefinition(String name, Kind kind) { - this.name = name; + public TypeDefinition(String typeName, Kind kind, List fields) { + this.typeName = typeName; this.kind = kind; + this.fields = fields; } @Override diff --git a/src/tile/ast/stmt/VariableDecleration.java b/src/tile/ast/stmt/VariableDecleration.java index 6734d0b..5590395 100644 --- a/src/tile/ast/stmt/VariableDecleration.java +++ b/src/tile/ast/stmt/VariableDecleration.java @@ -37,8 +37,8 @@ public String generateTasm(String generatedCode) { // 0 for all defined types // user defined null (0) if (isGlobal) { - generatedCode += "push 0\n"; - generatedCode += "gstore " + tasmIdx + " ; " + typeInfo + " " + varId + "\n"; + // generatedCode += "push 0\n"; + // generatedCode += "gstore " + tasmIdx + " ; " + typeInfo + " " + varId + "\n"; } else { generatedCode += " push 0\n"; generatedCode += " store " + tasmIdx + " ; " + typeInfo + " " + varId + "\n"; diff --git a/tileParser.g4 b/tileParser.g4 index 406c4a2..d2565bd 100644 --- a/tileParser.g4 +++ b/tileParser.g4 @@ -87,6 +87,10 @@ objectLiteralFieldAssignment : '.' IDENTIFIER assignmentOperator expression ; +objectAccessor + : IDENTIFIER '.' IDENTIFIER + ; + unaryExpression : incDecOperator primaryExpression | primaryExpression incDecOperator @@ -233,6 +237,7 @@ variableDefinition variableAssignment : IDENTIFIER assignmentOperator expressionStmt | arrayIndexAccessorSetter assignmentOperator expressionStmt + | objectAccessor assignmentOperator expressionStmt ; loopStmt