Merge branch '25-floats' into 'master'
Resolve "Floats" Closes #25 See merge request mkais001/klang!15
This commit is contained in:
@@ -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'
|
||||
|
||||
@@ -18,6 +18,13 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
|
||||
Map<String, FunctionInformation> 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<String, FunctionInformation> funcs) {
|
||||
this.funcs = funcs;
|
||||
}
|
||||
@@ -256,6 +263,10 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
|
||||
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<Node> {
|
||||
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<Node> {
|
||||
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<Node> {
|
||||
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<Node> {
|
||||
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<Node> {
|
||||
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<Node> {
|
||||
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<Node> {
|
||||
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<Node> {
|
||||
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<Node> {
|
||||
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<Node> {
|
||||
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<Node> {
|
||||
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<Node> {
|
||||
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<Node> {
|
||||
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<Node> {
|
||||
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);
|
||||
@@ -620,10 +697,8 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
40
src/main/java/de/hsrm/compiler/Klang/types/FloatType.java
Normal file
40
src/main/java/de/hsrm/compiler/Klang/types/FloatType.java
Normal 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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.hsrm.compiler.Klang.types;
|
||||
|
||||
public abstract class NumericType extends PrimitiveType {
|
||||
@Override
|
||||
public boolean isNumericType() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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<Value> {
|
||||
|
||||
@@ -21,115 +22,309 @@ public class EvalVisitor implements Visitor<Value> {
|
||||
|
||||
@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
|
||||
|
||||
@@ -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;
|
||||
@@ -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.WhileLoop;
|
||||
import de.hsrm.compiler.Klang.nodes.statements.*;
|
||||
import de.hsrm.compiler.Klang.types.Type;
|
||||
|
||||
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;
|
||||
private FloatWriter fw = new FloatWriter();
|
||||
private String mainName;
|
||||
Map<String, Integer> env = new HashMap<>();
|
||||
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 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) {
|
||||
this.ex = ex;
|
||||
this.mainName = mainName;
|
||||
@@ -78,6 +163,13 @@ public class GenASM implements Visitor<Void> {
|
||||
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 +178,11 @@ public class GenASM implements Visitor<Void> {
|
||||
|
||||
@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,11 +191,12 @@ public class GenASM implements Visitor<Void> {
|
||||
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 %xmm1, %xmm0\n");
|
||||
} else {
|
||||
this.ex.write(" cmp %rbx, %rax\n");
|
||||
}
|
||||
this.ex.write(" je .L" + lblTrue + "\n");
|
||||
// false
|
||||
this.ex.write(" movq $0, %rax\n");
|
||||
@@ -116,11 +213,12 @@ public class GenASM implements Visitor<Void> {
|
||||
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 +235,12 @@ public class GenASM implements Visitor<Void> {
|
||||
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 %xmm1, %xmm0\n");
|
||||
} else {
|
||||
this.ex.write(" cmp %rbx, %rax\n");
|
||||
}
|
||||
this.ex.write(" jg .L" + lblTrue + "\n");
|
||||
// false
|
||||
this.ex.write(" movq $0, %rax\n");
|
||||
@@ -158,11 +257,12 @@ public class GenASM implements Visitor<Void> {
|
||||
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 %xmm1, %xmm0\n");
|
||||
} else {
|
||||
this.ex.write(" cmp %rbx, %rax\n");
|
||||
}
|
||||
this.ex.write(" jge .L" + lblTrue + "\n");
|
||||
// false
|
||||
this.ex.write(" movq $0, %rax\n");
|
||||
@@ -179,11 +279,12 @@ public class GenASM implements Visitor<Void> {
|
||||
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 %xmm1, %xmm0\n");
|
||||
} else {
|
||||
this.ex.write(" cmp %rbx, %rax\n");
|
||||
}
|
||||
this.ex.write(" jl .L" + lblTrue + "\n");
|
||||
// false
|
||||
this.ex.write(" movq $0, %rax\n");
|
||||
@@ -200,11 +301,12 @@ public class GenASM implements Visitor<Void> {
|
||||
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 %xmm1, %xmm0\n");
|
||||
} else {
|
||||
this.ex.write(" cmp %rbx, %rax\n");
|
||||
}
|
||||
this.ex.write(" jle .L" + lblTrue + "\n");
|
||||
// false
|
||||
this.ex.write(" movq $0, %rax\n");
|
||||
@@ -218,43 +320,46 @@ public class GenASM implements Visitor<Void> {
|
||||
|
||||
@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 %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(" 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;
|
||||
}
|
||||
|
||||
@@ -265,7 +370,7 @@ public class GenASM implements Visitor<Void> {
|
||||
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;
|
||||
@@ -274,7 +379,13 @@ public class GenASM implements Visitor<Void> {
|
||||
@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;
|
||||
}
|
||||
|
||||
@@ -331,20 +442,20 @@ public class GenASM implements Visitor<Void> {
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -352,26 +463,26 @@ public class GenASM implements Visitor<Void> {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -466,7 +577,15 @@ public class GenASM implements Visitor<Void> {
|
||||
public Void visit(VariableAssignment e) {
|
||||
e.expression.welcome(this);
|
||||
int offset = this.env.get(e.name);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -497,26 +616,59 @@ public class GenASM implements Visitor<Void> {
|
||||
|
||||
// hole die anzahl der lokalen variablen
|
||||
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);
|
||||
|
||||
// Erzeuge ein environment
|
||||
this.env = new HashMap<String, Integer>();
|
||||
|
||||
// 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<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);
|
||||
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
|
||||
@@ -532,16 +684,80 @@ public class GenASM implements Visitor<Void> {
|
||||
|
||||
@Override
|
||||
public Void visit(FunctionCall e) {
|
||||
// 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");
|
||||
}
|
||||
if (e.arguments.length > 0) {
|
||||
// Mapping arguments index -> xmm registers index
|
||||
int[] xmmIdxs = new int[this.floatRegisters.length];
|
||||
int fi = -1;
|
||||
|
||||
// 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");
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
|
||||
// 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");
|
||||
@@ -565,6 +781,10 @@ public class GenASM implements Visitor<Void> {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Void> {
|
||||
|
||||
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.types = types;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -22,6 +26,11 @@ class GetVars implements Visitor<Void> {
|
||||
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<Void> {
|
||||
@Override
|
||||
public Void visit(VariableDeclaration e) {
|
||||
vars.add(e.name);
|
||||
types.put(e.name, e.type);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,12 @@ public class PrettyPrintVisitor implements Visitor<Void> {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(FloatExpression e) {
|
||||
ex.write(e.value);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(BooleanExpression e) {
|
||||
ex.write(e.value);
|
||||
|
||||
@@ -13,6 +13,7 @@ public interface Visitor<R> {
|
||||
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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
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);
|
||||
|
||||
@@ -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,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 () {
|
||||
printf("\nFunction Call Tests \n");
|
||||
// Checks that parameters are correctly passed from gcc to functions
|
||||
@@ -36,4 +46,50 @@ 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());
|
||||
|
||||
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());
|
||||
}
|
||||
@@ -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);
|
||||
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);
|
||||
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();
|
||||
@@ -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;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
int myWhile(int x);
|
||||
int myDoWhile(int x);
|
||||
int myFor(int x);
|
||||
long myWhile(long x);
|
||||
long myDoWhile(long x);
|
||||
long myFor(long x);
|
||||
@@ -1,38 +1,69 @@
|
||||
#include <stdio.h>
|
||||
#include "math.h"
|
||||
#include <math.h>
|
||||
#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 cDiv(long x, long y)
|
||||
{
|
||||
return x / y;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -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 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)
|
||||
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 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) {
|
||||
succ(name, expected, result);
|
||||
} 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()
|
||||
{
|
||||
printf("\nAddition Tests \n");
|
||||
@@ -100,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);
|
||||
@@ -110,17 +196,62 @@ 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);
|
||||
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);
|
||||
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");
|
||||
math_testOneArg("selfMinus", cSelfMinus, selfMinus, 5);
|
||||
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());
|
||||
@@ -129,4 +260,53 @@ 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)", 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));
|
||||
|
||||
|
||||
}
|
||||
@@ -2,18 +2,29 @@
|
||||
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 div(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, long y);
|
||||
double mixsub(double x, long y);
|
||||
double mixmul(double x, long y);
|
||||
double mixdiv(double x, long y);
|
||||
@@ -8,44 +8,74 @@ 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 succPrefixOne(char* name, int x, int expected, int result) {
|
||||
void succ_f(char* name, double expected, double 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:\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();
|
||||
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();
|
||||
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();
|
||||
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) {
|
||||
|
||||
@@ -3,17 +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 succPrefixOne(char* name, int x, int expected, int result);
|
||||
void errPrefixOne(char* name, int x, int expected, int result);
|
||||
void succ_f(char* name, double expected, double result);
|
||||
void err_f(char* name, 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 succPrefixOne(char* name, long x, long expected, long result);
|
||||
void errPrefixOne(char* name, long x, long expected, long 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 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, 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_errPrefixOne(char* name, bool x, bool expected, bool result);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1 +1 @@
|
||||
int fac(int x);
|
||||
long fac(long x);
|
||||
207
src/test/test.k
207
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);
|
||||
}
|
||||
@@ -102,6 +106,195 @@ 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);
|
||||
}
|
||||
|
||||
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 {
|
||||
if (x) {
|
||||
return (x * fac((x - 1)));
|
||||
@@ -206,6 +399,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);
|
||||
|
||||
Reference in New Issue
Block a user