Merge branch '25-floats' into 'master'

Resolve "Floats"

Closes #25

See merge request mkais001/klang!15
This commit is contained in:
Dennis Kaiser
2020-03-06 00:36:10 +01:00
27 changed files with 1352 additions and 209 deletions

View File

@@ -87,6 +87,7 @@ expression
atom atom
: INTEGER_LITERAL #intAtom : INTEGER_LITERAL #intAtom
| BOOLEAN_LITERAL #boolAtom | BOOLEAN_LITERAL #boolAtom
| FLOAT_LITERAL #floatAtom
| IDENT #variable | IDENT #variable
; ;
@@ -97,6 +98,7 @@ type_annotation
type type
: INTEGER : INTEGER
| BOOLEAN | BOOLEAN
| FLOAT
; ;
functionCall functionCall
@@ -131,6 +133,7 @@ WHILE: 'while';
DO: 'do'; DO: 'do';
FOR: 'for'; FOR: 'for';
PERIOD: '.';
COL: ':'; COL: ':';
SCOL: ';'; SCOL: ';';
OBRK: '{'; OBRK: '{';
@@ -157,11 +160,16 @@ DIV: '/';
BOOLEAN: 'bool'; BOOLEAN: 'bool';
INTEGER: 'int'; INTEGER: 'int';
FLOAT: 'float';
INTEGER_LITERAL INTEGER_LITERAL
: [0-9]+ : [0-9]+
; ;
FLOAT_LITERAL
: INTEGER_LITERAL PERIOD INTEGER_LITERAL
;
BOOLEAN_LITERAL BOOLEAN_LITERAL
: 'true' : 'true'
| 'false' | 'false'

View File

@@ -18,6 +18,13 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
Map<String, FunctionInformation> funcs; Map<String, FunctionInformation> funcs;
Type currentDeclaredReturnType; 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<String, FunctionInformation> funcs) { public ContextAnalysis(Map<String, FunctionInformation> funcs) {
this.funcs = funcs; this.funcs = funcs;
} }
@@ -256,6 +263,10 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
result.type = Type.getBooleanType(); result.type = Type.getBooleanType();
result.line = ctx.start.getLine(); result.line = ctx.start.getLine();
result.col = ctx.start.getCharPositionInLine(); 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; return result;
} }
@@ -267,6 +278,10 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
result.type = Type.getBooleanType(); result.type = Type.getBooleanType();
result.line = ctx.start.getLine(); result.line = ctx.start.getLine();
result.col = ctx.start.getCharPositionInLine(); 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; return result;
} }
@@ -277,11 +292,15 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
int line = ctx.start.getLine(); int line = ctx.start.getLine();
int col = ctx.start.getCharPositionInLine(); int col = ctx.start.getCharPositionInLine();
AdditionExpression result = new AdditionExpression((Expression) lhs, (Expression) rhs); AdditionExpression result = new AdditionExpression((Expression) lhs, (Expression) rhs);
try { try {
result.type = lhs.type.combine(rhs.type); result.type = lhs.type.combine(rhs.type);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage()); throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage());
} }
checkNumeric(lhs, rhs, line, col);
result.line = ctx.start.getLine(); result.line = ctx.start.getLine();
result.col = ctx.start.getCharPositionInLine(); result.col = ctx.start.getCharPositionInLine();
return result; return result;
@@ -319,9 +338,10 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
int line = ctx.start.getLine(); int line = ctx.start.getLine();
int col = ctx.start.getCharPositionInLine(); int col = ctx.start.getCharPositionInLine();
if (lhs.type != Type.getIntegerType() || rhs.type != Type.getIntegerType()) { try {
String error = "Both operants of this expression have to be a number."; lhs.type.combine(rhs.type);
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); } catch (Exception e) {
throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage());
} }
NotEqualityExpression result = new NotEqualityExpression((Expression) lhs, (Expression) rhs); NotEqualityExpression result = new NotEqualityExpression((Expression) lhs, (Expression) rhs);
@@ -338,11 +358,14 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
int line = ctx.start.getLine(); int line = ctx.start.getLine();
int col = ctx.start.getCharPositionInLine(); int col = ctx.start.getCharPositionInLine();
if (lhs.type != Type.getIntegerType() || rhs.type != Type.getIntegerType()) { try {
String error = "Both operants of this expression have to be a number."; lhs.type.combine(rhs.type);
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); } 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); LTExpression result = new LTExpression((Expression) lhs, (Expression) rhs);
result.type = Type.getBooleanType(); result.type = Type.getBooleanType();
result.line = line; result.line = line;
@@ -357,8 +380,14 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
int line = ctx.start.getLine(); int line = ctx.start.getLine();
int col = ctx.start.getCharPositionInLine(); int col = ctx.start.getCharPositionInLine();
if (lhs.type != Type.getIntegerType() || rhs.type != Type.getIntegerType()) { try {
String error = "Both operants of this expression have to be a number."; 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); throw new RuntimeException(Helper.getErrorPrefix(line, col) + error);
} }
@@ -376,11 +405,14 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
int line = ctx.start.getLine(); int line = ctx.start.getLine();
int col = ctx.start.getCharPositionInLine(); int col = ctx.start.getCharPositionInLine();
if (lhs.type != Type.getIntegerType() || rhs.type != Type.getIntegerType()) { try {
String error = "Both operants of this expression have to be a number."; lhs.type.combine(rhs.type);
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); } 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); LTEExpression result = new LTEExpression((Expression) lhs, (Expression) rhs);
result.type = Type.getBooleanType(); result.type = Type.getBooleanType();
result.line = line; result.line = line;
@@ -395,11 +427,14 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
int line = ctx.start.getLine(); int line = ctx.start.getLine();
int col = ctx.start.getCharPositionInLine(); int col = ctx.start.getCharPositionInLine();
if (lhs.type != Type.getIntegerType() || rhs.type != Type.getIntegerType()) { try {
String error = "Both operants of this expression have to be a number."; lhs.type.combine(rhs.type);
throw new RuntimeException(Helper.getErrorPrefix(line, col) + error); } 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); GTEExpression result = new GTEExpression((Expression) lhs, (Expression) rhs);
result.type = Type.getBooleanType(); result.type = Type.getBooleanType();
result.line = line; result.line = line;
@@ -414,11 +449,15 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
int line = ctx.start.getLine(); int line = ctx.start.getLine();
int col = ctx.start.getCharPositionInLine(); int col = ctx.start.getCharPositionInLine();
SubstractionExpression result = new SubstractionExpression((Expression) lhs, (Expression) rhs); SubstractionExpression result = new SubstractionExpression((Expression) lhs, (Expression) rhs);
try { try {
result.type = lhs.type.combine(rhs.type); result.type = lhs.type.combine(rhs.type);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage()); throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage());
} }
checkNumeric(lhs, rhs, line, col);
result.line = line; result.line = line;
result.col = col; result.col = col;
return result; return result;
@@ -431,11 +470,15 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
int line = ctx.start.getLine(); int line = ctx.start.getLine();
int col = ctx.start.getCharPositionInLine(); int col = ctx.start.getCharPositionInLine();
MultiplicationExpression result = new MultiplicationExpression((Expression) lhs, (Expression) rhs); MultiplicationExpression result = new MultiplicationExpression((Expression) lhs, (Expression) rhs);
try { try {
result.type = lhs.type.combine(rhs.type); result.type = lhs.type.combine(rhs.type);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage()); throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage());
} }
checkNumeric(lhs, rhs, line, col);
result.line = line; result.line = line;
result.col = col; result.col = col;
return result; return result;
@@ -448,11 +491,15 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
int line = ctx.start.getLine(); int line = ctx.start.getLine();
int col = ctx.start.getCharPositionInLine(); int col = ctx.start.getCharPositionInLine();
DivisionExpression result = new DivisionExpression((Expression) lhs, (Expression) rhs); DivisionExpression result = new DivisionExpression((Expression) lhs, (Expression) rhs);
try { try {
result.type = lhs.type.combine(rhs.type); result.type = lhs.type.combine(rhs.type);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage()); throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage());
} }
checkNumeric(lhs, rhs, line, col);
result.line = line; result.line = line;
result.col = col; result.col = col;
return result; return result;
@@ -465,11 +512,20 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
int line = ctx.start.getLine(); int line = ctx.start.getLine();
int col = ctx.start.getCharPositionInLine(); int col = ctx.start.getCharPositionInLine();
ModuloExpression result = new ModuloExpression((Expression) lhs, (Expression) rhs); ModuloExpression result = new ModuloExpression((Expression) lhs, (Expression) rhs);
try { try {
result.type = lhs.type.combine(rhs.type); result.type = lhs.type.combine(rhs.type);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(Helper.getErrorPrefix(line, col) + e.getMessage()); 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.line = line;
result.col = col; result.col = col;
return result; return result;
@@ -482,6 +538,12 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
result.type = expression.type; result.type = expression.type;
result.line = ctx.start.getLine(); result.line = ctx.start.getLine();
result.col = ctx.start.getCharPositionInLine(); 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; return result;
} }
@@ -492,6 +554,12 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
result.type = expression.type; result.type = expression.type;
result.line = ctx.start.getLine(); result.line = ctx.start.getLine();
result.col = ctx.start.getCharPositionInLine(); 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; return result;
} }
@@ -534,6 +602,15 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
return n; 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 @Override
public Node visitBoolAtom(KlangParser.BoolAtomContext ctx) { public Node visitBoolAtom(KlangParser.BoolAtomContext ctx) {
Node n = new BooleanExpression(ctx.getText().equals("true") ? true : false); Node n = new BooleanExpression(ctx.getText().equals("true") ? true : false);
@@ -620,10 +697,8 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
Expression[] args = new Expression[argCount]; Expression[] args = new Expression[argCount];
for (int i = 0; i < argCount; i++) { for (int i = 0; i < argCount; i++) {
Expression expression = (Expression) this.visit(ctx.functionCall().arguments().expression(i)); Expression expression = (Expression) this.visit(ctx.functionCall().arguments().expression(i));
try { if (!expression.type.equals(func.signature[i])) {
expression.type.combine(func.signature[i]); // Make sure the types are matching throw new RuntimeException(Helper.getErrorPrefix(line, col) + "argument " + i + " Expected " + func.signature[i].getName() + " but got: " + expression.type.getName());
} catch (Exception e) {
throw new RuntimeException(Helper.getErrorPrefix(line, col) + "argument " + i + " " + e.getMessage());
} }
args[i] = expression; args[i] = expression;
} }

View File

@@ -1,12 +1,20 @@
package de.hsrm.compiler.Klang; package de.hsrm.compiler.Klang;
import de.hsrm.compiler.Klang.types.Type;
public class Value { public class Value {
public Type type;
private Object value; private Object value;
public Value(Object value) { public Value(Object value) {
this.value = value; this.value = value;
} }
public Value(Object value, Type type) {
this.value = value;
this.type = type;
}
public Object asObject() { public Object asObject() {
return this.value; return this.value;
} }
@@ -15,6 +23,10 @@ public class Value {
return (int) this.value; return (int) this.value;
} }
public double asFloat() {
return (double) this.value;
}
public boolean asBoolean() { public boolean asBoolean() {
return (boolean) this.value; return (boolean) this.value;
} }

View File

@@ -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> R welcome(Visitor<R> v) {
return v.visit(this);
}
}

View File

@@ -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());
}
}

View File

@@ -1,6 +1,6 @@
package de.hsrm.compiler.Klang.types; package de.hsrm.compiler.Klang.types;
public class IntegerType extends PrimitiveType { public class IntegerType extends NumericType {
private static IntegerType instance = null; private static IntegerType instance = null;
@@ -29,8 +29,9 @@ public class IntegerType extends PrimitiveType {
return this; return this;
} }
// Check other possible combinations if (that.equals(Type.getFloatType())) {
// if (that.equals(Type.getFloatType())) return Type.getFloatType(); return Type.getFloatType();
}
// Every remaining type will throw a RuntimeException // Every remaining type will throw a RuntimeException
throw new RuntimeException("Type missmatch: cannot combine " + this.getName() + " and " + that.getName()); throw new RuntimeException("Type missmatch: cannot combine " + this.getName() + " and " + that.getName());

View File

@@ -0,0 +1,8 @@
package de.hsrm.compiler.Klang.types;
public abstract class NumericType extends PrimitiveType {
@Override
public boolean isNumericType() {
return true;
}
}

View File

@@ -14,4 +14,12 @@ public abstract class PrimitiveType extends Type {
public boolean isBooleanType() { public boolean isBooleanType() {
return false; return false;
}; };
public boolean isFloatType() {
return false;
};
public boolean isNumericType() {
return false;
}
} }

View File

@@ -12,10 +12,15 @@ public abstract class Type {
return BooleanType.getType(); return BooleanType.getType();
} }
public static FloatType getFloatType() {
return FloatType.getType();
}
public static Type getByName(String name) { public static Type getByName(String name) {
switch (name) { switch (name) {
case "bool": return getBooleanType(); case "bool": return getBooleanType();
case "int": return getIntegerType(); case "int": return getIntegerType();
case "float": return getFloatType();
default: throw new RuntimeException("Unknown type " + name); default: throw new RuntimeException("Unknown type " + name);
} }
} }
@@ -23,4 +28,5 @@ public abstract class Type {
public abstract String getName(); public abstract String getName();
public abstract Type combine(Type that); public abstract Type combine(Type that);
public abstract boolean isPrimitiveType(); public abstract boolean isPrimitiveType();
public abstract boolean isNumericType();
} }

View File

@@ -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.ForLoop;
import de.hsrm.compiler.Klang.nodes.loops.WhileLoop; import de.hsrm.compiler.Klang.nodes.loops.WhileLoop;
import de.hsrm.compiler.Klang.nodes.statements.*; import de.hsrm.compiler.Klang.nodes.statements.*;
import de.hsrm.compiler.Klang.types.Type;
public class EvalVisitor implements Visitor<Value> { public class EvalVisitor implements Visitor<Value> {
@@ -21,115 +22,309 @@ public class EvalVisitor implements Visitor<Value> {
@Override @Override
public Value visit(IntegerExpression e) { 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 @Override
public Value visit(BooleanExpression e) { public Value visit(BooleanExpression e) {
return new Value(e.value); Value result = new Value(e.value);
result.type = Type.getBooleanType();
return result;
} }
@Override @Override
public Value visit(EqualityExpression e) { public Value visit(EqualityExpression e) {
Value lhs = e.lhs.welcome(this); Value lhs = e.lhs.welcome(this);
Value rhs = e.rhs.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 @Override
public Value visit(NotEqualityExpression e) { public Value visit(NotEqualityExpression e) {
Value lhs = e.lhs.welcome(this); Value lhs = e.lhs.welcome(this);
Value rhs = e.rhs.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 @Override
public Value visit(GTExpression e) { public Value visit(GTExpression e) {
Value lhs = e.lhs.welcome(this); Value lhs = e.lhs.welcome(this);
Value rhs = e.rhs.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 @Override
public Value visit(GTEExpression e) { public Value visit(GTEExpression e) {
Value lhs = e.lhs.welcome(this); Value lhs = e.lhs.welcome(this);
Value rhs = e.rhs.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 @Override
public Value visit(LTExpression e) { public Value visit(LTExpression e) {
Value lhs = e.lhs.welcome(this); Value lhs = e.lhs.welcome(this);
Value rhs = e.rhs.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 @Override
public Value visit(LTEExpression e) { public Value visit(LTEExpression e) {
Value lhs = e.lhs.welcome(this); Value lhs = e.lhs.welcome(this);
Value rhs = e.rhs.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 @Override
public Value visit(AdditionExpression e) { public Value visit(AdditionExpression e) {
Value lhs = e.lhs.welcome(this); Value lhs = e.lhs.welcome(this);
Value rhs = e.rhs.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 @Override
public Value visit(SubstractionExpression e) { public Value visit(SubstractionExpression e) {
Value lhs = e.lhs.welcome(this); Value lhs = e.lhs.welcome(this);
Value rhs = e.rhs.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 @Override
public Value visit(MultiplicationExpression e) { public Value visit(MultiplicationExpression e) {
Value lhs = e.lhs.welcome(this); Value lhs = e.lhs.welcome(this);
Value rhs = e.rhs.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 @Override
public Value visit(DivisionExpression e) { public Value visit(DivisionExpression e) {
Value lhs = e.lhs.welcome(this); Value lhs = e.lhs.welcome(this);
Value rhs = e.rhs.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 @Override
public Value visit(ModuloExpression e) { public Value visit(ModuloExpression e) {
Value lhs = e.lhs.welcome(this); Value lhs = e.lhs.welcome(this);
Value rhs = e.rhs.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 @Override
public Value visit(NegateExpression e) { public Value visit(NegateExpression e) {
Value a = e.lhs.welcome(this); 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 @Override
public Value visit(OrExpression e) { public Value visit(OrExpression e) {
Value lhs = e.lhs.welcome(this); Value lhs = e.lhs.welcome(this);
Value rhs = e.rhs.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 @Override
public Value visit(AndExpression e) { public Value visit(AndExpression e) {
Value lhs = e.lhs.welcome(this); Value lhs = e.lhs.welcome(this);
Value rhs = e.rhs.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 @Override
public Value visit(NotExpression e) { public Value visit(NotExpression e) {
Value lhs = e.lhs.welcome(this); 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 @Override

View File

@@ -1,6 +1,7 @@
package de.hsrm.compiler.Klang.visitors; package de.hsrm.compiler.Klang.visitors;
import java.io.*; import java.io.*;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -12,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.ForLoop;
import de.hsrm.compiler.Klang.nodes.loops.WhileLoop; import de.hsrm.compiler.Klang.nodes.loops.WhileLoop;
import de.hsrm.compiler.Klang.nodes.statements.*; import de.hsrm.compiler.Klang.nodes.statements.*;
import de.hsrm.compiler.Klang.types.Type;
public class GenASM implements Visitor<Void> { public class GenASM implements Visitor<Void> {
@@ -55,13 +57,96 @@ public class GenASM implements Visitor<Void> {
} }
} }
private class FloatWriter {
private StringBuilder sb = new StringBuilder();
private int id = -1;
public String getFloat(double d) {
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;
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; public ExWriter ex;
private FloatWriter fw = new FloatWriter();
private String mainName; private String mainName;
Map<String, Integer> env = new HashMap<>(); Map<String, Integer> env = new HashMap<>();
Set<String> vars; Set<String> vars;
String[] rs = { "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9" }; 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 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);
this.ex.write(" movsd %xmm0, %xmm2\n");
rhs.welcome(this);
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;
}
}
public GenASM(ExWriter ex, String mainName) { public GenASM(ExWriter ex, String mainName) {
this.ex = ex; this.ex = ex;
this.mainName = mainName; this.mainName = mainName;
@@ -78,6 +163,13 @@ public class GenASM implements Visitor<Void> {
return null; 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 @Override
public Void visit(BooleanExpression e) { public Void visit(BooleanExpression e) {
this.ex.write(" movq $" + (e.value ? 1 : 0) + ", %rax\n"); this.ex.write(" movq $" + (e.value ? 1 : 0) + ", %rax\n");
@@ -86,7 +178,11 @@ public class GenASM implements Visitor<Void> {
@Override @Override
public Void visit(Variable e) { public Void visit(Variable e) {
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"); this.ex.write(" movq " + this.env.get(e.name) + "(%rbp), %rax\n");
}
return null; return null;
} }
@@ -95,11 +191,12 @@ public class GenASM implements Visitor<Void> {
int lblTrue = ++lCount; int lblTrue = ++lCount;
int lblEnd = ++lCount; int lblEnd = ++lCount;
e.lhs.welcome(this); boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
this.ex.write(" pushq %rax\n"); if (isFloatOperation) {
e.rhs.welcome(this); this.ex.write(" ucomisd %xmm1, %xmm0\n");
this.ex.write(" popq %rbx\n"); } else {
this.ex.write(" cmp %rax, %rbx\n"); this.ex.write(" cmp %rbx, %rax\n");
}
this.ex.write(" je .L" + lblTrue + "\n"); this.ex.write(" je .L" + lblTrue + "\n");
// false // false
this.ex.write(" movq $0, %rax\n"); this.ex.write(" movq $0, %rax\n");
@@ -116,11 +213,12 @@ public class GenASM implements Visitor<Void> {
int lblTrue = ++lCount; int lblTrue = ++lCount;
int lblEnd = ++lCount; int lblEnd = ++lCount;
e.lhs.welcome(this); boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
this.ex.write(" pushq %rax\n"); if (isFloatOperation) {
e.rhs.welcome(this); this.ex.write(" ucomisd %xmm0, %xmm1\n");
this.ex.write(" popq %rbx\n"); } else {
this.ex.write(" cmp %rax, %rbx\n"); this.ex.write(" cmp %rax, %rbx\n");
}
this.ex.write(" jne .L" + lblTrue + "\n"); this.ex.write(" jne .L" + lblTrue + "\n");
// false // false
this.ex.write(" movq $0, %rax\n"); this.ex.write(" movq $0, %rax\n");
@@ -137,11 +235,12 @@ public class GenASM implements Visitor<Void> {
int lblTrue = ++lCount; int lblTrue = ++lCount;
int lblEnd = ++lCount; int lblEnd = ++lCount;
e.lhs.welcome(this); boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
this.ex.write(" pushq %rax\n"); if (isFloatOperation) {
e.rhs.welcome(this); this.ex.write(" ucomisd %xmm1, %xmm0\n");
this.ex.write(" popq %rbx\n"); } else {
this.ex.write(" cmp %rax, %rbx\n"); this.ex.write(" cmp %rbx, %rax\n");
}
this.ex.write(" jg .L" + lblTrue + "\n"); this.ex.write(" jg .L" + lblTrue + "\n");
// false // false
this.ex.write(" movq $0, %rax\n"); this.ex.write(" movq $0, %rax\n");
@@ -158,11 +257,12 @@ public class GenASM implements Visitor<Void> {
int lblTrue = ++lCount; int lblTrue = ++lCount;
int lblEnd = ++lCount; int lblEnd = ++lCount;
e.lhs.welcome(this); boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
this.ex.write(" pushq %rax\n"); if (isFloatOperation) {
e.rhs.welcome(this); this.ex.write(" ucomisd %xmm1, %xmm0\n");
this.ex.write(" popq %rbx\n"); } else {
this.ex.write(" cmp %rax, %rbx\n"); this.ex.write(" cmp %rbx, %rax\n");
}
this.ex.write(" jge .L" + lblTrue + "\n"); this.ex.write(" jge .L" + lblTrue + "\n");
// false // false
this.ex.write(" movq $0, %rax\n"); this.ex.write(" movq $0, %rax\n");
@@ -179,11 +279,12 @@ public class GenASM implements Visitor<Void> {
int lblTrue = ++lCount; int lblTrue = ++lCount;
int lblEnd = ++lCount; int lblEnd = ++lCount;
e.lhs.welcome(this); boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
this.ex.write(" pushq %rax\n"); if (isFloatOperation) {
e.rhs.welcome(this); this.ex.write(" ucomisd %xmm1, %xmm0\n");
this.ex.write(" popq %rbx\n"); } else {
this.ex.write(" cmp %rax, %rbx\n"); this.ex.write(" cmp %rbx, %rax\n");
}
this.ex.write(" jl .L" + lblTrue + "\n"); this.ex.write(" jl .L" + lblTrue + "\n");
// false // false
this.ex.write(" movq $0, %rax\n"); this.ex.write(" movq $0, %rax\n");
@@ -200,11 +301,12 @@ public class GenASM implements Visitor<Void> {
int lblTrue = ++lCount; int lblTrue = ++lCount;
int lblEnd = ++lCount; int lblEnd = ++lCount;
e.lhs.welcome(this); boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
this.ex.write(" pushq %rax\n"); if (isFloatOperation) {
e.rhs.welcome(this); this.ex.write(" ucomisd %xmm1, %xmm0\n");
this.ex.write(" popq %rbx\n"); } else {
this.ex.write(" cmp %rax, %rbx\n"); this.ex.write(" cmp %rbx, %rax\n");
}
this.ex.write(" jle .L" + lblTrue + "\n"); this.ex.write(" jle .L" + lblTrue + "\n");
// false // false
this.ex.write(" movq $0, %rax\n"); this.ex.write(" movq $0, %rax\n");
@@ -218,43 +320,46 @@ public class GenASM implements Visitor<Void> {
@Override @Override
public Void visit(AdditionExpression e) { public Void visit(AdditionExpression e) {
e.lhs.welcome(this); boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
this.ex.write(" pushq %rax\n"); if (isFloatOperation) {
e.rhs.welcome(this); this.ex.write(" addsd %xmm1, %xmm0\n");
this.ex.write(" popq %rbx\n"); } else {
this.ex.write(" addq %rbx, %rax\n"); this.ex.write(" addq %rbx, %rax\n");
}
return null; return null;
} }
@Override @Override
public Void visit(SubstractionExpression e) { public Void visit(SubstractionExpression e) {
e.rhs.welcome(this); boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
this.ex.write(" pushq %rax\n"); if (isFloatOperation) {
e.lhs.welcome(this); this.ex.write(" subsd %xmm1, %xmm0\n");
this.ex.write(" popq %rbx\n"); } else {
this.ex.write(" subq %rbx, %rax\n"); this.ex.write(" subq %rbx, %rax\n");
}
return null; return null;
} }
@Override @Override
public Void visit(MultiplicationExpression e) { public Void visit(MultiplicationExpression e) {
e.lhs.welcome(this); boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
this.ex.write(" pushq %rax\n"); if (isFloatOperation) {
e.rhs.welcome(this); this.ex.write(" mulsd %xmm1, %xmm0\n");
this.ex.write(" popq %rbx\n"); } else {
this.ex.write(" imulq %rbx, %rax\n"); this.ex.write(" imulq %rbx, %rax\n");
}
return null; return null;
} }
@Override @Override
public Void visit(DivisionExpression e) { public Void visit(DivisionExpression e) {
e.lhs.welcome(this); boolean isFloatOperation = this.prepareRegisters(e.lhs, e.rhs);
this.ex.write(" pushq %rax\n"); if (isFloatOperation) {
e.rhs.welcome(this); this.ex.write(" divsd %xmm1, %xmm0\n");
this.ex.write(" movq %rax, %rbx\n"); } else {
this.ex.write(" popq %rax\n"); this.ex.write(" cqto\n"); // sign extend rax into rdx since we're dealing with signed values
this.ex.write(" xor %rdx, %rdx\n"); // clear upper part of division
this.ex.write(" idiv %rbx\n"); // %rax/%rbx, quotient now in %rax this.ex.write(" idiv %rbx\n"); // %rax/%rbx, quotient now in %rax
}
return null; return null;
} }
@@ -265,7 +370,7 @@ public class GenASM implements Visitor<Void> {
e.rhs.welcome(this); e.rhs.welcome(this);
this.ex.write(" movq %rax, %rbx\n"); this.ex.write(" movq %rax, %rbx\n");
this.ex.write(" popq %rax\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(" idiv %rbx\n"); // %rax/%rbx, remainder now in %rdx
this.ex.write(" movq %rdx, %rax\n"); this.ex.write(" movq %rdx, %rax\n");
return null; return null;
@@ -274,7 +379,13 @@ public class GenASM implements Visitor<Void> {
@Override @Override
public Void visit(NegateExpression e) { public Void visit(NegateExpression e) {
e.lhs.welcome(this); e.lhs.welcome(this);
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"); this.ex.write(" neg %rax\n");
}
return null; return null;
} }
@@ -466,7 +577,15 @@ public class GenASM implements Visitor<Void> {
public Void visit(VariableAssignment e) { public Void visit(VariableAssignment e) {
e.expression.welcome(this); e.expression.welcome(this);
int offset = this.env.get(e.name); int offset = this.env.get(e.name);
// 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"); this.ex.write(" movq %rax, " + offset + "(%rbp)\n");
}
return null; return null;
} }
@@ -497,26 +616,59 @@ public class GenASM implements Visitor<Void> {
// hole die anzahl der lokalen variablen // hole die anzahl der lokalen variablen
this.vars = new TreeSet<String>(); this.vars = new TreeSet<String>();
GetVars getvars = new GetVars(vars); HashMap<String, Type> types = new HashMap<String, Type>();
GetVars getvars = new GetVars(vars, types);
getvars.visit(e); getvars.visit(e);
// Erzeuge ein environment // Erzeuge ein environment
this.env = new HashMap<String, Integer>(); this.env = new HashMap<String, Integer>();
// Merke dir die offsets der parameter, die direkt auf den stack gelegt wurden // 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 // Per stack übergebene variablen in env registrieren
for (int i = this.rs.length; i < e.parameters.length; i++) { var registerParameters = new ArrayList<Parameter>();
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); env.put(e.parameters[i].name, offset);
offset += 8; 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; offset = 0;
for (int i = 0; i < Math.min(this.rs.length, e.parameters.length); i++) { ri = 0;
this.ex.write(" pushq " + this.rs[i] + "\n"); 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; offset -= 8;
this.env.put(e.parameters[i].name, offset); // negative, liegt unter aktuellem BP 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 // Reserviere Platz auf dem Stack für jede lokale variable
@@ -532,16 +684,80 @@ public class GenASM implements Visitor<Void> {
@Override @Override
public Void visit(FunctionCall e) { public Void visit(FunctionCall e) {
// Die ersten sechs params in die register schieben if (e.arguments.length > 0) {
for (int i = 0; i < Math.min(this.rs.length, e.arguments.length); i++) { // Mapping arguments index -> xmm registers index
e.arguments[i].welcome(this); int[] xmmIdxs = new int[this.floatRegisters.length];
this.ex.write(" movq %rax, " + this.rs[i] + "\n"); int fi = -1;
// Mapping arguments index -> all purpose registers index
int[] rIdxs = new int[this.registers.length];
int ri = -1;
// Mapping arguments index -> stack
ArrayList<Integer> stackIdxs = new ArrayList<Integer>();
// 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);
}
}
} }
// Den Rest auf den stack pushen // Welcome the arguments in order, push everything onto the stack
for (int i = e.arguments.length - 1; i >= this.rs.length; i--) { for (var arg : e.arguments) {
e.arguments[i].welcome(this); arg.welcome(this);
if (arg.type.equals(Type.getFloatType())) {
this.ex.write(" movq %xmm0, %rax\n");
this.ex.write(" pushq %rax\n"); this.ex.write(" pushq %rax\n");
} else {
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"); this.ex.write(" call " + e.name + "\n");
@@ -565,6 +781,10 @@ public class GenASM implements Visitor<Void> {
this.ex.write(" movq %rbp, %rsp\n"); this.ex.write(" movq %rbp, %rsp\n");
this.ex.write(" popq %rbp\n"); this.ex.write(" popq %rbp\n");
this.ex.write(" ret\n"); this.ex.write(" ret\n");
// PRINT FLOATS HERE
this.ex.write("\n");
this.ex.write(fw.getFloatSection());
return null; return null;
} }

View File

@@ -1,5 +1,6 @@
package de.hsrm.compiler.Klang.visitors; package de.hsrm.compiler.Klang.visitors;
import java.util.Map;
import java.util.Set; import java.util.Set;
import de.hsrm.compiler.Klang.nodes.*; 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.ForLoop;
import de.hsrm.compiler.Klang.nodes.loops.WhileLoop; import de.hsrm.compiler.Klang.nodes.loops.WhileLoop;
import de.hsrm.compiler.Klang.nodes.statements.*; import de.hsrm.compiler.Klang.nodes.statements.*;
import de.hsrm.compiler.Klang.types.Type;
class GetVars implements Visitor<Void> { class GetVars implements Visitor<Void> {
public Set<String> vars; public Set<String> vars;
public Map<String, Type> types;
public GetVars(Set<String> vars) { public GetVars(Set<String> vars, Map<String, Type> types) {
this.vars = vars; this.vars = vars;
this.types = types;
} }
@Override @Override
@@ -22,6 +26,11 @@ class GetVars implements Visitor<Void> {
return null; return null;
} }
@Override
public Void visit(FloatExpression e) {
return null;
}
@Override @Override
public Void visit(BooleanExpression e) { public Void visit(BooleanExpression e) {
return null; return null;
@@ -179,6 +188,7 @@ class GetVars implements Visitor<Void> {
@Override @Override
public Void visit(VariableDeclaration e) { public Void visit(VariableDeclaration e) {
vars.add(e.name); vars.add(e.name);
types.put(e.name, e.type);
return null; return null;
} }

View File

@@ -72,6 +72,12 @@ public class PrettyPrintVisitor implements Visitor<Void> {
return null; return null;
} }
@Override
public Void visit(FloatExpression e) {
ex.write(e.value);
return null;
}
@Override @Override
public Void visit(BooleanExpression e) { public Void visit(BooleanExpression e) {
ex.write(e.value); ex.write(e.value);

View File

@@ -13,6 +13,7 @@ public interface Visitor<R> {
R visit(AndExpression e); R visit(AndExpression e);
R visit (NotExpression e); R visit (NotExpression e);
R visit(IntegerExpression e); R visit(IntegerExpression e);
R visit(FloatExpression e);
R visit(BooleanExpression e); R visit(BooleanExpression e);
R visit(Variable e); R visit(Variable e);
R visit(AdditionExpression e); R visit(AdditionExpression e);

View File

@@ -2,7 +2,7 @@
#include "comparison.h" #include "comparison.h"
#include "../print/print.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) { if (expected == result) {
succInfixTwo(name, x, y, expected, result); succInfixTwo(name, x, y, expected, result);
return 0; return 0;

View File

@@ -1,11 +1,11 @@
#include <stdbool.h> #include <stdbool.h>
bool eq(int x, int y); bool eq(long x, long y);
bool neq(int x, int y); bool neq(long x, long y);
bool lt(int x, int y); bool lt(long x, long y);
bool lte(int x, int y); bool lte(long x, long y);
bool gt(int x, int y); bool gt(long x, long y);
bool gte(int x, int y); bool gte(long x, long y);
bool and(bool a, bool b); bool and(bool a, bool b);
bool or(bool a, bool b); bool or(bool a, bool b);

View File

@@ -2,7 +2,7 @@
#include "functionCall.h" #include "functionCall.h"
#include "../print/print.h" #include "../print/print.h"
int argumentTest(char* name, int expected, int result) { int argumentTest(char* name, long expected, long result) {
if (expected == result) { if (expected == result) {
succ(name, expected, result); succ(name, expected, result);
return 0; return 0;
@@ -12,6 +12,16 @@ int argumentTest(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;
} else {
err_f(name, expected, result);
return 1;
}
}
int runFunctionCallTests () { int runFunctionCallTests () {
printf("\nFunction Call Tests \n"); printf("\nFunction Call Tests \n");
// Checks that parameters are correctly passed from gcc to functions // Checks that parameters are correctly passed from gcc to functions
@@ -36,4 +46,50 @@ int runFunctionCallTests () {
argumentTest("get8(...args)", 8, get8()); argumentTest("get8(...args)", 8, get8());
argumentTest("get9(...args)", 9, get9()); argumentTest("get9(...args)", 9, get9());
argumentTest("get10(...args)", 10, get10()); 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());
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());
} }

View File

@@ -1,21 +1,65 @@
int arg1(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);
int arg2(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); long arg2(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j);
int arg3(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); long arg3(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j);
int arg4(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); long arg4(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j);
int arg5(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); long arg5(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j);
int arg6(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); long arg6(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j);
int arg7(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); long arg7(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j);
int arg8(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); long arg8(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j);
int arg9(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j); long arg9(long a, long b, long c, long d, long e, long f, long g, long h, long i, long j);
int arg10(int a, int b, int c, int d, int e, int f, int g, int h, int i, int 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(); long get1();
int get2(); long get2();
int get3(); long get3();
int get4(); long get4();
int get5(); long get5();
int get6(); long get6();
int get7(); long get7();
int get8(); long get8();
int get9(); long get9();
int get10(); 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);
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 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();
double fget3();
double fget4();
double fget5();
double fget6();
double fget7();
double fget8();
double fget9();
double fget10();
double fgetMix1();
long fgetMix2();
double fgetMix3();
long fgetMix4();
double fgetMix5();
long fgetMix6();
double fgetMix7();
long fgetMix8();
double fgetMix9();
long fgetMix10();

View File

@@ -2,7 +2,7 @@
#include "loop.h" #include "loop.h"
#include "../print/print.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) { if (expected == result) {
succPrefixOne(name, x, expected, result); succPrefixOne(name, x, expected, result);
return 0; return 0;

View File

@@ -1,3 +1,3 @@
int myWhile(int x); long myWhile(long x);
int myDoWhile(int x); long myDoWhile(long x);
int myFor(int x); long myFor(long x);

View File

@@ -1,38 +1,69 @@
#include <stdio.h> #include <stdio.h>
#include "math.h" #include "math.h"
#include <math.h>
#include "../print/print.h" #include "../print/print.h"
int cAdd(int x, int y) long cAdd(long x, long y)
{ {
return x + y; return x + y;
} }
int cSub(int x, int y) long cSub(long x, long y)
{ {
return x - y; return x - y;
} }
int cMul(int x, int y) long cMul(long x, long y)
{ {
return x * y; return x * y;
} }
int cModulo(int x, int y) long cModulo(long x, long y)
{ {
return x % y; return x % y;
} }
int cNeg(int x) long cDiv(long x, long y)
{
return x / y;
}
long cNeg(long x)
{ {
return -x; return -x;
} }
int cId(int x) long cId(long x)
{ {
return x; return x;
} }
int cSelfMinus(int x) long cSelfMinus(long x)
{ {
x = x - 1; x = x - 1;
return x; return x;
} }
int math_testExpected(char *name, int x, int y, int expected, int result) 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, long x, long y, long expected, long result)
{ {
if (expected == result) if (expected == result)
{ {
@@ -46,14 +77,34 @@ int math_testExpected(char *name, int x, int y, int expected, int result)
} }
} }
int math_test(char *name, int (*correctFunction)(int, int), int (*testFunction)(int, int), int x, int y) 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, long (*correctFunction)(long, long), long (*testFunction)(long, long), long x, long y)
{ {
int expected = correctFunction(x, y); int expected = correctFunction(x, y);
int result = testFunction(x, y); int result = testFunction(x, y);
return math_testExpected(name, x, y, expected, result); return math_testExpected(name, x, y, expected, result);
} }
int math_testOneArg(char *name, int (*correctFunction)(int), int (*testFunction)(int), int x) 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, long (*correctFunction)(long), long (*testFunction)(long), long x)
{ {
int expected = correctFunction(x); int expected = correctFunction(x);
int result = testFunction(x); int result = testFunction(x);
@@ -69,7 +120,23 @@ int math_testOneArg(char *name, int (*correctFunction)(int), int (*testFunction)
} }
} }
void math_simpleTest(char *name, int expected, int result) { 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)
{
float_succPrefixOne(name, x, expected, result);
return 0;
}
else
{
float_errPrefixOne(name, x, expected, result);
return 1;
}
}
void math_simpleTest(char *name, long expected, long result) {
if (expected == result) { if (expected == result) {
succ(name, expected, result); succ(name, expected, result);
} else { } else {
@@ -77,6 +144,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() int runMathTests()
{ {
printf("\nAddition Tests \n"); printf("\nAddition Tests \n");
@@ -100,6 +177,15 @@ int runMathTests()
math_test("mul", cMul, mul, 1, 5); math_test("mul", cMul, mul, 1, 5);
math_test("mul", cMul, mul, -1, -1); 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"); printf("\nModulo Tests \n");
math_test("modulo", cModulo, modulo, 1, 1); math_test("modulo", cModulo, modulo, 1, 1);
math_test("modulo", cModulo, modulo, 1, 5); math_test("modulo", cModulo, modulo, 1, 5);
@@ -110,17 +196,62 @@ int runMathTests()
math_testOneArg("neg", cNeg, neg, 0); math_testOneArg("neg", cNeg, neg, 0);
math_testOneArg("neg", cNeg, neg, 1); math_testOneArg("neg", cNeg, neg, 1);
math_testOneArg("neg", cNeg, neg, -1); math_testOneArg("neg", cNeg, neg, -1);
math_testOneArg("neg", cNeg, neg, -10);
printf("\nIdentity Tests\n"); printf("\nIdentity Tests\n");
math_testOneArg("id", cId, id, 0); math_testOneArg("id", cId, id, 0);
math_testOneArg("id", cId, id, -1); math_testOneArg("id", cId, id, -1);
math_testOneArg("id", cId, id, 15); 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);
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);
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);
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);
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);
math_testOneArg_f("fneg", fcNeg, fneg, -10.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"); printf("\nMisc Tests\n");
math_testOneArg("selfMinus", cSelfMinus, selfMinus, 5); math_testOneArg("selfMinus", cSelfMinus, selfMinus, 5);
math_testOneArg("selfMinus", cSelfMinus, selfMinus, 0); math_testOneArg("selfMinus", cSelfMinus, selfMinus, 0);
math_testOneArg("selfMinus", cSelfMinus, selfMinus, 100); math_testOneArg("selfMinus", cSelfMinus, selfMinus, 100);
math_testOneArg("selfMinus", cSelfMinus, selfMinus, -50); 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 t1", 16, t1());
math_simpleTest("precedence t2", 16, t2()); math_simpleTest("precedence t2", 16, t2());
math_simpleTest("precedence t3", 16, t3()); math_simpleTest("precedence t3", 16, t3());
@@ -129,4 +260,53 @@ int runMathTests()
math_simpleTest("precedence t6", 16, t6()); math_simpleTest("precedence t6", 16, t6());
math_simpleTest("precedence t7", 16, t7()); math_simpleTest("precedence t7", 16, t7());
math_simpleTest("precedence t8", 18, t8()); 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)", 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));
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(-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));
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));
} }

View File

@@ -2,18 +2,29 @@
Die nachfolgenden Funktionen werden später dazu gelinkt Die nachfolgenden Funktionen werden später dazu gelinkt
Der Ursprung ist die tests.k Datei, dort sind diese Funktionen implementiert Der Ursprung ist die tests.k Datei, dort sind diese Funktionen implementiert
*/ */
int add(int x, int y); long add(long x, long y);
int sub(int x, int y); long sub(long x, long y);
int mul(int x, int y); long mul(long x, long y);
int modulo(int x, int y); long div(long x, long y);
int neg(int x); long modulo(long x, long y);
int id(int x); long neg(long x);
int selfMinus(int x); long id(long x);
int t1(); long selfMinus(long x);
int t2(); long t1();
int t3(); long t2();
int t4(); long t3();
int t5(); long t4();
int t6(); long t5();
int t7(); long t6();
int t8(); 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, long y);
double mixsub(double x, long y);
double mixmul(double x, long y);
double mixdiv(double x, long y);

View File

@@ -8,44 +8,74 @@ char* printBool(bool a) {
return "false"; 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(); 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(); 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(); 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(); 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 succPrefixOne(char* name, int x, int expected, int result) { void succ_f(char* name, double expected, double result) {
incSuccess(); 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:\tGOT: %f\tExpected: %f\033[0;0m\n", name, result, expected);
} }
void errPrefixOne(char* name, int x, int expected, int result) { void err_f(char* name, double expected, double result) {
incFailure(); 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:\tGOT: %f\tExpected: %f\033[0;0m\n", name, result, expected);
} }
void succPrefixTwo(char* name, int x, int y, int expected, int result) { void succPrefixOne(char* name, long x, long expected, long result) {
incSuccess(); 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)\tGOT: %ld\tExpected: %ld\033[0;0m\n", name, x, result, expected);
} }
void errPrefixTwo(char* name, int x, int y, int expected, int result) { void errPrefixOne(char* name, long x, long expected, long result) {
incFailure(); 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)\tGOT: %ld\tExpected: %ld\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, long x, long y, long expected, long result) {
incSuccess();
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, long x, long y, long expected, long result) {
incFailure();
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) {
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) { void bool_succPrefixOne(char* name, bool x, bool expected, bool result) {

View File

@@ -3,17 +3,26 @@
void incSuccess(); void incSuccess();
void incFailure(); void incFailure();
void succ(char* name, int expected, int result); void succ(char* name, long expected, long result);
void err(char* name, int expected, int result); void err(char* name, long expected, long result);
void succPrefixOne(char* name, int x, int expected, int result); void succ_f(char* name, double expected, double result);
void errPrefixOne(char* name, int x, int expected, int result); void err_f(char* name, double expected, double result);
void succPrefixTwo(char* name, int x, int y, int expected, int result); void succPrefixOne(char* name, long x, long expected, long result);
void errPrefixTwo(char* name, int x, int y, int expected, int result); void errPrefixOne(char* name, long x, long expected, long result);
void succInfixTwo(char* name, int x, int y, int expected, int result); void float_succPrefixOne(char* name, double x, double expected, double result);
void errInfixTwo(char* name, int x, int y, int expected, int result); void float_errPrefixOne(char* name, double x, double expected, double 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, 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_succPrefixOne(char* name, bool x, bool expected, bool result);
void bool_errPrefixOne(char* name, bool x, bool expected, bool result); void bool_errPrefixOne(char* name, bool x, bool expected, bool result);

View File

@@ -2,7 +2,7 @@
#include "recursive.h" #include "recursive.h"
#include "../print/print.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) { if (expected == result) {
succPrefixOne(name, x, expected, result); succPrefixOne(name, x, expected, result);
return 0; return 0;

View File

@@ -1 +1 @@
int fac(int x); long fac(long x);

View File

@@ -10,6 +10,10 @@ function mul(x: int, y: int): int {
return (x * y); return (x * y);
} }
function div(x: int, y: int): int {
return (x / y);
}
function modulo(x: int, y: int): int { function modulo(x: int, y: int): int {
return (x % y); return (x % y);
} }
@@ -102,6 +106,195 @@ function get10(): int {
return arg10(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 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);
}
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;
}
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 { function fac(x: int): int {
if (x) { if (x) {
return (x * fac((x - 1))); return (x * fac((x - 1)));
@@ -206,6 +399,20 @@ function t8(): int {
return (1 + 5) * 3; 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); add(1, 1);