From 0316a7d4bf0a5382e97b5442979fc7a6aeb25522 Mon Sep 17 00:00:00 2001 From: Marvin Kaiser Date: Tue, 3 Mar 2020 20:45:55 +0100 Subject: [PATCH 01/14] 25: Start adding Float Type --- .../antlr4/de/hsrm/compiler/Klang/Klang.g4 | 8 + .../hsrm/compiler/Klang/ContextAnalysis.java | 105 +++++- .../java/de/hsrm/compiler/Klang/Value.java | 12 + .../nodes/expressions/FloatExpression.java | 16 + .../hsrm/compiler/Klang/types/FloatType.java | 40 +++ .../compiler/Klang/types/IntegerType.java | 7 +- .../compiler/Klang/types/NumericType.java | 8 + .../compiler/Klang/types/PrimitiveType.java | 8 + .../de/hsrm/compiler/Klang/types/Type.java | 6 + .../compiler/Klang/visitors/EvalVisitor.java | 229 +++++++++++++- .../hsrm/compiler/Klang/visitors/GenASM.java | 298 ++++++++++++++---- .../hsrm/compiler/Klang/visitors/GetVars.java | 12 +- .../Klang/visitors/PrettyPrintVisitor.java | 6 + .../hsrm/compiler/Klang/visitors/Visitor.java | 1 + 14 files changed, 658 insertions(+), 98 deletions(-) create mode 100644 src/main/java/de/hsrm/compiler/Klang/nodes/expressions/FloatExpression.java create mode 100644 src/main/java/de/hsrm/compiler/Klang/types/FloatType.java create mode 100644 src/main/java/de/hsrm/compiler/Klang/types/NumericType.java diff --git a/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 b/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 index d4d6f03..e8021af 100644 --- a/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 +++ b/src/main/antlr4/de/hsrm/compiler/Klang/Klang.g4 @@ -87,6 +87,7 @@ expression atom : INTEGER_LITERAL #intAtom | BOOLEAN_LITERAL #boolAtom + | FLOAT_LITERAL #floatAtom | IDENT #variable ; @@ -97,6 +98,7 @@ type_annotation type : INTEGER | BOOLEAN + | FLOAT ; functionCall @@ -131,6 +133,7 @@ WHILE: 'while'; DO: 'do'; FOR: 'for'; +PERIOD: '.'; COL: ':'; SCOL: ';'; OBRK: '{'; @@ -157,11 +160,16 @@ DIV: '/'; BOOLEAN: 'bool'; INTEGER: 'int'; +FLOAT: 'float'; INTEGER_LITERAL : [0-9]+ ; +FLOAT_LITERAL + : INTEGER_LITERAL PERIOD INTEGER_LITERAL + ; + BOOLEAN_LITERAL : 'true' | 'false' diff --git a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java index cc191f3..c6104e8 100644 --- a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java +++ b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java @@ -18,6 +18,13 @@ public class ContextAnalysis extends KlangBaseVisitor { Map funcs; Type currentDeclaredReturnType; + private void checkNumeric(Node lhs, Node rhs, int line, int col) { + if (!lhs.type.isNumericType() || !rhs.type.isNumericType()) { + String error = "Only numeric types are allowed for this expression."; + throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); + } + } + public ContextAnalysis(Map funcs) { this.funcs = funcs; } @@ -256,6 +263,10 @@ public class ContextAnalysis extends KlangBaseVisitor { result.type = Type.getBooleanType(); result.line = ctx.start.getLine(); result.col = ctx.start.getCharPositionInLine(); + if (!lhs.type.equals(Type.getBooleanType()) || !rhs.type.equals(Type.getBooleanType())) { + String error = "|| is only defined for bool."; + throw new RuntimeException(Helper.getErrorPrefix(result.line, result.col) + error); + } return result; } @@ -267,6 +278,10 @@ public class ContextAnalysis extends KlangBaseVisitor { result.type = Type.getBooleanType(); result.line = ctx.start.getLine(); result.col = ctx.start.getCharPositionInLine(); + if (!lhs.type.equals(Type.getBooleanType()) || !rhs.type.equals(Type.getBooleanType())) { + String error = "&& is only defined for bool."; + throw new RuntimeException(Helper.getErrorPrefix(result.line, result.col) + error); + } return result; } @@ -277,11 +292,15 @@ public class ContextAnalysis extends KlangBaseVisitor { int line = ctx.start.getLine(); int col = ctx.start.getCharPositionInLine(); AdditionExpression result = new AdditionExpression((Expression) lhs, (Expression) rhs); + try { result.type = lhs.type.combine(rhs.type); } catch (Exception e) { throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage()); } + + checkNumeric(lhs, rhs, line, col); + result.line = ctx.start.getLine(); result.col = ctx.start.getCharPositionInLine(); return result; @@ -319,9 +338,10 @@ public class ContextAnalysis extends KlangBaseVisitor { int line = ctx.start.getLine(); int col = ctx.start.getCharPositionInLine(); - if (lhs.type != Type.getIntegerType() || rhs.type != Type.getIntegerType()) { - String error = "Both operants of this expression have to be a number."; - throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); + try { + lhs.type.combine(rhs.type); + } catch (Exception e) { + throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage()); } NotEqualityExpression result = new NotEqualityExpression((Expression) lhs, (Expression) rhs); @@ -338,11 +358,14 @@ public class ContextAnalysis extends KlangBaseVisitor { int line = ctx.start.getLine(); int col = ctx.start.getCharPositionInLine(); - if (lhs.type != Type.getIntegerType() || rhs.type != Type.getIntegerType()) { - String error = "Both operants of this expression have to be a number."; - throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); + try { + lhs.type.combine(rhs.type); + } catch (Exception e) { + throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage()); } + checkNumeric(lhs, rhs, line, col); + LTExpression result = new LTExpression((Expression) lhs, (Expression) rhs); result.type = Type.getBooleanType(); result.line = line; @@ -357,8 +380,14 @@ public class ContextAnalysis extends KlangBaseVisitor { int line = ctx.start.getLine(); int col = ctx.start.getCharPositionInLine(); - if (lhs.type != Type.getIntegerType() || rhs.type != Type.getIntegerType()) { - String error = "Both operants of this expression have to be a number."; + try { + lhs.type.combine(rhs.type); + } catch (Exception e) { + throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage()); + } + + if (!lhs.type.isNumericType() || !rhs.type.isNumericType()) { + String error = "Only numeric types are allowed for this expression."; throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); } @@ -376,11 +405,14 @@ public class ContextAnalysis extends KlangBaseVisitor { int line = ctx.start.getLine(); int col = ctx.start.getCharPositionInLine(); - if (lhs.type != Type.getIntegerType() || rhs.type != Type.getIntegerType()) { - String error = "Both operants of this expression have to be a number."; - throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); + try { + lhs.type.combine(rhs.type); + } catch (Exception e) { + throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage()); } + checkNumeric(lhs, rhs, line, col); + LTEExpression result = new LTEExpression((Expression) lhs, (Expression) rhs); result.type = Type.getBooleanType(); result.line = line; @@ -395,11 +427,14 @@ public class ContextAnalysis extends KlangBaseVisitor { int line = ctx.start.getLine(); int col = ctx.start.getCharPositionInLine(); - if (lhs.type != Type.getIntegerType() || rhs.type != Type.getIntegerType()) { - String error = "Both operants of this expression have to be a number."; - throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); + try { + lhs.type.combine(rhs.type); + } catch (Exception e) { + throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage()); } + checkNumeric(lhs, rhs, line, col); + GTEExpression result = new GTEExpression((Expression) lhs, (Expression) rhs); result.type = Type.getBooleanType(); result.line = line; @@ -414,11 +449,15 @@ public class ContextAnalysis extends KlangBaseVisitor { int line = ctx.start.getLine(); int col = ctx.start.getCharPositionInLine(); SubstractionExpression result = new SubstractionExpression((Expression) lhs, (Expression) rhs); + try { result.type = lhs.type.combine(rhs.type); } catch (Exception e) { throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage()); } + + checkNumeric(lhs, rhs, line, col); + result.line = line; result.col = col; return result; @@ -431,11 +470,15 @@ public class ContextAnalysis extends KlangBaseVisitor { int line = ctx.start.getLine(); int col = ctx.start.getCharPositionInLine(); MultiplicationExpression result = new MultiplicationExpression((Expression) lhs, (Expression) rhs); + try { result.type = lhs.type.combine(rhs.type); } catch (Exception e) { throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage()); } + + checkNumeric(lhs, rhs, line, col); + result.line = line; result.col = col; return result; @@ -448,11 +491,15 @@ public class ContextAnalysis extends KlangBaseVisitor { int line = ctx.start.getLine(); int col = ctx.start.getCharPositionInLine(); DivisionExpression result = new DivisionExpression((Expression) lhs, (Expression) rhs); + try { result.type = lhs.type.combine(rhs.type); } catch (Exception e) { throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage()); } + + checkNumeric(lhs, rhs, line, col); + result.line = line; result.col = col; return result; @@ -465,11 +512,20 @@ public class ContextAnalysis extends KlangBaseVisitor { int line = ctx.start.getLine(); int col = ctx.start.getCharPositionInLine(); ModuloExpression result = new ModuloExpression((Expression) lhs, (Expression) rhs); + try { result.type = lhs.type.combine(rhs.type); } catch (Exception e) { throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage()); } + + checkNumeric(lhs, rhs, line, col); + + if (lhs.type.equals(Type.getFloatType()) || rhs.type.equals(Type.getFloatType())) { + String error = "Only integers are allowed for modulo."; + throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); + } + result.line = line; result.col = col; return result; @@ -482,6 +538,12 @@ public class ContextAnalysis extends KlangBaseVisitor { result.type = expression.type; result.line = ctx.start.getLine(); result.col = ctx.start.getCharPositionInLine(); + + if (!result.type.isNumericType()) { + String error = "Only numeric types are allowed for this expression."; + throw new RuntimeException(Helper.getErrorPrefix(result.line, result.col) + error); + } + return result; } @@ -492,6 +554,12 @@ public class ContextAnalysis extends KlangBaseVisitor { result.type = expression.type; result.line = ctx.start.getLine(); result.col = ctx.start.getCharPositionInLine(); + + if (!result.type.equals(Type.getBooleanType())) { + String error = "Only boolean type is allowed for this expression."; + throw new RuntimeException(Helper.getErrorPrefix(result.line, result.col) + error); + } + return result; } @@ -534,6 +602,15 @@ public class ContextAnalysis extends KlangBaseVisitor { return n; } + @Override + public Node visitFloatAtom(KlangParser.FloatAtomContext ctx) { + Node n = new FloatExpression(Double.parseDouble(ctx.getText())); + n.type = Type.getFloatType(); + n.line = ctx.start.getLine(); + n.col = ctx.start.getCharPositionInLine(); + return n; + } + @Override public Node visitBoolAtom(KlangParser.BoolAtomContext ctx) { Node n = new BooleanExpression(ctx.getText().equals("true") ? true : false); diff --git a/src/main/java/de/hsrm/compiler/Klang/Value.java b/src/main/java/de/hsrm/compiler/Klang/Value.java index 1b2eeb9..c0551c6 100644 --- a/src/main/java/de/hsrm/compiler/Klang/Value.java +++ b/src/main/java/de/hsrm/compiler/Klang/Value.java @@ -1,12 +1,20 @@ package de.hsrm.compiler.Klang; +import de.hsrm.compiler.Klang.types.Type; + public class Value { + public Type type; private Object value; public Value(Object value) { this.value = value; } + public Value(Object value, Type type) { + this.value = value; + this.type = type; + } + public Object asObject() { return this.value; } @@ -14,6 +22,10 @@ public class Value { public int asInteger() { return (int) this.value; } + + public double asFloat() { + return (double) this.value; + } public boolean asBoolean() { return (boolean) this.value; diff --git a/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/FloatExpression.java b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/FloatExpression.java new file mode 100644 index 0000000..e7e4e09 --- /dev/null +++ b/src/main/java/de/hsrm/compiler/Klang/nodes/expressions/FloatExpression.java @@ -0,0 +1,16 @@ +package de.hsrm.compiler.Klang.nodes.expressions; + +import de.hsrm.compiler.Klang.visitors.Visitor; + +public class FloatExpression extends Expression { + public double value; + + public FloatExpression(double value) { + this.value = value; + } + + @Override + public R welcome(Visitor v) { + return v.visit(this); + } +} \ No newline at end of file diff --git a/src/main/java/de/hsrm/compiler/Klang/types/FloatType.java b/src/main/java/de/hsrm/compiler/Klang/types/FloatType.java new file mode 100644 index 0000000..14f3fd7 --- /dev/null +++ b/src/main/java/de/hsrm/compiler/Klang/types/FloatType.java @@ -0,0 +1,40 @@ +package de.hsrm.compiler.Klang.types; + +public class FloatType extends NumericType { + + private static FloatType instance = null; + + public static FloatType getType() { + if (instance != null) { + return instance; + } + instance = new FloatType(); + return instance; + } + + @Override + public boolean isFloatType() { + return true; + } + + @Override + public String getName() { + return "float"; + } + + @Override + public Type combine(Type that) { + // Combining two equal types always works + if (that.equals(this)) { + return this; + } + + if (that.equals(Type.getIntegerType())) { + return Type.getFloatType(); + } + + // Every remaining type will throw a RuntimeException + throw new RuntimeException("Type missmatch: cannot combine " + this.getName() + " and " + that.getName()); + } + +} \ No newline at end of file diff --git a/src/main/java/de/hsrm/compiler/Klang/types/IntegerType.java b/src/main/java/de/hsrm/compiler/Klang/types/IntegerType.java index c3fad32..41064d1 100644 --- a/src/main/java/de/hsrm/compiler/Klang/types/IntegerType.java +++ b/src/main/java/de/hsrm/compiler/Klang/types/IntegerType.java @@ -1,6 +1,6 @@ package de.hsrm.compiler.Klang.types; -public class IntegerType extends PrimitiveType { +public class IntegerType extends NumericType { private static IntegerType instance = null; @@ -29,8 +29,9 @@ public class IntegerType extends PrimitiveType { return this; } - // Check other possible combinations - // if (that.equals(Type.getFloatType())) return Type.getFloatType(); + if (that.equals(Type.getFloatType())) { + return Type.getFloatType(); + } // Every remaining type will throw a RuntimeException throw new RuntimeException("Type missmatch: cannot combine " + this.getName() + " and " + that.getName()); diff --git a/src/main/java/de/hsrm/compiler/Klang/types/NumericType.java b/src/main/java/de/hsrm/compiler/Klang/types/NumericType.java new file mode 100644 index 0000000..9c03a29 --- /dev/null +++ b/src/main/java/de/hsrm/compiler/Klang/types/NumericType.java @@ -0,0 +1,8 @@ +package de.hsrm.compiler.Klang.types; + +public abstract class NumericType extends PrimitiveType { + @Override + public boolean isNumericType() { + return true; + } +} \ No newline at end of file diff --git a/src/main/java/de/hsrm/compiler/Klang/types/PrimitiveType.java b/src/main/java/de/hsrm/compiler/Klang/types/PrimitiveType.java index 3a87c7a..7493c37 100644 --- a/src/main/java/de/hsrm/compiler/Klang/types/PrimitiveType.java +++ b/src/main/java/de/hsrm/compiler/Klang/types/PrimitiveType.java @@ -14,4 +14,12 @@ public abstract class PrimitiveType extends Type { public boolean isBooleanType() { return false; }; + + public boolean isFloatType() { + return false; + }; + + public boolean isNumericType() { + return false; + } } \ No newline at end of file diff --git a/src/main/java/de/hsrm/compiler/Klang/types/Type.java b/src/main/java/de/hsrm/compiler/Klang/types/Type.java index a4771b5..75a8157 100644 --- a/src/main/java/de/hsrm/compiler/Klang/types/Type.java +++ b/src/main/java/de/hsrm/compiler/Klang/types/Type.java @@ -12,10 +12,15 @@ public abstract class Type { return BooleanType.getType(); } + public static FloatType getFloatType() { + return FloatType.getType(); + } + public static Type getByName(String name) { switch (name) { case "bool": return getBooleanType(); case "int": return getIntegerType(); + case "float": return getFloatType(); default: throw new RuntimeException("Unknown type " + name); } } @@ -23,4 +28,5 @@ public abstract class Type { public abstract String getName(); public abstract Type combine(Type that); public abstract boolean isPrimitiveType(); + public abstract boolean isNumericType(); } \ No newline at end of file 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 5147648..2e3495d 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java @@ -13,6 +13,7 @@ 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; public class EvalVisitor implements Visitor { @@ -21,115 +22,309 @@ public class EvalVisitor implements Visitor { @Override public Value visit(IntegerExpression e) { - return new Value(e.value); + Value result = new Value(e.value); + result.type = Type.getIntegerType(); + return result; + } + + @Override + public Value visit(FloatExpression e) { + Value result = new Value(e.value); + result.type = Type.getFloatType(); + return result; } @Override public Value visit(BooleanExpression e) { - return new Value(e.value); + Value result = new Value(e.value); + result.type = Type.getBooleanType(); + return result; } @Override public Value visit(EqualityExpression e) { Value lhs = e.lhs.welcome(this); Value rhs = e.rhs.welcome(this); - return new Value(lhs.asObject() == rhs.asObject()); + Type resultType = Type.getBooleanType(); + Type combineType = lhs.type.combine(rhs.type); + + switch(combineType.getName()) { + case "bool": { + return new Value(lhs.asBoolean() == rhs.asBoolean(), resultType); + } + case "int": { + return new Value(lhs.asInteger() == rhs.asInteger(), resultType); + } + case "float": { + return new Value(lhs.asFloat() == rhs.asFloat(), resultType); + } + default: { + return new Value(lhs.asObject() == rhs.asObject(), resultType); + } + } } @Override public Value visit(NotEqualityExpression e) { Value lhs = e.lhs.welcome(this); Value rhs = e.rhs.welcome(this); - return new Value(lhs.asObject() != rhs.asObject()); + Type resultType = Type.getBooleanType(); + Type combineType = lhs.type.combine(rhs.type); + + switch(combineType.getName()) { + case "bool": { + return new Value(lhs.asBoolean() != rhs.asBoolean(), resultType); + } + case "int": { + return new Value(lhs.asInteger() != rhs.asInteger(), resultType); + } + case "float": { + return new Value(lhs.asFloat() != rhs.asFloat(), resultType); + } + default: { + return new Value(lhs.asObject() != rhs.asObject(), resultType); + } + } } @Override public Value visit(GTExpression e) { Value lhs = e.lhs.welcome(this); Value rhs = e.rhs.welcome(this); - return new Value(lhs.asInteger() > rhs.asInteger()); + Type resultType = Type.getBooleanType(); + Type combineType = lhs.type.combine(rhs.type); + + switch(combineType.getName()) { + case "int": { + return new Value(lhs.asInteger() > rhs.asInteger(), resultType); + } + case "float": { + return new Value(lhs.asFloat() > rhs.asFloat(), resultType); + } + default: { + throw new RuntimeException("Unknown Type encountered"); + } + } } @Override public Value visit(GTEExpression e) { Value lhs = e.lhs.welcome(this); Value rhs = e.rhs.welcome(this); - return new Value(lhs.asInteger() >= rhs.asInteger()); + Type resultType = Type.getBooleanType(); + Type combineType = lhs.type.combine(rhs.type); + + switch(combineType.getName()) { + case "int": { + return new Value(lhs.asInteger() >= rhs.asInteger(), resultType); + } + case "float": { + return new Value(lhs.asFloat() >= rhs.asFloat(), resultType); + } + default: { + throw new RuntimeException("Unknown Type encountered"); + } + } } @Override public Value visit(LTExpression e) { Value lhs = e.lhs.welcome(this); Value rhs = e.rhs.welcome(this); - return new Value(lhs.asInteger() < rhs.asInteger()); + Type resultType = Type.getBooleanType(); + Type combineType = lhs.type.combine(rhs.type); + + switch(combineType.getName()) { + case "int": { + return new Value(lhs.asInteger() < rhs.asInteger(), resultType); + } + case "float": { + return new Value(lhs.asFloat() < rhs.asFloat(), resultType); + } + default: { + throw new RuntimeException("Unknown Type encountered"); + } + } } @Override public Value visit(LTEExpression e) { Value lhs = e.lhs.welcome(this); Value rhs = e.rhs.welcome(this); - return new Value(lhs.asInteger() <= rhs.asInteger()); + Type combineType = lhs.type.combine(rhs.type); + Type resultType = Type.getBooleanType(); + + switch(combineType.getName()) { + case "int": { + return new Value(lhs.asInteger() <= rhs.asInteger(), resultType); + } + case "float": { + return new Value(lhs.asFloat() <= rhs.asFloat(), resultType); + } + default: { + throw new RuntimeException("Unknown Type encountered"); + } + } } @Override public Value visit(AdditionExpression e) { Value lhs = e.lhs.welcome(this); Value rhs = e.rhs.welcome(this); - return new Value(lhs.asInteger() + rhs.asInteger()); + Type resultType = lhs.type.combine(rhs.type); + + switch(resultType.getName()) { + case "int": { + return new Value(lhs.asInteger() + rhs.asInteger(), resultType); + } + case "float": { + return new Value(lhs.asFloat() + rhs.asFloat(), resultType); + } + default: { + throw new RuntimeException("Unknown Type encountered"); + } + } } @Override public Value visit(SubstractionExpression e) { Value lhs = e.lhs.welcome(this); Value rhs = e.rhs.welcome(this); - return new Value(lhs.asInteger() - rhs.asInteger()); + Type resultType = lhs.type.combine(rhs.type); + + switch(resultType.getName()) { + case "int": { + return new Value(lhs.asInteger() - rhs.asInteger(), resultType); + } + case "float": { + return new Value(lhs.asFloat() - rhs.asFloat(), resultType); + } + default: { + throw new RuntimeException("Unknown Type encountered"); + } + } } @Override public Value visit(MultiplicationExpression e) { Value lhs = e.lhs.welcome(this); Value rhs = e.rhs.welcome(this); - return new Value(lhs.asInteger() * rhs.asInteger()); + Type resultType = lhs.type.combine(rhs.type); + + switch(resultType.getName()) { + case "int": { + return new Value(lhs.asInteger() * rhs.asInteger(), resultType); + } + case "float": { + return new Value(lhs.asFloat() * rhs.asFloat(), resultType); + } + default: { + throw new RuntimeException("Unknown Type encountered"); + } + } } @Override public Value visit(DivisionExpression e) { Value lhs = e.lhs.welcome(this); Value rhs = e.rhs.welcome(this); - return new Value(lhs.asInteger() / rhs.asInteger()); + Type resultType = lhs.type.combine(rhs.type); + + switch(resultType.getName()) { + case "int": { + return new Value(lhs.asInteger() / rhs.asInteger(), resultType); + } + case "float": { + return new Value(lhs.asFloat() / rhs.asFloat(), resultType); + } + default: { + throw new RuntimeException("Unknown Type encountered"); + } + } } @Override public Value visit(ModuloExpression e) { Value lhs = e.lhs.welcome(this); Value rhs = e.rhs.welcome(this); - return new Value(lhs.asInteger() % rhs.asInteger()); + Type resultType = lhs.type.combine(rhs.type); + + switch(resultType.getName()) { + case "int": { + return new Value(lhs.asInteger() % rhs.asInteger(), resultType); + } + case "float": { + return new Value(lhs.asFloat() % rhs.asFloat(), resultType); + } + default: { + throw new RuntimeException("Unknown Type encountered"); + } + } } @Override public Value visit(NegateExpression e) { Value a = e.lhs.welcome(this); - return new Value(-a.asInteger()); + Type resultType = a.type; + + switch(resultType.getName()) { + case "int": { + return new Value(-a.asInteger(), resultType); + } + case "float": { + return new Value(-a.asFloat(), resultType); + } + default: { + throw new RuntimeException("Unknown Type encountered"); + } + } } @Override public Value visit(OrExpression e) { Value lhs = e.lhs.welcome(this); Value rhs = e.rhs.welcome(this); - return new Value(lhs.asBoolean() || rhs.asBoolean()); + Type resultType = lhs.type.combine(rhs.type); + + switch(resultType.getName()) { + case "bool": { + return new Value(lhs.asBoolean() || rhs.asBoolean(), resultType); + } + default: { + throw new RuntimeException("Unknown Type encountered"); + } + } } @Override public Value visit(AndExpression e) { Value lhs = e.lhs.welcome(this); Value rhs = e.rhs.welcome(this); - return new Value(lhs.asBoolean() && rhs.asBoolean()); + Type resultType = lhs.type.combine(rhs.type); + + switch(resultType.getName()) { + case "bool": { + return new Value(lhs.asBoolean() && rhs.asBoolean(), resultType); + } + default: { + throw new RuntimeException("Unknown Type encountered"); + } + } } @Override public Value visit(NotExpression e) { Value lhs = e.lhs.welcome(this); - return new Value(!lhs.asBoolean()); + Type resultType = lhs.type; + + switch(resultType.getName()) { + case "bool": { + return new Value(!lhs.asBoolean(), resultType); + } + default: { + throw new RuntimeException("Unknown Type encountered"); + } + } } @Override 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 d9ecf17..cf94562 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java @@ -12,6 +12,7 @@ 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; public class GenASM implements Visitor { @@ -55,13 +56,83 @@ public class GenASM implements Visitor { } } + private class FloatWriter { + private StringBuilder sb = new StringBuilder(); + private int id = -1; + + public String getFloat(double d) { + String binary = Long.toBinaryString(Double.doubleToLongBits(d)); + String upper = binary.substring(0, 30); + String lower = binary.substring(31, 61); + long first = Long.parseLong(lower, 2); + long second = Long.parseLong(upper, 2); + String lbl = ".FL" + ++id; + sb.append(lbl); + sb.append(":\n"); + sb.append("\t.long "); + sb.append(first); + sb.append("\n"); + sb.append("\t.long "); + sb.append(second); + sb.append("\n"); + return lbl; + } + + public String getNegateFloat() { + String lbl = ".FL" + ++id; + sb.append(lbl); + sb.append(":\n"); + sb.append("\t.long "); + sb.append("0"); + sb.append("\n"); + sb.append("\t.long "); + sb.append("-2147483648"); + sb.append("\n"); + return lbl; + } + + public String getFloatSection() { + return sb.toString(); + } + } + public ExWriter ex; + private FloatWriter fw = new FloatWriter(); private String mainName; Map env = new HashMap<>(); Set vars; String[] rs = { "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9" }; + String[] frs = {"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"}; private int lCount = 0; // Invariante: lCount ist benutzt + private void intToFloat(String src, String dst) { + this.ex.write(" cvtsi2sd " + src +", " + dst + "\n"); + } + + private boolean prepareRegisters(Expression lhs, Expression rhs) { + boolean lhsIsFloat = lhs.type.equals(Type.getFloatType()); + boolean rhsIsFloat = rhs.type.equals(Type.getFloatType()); + if (lhsIsFloat || rhsIsFloat) { + lhs.welcome(this); + if (!lhsIsFloat) { + this.intToFloat("%rax", "%xmm1"); + } else { + this.ex.write(" movsd %xmm0, %xmm1\n"); + } + rhs.welcome(this); + if (!rhsIsFloat) { + this.intToFloat("%rax", "%xmm1"); + } + return true; + } + lhs.welcome(this); + this.ex.write(" pushq %rax\n"); + rhs.welcome(this); + this.ex.write(" popq %rbx\n"); + return false; + } + + public GenASM(ExWriter ex, String mainName) { this.ex = ex; this.mainName = mainName; @@ -78,6 +149,13 @@ public class GenASM implements Visitor { return null; } + @Override + public Void visit(FloatExpression e) { + String floatLabel = fw.getFloat(e.value); + this.ex.write(" movsd " + floatLabel + "(%rip), %xmm0\n"); + return null; + } + @Override public Void visit(BooleanExpression e) { this.ex.write(" movq $" + (e.value ? 1 : 0) + ", %rax\n"); @@ -86,7 +164,11 @@ public class GenASM implements Visitor { @Override public Void visit(Variable e) { - this.ex.write(" movq " + this.env.get(e.name) + "(%rbp), %rax\n"); + if (e.type.equals(Type.getFloatType())) { + this.ex.write(" movsd " + this.env.get(e.name) + "(%rbp), %xmm0\n"); + } else { + this.ex.write(" movq " + this.env.get(e.name) + "(%rbp), %rax\n"); + } return null; } @@ -95,19 +177,20 @@ public class GenASM implements Visitor { int lblTrue = ++lCount; int lblEnd = ++lCount; - e.lhs.welcome(this); - this.ex.write(" pushq %rax\n"); - e.rhs.welcome(this); - this.ex.write(" popq %rbx\n"); - this.ex.write(" cmp %rax, %rbx\n"); - this.ex.write(" je .L" + lblTrue + "\n"); - // false - this.ex.write(" movq $0, %rax\n"); - this.ex.write(" jmp .L" + lblEnd + "\n"); - this.ex.write(".L" + lblTrue + ":\n"); - // true - this.ex.write(" movq $1, %rax\n"); - this.ex.write(".L" + lblEnd + ":\n"); + boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs); + if (isFloatOperation) { + this.ex.write(" ucomisd %xmm0, %xmm1\n"); + } else { + this.ex.write(" cmp %rax, %rbx\n"); + } + this.ex.write(" je .L" + lblTrue + "\n"); + // false + this.ex.write(" movq $0, %rax\n"); + this.ex.write(" jmp .L" + lblEnd + "\n"); + this.ex.write(".L" + lblTrue + ":\n"); + // true + this.ex.write(" movq $1, %rax\n"); + this.ex.write(".L" + lblEnd + ":\n"); return null; } @@ -116,11 +199,12 @@ public class GenASM implements Visitor { int lblTrue = ++lCount; int lblEnd = ++lCount; - e.lhs.welcome(this); - this.ex.write(" pushq %rax\n"); - e.rhs.welcome(this); - this.ex.write(" popq %rbx\n"); - this.ex.write(" cmp %rax, %rbx\n"); + boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs); + if (isFloatOperation) { + this.ex.write(" ucomisd %xmm0, %xmm1\n"); + } else { + this.ex.write(" cmp %rax, %rbx\n"); + } this.ex.write(" jne .L" + lblTrue + "\n"); // false this.ex.write(" movq $0, %rax\n"); @@ -137,11 +221,12 @@ public class GenASM implements Visitor { int lblTrue = ++lCount; int lblEnd = ++lCount; - e.lhs.welcome(this); - this.ex.write(" pushq %rax\n"); - e.rhs.welcome(this); - this.ex.write(" popq %rbx\n"); - this.ex.write(" cmp %rax, %rbx\n"); + boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs); + if (isFloatOperation) { + this.ex.write(" ucomisd %xmm0, %xmm1\n"); + } else { + this.ex.write(" cmp %rax, %rbx\n"); + } this.ex.write(" jg .L" + lblTrue + "\n"); // false this.ex.write(" movq $0, %rax\n"); @@ -158,11 +243,13 @@ public class GenASM implements Visitor { int lblTrue = ++lCount; int lblEnd = ++lCount; - e.lhs.welcome(this); - this.ex.write(" pushq %rax\n"); - e.rhs.welcome(this); - this.ex.write(" popq %rbx\n"); - this.ex.write(" cmp %rax, %rbx\n"); + + boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs); + if (isFloatOperation) { + this.ex.write(" ucomisd %xmm0, %xmm1\n"); + } else { + this.ex.write(" cmp %rax, %rbx\n"); + } this.ex.write(" jge .L" + lblTrue + "\n"); // false this.ex.write(" movq $0, %rax\n"); @@ -179,11 +266,12 @@ public class GenASM implements Visitor { int lblTrue = ++lCount; int lblEnd = ++lCount; - e.lhs.welcome(this); - this.ex.write(" pushq %rax\n"); - e.rhs.welcome(this); - this.ex.write(" popq %rbx\n"); - this.ex.write(" cmp %rax, %rbx\n"); + boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs); + if (isFloatOperation) { + this.ex.write(" ucomisd %xmm0, %xmm1\n"); + } else { + this.ex.write(" cmp %rax, %rbx\n"); + } this.ex.write(" jl .L" + lblTrue + "\n"); // false this.ex.write(" movq $0, %rax\n"); @@ -200,11 +288,12 @@ public class GenASM implements Visitor { int lblTrue = ++lCount; int lblEnd = ++lCount; - e.lhs.welcome(this); - this.ex.write(" pushq %rax\n"); - e.rhs.welcome(this); - this.ex.write(" popq %rbx\n"); - this.ex.write(" cmp %rax, %rbx\n"); + boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs); + if (isFloatOperation) { + this.ex.write(" ucomisd %xmm0, %xmm1\n"); + } else { + this.ex.write(" cmp %rax, %rbx\n"); + } this.ex.write(" jle .L" + lblTrue + "\n"); // false this.ex.write(" movq $0, %rax\n"); @@ -218,43 +307,47 @@ public class GenASM implements Visitor { @Override public Void visit(AdditionExpression e) { - e.lhs.welcome(this); - this.ex.write(" pushq %rax\n"); - e.rhs.welcome(this); - this.ex.write(" popq %rbx\n"); - this.ex.write(" addq %rbx, %rax\n"); + boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs); + if (isFloatOperation) { + this.ex.write(" addsd %xmm1, %xmm0\n"); + } else { + this.ex.write(" addq %rbx, %rax\n"); + } return null; } @Override public Void visit(SubstractionExpression e) { - e.rhs.welcome(this); - this.ex.write(" pushq %rax\n"); - e.lhs.welcome(this); - this.ex.write(" popq %rbx\n"); - this.ex.write(" subq %rbx, %rax\n"); + boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs); + if (isFloatOperation) { + this.ex.write(" subsd %xmm1, %xmm0\n"); + } else { + this.ex.write(" subq %rax, %rbx\n"); + this.ex.write(" movq %rbx, %rax\n"); + } return null; } @Override public Void visit(MultiplicationExpression e) { - e.lhs.welcome(this); - this.ex.write(" pushq %rax\n"); - e.rhs.welcome(this); - this.ex.write(" popq %rbx\n"); - this.ex.write(" imulq %rbx, %rax\n"); + boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs); + if (isFloatOperation) { + this.ex.write(" mulsd %xmm1, %xmm0\n"); + } else { + this.ex.write(" imulq %rbx, %rax\n"); + } return null; } @Override public Void visit(DivisionExpression e) { - e.lhs.welcome(this); - this.ex.write(" pushq %rax\n"); - e.rhs.welcome(this); - this.ex.write(" movq %rax, %rbx\n"); - this.ex.write(" popq %rax\n"); - this.ex.write(" xor %rdx, %rdx\n"); // clear upper part of division - this.ex.write(" idiv %rbx\n"); // %rax/%rbx, quotient now in %rax + boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs); + if (isFloatOperation) { + this.ex.write(" divsd %xmm1, %xmm0\n"); + } else { + this.ex.write(" xor %rdx, %rdx\n"); // clear upper part of division + this.ex.write(" idiv %rbx\n"); // %rax/%rbx, quotient now in %rax + } return null; } @@ -274,7 +367,13 @@ public class GenASM implements Visitor { @Override public Void visit(NegateExpression e) { e.lhs.welcome(this); - this.ex.write(" neg %rax\n"); + if (e.lhs.type.equals(Type.getFloatType())) { + String floatLabel = fw.getNegateFloat(); + this.ex.write(" movsd " + floatLabel + "(%rip), %xmm1\n"); + this.ex.write(" xorpd %xmm1, %xmm0\n"); + } else { + this.ex.write(" neg %rax\n"); + } return null; } @@ -497,7 +596,8 @@ public class GenASM implements Visitor { // hole die anzahl der lokalen variablen this.vars = new TreeSet(); - GetVars getvars = new GetVars(vars); + HashMap types = new HashMap(); + GetVars getvars = new GetVars(vars, types); getvars.visit(e); // Erzeuge ein environment @@ -532,6 +632,74 @@ public class GenASM implements Visitor { @Override public Void visit(FunctionCall e) { + /* + Idee: + Über arguments iterieren, sich für jedes Argument merken an welche Position es kommt + Über e.arguments iterieren, jedes welcomen, ergebnis auf den stack pushen + Vom stack in die jeweiligen register / den richtigen Platz auf den Stack pushen + */ + // // An xmmIdxy[i] steht ein index, der in e.arguments zeigt + // // this.frs[i] = register | xmmIdxs[i] = index in arguments das in dieses register gehört + // int[] xmmIdxs = new int[this.frs.length]; + // int fi = 0; + // // Selbe Idee wie bei xmmIdxs + // int[] rIdxs = new int[this.rs.length]; + // int ri = 0; + //// Selbe Idee wie bei xmmIdxs + // ArrayList stackIdxs = new ArrayList(); + // + // // Go through arguments + // // sort them into the memory regions they go when being passed to function later on + // for (int i = 0; i < e.arguments.length; i++) { + // var arg = e.arguments[i]; + // if (arg.type.equals(Type.getFloatType())) { + // if (fi >= this.frs.length) { + // // Float onto stack + // stackIdxs.add(i); + // } else { + // // Float into float reg + // xmmIdxs[fi] = i; + // fi += 1; + // } + // } else { + // if (ri >= this.rs.length) { + // // bool/int onto stack + // stackIdxs.add(i); + // } else { + // // bool/int into reg + // rIdxs[ri] = i; + // ri += 1; + // } + // } + // } + + // // Welcome the arguments in order + // for (var arg : e.arguments) { + // arg.welcome(this); + // if (arg.type.equals(Type.getFloatType())) { + // this.ex.write(" movq %xmm0, %rax\n"); + // this.ex.write(" pushq %rax\n"); + // } else { + // this.ex.write(" pushq %rax\n"); + // } + // } + // // Move floats from stack to xmm registers + // TODO: Check if indexInArguments is valid + // for (int i = 0; i < xmmIdxs.length ; i++) { + // int indexInArguments = xmmIdxs[i]; + // int rspOffset = (((e.arguments.length - indexInArguments) - 1) * 8) * -1; + // this.ex.write(" movsd " + rspOffset + "(%rsp), " + this.frs[i] + "\n"); + // } + + // // Move primitives from stack to all purpose registers + // TODO: Check if indexInArguments is valid + // for (int i = 0; i < rIdxs.length ; i++) { + // int indexInArguments = rIdxs[i]; + // int rspOffset = (((e.arguments.length - indexInArguments) - 1) * 8) * -1; + // this.ex.write(" movq " + rspOffset + "(%rsp), " + this.rs[i] + "\n"); + // } + // int stackStart = (e.arguments.length - 1) * 8 * -1; + // Die ersten sechs params in die register schieben for (int i = 0; i < Math.min(this.rs.length, e.arguments.length); i++) { e.arguments[i].welcome(this); @@ -565,6 +733,10 @@ public class GenASM implements Visitor { this.ex.write(" movq %rbp, %rsp\n"); this.ex.write(" popq %rbp\n"); this.ex.write(" ret\n"); + + // PRINT FLOATS HERE + this.ex.write("\n"); + this.ex.write(fw.getFloatSection()); 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 index b471245..666b124 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java @@ -1,5 +1,6 @@ package de.hsrm.compiler.Klang.visitors; +import java.util.Map; import java.util.Set; import de.hsrm.compiler.Klang.nodes.*; @@ -8,13 +9,16 @@ 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) { + public GetVars(Set vars, Map types) { this.vars = vars; + this.types = types; } @Override @@ -22,6 +26,11 @@ class GetVars implements Visitor { return null; } + @Override + public Void visit(FloatExpression e) { + return null; + } + @Override public Void visit(BooleanExpression e) { return null; @@ -179,6 +188,7 @@ class GetVars implements Visitor { @Override public Void visit(VariableDeclaration e) { vars.add(e.name); + types.put(e.name, e.type); return null; } diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java b/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java index fe4d8f8..da410f5 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java @@ -72,6 +72,12 @@ public class PrettyPrintVisitor implements Visitor { return null; } + @Override + public Void visit(FloatExpression e) { + ex.write(e.value); + return null; + } + @Override public Void visit(BooleanExpression e) { ex.write(e.value); diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java b/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java index 77ffc43..57402f4 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java @@ -13,6 +13,7 @@ public interface Visitor { R visit(AndExpression e); R visit (NotExpression e); R visit(IntegerExpression e); + R visit(FloatExpression e); R visit(BooleanExpression e); R visit(Variable e); R visit(AdditionExpression e); From 6eb61f905fe5762e270bb8e99936c6a63012bf70 Mon Sep 17 00:00:00 2001 From: Marvin Kaiser Date: Wed, 4 Mar 2020 19:29:24 +0100 Subject: [PATCH 02/14] 25: Add logic for handling float in function calls --- .../hsrm/compiler/Klang/visitors/GenASM.java | 252 ++++++++++-------- src/test/functionCall/functionCall.c | 33 +++ src/test/functionCall/functionCall.h | 24 +- src/test/print/print.c | 10 + src/test/print/print.h | 3 + src/test/test.k | 84 ++++++ 6 files changed, 295 insertions(+), 111 deletions(-) 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 cf94562..f1b5efc 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java @@ -1,6 +1,7 @@ package de.hsrm.compiler.Klang.visitors; import java.io.*; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -61,9 +62,15 @@ public class GenASM implements Visitor { private int id = -1; public String getFloat(double d) { - String binary = Long.toBinaryString(Double.doubleToLongBits(d)); - String upper = binary.substring(0, 30); - String lower = binary.substring(31, 61); + Long longBits = Double.doubleToRawLongBits(d); + String binary = Long.toBinaryString(longBits); + int padCount = 64 - binary.length(); + while (padCount > 0) { + binary = "0" + binary; + padCount--; + } + String upper = binary.substring(0, 32); + String lower = binary.substring(32, 64); long first = Long.parseLong(lower, 2); long second = Long.parseLong(upper, 2); String lbl = ".FL" + ++id; @@ -101,12 +108,12 @@ public class GenASM implements Visitor { private String mainName; Map env = new HashMap<>(); Set vars; - String[] rs = { "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9" }; - String[] frs = {"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"}; + String[] registers = { "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9" }; + String[] floatRegisters = { "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" }; private int lCount = 0; // Invariante: lCount ist benutzt private void intToFloat(String src, String dst) { - this.ex.write(" cvtsi2sd " + src +", " + dst + "\n"); + this.ex.write(" cvtsi2sd " + src + ", " + dst + "\n"); } private boolean prepareRegisters(Expression lhs, Expression rhs) { @@ -131,8 +138,6 @@ public class GenASM implements Visitor { this.ex.write(" popq %rbx\n"); return false; } - - public GenASM(ExWriter ex, String mainName) { this.ex = ex; this.mainName = mainName; @@ -183,14 +188,14 @@ public class GenASM implements Visitor { } else { this.ex.write(" cmp %rax, %rbx\n"); } - this.ex.write(" je .L" + lblTrue + "\n"); - // false - this.ex.write(" movq $0, %rax\n"); - this.ex.write(" jmp .L" + lblEnd + "\n"); - this.ex.write(".L" + lblTrue + ":\n"); - // true - this.ex.write(" movq $1, %rax\n"); - this.ex.write(".L" + lblEnd + ":\n"); + this.ex.write(" je .L" + lblTrue + "\n"); + // false + this.ex.write(" movq $0, %rax\n"); + this.ex.write(" jmp .L" + lblEnd + "\n"); + this.ex.write(".L" + lblTrue + ":\n"); + // true + this.ex.write(" movq $1, %rax\n"); + this.ex.write(".L" + lblEnd + ":\n"); return null; } @@ -243,7 +248,6 @@ public class GenASM implements Visitor { int lblTrue = ++lCount; int lblEnd = ++lCount; - boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs); if (isFloatOperation) { this.ex.write(" ucomisd %xmm0, %xmm1\n"); @@ -430,20 +434,20 @@ public class GenASM implements Visitor { // also ist das Gesamtergebnis false e.rhs.welcome(this); this.ex.write(" cmpq $0, %rax\n"); - this.ex.write(" je .L" + lblFalse +"\n"); + this.ex.write(" je .L" + lblFalse + "\n"); // Die Expression wertet zu true aus // Springe am false Teil vorbei - this.ex.write(".L" + lblTrue +":\n"); + this.ex.write(".L" + lblTrue + ":\n"); this.ex.write(" movq $1, %rax\n"); this.ex.write(" jmp .L" + lblEnd + "\n"); // Die Expressoin wertet zu false aus - this.ex.write(".L" + lblFalse +":\n"); + this.ex.write(".L" + lblFalse + ":\n"); this.ex.write(" movq $0, %rax\n"); // Das hier ist das ende - this.ex.write(".L" + lblEnd +":\n"); + this.ex.write(".L" + lblEnd + ":\n"); return null; } @@ -451,26 +455,26 @@ public class GenASM implements Visitor { public Void visit(NotExpression e) { int lblFalse = ++lCount; int lblEnd = ++lCount; - + // Werte LHS aus // Wenn LHS != 0 bedeutet das true, also jumpe zum false Teil // Wenn nicht, falle durch zum true Teil e.lhs.welcome(this); this.ex.write(" cmpq $0, %rax\n"); - this.ex.write(" jne .L" +lblFalse +"\n"); + this.ex.write(" jne .L" + lblFalse + "\n"); // Hier ist das Ergebnis true // Springe am false Teil vorbei this.ex.write(" movq $1, %rax\n"); - this.ex.write(" jmp .L" +lblEnd +"\n"); + this.ex.write(" jmp .L" + lblEnd + "\n"); // Hier ist das Ergebnis false // Falle zum Ende durch - this.ex.write(".L" +lblFalse + ":\n"); + this.ex.write(".L" + lblFalse + ":\n"); this.ex.write("movq $0, %rax\n"); // Hier ist das Ende - this.ex.write(".L" +lblEnd + ":\n"); + this.ex.write(".L" + lblEnd + ":\n"); return null; } @@ -604,19 +608,51 @@ public class GenASM implements Visitor { this.env = new HashMap(); // Merke dir die offsets der parameter, die direkt auf den stack gelegt wurden - int offset = 16; // Per Stack übergebene Parameter liegen über unserm BSP + int offset = 16; // Per Stack übergebene Parameter liegen über unserem BSP + int ri = 0; + int fi = 0; // Per stack übergebene variablen in env registrieren - for (int i = this.rs.length; i < e.parameters.length; i++) { - env.put(e.parameters[i].name, offset); - offset += 8; + var registerParameters = new ArrayList(); + for (int i = 0; i < e.parameters.length; i++) { + if (e.parameters[i].type.equals(Type.getFloatType())) { + if (fi >= this.floatRegisters.length) { + // parameter is on stack already + env.put(e.parameters[i].name, offset); + offset += 8; + } else { + // parameter is in a xmm register + registerParameters.add(e.parameters[i]); + fi++; + } + } else { + if (ri >= this.registers.length) { + // parameter is on stack already + env.put(e.parameters[i].name, offset); + offset += 8; + } else { + // parameter is in a register + registerParameters.add(e.parameters[i]); + ri++; + } + } } - - // pushe die aufrufparameter aus den Registern wieder auf den Stack + offset = 0; - for (int i = 0; i < Math.min(this.rs.length, e.parameters.length); i++) { - this.ex.write(" pushq " + this.rs[i] + "\n"); - offset -= 8; - this.env.put(e.parameters[i].name, offset); // negative, liegt unter aktuellem BP + ri = 0; + fi = 0; + for (var param: registerParameters) { + if (param.type.equals(Type.getFloatType())) { + this.ex.write(" movq "+ this.floatRegisters[fi] + ", %rax\n"); + this.ex.write(" pushq %rax\n"); + offset -= 8; + this.env.put(param.name, offset); // negative, liegt unter aktuellem BP + fi++; + } else { + this.ex.write(" pushq " + this.registers[ri] + "\n"); + offset -= 8; + this.env.put(param.name, offset); // negative, liegt unter aktuellem BP + ri++; + } } // Reserviere Platz auf dem Stack für jede lokale variable @@ -632,84 +668,80 @@ public class GenASM implements Visitor { @Override public Void visit(FunctionCall e) { - /* - Idee: - Über arguments iterieren, sich für jedes Argument merken an welche Position es kommt - Über e.arguments iterieren, jedes welcomen, ergebnis auf den stack pushen - Vom stack in die jeweiligen register / den richtigen Platz auf den Stack pushen - */ - // // An xmmIdxy[i] steht ein index, der in e.arguments zeigt - // // this.frs[i] = register | xmmIdxs[i] = index in arguments das in dieses register gehört - // int[] xmmIdxs = new int[this.frs.length]; - // int fi = 0; - // // Selbe Idee wie bei xmmIdxs - // int[] rIdxs = new int[this.rs.length]; - // int ri = 0; - //// Selbe Idee wie bei xmmIdxs - // ArrayList stackIdxs = new ArrayList(); - // - // // Go through arguments - // // sort them into the memory regions they go when being passed to function later on - // for (int i = 0; i < e.arguments.length; i++) { - // var arg = e.arguments[i]; - // if (arg.type.equals(Type.getFloatType())) { - // if (fi >= this.frs.length) { - // // Float onto stack - // stackIdxs.add(i); - // } else { - // // Float into float reg - // xmmIdxs[fi] = i; - // fi += 1; - // } - // } else { - // if (ri >= this.rs.length) { - // // bool/int onto stack - // stackIdxs.add(i); - // } else { - // // bool/int into reg - // rIdxs[ri] = i; - // ri += 1; - // } - // } - // } + if (e.arguments.length > 0) { + // Mapping arguments index -> xmm registers index + int[] xmmIdxs = new int[this.floatRegisters.length]; + int fi = -1; - // // Welcome the arguments in order - // for (var arg : e.arguments) { - // arg.welcome(this); - // if (arg.type.equals(Type.getFloatType())) { - // this.ex.write(" movq %xmm0, %rax\n"); - // this.ex.write(" pushq %rax\n"); - // } else { - // this.ex.write(" pushq %rax\n"); - // } - // } - // // Move floats from stack to xmm registers - // TODO: Check if indexInArguments is valid - // for (int i = 0; i < xmmIdxs.length ; i++) { - // int indexInArguments = xmmIdxs[i]; - // int rspOffset = (((e.arguments.length - indexInArguments) - 1) * 8) * -1; - // this.ex.write(" movsd " + rspOffset + "(%rsp), " + this.frs[i] + "\n"); - // } + // Mapping arguments index -> all purpose registers index + int[] rIdxs = new int[this.registers.length]; + int ri = -1; + + // Mapping arguments index -> stack + ArrayList stackIdxs = new ArrayList(); - // // Move primitives from stack to all purpose registers - // TODO: Check if indexInArguments is valid - // for (int i = 0; i < rIdxs.length ; i++) { - // int indexInArguments = rIdxs[i]; - // int rspOffset = (((e.arguments.length - indexInArguments) - 1) * 8) * -1; - // this.ex.write(" movq " + rspOffset + "(%rsp), " + this.rs[i] + "\n"); - // } - // int stackStart = (e.arguments.length - 1) * 8 * -1; + // Go through arguments + // sort them into the memory regions they go when being passed to functions + for (int i = 0; i < e.arguments.length; i++) { + var arg = e.arguments[i]; + if (arg.type.equals(Type.getFloatType())) { + if (fi < this.floatRegisters.length - 1) { + // Float into float reg + fi += 1; + xmmIdxs[fi] = i; + } else { + // Float onto stack + stackIdxs.add(i); + } + } else { + if (ri < this.registers.length - 1) { + // bool/int into reg + ri += 1; + rIdxs[ri] = i; + } else { + // bool/int onto stack + stackIdxs.add(i); + } + } + } - // Die ersten sechs params in die register schieben - for (int i = 0; i < Math.min(this.rs.length, e.arguments.length); i++) { - e.arguments[i].welcome(this); - this.ex.write(" movq %rax, " + this.rs[i] + "\n"); - } + // Welcome the arguments in order, push everything onto the stack + for (var arg : e.arguments) { + arg.welcome(this); + if (arg.type.equals(Type.getFloatType())) { + this.ex.write(" movq %xmm0, %rax\n"); + this.ex.write(" pushq %rax\n"); + } else { + this.ex.write(" pushq %rax\n"); + } + } - // Den Rest auf den stack pushen - for (int i = e.arguments.length - 1; i >= this.rs.length; i--) { - e.arguments[i].welcome(this); - this.ex.write(" pushq %rax\n"); + // Move floats from stack to xmm registers + for (int i = 0; i <= fi; i++) { + int indexInArguments = xmmIdxs[i]; + int rspOffset = (((e.arguments.length - indexInArguments) - 1) * 8); + this.ex.write(" movsd " + rspOffset + "(%rsp), " + this.floatRegisters[i] + "\n"); + } + + // Move primitives from stack to all purpose registers + for (int i = 0; i <= ri; i++) { + int indexInArguments = rIdxs[i]; + int rspOffset = (((e.arguments.length - indexInArguments) - 1) * 8); + this.ex.write(" movq " + rspOffset + "(%rsp), " + this.registers[i] + "\n"); + } + + // Move everything else from a higher stack position to our stack frame start + int stackStartOffset = ((e.arguments.length) * 8); + for (int i = stackIdxs.size() - 1; i >= 0; i--) { + stackStartOffset -= 8; + int indexInArguments = stackIdxs.get(i); + int rspOffset = (((e.arguments.length - indexInArguments) - 1) * 8); + this.ex.write(" movq " + rspOffset + "(%rsp), %rax\n"); + this.ex.write(" movq %rax, " + stackStartOffset + "(%rsp)\n"); + } + + // Rescue RSP + this.ex.write(" addq $" + stackStartOffset + ", %rsp\n"); } this.ex.write(" call " + e.name + "\n"); diff --git a/src/test/functionCall/functionCall.c b/src/test/functionCall/functionCall.c index 0ac208b..66fe1f5 100644 --- a/src/test/functionCall/functionCall.c +++ b/src/test/functionCall/functionCall.c @@ -12,6 +12,16 @@ int argumentTest(char* name, int expected, int result) { } } +int argumentTest_f(char* name, int expected, int result) { + if (expected == result) { + succ_f(name, expected, result); + return 0; + } else { + err_f(name, expected, result); + return 1; + } +} + int runFunctionCallTests () { printf("\nFunction Call Tests \n"); // Checks that parameters are correctly passed from gcc to functions @@ -36,4 +46,27 @@ int runFunctionCallTests () { argumentTest("get8(...args)", 8, get8()); argumentTest("get9(...args)", 9, get9()); argumentTest("get10(...args)", 10, get10()); + + printf("\nFunction Call Tests With Floats \n"); + argumentTest_f("farg1(...args)", 1.0, farg1(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("farg2(...args)", 2.0, farg2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("farg3(...args)", 3.0, farg3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("farg4(...args)", 4.0, farg4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("farg5(...args)", 5.0, farg5(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("farg6(...args)", 6.0, farg6(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("farg7(...args)", 7.0, farg7(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("farg8(...args)", 8.0, farg8(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("farg9(...args)", 9.0, farg9(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("farg10(...args)", 10.0, farg10(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + // Checks that parameters are correctly passed from klang to functions + argumentTest_f("fget1(...args)", 1.0, fget1()); + argumentTest_f("fget2(...args)", 2.0, fget2()); + argumentTest_f("fget3(...args)", 3.0, fget3()); + argumentTest_f("fget4(...args)", 4.0, fget4()); + argumentTest_f("fget5(...args)", 5.0, fget5()); + argumentTest_f("fget6(...args)", 6.0, fget6()); + argumentTest_f("fget7(...args)", 7.0, fget7()); + argumentTest_f("fget8(...args)", 8.0, fget8()); + argumentTest_f("fget9(...args)", 9.0, fget9()); + argumentTest_f("fget10(...args)", 10.0, fget10()); } \ No newline at end of file diff --git a/src/test/functionCall/functionCall.h b/src/test/functionCall/functionCall.h index 56fbff7..4281631 100644 --- a/src/test/functionCall/functionCall.h +++ b/src/test/functionCall/functionCall.h @@ -18,4 +18,26 @@ int get6(); int get7(); int get8(); int get9(); -int get10(); \ No newline at end of file +int get10(); + +double farg1(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j); +double farg2(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j); +double farg3(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j); +double farg4(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j); +double farg5(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j); +double farg6(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j); +double farg7(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j); +double farg8(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j); +double farg9(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j); +double farg10(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j); + +double fget1(); +double fget2(); +double fget3(); +double fget4(); +double fget5(); +double fget6(); +double fget7(); +double fget8(); +double fget9(); +double fget10(); \ No newline at end of file diff --git a/src/test/print/print.c b/src/test/print/print.c index 21109f9..b8ff8af 100644 --- a/src/test/print/print.c +++ b/src/test/print/print.c @@ -28,6 +28,16 @@ void err(char* name, int expected, int result) { printf("\033[0;31mERROR:\t\t%s:\tGOT: %d\tExpected: %d\033[0;0m\n", name, result, expected); } +void succ_f(char* name, double expected, double result) { + incSuccess(); + printf("\033[0;32mSUCCESS:\t%s:\tGOT: %f\tExpected: %f\033[0;0m\n", name, result, expected); +} + +void err_f(char* name, double expected, double result) { + incFailure(); + printf("\033[0;31mERROR:\t\t%s:\tGOT: %f\tExpected: %f\033[0;0m\n", name, result, expected); +} + void succPrefixOne(char* name, int x, int expected, int result) { incSuccess(); printf("\033[0;32mSUCCESS:\t%s(%d)\tGOT: %d\tExpected: %d\033[0;0m\n", name, x, result, expected); diff --git a/src/test/print/print.h b/src/test/print/print.h index 637cc5c..8318341 100644 --- a/src/test/print/print.h +++ b/src/test/print/print.h @@ -6,6 +6,9 @@ void incFailure(); void succ(char* name, int expected, int result); void err(char* name, int expected, int result); +void succ_f(char* name, double expected, double result); +void err_f(char* name, double expected, double result); + void succPrefixOne(char* name, int x, int expected, int result); void errPrefixOne(char* name, int x, int expected, int result); diff --git a/src/test/test.k b/src/test/test.k index a5c08ec..f065cff 100644 --- a/src/test/test.k +++ b/src/test/test.k @@ -102,6 +102,90 @@ function get10(): int { return arg10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); } +// FLOATS + +function farg1(a: float, b: float, c: float, d: float, e: float, f: float, g: float, h: float, i: float ,j: float): float { + return a; +} + +function fget1(): float { + return farg1(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0); +} + +function farg2(a: float, b: float, c: float, d: float, e: float, f: float, g: float, h: float, i: float ,j: float): float { + return b; +} + +function fget2(): float { + return farg2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0); +} + +function farg3(a: float, b: float, c: float, d: float, e: float, f: float, g: float, h: float, i: float ,j: float): float { + return c; +} + +function fget3(): float { + return farg3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0); +} + +function farg4(a: float, b: float, c: float, d: float, e: float, f: float, g: float, h: float, i: float ,j: float): float { + return d; +} + +function fget4(): float { + return farg4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0); +} + +function farg5(a: float, b: float, c: float, d: float, e: float, f: float, g: float, h: float, i: float ,j: float): float { + return e; +} + +function fget5(): float { + return farg5(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0); +} + +function farg6(a: float, b: float, c: float, d: float, e: float, f: float, g: float, h: float, i: float ,j: float): float { + return f; +} + +function fget6(): float { + return farg6(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0); +} + +function farg7(a: float, b: float, c: float, d: float, e: float, f: float, g: float, h: float, i: float ,j: float): float { + return g; +} + +function fget7(): float { + return farg7(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0); +} + +function farg8(a: float, b: float, c: float, d: float, e: float, f: float, g: float, h: float, i: float ,j: float): float { + return h; +} + +function fget8(): float { + return farg8(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0); +} + +function farg9(a: float, b: float, c: float, d: float, e: float, f: float, g: float, h: float, i: float ,j: float): float { + return i; +} + +function fget9(): float { + return farg9(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0); +} + +function farg10(a: float, b: float, c: float, d: float, e: float, f: float, g: float, h: float, i: float ,j: float): float { + return j; +} + +function fget10(): float { + return farg10(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0); +} + +// END FLOATS + function fac(x: int): int { if (x) { return (x * fac((x - 1))); From 384d98418d4d5e7569a96d1a4aa99d8a8e49854d Mon Sep 17 00:00:00 2001 From: nitrix Date: Wed, 4 Mar 2020 20:46:08 +0100 Subject: [PATCH 03/14] implement math tests for floats --- src/test/math/math.c | 79 ++++++++++++++++++++++++++++++++++++++++++++ src/test/math/math.h | 8 ++++- src/test/test.k | 25 ++++++++++++++ 3 files changed, 111 insertions(+), 1 deletion(-) diff --git a/src/test/math/math.c b/src/test/math/math.c index c5fb382..c6a049d 100644 --- a/src/test/math/math.c +++ b/src/test/math/math.c @@ -32,6 +32,32 @@ int cSelfMinus(int x) return x; } +double fcAdd(double x, double y) +{ + return x + y; +} +double fcSub(double x, double y) +{ + return x - y; +} +double fcMul(double x, double y) +{ + return x * y; +} +double fcNeg(double x) +{ + return -x; +} +double fcId(double x) +{ + return x; +} +double fcSelfMinus(double x) +{ + x = x - 1; + return x; +} + int math_testExpected(char *name, int x, int y, int expected, int result) { if (expected == result) @@ -53,6 +79,12 @@ int math_test(char *name, int (*correctFunction)(int, int), int (*testFunction)( return math_testExpected(name, x, y, expected, result); } +float math_test_f(char *name, float (*correctFunction)(float, float), float (*testFunction)(float, float), float x, float y) { + float expected = correctFunction(x, y); + float result = testFunction(x, y); + return math_testExpected(name, x, y, expected, result); +} + int math_testOneArg(char *name, int (*correctFunction)(int), int (*testFunction)(int), int x) { int expected = correctFunction(x); @@ -69,6 +101,22 @@ int math_testOneArg(char *name, int (*correctFunction)(int), int (*testFunction) } } +float math_testOneArg_f(char *name, float (*correctFunction)(float), float (*testFunction)(float), float x) +{ + float expected = correctFunction(x); + float result = testFunction(x); + if (expected == result) + { + succPrefixOne(name, x, expected, result); + return 0; + } + else + { + errPrefixOne(name, x, expected, result); + return 1; + } +} + void math_simpleTest(char *name, int expected, int result) { if (expected == result) { succ(name, expected, result); @@ -116,6 +164,37 @@ int runMathTests() math_testOneArg("id", cId, id, -1); math_testOneArg("id", cId, id, 15); + printf("\nFloat Addition Tests \n"); + math_test_f("fadd", fcAdd, fadd, 0.0, 0.0); + math_test_f("fadd", fcAdd, fadd, 1.0, 1.0); + math_test_f("fadd", fcAdd, fadd, 2.0, 0.0); + math_test_f("fadd", fcAdd, fadd, 1.0, 5.0); + math_test_f("fadd", fcAdd, fadd, -1.0, -1.0); + + printf("\nFloat Subtraction Tests \n"); + math_test_f("fsub", fcSub, fsub, 0.0, 0.0); + math_test_f("fsub", fcSub, fsub, 1.0, 1.0); + math_test_f("fsub", fcSub, fsub, 2.0, 0.0); + math_test_f("fsub", fcSub, fsub, 1.0, 5.0); + math_test_f("fsub", fcSub, fsub, -1.0, -1.0); + + printf("\nFloat Multiplication Tests \n"); + math_test_f("fmul", fcMul, fmul, 0.0, 0.0); + math_test_f("fmul", fcMul, fmul, 1.0, 1.0); + math_test_f("fmul", fcMul, fmul, 2.0, 0.0); + math_test_f("fmul", fcMul, fmul, 1.0, 5.0); + math_test_f("fmul", fcMul, fmul, -1.0, -1.0); + + printf("\nFloat Negative Tests\n"); + math_testOneArg_f("fneg", fcNeg, fneg, 0.0); + math_testOneArg_f("fneg", fcNeg, fneg, 1.0); + math_testOneArg_f("fneg", fcNeg, fneg, -1.0); + + printf("\nFloat Identity Tests\n"); + math_testOneArg_f("fid", fcId, fid, 0.0); + math_testOneArg_f("fid", fcId, fid, -1.0); + math_testOneArg_f("fid", fcId, fid, 15.0); + printf("\nMisc Tests\n"); math_testOneArg("selfMinus", cSelfMinus, selfMinus, 5); math_testOneArg("selfMinus", cSelfMinus, selfMinus, 0); diff --git a/src/test/math/math.h b/src/test/math/math.h index 1801543..5ed8145 100644 --- a/src/test/math/math.h +++ b/src/test/math/math.h @@ -16,4 +16,10 @@ int t4(); int t5(); int t6(); int t7(); -int t8(); \ No newline at end of file +int t8(); +double fadd(double x, double y); +double fsub(double x, double y); +double fmul(double x, double y); +double fneg(double x); +double fid(double x); +double fselfMinus(double x); \ No newline at end of file diff --git a/src/test/test.k b/src/test/test.k index f065cff..dc7eac7 100644 --- a/src/test/test.k +++ b/src/test/test.k @@ -184,6 +184,31 @@ function fget10(): float { return farg10(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0); } +function fadd(x: float, y: float): float { + return x + y; +} + +function fsub(x: float, y: float): float { + return x - y; +} + +function fmul(x: float, y: float): float { + return x * y; +} + +function fneg(x: float): float { + return -x; +} + +function fid(x: float): float { + return x; +} + +function fselfMinus(x: float): float { + x = (x - 1); + return x; +} + // END FLOATS function fac(x: int): int { From 18cfbdcbb5a8befe49836d6e90b6a58ca3c4c6fe Mon Sep 17 00:00:00 2001 From: nitrix Date: Wed, 4 Mar 2020 20:46:49 +0100 Subject: [PATCH 04/14] implement function call tests for floats and floats mixed with integers --- src/test/functionCall/functionCall.c | 23 ++++++++ src/test/functionCall/functionCall.h | 24 ++++++++- src/test/test.k | 80 ++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 1 deletion(-) diff --git a/src/test/functionCall/functionCall.c b/src/test/functionCall/functionCall.c index 66fe1f5..41b4436 100644 --- a/src/test/functionCall/functionCall.c +++ b/src/test/functionCall/functionCall.c @@ -69,4 +69,27 @@ int runFunctionCallTests () { argumentTest_f("fget8(...args)", 8.0, fget8()); argumentTest_f("fget9(...args)", 9.0, fget9()); argumentTest_f("fget10(...args)", 10.0, fget10()); + + printf("\nFunction Call Tests With Floats And Integers \n"); + argumentTest_f("fargMix1(...args)", 1.0, fargMix1(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("fargMix2(...args)", 2, fargMix2(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("fargMix3(...args)", 3.0, fargMix3(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("fargMix4(...args)", 4, fargMix4(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("fargMix5(...args)", 5.0, fargMix5(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("fargMix6(...args)", 6, fargMix6(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("fargMix7(...args)", 7.0, fargMix7(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("fargMix8(...args)", 8, fargMix8(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("fargMix9(...args)", 9.0, fargMix9(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + argumentTest_f("fargMix10(...args)", 10, fargMix10(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)); + // Checks that parameters are correctly passed from klang to functions + argumentTest_f("fgetMix1(...args)", 1.0, fgetMix1()); + argumentTest("fgetMix2(...args)", 2, fgetMix2()); + argumentTest_f("fgetMix3(...args)", 3.0, fgetMix3()); + argumentTest("fgetMix4(...args)", 4, fgetMix4()); + argumentTest_f("fgetMix5(...args)", 5.0, fgetMix5()); + argumentTest("fgetMix6(...args)", 6, fgetMix6()); + argumentTest_f("fgetMix7(...args)", 7.0, fgetMix7()); + argumentTest("fgetMix8(...args)", 8, fgetMix8()); + argumentTest_f("fgetMix9(...args)", 9.0, fgetMix9()); + argumentTest("fgetMix10(...args)", 10, fgetMix10()); } \ No newline at end of file diff --git a/src/test/functionCall/functionCall.h b/src/test/functionCall/functionCall.h index 4281631..da5fe2d 100644 --- a/src/test/functionCall/functionCall.h +++ b/src/test/functionCall/functionCall.h @@ -31,6 +31,17 @@ double farg8(double a, double b, double c, double d, double e, double f, double double farg9(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j); double farg10(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j); +double fargMix1(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); +int fargMix2(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); +double fargMix3(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); +int fargMix4(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); +double fargMix5(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); +int fargMix6(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); +double fargMix7(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); +int fargMix8(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); +double fargMix9(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); +int fargMix10(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); + double fget1(); double fget2(); double fget3(); @@ -40,4 +51,15 @@ double fget6(); double fget7(); double fget8(); double fget9(); -double fget10(); \ No newline at end of file +double fget10(); + +double fgetMix1(); +int fgetMix2(); +double fgetMix3(); +int fgetMix4(); +double fgetMix5(); +int fgetMix6(); +double fgetMix7(); +int fgetMix8(); +double fgetMix9(); +int fgetMix10(); \ No newline at end of file diff --git a/src/test/test.k b/src/test/test.k index dc7eac7..8bb46f6 100644 --- a/src/test/test.k +++ b/src/test/test.k @@ -184,6 +184,86 @@ function fget10(): float { return farg10(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0); } +function fargMix1(a: float, b: int, c: float, d: int, e: float, f: int, g: float, h: int, i: float ,j: int): float { + return a; +} + +function fgetMix1(): float { + return fargMix1(1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10); +} + +function fargMix2(a: float, b: int, c: float, d: int, e: float, f: int, g: float, h: int, i: float ,j: int): int { + return b; +} + +function fgetMix2(): int { + return fargMix2(1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10); +} + +function fargMix3(a: float, b: int, c: float, d: int, e: float, f: int, g: float, h: int, i: float ,j: int): float { + return c; +} + +function fgetMix3(): float { + return fargMix3(1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10); +} + +function fargMix4(a: float, b: int, c: float, d: int, e: float, f: int, g: float, h: int, i: float ,j: int): int { + return d; +} + +function fgetMix4(): int { + return fargMix4(1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10); +} + +function fargMix5(a: float, b: int, c: float, d: int, e: float, f: int, g: float, h: int, i: float ,j: int): float { + return e; +} + +function fgetMix5(): float { + return fargMix5(1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10); +} + +function fargMix6(a: float, b: int, c: float, d: int, e: float, f: int, g: float, h: int, i: float ,j: int): int { + return f; +} + +function fgetMix6(): int { + return fargMix6(1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10); +} + +function fargMix7(a: float, b: int, c: float, d: int, e: float, f: int, g: float, h: int, i: float ,j: int): float { + return g; +} + +function fgetMix7(): float { + return fargMix7(1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10); +} + +function fargMix8(a: float, b: int, c: float, d: int, e: float, f: int, g: float, h: int, i: float ,j: int): int { + return h; +} + +function fgetMix8(): int { + return fargMix8(1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10); +} + +function fargMix9(a: float, b: int, c: float, d: int, e: float, f: int, g: float, h: int, i: float ,j: int): float { + return i; +} + +function fgetMix9(): float { + return fargMix9(1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10); +} + +function fargMix10(a: float, b: int, c: float, d: int, e: float, f: int, g: float, h: int, i: float ,j: int): int { + return j; +} + +function fgetMix10(): int { + return fargMix10(1.0, 2, 3.0, 4, 5.0, 6, 7.0, 8, 9.0, 10); +} + function fadd(x: float, y: float): float { return x + y; } From 229920946dfb107c6281acee3d892ffc467b0328 Mon Sep 17 00:00:00 2001 From: Marvin Kaiser Date: Wed, 4 Mar 2020 20:53:50 +0100 Subject: [PATCH 05/14] 25- Strict check between function signature and function call --- src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java index c6104e8..3db76bd 100644 --- a/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java +++ b/src/main/java/de/hsrm/compiler/Klang/ContextAnalysis.java @@ -697,10 +697,8 @@ public class ContextAnalysis extends KlangBaseVisitor { Expression[] args = new Expression[argCount]; for (int i = 0; i < argCount; i++) { Expression expression = (Expression) this.visit(ctx.functionCall().arguments().expression(i)); - try { - expression.type.combine(func.signature[i]); // Make sure the types are matching - } catch (Exception e) { - throw new RuntimeException(Helper.getErrorPrefix(line, col) + "argument " + i + " " + e.getMessage()); + if (!expression.type.equals(func.signature[i])) { + throw new RuntimeException(Helper.getErrorPrefix(line, col) + "argument " + i + " Expected " + func.signature[i].getName() + " but got: " + expression.type.getName()); } args[i] = expression; } From 58cdaf04dd6e8641302b0439800f1a9544aced95 Mon Sep 17 00:00:00 2001 From: Marvin Kaiser Date: Thu, 5 Mar 2020 07:58:16 +0100 Subject: [PATCH 06/14] 25-Add more tests for floats --- src/test/math/math.c | 100 ++++++++++++++++++++++++++++++++++++++--- src/test/math/math.h | 6 ++- src/test/print/print.c | 32 ++++++++++++- src/test/print/print.h | 6 +++ src/test/test.k | 14 ++++++ 5 files changed, 148 insertions(+), 10 deletions(-) diff --git a/src/test/math/math.c b/src/test/math/math.c index c6a049d..7b144c4 100644 --- a/src/test/math/math.c +++ b/src/test/math/math.c @@ -1,5 +1,6 @@ #include #include "math.h" +#include #include "../print/print.h" int cAdd(int x, int y) @@ -72,6 +73,20 @@ int math_testExpected(char *name, int x, int y, int expected, int result) } } +int math_testExpected_f(char *name, double x, double y, double expected, double result) +{ + if (expected == result) + { + float_succPrefixTwo(name, x, y, expected, result); + return 0; + } + else + { + float_errPrefixTwo(name, x, y, expected, result); + return 1; + } +} + int math_test(char *name, int (*correctFunction)(int, int), int (*testFunction)(int, int), int x, int y) { int expected = correctFunction(x, y); @@ -79,10 +94,10 @@ int math_test(char *name, int (*correctFunction)(int, int), int (*testFunction)( return math_testExpected(name, x, y, expected, result); } -float math_test_f(char *name, float (*correctFunction)(float, float), float (*testFunction)(float, float), float x, float y) { - float expected = correctFunction(x, y); - float result = testFunction(x, y); - return math_testExpected(name, x, y, expected, result); +float math_test_f(char *name, double (*correctFunction)(double, double), double (*testFunction)(double, double), double x, double y) { + double expected = correctFunction(x, y); + double result = testFunction(x, y); + return math_testExpected_f(name, x, y, expected, result); } int math_testOneArg(char *name, int (*correctFunction)(int), int (*testFunction)(int), int x) @@ -101,18 +116,18 @@ int math_testOneArg(char *name, int (*correctFunction)(int), int (*testFunction) } } -float math_testOneArg_f(char *name, float (*correctFunction)(float), float (*testFunction)(float), float x) +double math_testOneArg_f(char *name, double (*correctFunction)(double), double (*testFunction)(double), double x) { float expected = correctFunction(x); float result = testFunction(x); if (expected == result) { - succPrefixOne(name, x, expected, result); + float_succPrefixOne(name, x, expected, result); return 0; } else { - errPrefixOne(name, x, expected, result); + float_errPrefixOne(name, x, expected, result); return 1; } } @@ -125,6 +140,16 @@ void math_simpleTest(char *name, int expected, int result) { } } +int math_argumentTest_f(char* name, double expected, double result) { + if (expected == result) { + succ_f(name, expected, result); + return 0; + } else { + err_f(name, expected, result); + return 1; + } +} + int runMathTests() { printf("\nAddition Tests \n"); @@ -170,6 +195,12 @@ int runMathTests() math_test_f("fadd", fcAdd, fadd, 2.0, 0.0); math_test_f("fadd", fcAdd, fadd, 1.0, 5.0); math_test_f("fadd", fcAdd, fadd, -1.0, -1.0); + math_test_f("fadd", fcAdd, fadd, 10.0, 10.0); + math_test_f("fadd", fcAdd, fadd, 1.337, 0.0); + math_test_f("fadd", fcAdd, fadd, 1.5, 2.0); + math_test_f("fadd", fcAdd, fadd, -10.0, 10.0); + math_test_f("fadd", fcAdd, fadd, -10.0, -10.0); + math_test_f("fadd", fcAdd, fadd, -10.0, -1.0); printf("\nFloat Subtraction Tests \n"); math_test_f("fsub", fcSub, fsub, 0.0, 0.0); @@ -177,6 +208,8 @@ int runMathTests() math_test_f("fsub", fcSub, fsub, 2.0, 0.0); math_test_f("fsub", fcSub, fsub, 1.0, 5.0); math_test_f("fsub", fcSub, fsub, -1.0, -1.0); + math_test_f("fsub", fcSub, fsub, -1.0, 0.0); + math_test_f("fsub", fcSub, fsub, -1.0, 1.337); printf("\nFloat Multiplication Tests \n"); math_test_f("fmul", fcMul, fmul, 0.0, 0.0); @@ -189,6 +222,7 @@ int runMathTests() math_testOneArg_f("fneg", fcNeg, fneg, 0.0); math_testOneArg_f("fneg", fcNeg, fneg, 1.0); math_testOneArg_f("fneg", fcNeg, fneg, -1.0); + math_testOneArg_f("fneg", fcNeg, fneg, -10.0); printf("\nFloat Identity Tests\n"); math_testOneArg_f("fid", fcId, fid, 0.0); @@ -200,6 +234,10 @@ int runMathTests() math_testOneArg("selfMinus", cSelfMinus, selfMinus, 0); math_testOneArg("selfMinus", cSelfMinus, selfMinus, 100); math_testOneArg("selfMinus", cSelfMinus, selfMinus, -50); + math_testOneArg_f("fselfMinus", fcSelfMinus, fselfMinus, 5); + math_testOneArg_f("fselfMinus", fcSelfMinus, fselfMinus, 0); + math_testOneArg_f("fselfMinus", fcSelfMinus, fselfMinus, 100); + math_testOneArg_f("fselfMinus", fcSelfMinus, fselfMinus, -50); math_simpleTest("precedence t1", 16, t1()); math_simpleTest("precedence t2", 16, t2()); math_simpleTest("precedence t3", 16, t3()); @@ -208,4 +246,52 @@ int runMathTests() math_simpleTest("precedence t6", 16, t6()); math_simpleTest("precedence t7", 16, t7()); math_simpleTest("precedence t8", 18, t8()); + + printf("\nFloat And Integer Addition\n"); + math_argumentTest_f("mixadd(1.0, 1)", 2.0, mixadd(1.0, 1)); + math_argumentTest_f("mixadd(0.0, 0)", 0.0, mixadd(0.0, 0)); + math_argumentTest_f("mixadd(10.0, 10)", 20.0, mixadd(10.0, 10)); + math_argumentTest_f("mixadd(1.337, 0)", 1.337, mixadd(1.337, 0)); + math_argumentTest_f("mixadd(1.5, 2)", 3.5, mixadd(1.5, 2)); + math_argumentTest_f("mixadd(-10.0, 10)", 0.0, mixadd(-10.0, 10)); + math_argumentTest_f("mixadd(-10.0, -10)", -20.0, mixadd(-10.0, -10)); + math_argumentTest_f("mixadd(-10.0, -1)", -11.0, mixadd(-10.0, -1)); + + printf("\nFloat And Integer Subtraction\n"); + math_argumentTest_f("mixsub(10.0, 10)", 0.0, mixsub(10.0, 10)); + math_argumentTest_f("mixsub(0.0, 0)", 0.0, mixsub(0.0, 0)); + math_argumentTest_f("mixsub(-10.0, -10)", -20.0, mixsub(-10.0, -10)); + math_argumentTest_f("mixsub(-1.0, 1)", -2.0, mixsub(-1.0, 1)); + math_argumentTest_f("mixsub(0.0, -1)", 1.0, mixsub(0.0, -1)); + + printf("\nFloat And Integer Multiplication\n"); + math_argumentTest_f("mixmul(0.0, 0)", 0.0, mixmul(0.0, 0)); + math_argumentTest_f("mixmul(10.0, 0)", 0.0, mixmul(10.0, 0)); + math_argumentTest_f("mixmul(-1.0, 0)", 0.0, mixmul(-1.0, 0)); + math_argumentTest_f("mixmul(-10.0, 0)", 0.0, mixmul(-10.0, 0)); + math_argumentTest_f("mixmul(10.0, -1)", -10.0, mixmul(10.0, -1)); + math_argumentTest_f("mixmul(0.0, -1)", 0.0, mixmul(0.0, -1)); + math_argumentTest_f("mixmul(-1.0, -1)", 10, mixmul(-1.0, -1)); + math_argumentTest_f("mixmul(1.0, 1)", 1, mixmul(1.0, 1)); + math_argumentTest_f("mixmul(1.0, 1)", 0, mixmul(0.0, 1)); + math_argumentTest_f("mixmul(1.0, 1)", -1, mixmul(-1.0, 1)); + math_argumentTest_f("mixmul(1.5, 6)", 9, mixmul(1.5, 6)); + math_argumentTest_f("mixmul(2.0, 2)", 4, mixmul(2.0, 2)); + math_argumentTest_f("mixmul(100.0, 10)", 1000.0, mixmul(100.0, 10)); + + printf("\nFloat And Integer Division\n"); + math_argumentTest_f("mixdiv(10.0, 0)", INFINITY, mixdiv(10.0, 0)); + math_argumentTest_f("mixdiv(10.0, 1)", 10.0, mixdiv(10.0, 1)); + math_argumentTest_f("mixdiv(0.0, 1)", 0.0, mixdiv(0.0, 1)); + math_argumentTest_f("mixdiv(-1.0, 1)", -1.0, mixdiv(-1.0, 1)); + math_argumentTest_f("mixdiv(1.5, 2)", 1.5 / 2, mixdiv(1.5, 2)); + math_argumentTest_f("mixdiv(1.0, 10)", 1.0 / 10, mixdiv(1.0, 10)); + math_argumentTest_f("mixdiv(1.0, 100)", 1.0 / 100, mixdiv(1.0, 100)); + math_argumentTest_f("mixdiv(1.0, 1000)", 1.0 / 1000, mixdiv(1.0, 1000)); + math_argumentTest_f("mixdiv(1.0, 10000)", 1.0 / 10000, mixdiv(1.0, 10000)); + math_argumentTest_f("mixdiv(1.0, 100000)", 1.0 / 100000, mixdiv(1.0, 100000)); + math_argumentTest_f("mixdiv(1.0, 1000000)", 1.0 / 1000000, mixdiv(1.0, 1000000)); + math_argumentTest_f("mixdiv(1.0, 10000000)", 1.0 / 10000000, mixdiv(1.0, 10000000)); + + } \ No newline at end of file diff --git a/src/test/math/math.h b/src/test/math/math.h index 5ed8145..e84b8aa 100644 --- a/src/test/math/math.h +++ b/src/test/math/math.h @@ -22,4 +22,8 @@ double fsub(double x, double y); double fmul(double x, double y); double fneg(double x); double fid(double x); -double fselfMinus(double x); \ No newline at end of file +double fselfMinus(double x); +double mixadd(double x, int y); +double mixsub(double x, int y); +double mixmul(double x, int y); +double mixdiv(double x, int y); \ No newline at end of file diff --git a/src/test/print/print.c b/src/test/print/print.c index b8ff8af..b1b8445 100644 --- a/src/test/print/print.c +++ b/src/test/print/print.c @@ -30,12 +30,20 @@ void err(char* name, int expected, int result) { void succ_f(char* name, double expected, double result) { incSuccess(); - printf("\033[0;32mSUCCESS:\t%s:\tGOT: %f\tExpected: %f\033[0;0m\n", name, result, expected); + if (expected <= 0.000001 || result <= 0.000001) { + printf("\033[0;32mSUCCESS:\t%s:\tGOT: %.*e\tExpected: %.*e\033[0;0m\n", name, result, expected); + } else { + printf("\033[0;32mSUCCESS:\t%s:\tGOT: %f\tExpected: %f\033[0;0m\n", name, result, expected); + } } void err_f(char* name, double expected, double result) { incFailure(); - printf("\033[0;31mERROR:\t\t%s:\tGOT: %f\tExpected: %f\033[0;0m\n", name, result, expected); + if (expected <= 0.000001 || result <= 0.000001) { + printf("\033[0;31mERROR:\t\t%s:\tGOT: %.*e\tExpected: %.*e\033[0;0m\n", name, result, expected); + } else { + printf("\033[0;31mERROR:\t\t%s:\tGOT: %f\tExpected: %Df\033[0;0m\n", name, result, expected); + } } void succPrefixOne(char* name, int x, int expected, int result) { @@ -48,6 +56,16 @@ void errPrefixOne(char* name, int x, int expected, int result) { printf("\033[0;31mERROR:\t\t%s(%d)\tGOT: %d\tExpected: %d\033[0;0m\n", name, x, result, expected); } +void float_succPrefixOne(char* name, double x, double expected, double result) { + incSuccess(); + printf("\033[0;32mSUCCESS:\t%s(%f)\tGOT: %f\tExpected: %f\033[0;0m\n", name, x, result, expected); +} + +void float_errPrefixOne(char* name, double x, double expected, double result) { + incFailure(); + printf("\033[0;31mERROR:\t\t%s(%f)\tGOT: %f\tExpected: %f\033[0;0m\n", name, x, result, expected); +} + void succPrefixTwo(char* name, int x, int y, int expected, int result) { incSuccess(); printf("\033[0;32mSUCCESS:\t%s(%d, %d)\tGOT: %d\tExpected: %d\033[0;0m\n", name, x, y, result, expected); @@ -58,6 +76,16 @@ void errPrefixTwo(char* name, int x, int y, int expected, int result) { printf("\033[0;31mERROR:\t\t%s(%d, %d)\tGOT: %d\tExpected: %d\033[0;0m\n", name, x, y, result, expected); } +void float_succPrefixTwo(char* name, double x, double y, double expected, double result) { + incSuccess(); + printf("\033[0;32mSUCCESS:\t%s(%f, %f)\tGOT: %f\tExpected: %f\033[0;0m\n", name, x, y, result, expected); +} + +void float_errPrefixTwo(char* name, double x, double y, double expected, double result) { + incFailure(); + printf("\033[0;31mERROR:\t\t%s(%f, %f)\tGOT: %f\tExpected: %f\033[0;0m\n", name, x, y, result, expected); +} + void bool_succPrefixOne(char* name, bool x, bool expected, bool result) { incSuccess(); printf("\033[0;32mSUCCESS:\t%s%s\tGOT: %s\tExpected: %s\033[0;0m\n", name, printBool(x), printBool(result), printBool(expected)); diff --git a/src/test/print/print.h b/src/test/print/print.h index 8318341..9a82fe4 100644 --- a/src/test/print/print.h +++ b/src/test/print/print.h @@ -12,9 +12,15 @@ void err_f(char* name, double expected, double result); void succPrefixOne(char* name, int x, int expected, int result); void errPrefixOne(char* name, int x, int expected, int result); +void float_succPrefixOne(char* name, double x, double expected, double result); +void float_errPrefixOne(char* name, double x, double expected, double result); + void succPrefixTwo(char* name, int x, int y, int expected, int result); void errPrefixTwo(char* name, int x, int y, int expected, int result); +void float_succPrefixTwo(char* name, double x, double y, double expected, double result); +void float_errPrefixTwo(char* name, double x, double y, double expected, double result); + void succInfixTwo(char* name, int x, int y, int expected, int result); void errInfixTwo(char* name, int x, int y, int expected, int result); diff --git a/src/test/test.k b/src/test/test.k index 8bb46f6..5a9104b 100644 --- a/src/test/test.k +++ b/src/test/test.k @@ -395,6 +395,20 @@ function t8(): int { return (1 + 5) * 3; } +function mixadd(x: float, y: int): float { + return x + y; +} +function mixsub(x: float, y: int): float { + return x - y; +} + +function mixmul(x: float, y: int): float { + return x * y; +} + +function mixdiv(x: float, y: int): float { + return x / y; +} add(1, 1); From cbc8020e816f1733a056c905fe52175c0fe5b882 Mon Sep 17 00:00:00 2001 From: Marvin Kaiser Date: Thu, 5 Mar 2020 09:06:22 +0100 Subject: [PATCH 07/14] 25: Rewrite prepareRegisters, correct operator order for comparisons --- .../hsrm/compiler/Klang/visitors/GenASM.java | 60 +++++++++++-------- src/test/math/math.c | 1 + 2 files changed, 35 insertions(+), 26 deletions(-) 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 f1b5efc..dbed3fb 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java @@ -119,24 +119,33 @@ public class GenASM implements Visitor { private boolean prepareRegisters(Expression lhs, Expression rhs) { boolean lhsIsFloat = lhs.type.equals(Type.getFloatType()); boolean rhsIsFloat = rhs.type.equals(Type.getFloatType()); - if (lhsIsFloat || rhsIsFloat) { + if (lhsIsFloat && rhsIsFloat) { lhs.welcome(this); - if (!lhsIsFloat) { - this.intToFloat("%rax", "%xmm1"); - } else { - this.ex.write(" movsd %xmm0, %xmm1\n"); - } + this.ex.write(" movsd %xmm0, %xmm2\n"); rhs.welcome(this); - if (!rhsIsFloat) { - this.intToFloat("%rax", "%xmm1"); - } + this.ex.write(" movsd %xmm0, %xmm1\n"); + this.ex.write(" movsd %xmm2, %xmm0\n"); return true; + } else if (lhsIsFloat && !rhsIsFloat) { + lhs.welcome(this); + rhs.welcome(this); + this.intToFloat("%rax", "%xmm1"); + return true; + } else if (!lhsIsFloat && rhsIsFloat) { + lhs.welcome(this); + this.intToFloat("%rax", "%xmm2"); + rhs.welcome(this); + this.ex.write(" movsd %xmm0, %xmm1\n"); + this.ex.write(" movsd %xmm2, %xmm0\n"); + return true; + } else { + lhs.welcome(this); + this.ex.write(" pushq %rax\n"); + rhs.welcome(this); + this.ex.write(" movq %rax, %rbx\n"); + this.ex.write(" popq %rax\n"); + return false; } - lhs.welcome(this); - this.ex.write(" pushq %rax\n"); - rhs.welcome(this); - this.ex.write(" popq %rbx\n"); - return false; } public GenASM(ExWriter ex, String mainName) { this.ex = ex; @@ -184,9 +193,9 @@ public class GenASM implements Visitor { boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs); if (isFloatOperation) { - this.ex.write(" ucomisd %xmm0, %xmm1\n"); + this.ex.write(" ucomisd %xmm1, %xmm0\n"); } else { - this.ex.write(" cmp %rax, %rbx\n"); + this.ex.write(" cmp %rbx, %rax\n"); } this.ex.write(" je .L" + lblTrue + "\n"); // false @@ -228,9 +237,9 @@ public class GenASM implements Visitor { boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs); if (isFloatOperation) { - this.ex.write(" ucomisd %xmm0, %xmm1\n"); + this.ex.write(" ucomisd %xmm1, %xmm0\n"); } else { - this.ex.write(" cmp %rax, %rbx\n"); + this.ex.write(" cmp %rbx, %rax\n"); } this.ex.write(" jg .L" + lblTrue + "\n"); // false @@ -250,9 +259,9 @@ public class GenASM implements Visitor { boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs); if (isFloatOperation) { - this.ex.write(" ucomisd %xmm0, %xmm1\n"); + this.ex.write(" ucomisd %xmm1, %xmm0\n"); } else { - this.ex.write(" cmp %rax, %rbx\n"); + this.ex.write(" cmp %rbx, %rax\n"); } this.ex.write(" jge .L" + lblTrue + "\n"); // false @@ -272,9 +281,9 @@ public class GenASM implements Visitor { boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs); if (isFloatOperation) { - this.ex.write(" ucomisd %xmm0, %xmm1\n"); + this.ex.write(" ucomisd %xmm1, %xmm0\n"); } else { - this.ex.write(" cmp %rax, %rbx\n"); + this.ex.write(" cmp %rbx, %rax\n"); } this.ex.write(" jl .L" + lblTrue + "\n"); // false @@ -294,9 +303,9 @@ public class GenASM implements Visitor { boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs); if (isFloatOperation) { - this.ex.write(" ucomisd %xmm0, %xmm1\n"); + this.ex.write(" ucomisd %xmm1, %xmm0\n"); } else { - this.ex.write(" cmp %rax, %rbx\n"); + this.ex.write(" cmp %rbx, %rax\n"); } this.ex.write(" jle .L" + lblTrue + "\n"); // false @@ -326,8 +335,7 @@ public class GenASM implements Visitor { if (isFloatOperation) { this.ex.write(" subsd %xmm1, %xmm0\n"); } else { - this.ex.write(" subq %rax, %rbx\n"); - this.ex.write(" movq %rbx, %rax\n"); + this.ex.write(" subq %rbx, %rax\n"); } return null; } diff --git a/src/test/math/math.c b/src/test/math/math.c index 7b144c4..6a2d63a 100644 --- a/src/test/math/math.c +++ b/src/test/math/math.c @@ -183,6 +183,7 @@ int runMathTests() math_testOneArg("neg", cNeg, neg, 0); math_testOneArg("neg", cNeg, neg, 1); math_testOneArg("neg", cNeg, neg, -1); + math_testOneArg("neg", cNeg, neg, -10); printf("\nIdentity Tests\n"); math_testOneArg("id", cId, id, 0); From bba950c851074f1b8c889da336d68501d622680a Mon Sep 17 00:00:00 2001 From: Marvin Kaiser Date: Thu, 5 Mar 2020 12:31:09 +0100 Subject: [PATCH 08/14] 25: Fix tests --- .../hsrm/compiler/Klang/visitors/GenASM.java | 7 ++ src/test/comparison/comparison.c | 2 +- src/test/comparison/comparison.h | 12 ++-- src/test/functionCall/functionCall.c | 4 +- src/test/functionCall/functionCall.h | 70 +++++++++---------- src/test/loop/loop.c | 2 +- src/test/loop/loop.h | 6 +- src/test/math/math.c | 26 +++---- src/test/math/math.h | 38 +++++----- src/test/print/print.c | 44 +++++------- src/test/print/print.h | 16 ++--- src/test/recursive/recursive.c | 2 +- src/test/recursive/recursive.h | 2 +- 13 files changed, 115 insertions(+), 116 deletions(-) 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 dbed3fb..4735a05 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java @@ -577,6 +577,13 @@ public class GenASM implements Visitor { public Void visit(VariableAssignment e) { e.expression.welcome(this); int offset = this.env.get(e.name); + // TODO: Check why e.type is null + // x = (x - 1) + // if (e.type.equals(Type.getFloatType())) { + // this.ex.write(" movq %xmm0, " + offset + "(%rbp)\n"); + // } else { + // this.ex.write(" movq %rax, " + offset + "(%rbp)\n"); + // } this.ex.write(" movq %rax, " + offset + "(%rbp)\n"); return null; } diff --git a/src/test/comparison/comparison.c b/src/test/comparison/comparison.c index 46bc381..2679894 100644 --- a/src/test/comparison/comparison.c +++ b/src/test/comparison/comparison.c @@ -2,7 +2,7 @@ #include "comparison.h" #include "../print/print.h" -int comparisonTest(char* name, int x, int y, int expected, int result) { +int comparisonTest(char* name, long x, long y, long expected, long result) { if (expected == result) { succInfixTwo(name, x, y, expected, result); return 0; diff --git a/src/test/comparison/comparison.h b/src/test/comparison/comparison.h index 2030b9f..6e88f8f 100644 --- a/src/test/comparison/comparison.h +++ b/src/test/comparison/comparison.h @@ -1,11 +1,11 @@ #include -bool eq(int x, int y); -bool neq(int x, int y); -bool lt(int x, int y); -bool lte(int x, int y); -bool gt(int x, int y); -bool gte(int x, int y); +bool eq(long x, long y); +bool neq(long x, long y); +bool lt(long x, long y); +bool lte(long x, long y); +bool gt(long x, long y); +bool gte(long x, long y); bool and(bool a, bool b); bool or(bool a, bool b); diff --git a/src/test/functionCall/functionCall.c b/src/test/functionCall/functionCall.c index 41b4436..c438ddf 100644 --- a/src/test/functionCall/functionCall.c +++ b/src/test/functionCall/functionCall.c @@ -2,7 +2,7 @@ #include "functionCall.h" #include "../print/print.h" -int argumentTest(char* name, int expected, int result) { +int argumentTest(char* name, long expected, long result) { if (expected == result) { succ(name, expected, result); return 0; @@ -12,7 +12,7 @@ int argumentTest(char* name, int expected, int result) { } } -int argumentTest_f(char* name, int expected, int result) { +int argumentTest_f(char* name, long expected, long result) { if (expected == result) { succ_f(name, expected, result); return 0; diff --git a/src/test/functionCall/functionCall.h b/src/test/functionCall/functionCall.h index da5fe2d..7aac291 100644 --- a/src/test/functionCall/functionCall.h +++ b/src/test/functionCall/functionCall.h @@ -1,24 +1,24 @@ -int arg1(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); -int arg2(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); -int arg3(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); -int arg4(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); -int arg5(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); -int arg6(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); -int arg7(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); -int arg8(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); -int arg9(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); -int arg10(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); +long arg1(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j); +long arg2(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j); +long arg3(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j); +long arg4(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j); +long arg5(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j); +long arg6(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j); +long arg7(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j); +long arg8(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j); +long arg9(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j); +long arg10(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j); -int get1(); -int get2(); -int get3(); -int get4(); -int get5(); -int get6(); -int get7(); -int get8(); -int get9(); -int get10(); +long get1(); +long get2(); +long get3(); +long get4(); +long get5(); +long get6(); +long get7(); +long get8(); +long get9(); +long get10(); double farg1(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j); double farg2(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j); @@ -31,16 +31,16 @@ double farg8(double a, double b, double c, double d, double e, double f, double double farg9(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j); double farg10(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j); -double fargMix1(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); -int fargMix2(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); -double fargMix3(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); -int fargMix4(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); -double fargMix5(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); -int fargMix6(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); -double fargMix7(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); -int fargMix8(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); -double fargMix9(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); -int fargMix10(double a, int b, double c, int d, double e, int f, double g, int h, double i, int j); +double fargMix1(double a, long b, double c, long d, double e, long f, double g, long h, double i, long j); +long fargMix2(double a, long b, double c, long d, double e, long f, double g, long h, double i, long j); +double fargMix3(double a, long b, double c, long d, double e, long f, double g, long h, double i, long j); +long fargMix4(double a, long b, double c, long d, double e, long f, double g, long h, double i, long j); +double fargMix5(double a, long b, double c, long d, double e, long f, double g, long h, double i, long j); +long fargMix6(double a, long b, double c, long d, double e, long f, double g, long h, double i, long j); +double fargMix7(double a, long b, double c, long d, double e, long f, double g, long h, double i, long j); +long fargMix8(double a, long b, double c, long d, double e, long f, double g, long h, double i, long j); +double fargMix9(double a, long b, double c, long d, double e, long f, double g, long h, double i, long j); +long fargMix10(double a, long b, double c, long d, double e, long f, double g, long h, double i, long j); double fget1(); double fget2(); @@ -54,12 +54,12 @@ double fget9(); double fget10(); double fgetMix1(); -int fgetMix2(); +long fgetMix2(); double fgetMix3(); -int fgetMix4(); +long fgetMix4(); double fgetMix5(); -int fgetMix6(); +long fgetMix6(); double fgetMix7(); -int fgetMix8(); +long fgetMix8(); double fgetMix9(); -int fgetMix10(); \ No newline at end of file +long fgetMix10(); \ No newline at end of file diff --git a/src/test/loop/loop.c b/src/test/loop/loop.c index 55fa9a9..08c87d1 100644 --- a/src/test/loop/loop.c +++ b/src/test/loop/loop.c @@ -2,7 +2,7 @@ #include "loop.h" #include "../print/print.h" -int loopTest(char* name, int x, int expected, int result) { +int loopTest(char* name, long x, long expected, long result) { if (expected == result) { succPrefixOne(name, x, expected, result); return 0; diff --git a/src/test/loop/loop.h b/src/test/loop/loop.h index 7e8887e..fe403c8 100644 --- a/src/test/loop/loop.h +++ b/src/test/loop/loop.h @@ -1,3 +1,3 @@ -int myWhile(int x); -int myDoWhile(int x); -int myFor(int x); \ No newline at end of file +long myWhile(long x); +long myDoWhile(long x); +long myFor(long x); \ No newline at end of file diff --git a/src/test/math/math.c b/src/test/math/math.c index 6a2d63a..2f36cc6 100644 --- a/src/test/math/math.c +++ b/src/test/math/math.c @@ -3,31 +3,31 @@ #include #include "../print/print.h" -int cAdd(int x, int y) +long cAdd(long x, long y) { return x + y; } -int cSub(int x, int y) +long cSub(long x, long y) { return x - y; } -int cMul(int x, int y) +long cMul(long x, long y) { return x * y; } -int cModulo(int x, int y) +long cModulo(long x, long y) { return x % y; } -int cNeg(int x) +long cNeg(long x) { return -x; } -int cId(int x) +long cId(long x) { return x; } -int cSelfMinus(int x) +long cSelfMinus(long x) { x = x - 1; return x; @@ -59,7 +59,7 @@ double fcSelfMinus(double x) return x; } -int math_testExpected(char *name, int x, int y, int expected, int result) +int math_testExpected(char *name, long x, long y, long expected, long result) { if (expected == result) { @@ -87,7 +87,7 @@ int math_testExpected_f(char *name, double x, double y, double expected, double } } -int math_test(char *name, int (*correctFunction)(int, int), int (*testFunction)(int, int), int x, int y) +int math_test(char *name, long (*correctFunction)(long, long), long (*testFunction)(long, long), long x, long y) { int expected = correctFunction(x, y); int result = testFunction(x, y); @@ -100,7 +100,7 @@ float math_test_f(char *name, double (*correctFunction)(double, double), double return math_testExpected_f(name, x, y, expected, result); } -int math_testOneArg(char *name, int (*correctFunction)(int), int (*testFunction)(int), int x) +int math_testOneArg(char *name, long (*correctFunction)(long), long (*testFunction)(long), long x) { int expected = correctFunction(x); int result = testFunction(x); @@ -132,7 +132,7 @@ double math_testOneArg_f(char *name, double (*correctFunction)(double), double ( } } -void math_simpleTest(char *name, int expected, int result) { +void math_simpleTest(char *name, long expected, long result) { if (expected == result) { succ(name, expected, result); } else { @@ -176,7 +176,7 @@ int runMathTests() printf("\nModulo Tests \n"); math_test("modulo", cModulo, modulo, 1, 1); math_test("modulo", cModulo, modulo, 1, 5); - math_test("modulo", cModulo, modulo, -1, -1); + // math_test("modulo", cModulo, modulo, -1, -1); math_test("modulo", cModulo, modulo, 1337, 42); printf("\nNegative Tests\n"); @@ -272,7 +272,7 @@ int runMathTests() math_argumentTest_f("mixmul(-10.0, 0)", 0.0, mixmul(-10.0, 0)); math_argumentTest_f("mixmul(10.0, -1)", -10.0, mixmul(10.0, -1)); math_argumentTest_f("mixmul(0.0, -1)", 0.0, mixmul(0.0, -1)); - math_argumentTest_f("mixmul(-1.0, -1)", 10, mixmul(-1.0, -1)); + math_argumentTest_f("mixmul(-1.0, -1)", 1, mixmul(-1.0, -1)); math_argumentTest_f("mixmul(1.0, 1)", 1, mixmul(1.0, 1)); math_argumentTest_f("mixmul(1.0, 1)", 0, mixmul(0.0, 1)); math_argumentTest_f("mixmul(1.0, 1)", -1, mixmul(-1.0, 1)); diff --git a/src/test/math/math.h b/src/test/math/math.h index e84b8aa..d42636d 100644 --- a/src/test/math/math.h +++ b/src/test/math/math.h @@ -2,28 +2,28 @@ Die nachfolgenden Funktionen werden später dazu gelinkt Der Ursprung ist die tests.k Datei, dort sind diese Funktionen implementiert */ -int add(int x, int y); -int sub(int x, int y); -int mul(int x, int y); -int modulo(int x, int y); -int neg(int x); -int id(int x); -int selfMinus(int x); -int t1(); -int t2(); -int t3(); -int t4(); -int t5(); -int t6(); -int t7(); -int t8(); +long add(long x, long y); +long sub(long x, long y); +long mul(long x, long y); +long modulo(long x, long y); +long neg(long x); +long id(long x); +long selfMinus(long x); +long t1(); +long t2(); +long t3(); +long t4(); +long t5(); +long t6(); +long t7(); +long t8(); double fadd(double x, double y); double fsub(double x, double y); double fmul(double x, double y); double fneg(double x); double fid(double x); double fselfMinus(double x); -double mixadd(double x, int y); -double mixsub(double x, int y); -double mixmul(double x, int y); -double mixdiv(double x, int y); \ No newline at end of file +double mixadd(double x, long y); +double mixsub(double x, long y); +double mixmul(double x, long y); +double mixdiv(double x, long y); \ No newline at end of file diff --git a/src/test/print/print.c b/src/test/print/print.c index b1b8445..b995765 100644 --- a/src/test/print/print.c +++ b/src/test/print/print.c @@ -8,52 +8,44 @@ char* printBool(bool a) { return "false"; } -void succInfixTwo(char* name, int x, int y, int expected, int result) { +void succInfixTwo(char* name, long x, long y, long expected, long result) { incSuccess(); - printf("\033[0;32mSUCCESS:\t%d %s %d\tGOT: %d\tExpected: %d\033[0;0m\n", x, name, y, result, expected); + printf("\033[0;32mSUCCESS:\t%ld %s %ld\tGOT: %ld\tExpected: %ld\033[0;0m\n", x, name, y, result, expected); } -void errInfixTwo(char* name, int x, int y, int expected, int result) { +void errInfixTwo(char* name, long x, long y, long expected, long result) { incFailure(); - printf("\033[0;31mERROR:\t\t%d %s %d\tGOT: %d\tExpected: %d\033[0;0m\n", x, name, y, result, expected); + printf("\033[0;31mERROR:\t\t%ld %s %ld\tGOT: %ld\tExpected: %ld\033[0;0m\n", x, name, y, result, expected); } -void succ(char* name, int expected, int result) { +void succ(char* name, long expected, long result) { incSuccess(); - printf("\033[0;32mSUCCESS:\t%s:\tGOT: %d\tExpected: %d\033[0;0m\n", name, result, expected); + printf("\033[0;32mSUCCESS:\t%s:\tGOT: %ld\tExpected: %ld\033[0;0m\n", name, result, expected); } -void err(char* name, int expected, int result) { +void err(char* name, long expected, long result) { incFailure(); - printf("\033[0;31mERROR:\t\t%s:\tGOT: %d\tExpected: %d\033[0;0m\n", name, result, expected); + printf("\033[0;31mERROR:\t\t%s:\tGOT: %ld\tExpected: %ld\033[0;0m\n", name, result, expected); } void succ_f(char* name, double expected, double result) { incSuccess(); - if (expected <= 0.000001 || result <= 0.000001) { - printf("\033[0;32mSUCCESS:\t%s:\tGOT: %.*e\tExpected: %.*e\033[0;0m\n", name, result, expected); - } else { - printf("\033[0;32mSUCCESS:\t%s:\tGOT: %f\tExpected: %f\033[0;0m\n", name, result, expected); - } + printf("\033[0;32mSUCCESS:\t%s:\tGOT: %f\tExpected: %f\033[0;0m\n", name, result, expected); } void err_f(char* name, double expected, double result) { incFailure(); - if (expected <= 0.000001 || result <= 0.000001) { - printf("\033[0;31mERROR:\t\t%s:\tGOT: %.*e\tExpected: %.*e\033[0;0m\n", name, result, expected); - } else { - printf("\033[0;31mERROR:\t\t%s:\tGOT: %f\tExpected: %Df\033[0;0m\n", name, result, expected); - } + printf("\033[0;31mERROR:\t\t%s:\tGOT: %f\tExpected: %f\033[0;0m\n", name, result, expected); } -void succPrefixOne(char* name, int x, int expected, int result) { +void succPrefixOne(char* name, long x, long expected, long result) { incSuccess(); - printf("\033[0;32mSUCCESS:\t%s(%d)\tGOT: %d\tExpected: %d\033[0;0m\n", name, x, result, expected); + printf("\033[0;32mSUCCESS:\t%s(%ld)\tGOT: %ld\tExpected: %ld\033[0;0m\n", name, x, result, expected); } -void errPrefixOne(char* name, int x, int expected, int result) { +void errPrefixOne(char* name, long x, long expected, long result) { incFailure(); - printf("\033[0;31mERROR:\t\t%s(%d)\tGOT: %d\tExpected: %d\033[0;0m\n", name, x, result, expected); + printf("\033[0;31mERROR:\t\t%s(%ld)\tGOT: %ld\tExpected: %ld\033[0;0m\n", name, x, result, expected); } void float_succPrefixOne(char* name, double x, double expected, double result) { @@ -66,14 +58,14 @@ void float_errPrefixOne(char* name, double x, double expected, double result) { printf("\033[0;31mERROR:\t\t%s(%f)\tGOT: %f\tExpected: %f\033[0;0m\n", name, x, result, expected); } -void succPrefixTwo(char* name, int x, int y, int expected, int result) { +void succPrefixTwo(char* name, long x, long y, long expected, long result) { incSuccess(); - printf("\033[0;32mSUCCESS:\t%s(%d, %d)\tGOT: %d\tExpected: %d\033[0;0m\n", name, x, y, result, expected); + printf("\033[0;32mSUCCESS:\t%s(%ld, %ld)\tGOT: %ld\tExpected: %ld\033[0;0m\n", name, x, y, result, expected); } -void errPrefixTwo(char* name, int x, int y, int expected, int result) { +void errPrefixTwo(char* name, long x, long y, long expected, long result) { incFailure(); - printf("\033[0;31mERROR:\t\t%s(%d, %d)\tGOT: %d\tExpected: %d\033[0;0m\n", name, x, y, result, expected); + printf("\033[0;31mERROR:\t\t%s(%ld, %ld)\tGOT: %ld\tExpected: %ld\033[0;0m\n", name, x, y, result, expected); } void float_succPrefixTwo(char* name, double x, double y, double expected, double result) { diff --git a/src/test/print/print.h b/src/test/print/print.h index 9a82fe4..2c08103 100644 --- a/src/test/print/print.h +++ b/src/test/print/print.h @@ -3,26 +3,26 @@ void incSuccess(); void incFailure(); -void succ(char* name, int expected, int result); -void err(char* name, int expected, int result); +void succ(char* name, long expected, long result); +void err(char* name, long expected, long result); void succ_f(char* name, double expected, double result); void err_f(char* name, double expected, double result); -void succPrefixOne(char* name, int x, int expected, int result); -void errPrefixOne(char* name, int x, int expected, int result); +void succPrefixOne(char* name, long x, long expected, long result); +void errPrefixOne(char* name, long x, long expected, long result); void float_succPrefixOne(char* name, double x, double expected, double result); void float_errPrefixOne(char* name, double x, double expected, double result); -void succPrefixTwo(char* name, int x, int y, int expected, int result); -void errPrefixTwo(char* name, int x, int y, int expected, int result); +void succPrefixTwo(char* name, long x, long y, long expected, long result); +void errPrefixTwo(char* name, long x, long y, long expected, long result); void float_succPrefixTwo(char* name, double x, double y, double expected, double result); void float_errPrefixTwo(char* name, double x, double y, double expected, double result); -void succInfixTwo(char* name, int x, int y, int expected, int result); -void errInfixTwo(char* name, int x, int y, int expected, int result); +void succInfixTwo(char* name, long x, long y, long expected, long result); +void errInfixTwo(char* name, long x, long y, long expected, long result); void bool_succPrefixOne(char* name, bool x, bool expected, bool result); void bool_errPrefixOne(char* name, bool x, bool expected, bool result); diff --git a/src/test/recursive/recursive.c b/src/test/recursive/recursive.c index 61ee88c..f063a2b 100644 --- a/src/test/recursive/recursive.c +++ b/src/test/recursive/recursive.c @@ -2,7 +2,7 @@ #include "recursive.h" #include "../print/print.h" -int recursiveTest(char* name, int x, int expected, int result) { +int recursiveTest(char* name, long x, long expected, long result) { if (expected == result) { succPrefixOne(name, x, expected, result); return 0; diff --git a/src/test/recursive/recursive.h b/src/test/recursive/recursive.h index 704036e..592a361 100644 --- a/src/test/recursive/recursive.h +++ b/src/test/recursive/recursive.h @@ -1 +1 @@ -int fac(int x); \ No newline at end of file +long fac(long x); \ No newline at end of file From ebeabfe930d4c7ccaa69afeb940f8fe568ce79fa Mon Sep 17 00:00:00 2001 From: nitrix Date: Thu, 5 Mar 2020 16:39:47 +0100 Subject: [PATCH 09/14] fix input values to match expected value --- src/test/math/math.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/math/math.c b/src/test/math/math.c index 2f36cc6..563c45a 100644 --- a/src/test/math/math.c +++ b/src/test/math/math.c @@ -261,7 +261,7 @@ int runMathTests() printf("\nFloat And Integer Subtraction\n"); math_argumentTest_f("mixsub(10.0, 10)", 0.0, mixsub(10.0, 10)); math_argumentTest_f("mixsub(0.0, 0)", 0.0, mixsub(0.0, 0)); - math_argumentTest_f("mixsub(-10.0, -10)", -20.0, mixsub(-10.0, -10)); + math_argumentTest_f("mixsub(-10.0, 10)", -20.0, mixsub(-10.0, 10)); math_argumentTest_f("mixsub(-1.0, 1)", -2.0, mixsub(-1.0, 1)); math_argumentTest_f("mixsub(0.0, -1)", 1.0, mixsub(0.0, -1)); From 150e18e05bbf3600c02861e046776f1f72758a08 Mon Sep 17 00:00:00 2001 From: nitrix Date: Thu, 5 Mar 2020 16:40:31 +0100 Subject: [PATCH 10/14] inspec type of expression instead of the type of the assignment, since the assignment type is always null --- .../de/hsrm/compiler/Klang/visitors/GenASM.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) 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 4735a05..d75e87f 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java @@ -577,14 +577,15 @@ public class GenASM implements Visitor { public Void visit(VariableAssignment e) { e.expression.welcome(this); int offset = this.env.get(e.name); - // TODO: Check why e.type is null - // x = (x - 1) - // if (e.type.equals(Type.getFloatType())) { - // this.ex.write(" movq %xmm0, " + offset + "(%rbp)\n"); - // } else { - // this.ex.write(" movq %rax, " + offset + "(%rbp)\n"); - // } - this.ex.write(" movq %rax, " + offset + "(%rbp)\n"); + + // Determine where the result of this expression was placed into + // and move it onto the stack from there + if (e.expression.type.equals(Type.getFloatType())) { + this.ex.write(" movq %xmm0, " + offset + "(%rbp)\n"); + } else { + this.ex.write(" movq %rax, " + offset + "(%rbp)\n"); + } + return null; } From 09eec634b147b899b3b66441c2fdd733c873563d Mon Sep 17 00:00:00 2001 From: nitrix Date: Thu, 5 Mar 2020 16:50:37 +0100 Subject: [PATCH 11/14] add new mixdiv test for -1, -1 --- src/test/math/math.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/math/math.c b/src/test/math/math.c index 563c45a..1c39b2a 100644 --- a/src/test/math/math.c +++ b/src/test/math/math.c @@ -283,6 +283,7 @@ int runMathTests() printf("\nFloat And Integer Division\n"); math_argumentTest_f("mixdiv(10.0, 0)", INFINITY, mixdiv(10.0, 0)); math_argumentTest_f("mixdiv(10.0, 1)", 10.0, mixdiv(10.0, 1)); + math_argumentTest_f("mixdiv(-1.0, -1)", 1, mixdiv(-1.0, -1)); math_argumentTest_f("mixdiv(0.0, 1)", 0.0, mixdiv(0.0, 1)); math_argumentTest_f("mixdiv(-1.0, 1)", -1.0, mixdiv(-1.0, 1)); math_argumentTest_f("mixdiv(1.5, 2)", 1.5 / 2, mixdiv(1.5, 2)); From 1530dc6c5502bc3b6e2692b93d8658c1ea02502b Mon Sep 17 00:00:00 2001 From: nitrix Date: Thu, 5 Mar 2020 17:13:19 +0100 Subject: [PATCH 12/14] sign extend rax into rbx before calling idiv, the replaces the rbx zeroing --- src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 d75e87f..f8edb42 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java @@ -357,7 +357,7 @@ public class GenASM implements Visitor { if (isFloatOperation) { this.ex.write(" divsd %xmm1, %xmm0\n"); } else { - this.ex.write(" xor %rdx, %rdx\n"); // clear upper part of division + this.ex.write(" cqto\n"); // sign extend rax into rdx since we're dealing with signed values this.ex.write(" idiv %rbx\n"); // %rax/%rbx, quotient now in %rax } return null; @@ -370,7 +370,7 @@ public class GenASM implements Visitor { e.rhs.welcome(this); this.ex.write(" movq %rax, %rbx\n"); this.ex.write(" popq %rax\n"); - this.ex.write(" xor %rdx, %rdx\n"); // clear upper part of division + this.ex.write(" cqto\n"); // sign extend rax into rdx since we're dealing with signed values this.ex.write(" idiv %rbx\n"); // %rax/%rbx, remainder now in %rdx this.ex.write(" movq %rdx, %rax\n"); return null; From a8b093a005f5359fcabc2336a71db7a4162aa5da Mon Sep 17 00:00:00 2001 From: nitrix Date: Thu, 5 Mar 2020 17:13:36 +0100 Subject: [PATCH 13/14] reenable the mod test for -1, -1 --- src/test/math/math.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/math/math.c b/src/test/math/math.c index 1c39b2a..4a8319f 100644 --- a/src/test/math/math.c +++ b/src/test/math/math.c @@ -176,7 +176,7 @@ int runMathTests() printf("\nModulo Tests \n"); math_test("modulo", cModulo, modulo, 1, 1); math_test("modulo", cModulo, modulo, 1, 5); - // math_test("modulo", cModulo, modulo, -1, -1); + math_test("modulo", cModulo, modulo, -1, -1); math_test("modulo", cModulo, modulo, 1337, 42); printf("\nNegative Tests\n"); From 333475f27b3b2e9c788681a553ff901be804b025 Mon Sep 17 00:00:00 2001 From: nitrix Date: Thu, 5 Mar 2020 17:21:08 +0100 Subject: [PATCH 14/14] implement integer division tests --- src/test/math/math.c | 13 +++++++++++++ src/test/math/math.h | 1 + src/test/test.k | 4 ++++ 3 files changed, 18 insertions(+) diff --git a/src/test/math/math.c b/src/test/math/math.c index 4a8319f..42f245d 100644 --- a/src/test/math/math.c +++ b/src/test/math/math.c @@ -19,6 +19,10 @@ long cModulo(long x, long y) { return x % y; } +long cDiv(long x, long y) +{ + return x / y; +} long cNeg(long x) { return -x; @@ -173,6 +177,15 @@ int runMathTests() math_test("mul", cMul, mul, 1, 5); math_test("mul", cMul, mul, -1, -1); + printf("\nDivision Tests\n"); + math_test("div", cDiv, div, 10, 2); + math_test("div", cDiv, div, 8, 4); + math_test("div", cDiv, div, 6, -2); + math_test("div", cDiv, div, -9, 3); + math_test("div", cDiv, div, 9, 2); + math_test("div", cDiv, div, 9, -2); + math_test("div", cDiv, div, -9, 2); + printf("\nModulo Tests \n"); math_test("modulo", cModulo, modulo, 1, 1); math_test("modulo", cModulo, modulo, 1, 5); diff --git a/src/test/math/math.h b/src/test/math/math.h index d42636d..0af7ad9 100644 --- a/src/test/math/math.h +++ b/src/test/math/math.h @@ -5,6 +5,7 @@ long add(long x, long y); long sub(long x, long y); long mul(long x, long y); +long div(long x, long y); long modulo(long x, long y); long neg(long x); long id(long x); diff --git a/src/test/test.k b/src/test/test.k index 5a9104b..539f333 100644 --- a/src/test/test.k +++ b/src/test/test.k @@ -10,6 +10,10 @@ function mul(x: int, y: int): int { return (x * y); } +function div(x: int, y: int): int { + return (x / y); +} + function modulo(x: int, y: int): int { return (x % y); }