Added while loop
This commit is contained in:
@@ -1,2 +1,4 @@
|
|||||||
# Klang - The Kaiser language
|
# 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/test: ./src/test/tests.s
|
./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
|
./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
|
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_declaration
|
||||||
| variable_assignment
|
| variable_assignment
|
||||||
| return_statement
|
| return_statement
|
||||||
|
| whileLoop
|
||||||
;
|
;
|
||||||
|
|
||||||
print
|
print
|
||||||
@@ -79,12 +80,17 @@ arguments
|
|||||||
: (expression (COMMA expression)*)?
|
: (expression (COMMA expression)*)?
|
||||||
;
|
;
|
||||||
|
|
||||||
|
whileLoop
|
||||||
|
: WHILE OPAR cond = expression CPAR braced_block
|
||||||
|
;
|
||||||
|
|
||||||
PRINT: 'print';
|
PRINT: 'print';
|
||||||
IF: 'if';
|
IF: 'if';
|
||||||
ELSE: 'else';
|
ELSE: 'else';
|
||||||
FUNC: 'function';
|
FUNC: 'function';
|
||||||
RETURN: 'return';
|
RETURN: 'return';
|
||||||
LET: 'let';
|
LET: 'let';
|
||||||
|
WHILE: 'while';
|
||||||
|
|
||||||
SCOL: ';';
|
SCOL: ';';
|
||||||
OBRK: '{';
|
OBRK: '{';
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import java.util.HashSet;
|
|||||||
|
|
||||||
import de.hsrm.compiler.Klang.nodes.*;
|
import de.hsrm.compiler.Klang.nodes.*;
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
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.nodes.statements.*;
|
||||||
import de.hsrm.compiler.Klang.types.Type;
|
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
|
@Override
|
||||||
public Node visitVariable_declaration(KlangParser.Variable_declarationContext ctx) {
|
public Node visitVariable_declaration(KlangParser.Variable_declarationContext ctx) {
|
||||||
String name = ctx.IDENT().getText();
|
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.FunctionDefinition;
|
||||||
import de.hsrm.compiler.Klang.nodes.Program;
|
import de.hsrm.compiler.Klang.nodes.Program;
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
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.nodes.statements.*;
|
||||||
|
|
||||||
public class EvalVisitor implements Visitor<Value> {
|
public class EvalVisitor implements Visitor<Value> {
|
||||||
@@ -151,6 +152,18 @@ public class EvalVisitor implements Visitor<Value> {
|
|||||||
return result;
|
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
|
@Override
|
||||||
public Value visit(PrintStatement e) {
|
public Value visit(PrintStatement e) {
|
||||||
Value value = e.expression.welcome(this);
|
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.*;
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
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.nodes.statements.*;
|
||||||
|
|
||||||
public class GenASM implements Visitor<Void> {
|
public class GenASM implements Visitor<Void> {
|
||||||
@@ -264,30 +265,44 @@ public class GenASM implements Visitor<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(IfStatement e) {
|
public Void visit(IfStatement e) {
|
||||||
int lblElse = ++lCount;
|
int lblElse = ++lCount;
|
||||||
int lblEnd = ++lCount;
|
int lblEnd = ++lCount;
|
||||||
boolean hasElse = e.alt != null || e.elif != null;
|
boolean hasElse = e.alt != null || e.elif != null;
|
||||||
e.cond.welcome(this);
|
e.cond.welcome(this);
|
||||||
this.ex.write(" cmp $0, %rax\n");
|
this.ex.write(" cmp $0, %rax\n");
|
||||||
// in case of cond evaluating to false, jump to else/elif
|
// 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
|
// Jump to end if there is no else part, this saves a label declaration
|
||||||
if (hasElse) {
|
if (hasElse) {
|
||||||
this.ex.write(" jz .L" + lblElse + "\n");
|
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 {
|
} else {
|
||||||
this.ex.write(" jz .L" + lblEnd + "\n");
|
e.elif.welcome(this);
|
||||||
}
|
}
|
||||||
e.then.welcome(this);
|
}
|
||||||
if (hasElse) {
|
this.ex.write(".L" + lblEnd + ":\n");
|
||||||
this.ex.write(" jmp .L" + lblEnd + "\n");
|
return null;
|
||||||
this.ex.write(".L" + lblElse + ":\n");
|
}
|
||||||
if (e.alt != null) {
|
|
||||||
e.alt.welcome(this);
|
@Override
|
||||||
} else {
|
public Void visit(whileLoop e) {
|
||||||
e.elif.welcome(this);
|
int lblCond = ++lCount;
|
||||||
}
|
int lblEnd = ++lCount;
|
||||||
}
|
this.ex.write(".L" + lblCond + ":\n");
|
||||||
this.ex.write(".L" + lblEnd + ":\n");
|
e.cond.welcome(this);
|
||||||
return null;
|
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
|
@Override
|
||||||
@@ -351,10 +366,10 @@ public class GenASM implements Visitor<Void> {
|
|||||||
// Merke dir die offsets der parameter, die direkt auf den stack gelegt wurden
|
// Merke dir die offsets der parameter, die direkt auf den stack gelegt wurden
|
||||||
int offset = 16; // Per Stack übergebene Parameter liegen über unserm BSP
|
int offset = 16; // Per Stack übergebene Parameter liegen über unserm BSP
|
||||||
// Per stack übergebene variablen in env registrieren
|
// Per stack übergebene variablen in env registrieren
|
||||||
for (int i = this.rs.length; i < e.parameters.length; i++) {
|
for (int i = this.rs.length; i < e.parameters.length; i++) {
|
||||||
env.put(e.parameters[i], offset);
|
env.put(e.parameters[i], offset);
|
||||||
offset += 8;
|
offset += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pushe die aufrufparameter aus den Registern wieder auf den Stack
|
// pushe die aufrufparameter aus den Registern wieder auf den Stack
|
||||||
offset = 0;
|
offset = 0;
|
||||||
@@ -384,7 +399,7 @@ public class GenASM implements Visitor<Void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Den Rest auf den stack pushen
|
// 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);
|
e.arguments[i].welcome(this);
|
||||||
this.ex.write(" pushq %rax\n");
|
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.*;
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
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.nodes.statements.*;
|
||||||
|
|
||||||
class GetVars implements Visitor<Void> {
|
class GetVars implements Visitor<Void> {
|
||||||
@@ -119,6 +120,13 @@ class GetVars implements Visitor<Void> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(whileLoop e) {
|
||||||
|
e.cond.welcome(this);
|
||||||
|
e.block.welcome(this);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(PrintStatement e) {
|
public Void visit(PrintStatement e) {
|
||||||
e.expression.welcome(this);
|
e.expression.welcome(this);
|
||||||
|
|||||||
@@ -3,298 +3,308 @@ package de.hsrm.compiler.Klang.visitors;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import de.hsrm.compiler.Klang.nodes.*;
|
import de.hsrm.compiler.Klang.nodes.*;
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
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.nodes.statements.*;
|
||||||
|
|
||||||
public class PrettyPrintVisitor implements Visitor<Void> {
|
public class PrettyPrintVisitor implements Visitor<Void> {
|
||||||
|
|
||||||
public static class ExWriter {
|
public static class ExWriter {
|
||||||
Writer w;
|
Writer w;
|
||||||
String indent = "";
|
String indent = "";
|
||||||
|
|
||||||
void addIndent() {
|
void addIndent() {
|
||||||
indent = indent + " ";
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExWriter ex;
|
void subIndent() {
|
||||||
|
indent = indent.substring(2);
|
||||||
public PrettyPrintVisitor(ExWriter ex) {
|
|
||||||
this.ex = ex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
void nl() {
|
||||||
public Void visit(Program e) {
|
write("\n" + indent);
|
||||||
for (var funcDef : e.funcs) {
|
|
||||||
funcDef.welcome(this);
|
|
||||||
ex.nl();
|
|
||||||
ex.nl();
|
|
||||||
}
|
|
||||||
e.expression.welcome(this);
|
|
||||||
ex.write(";");
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
int lbl = 0;
|
||||||
public Void visit(IntegerExpression e) {
|
|
||||||
ex.write(e.value);
|
int next() {
|
||||||
return null;
|
return lbl++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public ExWriter(Writer w) {
|
||||||
public Void visit(EqualityExpression e) {
|
this.w = w;
|
||||||
ex.write("(");
|
|
||||||
e.lhs.welcome(this);
|
|
||||||
ex.write(" == ");
|
|
||||||
e.rhs.welcome(this);
|
|
||||||
ex.write(")");
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
void lnwrite(Object o) {
|
||||||
public Void visit(NotEqualityExpression e) {
|
nl();
|
||||||
ex.write("(");
|
write(o);
|
||||||
e.lhs.welcome(this);
|
|
||||||
ex.write(" != ");
|
|
||||||
e.rhs.welcome(this);
|
|
||||||
ex.write(")");
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
void write(Object o) {
|
||||||
public Void visit(GTExpression e) {
|
try {
|
||||||
ex.write("(");
|
w.write(o + "");
|
||||||
e.lhs.welcome(this);
|
} catch (IOException e) {
|
||||||
ex.write(" > ");
|
throw new RuntimeException(e);
|
||||||
e.rhs.welcome(this);
|
}
|
||||||
ex.write(")");
|
}
|
||||||
return null;
|
}
|
||||||
|
|
||||||
|
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
|
ex.write(";");
|
||||||
public Void visit(GTEExpression e) {
|
return null;
|
||||||
ex.write("(");
|
}
|
||||||
e.lhs.welcome(this);
|
|
||||||
ex.write(" >= ");
|
@Override
|
||||||
e.rhs.welcome(this);
|
public Void visit(VariableAssignment e) {
|
||||||
ex.write(")");
|
ex.write(e.name + " = ");
|
||||||
return null;
|
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
|
@Override
|
||||||
public Void visit(LTExpression e) {
|
public Void visit(FunctionDefinition e) {
|
||||||
ex.write("(");
|
ex.write("function ");
|
||||||
e.lhs.welcome(this);
|
ex.write(e.name);
|
||||||
ex.write(" < ");
|
ex.write("(");
|
||||||
e.rhs.welcome(this);
|
boolean first = true;
|
||||||
ex.write(")");
|
for (String param : e.parameters) {
|
||||||
return null;
|
if (!first) {
|
||||||
|
ex.write(", ");
|
||||||
|
} else {
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
ex.write(param);
|
||||||
}
|
}
|
||||||
|
ex.write(") ");
|
||||||
|
e.block.welcome(this);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(LTEExpression e) {
|
public Void visit(FunctionCall e) {
|
||||||
ex.write("(");
|
ex.write(e.name);
|
||||||
e.lhs.welcome(this);
|
ex.write("(");
|
||||||
ex.write(" <= ");
|
boolean first = true;
|
||||||
e.rhs.welcome(this);
|
for (Expression arg : e.arguments) {
|
||||||
ex.write(")");
|
if (!first) {
|
||||||
return null;
|
ex.write(", ");
|
||||||
|
} else {
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
arg.welcome(this);
|
||||||
}
|
}
|
||||||
|
ex.write(")");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(AdditionExpression e) {
|
public Void visit(Variable e) {
|
||||||
ex.write("(");
|
ex.write(e.name);
|
||||||
e.lhs.welcome(this);
|
return null;
|
||||||
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(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ import de.hsrm.compiler.Klang.nodes.Block;
|
|||||||
import de.hsrm.compiler.Klang.nodes.FunctionDefinition;
|
import de.hsrm.compiler.Klang.nodes.FunctionDefinition;
|
||||||
import de.hsrm.compiler.Klang.nodes.Program;
|
import de.hsrm.compiler.Klang.nodes.Program;
|
||||||
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
import de.hsrm.compiler.Klang.nodes.expressions.*;
|
||||||
|
import de.hsrm.compiler.Klang.nodes.loops.*;
|
||||||
import de.hsrm.compiler.Klang.nodes.statements.*;
|
import de.hsrm.compiler.Klang.nodes.statements.*;
|
||||||
|
|
||||||
public interface Visitor<R> {
|
public interface Visitor<R> {
|
||||||
@@ -22,6 +23,7 @@ public interface Visitor<R> {
|
|||||||
R visit(ModuloExpression e);
|
R visit(ModuloExpression e);
|
||||||
R visit(NegateExpression e);
|
R visit(NegateExpression e);
|
||||||
R visit(IfStatement e);
|
R visit(IfStatement e);
|
||||||
|
R visit(whileLoop e);
|
||||||
R visit(PrintStatement e);
|
R visit(PrintStatement e);
|
||||||
R visit(VariableDeclaration e);
|
R visit(VariableDeclaration e);
|
||||||
R visit(VariableAssignment e);
|
R visit(VariableAssignment e);
|
||||||
|
|||||||
@@ -114,6 +114,9 @@ int main(){
|
|||||||
// Tests for comparison expressions
|
// Tests for comparison expressions
|
||||||
failed += runComparisonTests();
|
failed += runComparisonTests();
|
||||||
|
|
||||||
|
// Tests for while loop
|
||||||
|
failed += runWhileTests();
|
||||||
|
|
||||||
printf("\n=== Failed Tests: %d\n", failed);
|
printf("\n=== Failed Tests: %d\n", failed);
|
||||||
|
|
||||||
if (failed > 0) {
|
if (failed > 0) {
|
||||||
|
|||||||
@@ -5,3 +5,4 @@
|
|||||||
int runFunctionCallTests();
|
int runFunctionCallTests();
|
||||||
int runRecursiveTests();
|
int runRecursiveTests();
|
||||||
int runComparisonTests();
|
int runComparisonTests();
|
||||||
|
int runWhileTests();
|
||||||
@@ -133,4 +133,12 @@ function gte(x, y) {
|
|||||||
return (x >= y);
|
return (x >= y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function myWhile(end) {
|
||||||
|
let cond = 0;
|
||||||
|
while ((cond < end)) {
|
||||||
|
cond = (cond + 1);
|
||||||
|
}
|
||||||
|
return cond;
|
||||||
|
}
|
||||||
|
|
||||||
add(1, 1);
|
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