Added while loop
This commit is contained in:
@@ -1,2 +1,4 @@
|
||||
# Klang - The Kaiser language
|
||||
This is the project for Klang - the Kaiser language.
|
||||
This is the project for Klang - the Kaiser language.
|
||||
|
||||
0 is false
|
||||
2
makefile
2
makefile
@@ -18,7 +18,7 @@ runTest: ./src/test/test
|
||||
./src/test/test
|
||||
|
||||
./src/test/test: ./src/test/tests.s
|
||||
gcc -o ./src/test/test ./src/test/tests.s ./src/test/functionCall/functionCall.c ./src/test/recursive/recursive.c ./src/test/comparison/comparison.c ./src/test/testCode.c
|
||||
gcc -o ./src/test/test ./src/test/tests.s ./src/test/functionCall/functionCall.c ./src/test/while/while.c ./src/test/recursive/recursive.c ./src/test/comparison/comparison.c ./src/test/testCode.c
|
||||
|
||||
./src/test/tests.s: target/klang-1.0-jar-with-dependencies.jar
|
||||
java -cp target/klang-1.0-jar-with-dependencies.jar de.hsrm.compiler.Klang.Klang < ./src/test/tests.k > ./src/test/tests.s
|
||||
|
||||
@@ -26,6 +26,7 @@ statement
|
||||
| variable_declaration
|
||||
| variable_assignment
|
||||
| return_statement
|
||||
| whileLoop
|
||||
;
|
||||
|
||||
print
|
||||
@@ -79,12 +80,17 @@ arguments
|
||||
: (expression (COMMA expression)*)?
|
||||
;
|
||||
|
||||
whileLoop
|
||||
: WHILE OPAR cond = expression CPAR braced_block
|
||||
;
|
||||
|
||||
PRINT: 'print';
|
||||
IF: 'if';
|
||||
ELSE: 'else';
|
||||
FUNC: 'function';
|
||||
RETURN: 'return';
|
||||
LET: 'let';
|
||||
WHILE: 'while';
|
||||
|
||||
SCOL: ';';
|
||||
OBRK: '{';
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.util.HashSet;
|
||||
|
||||
import de.hsrm.compiler.Klang.nodes.*;
|
||||
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
||||
import de.hsrm.compiler.Klang.nodes.loops.whileLoop;
|
||||
import de.hsrm.compiler.Klang.nodes.statements.*;
|
||||
import de.hsrm.compiler.Klang.types.Type;
|
||||
|
||||
@@ -57,6 +58,14 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visitWhileLoop(KlangParser.WhileLoopContext ctx) {
|
||||
Node condition = this.visit(ctx.cond);
|
||||
Node block = this.visit(ctx.braced_block());
|
||||
return new whileLoop((Expression) condition, (Block) block);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Node visitVariable_declaration(KlangParser.Variable_declarationContext ctx) {
|
||||
String name = ctx.IDENT().getText();
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package de.hsrm.compiler.Klang.nodes.loops;
|
||||
|
||||
import de.hsrm.compiler.Klang.nodes.Block;
|
||||
import de.hsrm.compiler.Klang.nodes.statements.Statement;;
|
||||
import de.hsrm.compiler.Klang.nodes.expressions.Expression;
|
||||
import de.hsrm.compiler.Klang.visitors.Visitor;
|
||||
|
||||
public class whileLoop extends Statement {
|
||||
|
||||
public Expression cond;
|
||||
public Block block;
|
||||
public Block alt;
|
||||
|
||||
public whileLoop(Expression cond, Block block) {
|
||||
this.cond = cond;
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R welcome(Visitor<R> v) {
|
||||
return v.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import de.hsrm.compiler.Klang.nodes.Block;
|
||||
import de.hsrm.compiler.Klang.nodes.FunctionDefinition;
|
||||
import de.hsrm.compiler.Klang.nodes.Program;
|
||||
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
||||
import de.hsrm.compiler.Klang.nodes.loops.whileLoop;
|
||||
import de.hsrm.compiler.Klang.nodes.statements.*;
|
||||
|
||||
public class EvalVisitor implements Visitor<Value> {
|
||||
@@ -151,6 +152,18 @@ public class EvalVisitor implements Visitor<Value> {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value visit(whileLoop e) {
|
||||
Value condition = e.cond.welcome(this);
|
||||
Value result = null;
|
||||
while(condition.asInteger() != 0) {
|
||||
System.out.println(condition.asInteger());
|
||||
result = e.block.welcome(this);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value visit(PrintStatement e) {
|
||||
Value value = e.expression.welcome(this);
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.util.TreeSet;
|
||||
|
||||
import de.hsrm.compiler.Klang.nodes.*;
|
||||
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
||||
import de.hsrm.compiler.Klang.nodes.loops.whileLoop;
|
||||
import de.hsrm.compiler.Klang.nodes.statements.*;
|
||||
|
||||
public class GenASM implements Visitor<Void> {
|
||||
@@ -264,30 +265,44 @@ public class GenASM implements Visitor<Void> {
|
||||
|
||||
@Override
|
||||
public Void visit(IfStatement e) {
|
||||
int lblElse = ++lCount;
|
||||
int lblEnd = ++lCount;
|
||||
boolean hasElse = e.alt != null || e.elif != null;
|
||||
e.cond.welcome(this);
|
||||
this.ex.write(" cmp $0, %rax\n");
|
||||
// in case of cond evaluating to false, jump to else/elif
|
||||
// Jump to end if there is no else part, this saves a label declaration
|
||||
if (hasElse) {
|
||||
this.ex.write(" jz .L" + lblElse + "\n");
|
||||
int lblElse = ++lCount;
|
||||
int lblEnd = ++lCount;
|
||||
boolean hasElse = e.alt != null || e.elif != null;
|
||||
e.cond.welcome(this);
|
||||
this.ex.write(" cmp $0, %rax\n");
|
||||
// in case of cond evaluating to false, jump to else/elif
|
||||
// Jump to end if there is no else part, this saves a label declaration
|
||||
if (hasElse) {
|
||||
this.ex.write(" jz .L" + lblElse + "\n");
|
||||
} else {
|
||||
this.ex.write(" jz .L" + lblEnd + "\n");
|
||||
}
|
||||
e.then.welcome(this);
|
||||
if (hasElse) {
|
||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
||||
this.ex.write(".L" + lblElse + ":\n");
|
||||
if (e.alt != null) {
|
||||
e.alt.welcome(this);
|
||||
} else {
|
||||
this.ex.write(" jz .L" + lblEnd + "\n");
|
||||
e.elif.welcome(this);
|
||||
}
|
||||
e.then.welcome(this);
|
||||
if (hasElse) {
|
||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
||||
this.ex.write(".L" + lblElse + ":\n");
|
||||
if (e.alt != null) {
|
||||
e.alt.welcome(this);
|
||||
} else {
|
||||
e.elif.welcome(this);
|
||||
}
|
||||
}
|
||||
this.ex.write(".L" + lblEnd + ":\n");
|
||||
return null;
|
||||
}
|
||||
this.ex.write(".L" + lblEnd + ":\n");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(whileLoop e) {
|
||||
int lblCond = ++lCount;
|
||||
int lblEnd = ++lCount;
|
||||
this.ex.write(".L" + lblCond + ":\n");
|
||||
e.cond.welcome(this);
|
||||
this.ex.write(" cmp $0, %rax\n");
|
||||
this.ex.write(" jz .L" + lblEnd + "\n");
|
||||
e.block.welcome(this);
|
||||
this.ex.write(" jmp .L" + lblCond + "\n");
|
||||
this.ex.write(".L" + lblEnd + ":\n");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -351,10 +366,10 @@ public class GenASM implements Visitor<Void> {
|
||||
// Merke dir die offsets der parameter, die direkt auf den stack gelegt wurden
|
||||
int offset = 16; // Per Stack übergebene Parameter liegen über unserm BSP
|
||||
// Per stack übergebene variablen in env registrieren
|
||||
for (int i = this.rs.length; i < e.parameters.length; i++) {
|
||||
env.put(e.parameters[i], offset);
|
||||
offset += 8;
|
||||
}
|
||||
for (int i = this.rs.length; i < e.parameters.length; i++) {
|
||||
env.put(e.parameters[i], offset);
|
||||
offset += 8;
|
||||
}
|
||||
|
||||
// pushe die aufrufparameter aus den Registern wieder auf den Stack
|
||||
offset = 0;
|
||||
@@ -363,7 +378,7 @@ public class GenASM implements Visitor<Void> {
|
||||
offset -= 8;
|
||||
this.env.put(e.parameters[i], offset); // negative, liegt unter aktuellem BP
|
||||
}
|
||||
|
||||
|
||||
// Reserviere Platz auf dem Stack für jede lokale variable
|
||||
for (String lok_var : vars) {
|
||||
offset -= 8;
|
||||
@@ -384,7 +399,7 @@ public class GenASM implements Visitor<Void> {
|
||||
}
|
||||
|
||||
// Den Rest auf den stack pushen
|
||||
for (int i = e.arguments.length -1; i >= this.rs.length; i--) {
|
||||
for (int i = e.arguments.length - 1; i >= this.rs.length; i--) {
|
||||
e.arguments[i].welcome(this);
|
||||
this.ex.write(" pushq %rax\n");
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.util.Set;
|
||||
|
||||
import de.hsrm.compiler.Klang.nodes.*;
|
||||
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
||||
import de.hsrm.compiler.Klang.nodes.loops.whileLoop;
|
||||
import de.hsrm.compiler.Klang.nodes.statements.*;
|
||||
|
||||
class GetVars implements Visitor<Void> {
|
||||
@@ -119,6 +120,13 @@ class GetVars implements Visitor<Void> {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(whileLoop e) {
|
||||
e.cond.welcome(this);
|
||||
e.block.welcome(this);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(PrintStatement e) {
|
||||
e.expression.welcome(this);
|
||||
|
||||
@@ -3,298 +3,308 @@ package de.hsrm.compiler.Klang.visitors;
|
||||
import java.io.*;
|
||||
import de.hsrm.compiler.Klang.nodes.*;
|
||||
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
||||
import de.hsrm.compiler.Klang.nodes.loops.whileLoop;
|
||||
import de.hsrm.compiler.Klang.nodes.statements.*;
|
||||
|
||||
public class PrettyPrintVisitor implements Visitor<Void> {
|
||||
|
||||
public static class ExWriter {
|
||||
Writer w;
|
||||
String indent = "";
|
||||
public static class ExWriter {
|
||||
Writer w;
|
||||
String indent = "";
|
||||
|
||||
void addIndent() {
|
||||
indent = indent + " ";
|
||||
}
|
||||
|
||||
void subIndent() {
|
||||
indent = indent.substring(2);
|
||||
}
|
||||
|
||||
void nl() {
|
||||
write("\n" + indent);
|
||||
}
|
||||
|
||||
int lbl = 0;
|
||||
|
||||
int next() {
|
||||
return lbl++;
|
||||
}
|
||||
|
||||
public ExWriter(Writer w) {
|
||||
this.w = w;
|
||||
}
|
||||
|
||||
void lnwrite(Object o) {
|
||||
nl();
|
||||
write(o);
|
||||
}
|
||||
|
||||
void write(Object o) {
|
||||
try {
|
||||
w.write(o + "");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
void addIndent() {
|
||||
indent = indent + " ";
|
||||
}
|
||||
|
||||
public ExWriter ex;
|
||||
|
||||
public PrettyPrintVisitor(ExWriter ex) {
|
||||
this.ex = ex;
|
||||
void subIndent() {
|
||||
indent = indent.substring(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(Program e) {
|
||||
for (var funcDef : e.funcs) {
|
||||
funcDef.welcome(this);
|
||||
ex.nl();
|
||||
ex.nl();
|
||||
}
|
||||
e.expression.welcome(this);
|
||||
ex.write(";");
|
||||
return null;
|
||||
void nl() {
|
||||
write("\n" + indent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(IntegerExpression e) {
|
||||
ex.write(e.value);
|
||||
return null;
|
||||
int lbl = 0;
|
||||
|
||||
int next() {
|
||||
return lbl++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(EqualityExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" == ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
public ExWriter(Writer w) {
|
||||
this.w = w;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(NotEqualityExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" != ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(GTExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" > ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(GTEExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" >= ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(LTExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" < ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(LTEExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" <= ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
void lnwrite(Object o) {
|
||||
nl();
|
||||
write(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(AdditionExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" + ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
void write(Object o) {
|
||||
try {
|
||||
w.write(o + "");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ExWriter ex;
|
||||
|
||||
public PrettyPrintVisitor(ExWriter ex) {
|
||||
this.ex = ex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(Program e) {
|
||||
for (var funcDef : e.funcs) {
|
||||
funcDef.welcome(this);
|
||||
ex.nl();
|
||||
ex.nl();
|
||||
}
|
||||
e.expression.welcome(this);
|
||||
ex.write(";");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(IntegerExpression e) {
|
||||
ex.write(e.value);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(EqualityExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" == ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(NotEqualityExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" != ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(GTExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" > ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(GTEExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" >= ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(LTExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" < ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(LTEExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" <= ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(AdditionExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" + ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(SubstractionExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" - ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(MultiplicationExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" * ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(DivisionExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" / ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(ModuloExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" % ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(NegateExpression e) {
|
||||
ex.write(" - ");
|
||||
e.lhs.welcome(this);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(IfStatement e) {
|
||||
ex.write("if (");
|
||||
e.cond.welcome(this);
|
||||
ex.write(") ");
|
||||
e.then.welcome(this);
|
||||
if (e.alt != null) {
|
||||
ex.write(" else ");
|
||||
e.alt.welcome(this);
|
||||
} else if (e.elif != null) {
|
||||
ex.write(" else ");
|
||||
e.elif.welcome(this);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(whileLoop e) {
|
||||
ex.write("while (");
|
||||
e.cond.welcome(this);
|
||||
ex.write(") ");
|
||||
e.block.welcome(this);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(PrintStatement e) {
|
||||
ex.write("print ");
|
||||
e.expression.welcome(this);
|
||||
ex.write(";");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(VariableDeclaration e) {
|
||||
ex.write("let " + e.name);
|
||||
|
||||
if (e.expression != null) {
|
||||
ex.write(" = ");
|
||||
e.expression.welcome(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(SubstractionExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" - ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
ex.write(";");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(VariableAssignment e) {
|
||||
ex.write(e.name + " = ");
|
||||
e.expression.welcome(this);
|
||||
ex.write(";");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(ReturnStatement e) {
|
||||
ex.write("return ");
|
||||
e.expression.welcome(this);
|
||||
ex.write(";");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(Block e) {
|
||||
ex.write("{");
|
||||
ex.addIndent();
|
||||
for (Statement stmt : e.statements) {
|
||||
ex.nl();
|
||||
stmt.welcome(this);
|
||||
}
|
||||
ex.subIndent();
|
||||
ex.nl();
|
||||
ex.write("}");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(MultiplicationExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" * ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
@Override
|
||||
public Void visit(FunctionDefinition e) {
|
||||
ex.write("function ");
|
||||
ex.write(e.name);
|
||||
ex.write("(");
|
||||
boolean first = true;
|
||||
for (String param : e.parameters) {
|
||||
if (!first) {
|
||||
ex.write(", ");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
ex.write(param);
|
||||
}
|
||||
ex.write(") ");
|
||||
e.block.welcome(this);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(DivisionExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" / ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
@Override
|
||||
public Void visit(FunctionCall e) {
|
||||
ex.write(e.name);
|
||||
ex.write("(");
|
||||
boolean first = true;
|
||||
for (Expression arg : e.arguments) {
|
||||
if (!first) {
|
||||
ex.write(", ");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
arg.welcome(this);
|
||||
}
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(ModuloExpression e) {
|
||||
ex.write("(");
|
||||
e.lhs.welcome(this);
|
||||
ex.write(" % ");
|
||||
e.rhs.welcome(this);
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(NegateExpression e) {
|
||||
ex.write(" - ");
|
||||
e.lhs.welcome(this);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(IfStatement e) {
|
||||
ex.write("if (");
|
||||
e.cond.welcome(this);
|
||||
ex.write(") ");
|
||||
e.then.welcome(this);
|
||||
if (e.alt != null) {
|
||||
ex.write(" else ");
|
||||
e.alt.welcome(this);
|
||||
} else if (e.elif != null) {
|
||||
ex.write(" else ");
|
||||
e.elif.welcome(this);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(PrintStatement e) {
|
||||
ex.write("print ");
|
||||
e.expression.welcome(this);
|
||||
ex.write(";");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(VariableDeclaration e) {
|
||||
ex.write("let " + e.name);
|
||||
|
||||
if (e.expression != null) {
|
||||
ex.write(" = ");
|
||||
e.expression.welcome(this);
|
||||
}
|
||||
|
||||
ex.write(";");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(VariableAssignment e) {
|
||||
ex.write(e.name + " = ");
|
||||
e.expression.welcome(this);
|
||||
ex.write(";");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(ReturnStatement e) {
|
||||
ex.write("return ");
|
||||
e.expression.welcome(this);
|
||||
ex.write(";");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(Block e) {
|
||||
ex.write("{");
|
||||
ex.addIndent();
|
||||
for (Statement stmt : e.statements) {
|
||||
ex.nl();
|
||||
stmt.welcome(this);
|
||||
}
|
||||
ex.subIndent();
|
||||
ex.nl();
|
||||
ex.write("}");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(FunctionDefinition e) {
|
||||
ex.write("function ");
|
||||
ex.write(e.name);
|
||||
ex.write("(");
|
||||
boolean first = true;
|
||||
for (String param : e.parameters) {
|
||||
if (!first) {
|
||||
ex.write(", ");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
ex.write(param);
|
||||
}
|
||||
ex.write(") ");
|
||||
e.block.welcome(this);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(FunctionCall e) {
|
||||
ex.write(e.name);
|
||||
ex.write("(");
|
||||
boolean first = true;
|
||||
for (Expression arg : e.arguments) {
|
||||
if (!first) {
|
||||
ex.write(", ");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
arg.welcome(this);
|
||||
}
|
||||
ex.write(")");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visit(Variable e) {
|
||||
ex.write(e.name);
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public Void visit(Variable e) {
|
||||
ex.write(e.name);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import de.hsrm.compiler.Klang.nodes.Block;
|
||||
import de.hsrm.compiler.Klang.nodes.FunctionDefinition;
|
||||
import de.hsrm.compiler.Klang.nodes.Program;
|
||||
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
||||
import de.hsrm.compiler.Klang.nodes.loops.*;
|
||||
import de.hsrm.compiler.Klang.nodes.statements.*;
|
||||
|
||||
public interface Visitor<R> {
|
||||
@@ -22,6 +23,7 @@ public interface Visitor<R> {
|
||||
R visit(ModuloExpression e);
|
||||
R visit(NegateExpression e);
|
||||
R visit(IfStatement e);
|
||||
R visit(whileLoop e);
|
||||
R visit(PrintStatement e);
|
||||
R visit(VariableDeclaration e);
|
||||
R visit(VariableAssignment e);
|
||||
|
||||
@@ -114,6 +114,9 @@ int main(){
|
||||
// Tests for comparison expressions
|
||||
failed += runComparisonTests();
|
||||
|
||||
// Tests for while loop
|
||||
failed += runWhileTests();
|
||||
|
||||
printf("\n=== Failed Tests: %d\n", failed);
|
||||
|
||||
if (failed > 0) {
|
||||
|
||||
@@ -4,4 +4,5 @@
|
||||
|
||||
int runFunctionCallTests();
|
||||
int runRecursiveTests();
|
||||
int runComparisonTests();
|
||||
int runComparisonTests();
|
||||
int runWhileTests();
|
||||
@@ -133,4 +133,12 @@ function gte(x, y) {
|
||||
return (x >= y);
|
||||
}
|
||||
|
||||
function myWhile(end) {
|
||||
let cond = 0;
|
||||
while ((cond < end)) {
|
||||
cond = (cond + 1);
|
||||
}
|
||||
return cond;
|
||||
}
|
||||
|
||||
add(1, 1);
|
||||
|
||||
27
src/test/while/while.c
Normal file
27
src/test/while/while.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <stdio.h>
|
||||
#include "while.h"
|
||||
|
||||
void printWhileSuccess(char* name, int x, int expected, int result) {
|
||||
printf("SUCCESS:\t%s(%d)\tGOT: %d\tExpected: %d\n", name, x, result, expected);
|
||||
}
|
||||
|
||||
void printWhileError(char* name, int x, int expected, int result) {
|
||||
printf("ERROR:\t\t%s(%d)\tGOT: %d\tExpected: %d\n", name, x, result, expected);
|
||||
}
|
||||
|
||||
int whileTest(char* name, int x, int expected, int result) {
|
||||
if (expected == result) {
|
||||
printWhileSuccess(name, x, expected, result);
|
||||
return 0;
|
||||
} else {
|
||||
printWhileError(name, x, expected, result);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int runWhileTests() {
|
||||
printf("\nWhile Tests \n");
|
||||
int failed = 0;
|
||||
failed += whileTest("while", 5, 5, myWhile(5));
|
||||
return failed;
|
||||
}
|
||||
1
src/test/while/while.h
Normal file
1
src/test/while/while.h
Normal file
@@ -0,0 +1 @@
|
||||
int myWhile(int x);
|
||||
Reference in New Issue
Block a user