implement for loops
This commit is contained in:
@@ -31,6 +31,7 @@ statement
|
|||||||
| return_statement
|
| return_statement
|
||||||
| whileLoop
|
| whileLoop
|
||||||
| doWhileLoop
|
| doWhileLoop
|
||||||
|
| forLoop
|
||||||
;
|
;
|
||||||
|
|
||||||
print
|
print
|
||||||
@@ -41,6 +42,11 @@ if_statement
|
|||||||
: IF OPAR cond = expression CPAR then = braced_block (ELSE (alt = braced_block | elif = if_statement) )?
|
: IF OPAR cond = expression CPAR then = braced_block (ELSE (alt = braced_block | elif = if_statement) )?
|
||||||
;
|
;
|
||||||
|
|
||||||
|
variableDeclarationOrAssignment
|
||||||
|
: variable_assignment
|
||||||
|
| variable_declaration
|
||||||
|
;
|
||||||
|
|
||||||
variable_declaration
|
variable_declaration
|
||||||
: LET IDENT (EQUAL expression)?
|
: LET IDENT (EQUAL expression)?
|
||||||
;
|
;
|
||||||
@@ -66,7 +72,6 @@ expression
|
|||||||
| OPAR lhs=expression GT rhs=expression CPAR #greaterThanExpression
|
| OPAR lhs=expression GT rhs=expression CPAR #greaterThanExpression
|
||||||
| OPAR lhs=expression LTE rhs=expression CPAR #lessThanOrEqualToExpression
|
| OPAR lhs=expression LTE rhs=expression CPAR #lessThanOrEqualToExpression
|
||||||
| OPAR lhs=expression GTE rhs=expression CPAR #GreaterThanOrEqualToExpression
|
| OPAR lhs=expression GTE rhs=expression CPAR #GreaterThanOrEqualToExpression
|
||||||
|
|
||||||
| SUB expression #negateExpression
|
| SUB expression #negateExpression
|
||||||
| functionCall #functionCallExpression
|
| functionCall #functionCallExpression
|
||||||
;
|
;
|
||||||
@@ -92,6 +97,12 @@ doWhileLoop
|
|||||||
: DO braced_block WHILE OPAR cond = expression CPAR SCOL
|
: DO braced_block WHILE OPAR cond = expression CPAR SCOL
|
||||||
;
|
;
|
||||||
|
|
||||||
|
forLoop
|
||||||
|
: FOR OPAR init = variableDeclarationOrAssignment SCOL
|
||||||
|
cond = expression SCOL
|
||||||
|
step = variable_assignment CPAR braced_block
|
||||||
|
;
|
||||||
|
|
||||||
PRINT: 'print';
|
PRINT: 'print';
|
||||||
IF: 'if';
|
IF: 'if';
|
||||||
ELSE: 'else';
|
ELSE: 'else';
|
||||||
@@ -100,6 +111,7 @@ RETURN: 'return';
|
|||||||
LET: 'let';
|
LET: 'let';
|
||||||
WHILE: 'while';
|
WHILE: 'while';
|
||||||
DO: 'do';
|
DO: 'do';
|
||||||
|
FOR: 'for';
|
||||||
|
|
||||||
SCOL: ';';
|
SCOL: ';';
|
||||||
OBRK: '{';
|
OBRK: '{';
|
||||||
|
|||||||
@@ -6,6 +6,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.DoWhileLoop;
|
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.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;
|
||||||
@@ -81,6 +82,14 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
|
|||||||
return new DoWhileLoop((Expression) condition, (Block) block);
|
return new DoWhileLoop((Expression) condition, (Block) block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node visitForLoop(KlangParser.ForLoopContext ctx) {
|
||||||
|
Node init = this.visit(ctx.init);
|
||||||
|
Node condition = this.visit(ctx.cond);
|
||||||
|
Node step = this.visit(ctx.step);
|
||||||
|
Node block = this.visit(ctx.braced_block());
|
||||||
|
return new ForLoop((Statement) init, (Expression) condition, (VariableAssignment) step, (Block) block);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node visitVariable_declaration(KlangParser.Variable_declarationContext ctx) {
|
public Node visitVariable_declaration(KlangParser.Variable_declarationContext ctx) {
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package de.hsrm.compiler.Klang.nodes.loops;
|
||||||
|
|
||||||
|
import de.hsrm.compiler.Klang.nodes.statements.Statement;
|
||||||
|
import de.hsrm.compiler.Klang.nodes.statements.VariableAssignment;
|
||||||
|
import de.hsrm.compiler.Klang.nodes.Block;
|
||||||
|
import de.hsrm.compiler.Klang.nodes.expressions.Expression;
|
||||||
|
import de.hsrm.compiler.Klang.visitors.Visitor;
|
||||||
|
|
||||||
|
public class ForLoop extends Statement {
|
||||||
|
|
||||||
|
public Statement init;
|
||||||
|
public Expression condition;
|
||||||
|
public VariableAssignment step;
|
||||||
|
public Block block;
|
||||||
|
|
||||||
|
public ForLoop(Statement init, Expression condition, VariableAssignment step, Block block) {
|
||||||
|
this.init = init;
|
||||||
|
this.condition = condition;
|
||||||
|
this.step = step;
|
||||||
|
this.block = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <R> R welcome(Visitor<R> v) {
|
||||||
|
return v.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ 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.DoWhileLoop;
|
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.loops.WhileLoop;
|
||||||
import de.hsrm.compiler.Klang.nodes.statements.*;
|
import de.hsrm.compiler.Klang.nodes.statements.*;
|
||||||
|
|
||||||
@@ -175,6 +176,20 @@ public class EvalVisitor implements Visitor<Value> {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Value visit(ForLoop e) {
|
||||||
|
e.init.welcome(this);
|
||||||
|
Value cond = e.condition.welcome(this);
|
||||||
|
Value result = null;
|
||||||
|
while (cond.asInteger() != 0) {
|
||||||
|
result = e.block.welcome(this);
|
||||||
|
e.step.welcome(this);
|
||||||
|
cond = e.condition.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);
|
||||||
|
|||||||
@@ -9,6 +9,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.DoWhileLoop;
|
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.loops.WhileLoop;
|
||||||
import de.hsrm.compiler.Klang.nodes.statements.*;
|
import de.hsrm.compiler.Klang.nodes.statements.*;
|
||||||
|
|
||||||
@@ -291,7 +292,7 @@ public class GenASM implements Visitor<Void> {
|
|||||||
this.ex.write(".L" + lblEnd + ":\n");
|
this.ex.write(".L" + lblEnd + ":\n");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(WhileLoop e) {
|
public Void visit(WhileLoop e) {
|
||||||
int lblCond = ++lCount;
|
int lblCond = ++lCount;
|
||||||
@@ -306,7 +307,6 @@ public class GenASM implements Visitor<Void> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(DoWhileLoop e) {
|
public Void visit(DoWhileLoop e) {
|
||||||
int lblStart = ++lCount;
|
int lblStart = ++lCount;
|
||||||
@@ -317,6 +317,23 @@ public class GenASM implements Visitor<Void> {
|
|||||||
this.ex.write(" jnz .L" + lblStart + "\n");
|
this.ex.write(" jnz .L" + lblStart + "\n");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(ForLoop e) {
|
||||||
|
int lblStart = ++lCount;
|
||||||
|
int lblEnd = ++lCount;
|
||||||
|
e.init.welcome(this);
|
||||||
|
this.ex.write(".L" + lblStart + ":\n");
|
||||||
|
e.condition.welcome(this);
|
||||||
|
this.ex.write(" cmp $0, %rax\n");
|
||||||
|
this.ex.write(" jz .L" + lblEnd + "\n");
|
||||||
|
e.block.welcome(this);
|
||||||
|
e.step.welcome(this);
|
||||||
|
this.ex.write(" jmp .L" + lblStart + "\n");
|
||||||
|
this.ex.write(".L" + lblEnd + ":\n");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(PrintStatement e) {
|
public Void visit(PrintStatement e) {
|
||||||
|
|||||||
@@ -5,6 +5,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.DoWhileLoop;
|
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.loops.WhileLoop;
|
||||||
import de.hsrm.compiler.Klang.nodes.statements.*;
|
import de.hsrm.compiler.Klang.nodes.statements.*;
|
||||||
|
|
||||||
@@ -135,6 +136,15 @@ class GetVars implements Visitor<Void> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(ForLoop e) {
|
||||||
|
e.init.welcome(this);
|
||||||
|
e.condition.welcome(this);
|
||||||
|
e.step.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);
|
||||||
|
|||||||
@@ -224,6 +224,19 @@ public class PrettyPrintVisitor implements Visitor<Void> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visit(ForLoop e) {
|
||||||
|
ex.write("for (");
|
||||||
|
e.init.welcome(this);
|
||||||
|
ex.write(" ");
|
||||||
|
e.condition.welcome(this);
|
||||||
|
ex.write("; ");
|
||||||
|
e.step.welcome(this);
|
||||||
|
ex.write(") ");
|
||||||
|
e.block.welcome(this);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(PrintStatement e) {
|
public Void visit(PrintStatement e) {
|
||||||
ex.write("print ");
|
ex.write("print ");
|
||||||
@@ -241,7 +254,6 @@ public class PrettyPrintVisitor implements Visitor<Void> {
|
|||||||
e.expression.welcome(this);
|
e.expression.welcome(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ex.write(";");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +261,6 @@ public class PrettyPrintVisitor implements Visitor<Void> {
|
|||||||
public Void visit(VariableAssignment e) {
|
public Void visit(VariableAssignment e) {
|
||||||
ex.write(e.name + " = ");
|
ex.write(e.name + " = ");
|
||||||
e.expression.welcome(this);
|
e.expression.welcome(this);
|
||||||
ex.write(";");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,6 +279,9 @@ public class PrettyPrintVisitor implements Visitor<Void> {
|
|||||||
for (Statement stmt : e.statements) {
|
for (Statement stmt : e.statements) {
|
||||||
ex.nl();
|
ex.nl();
|
||||||
stmt.welcome(this);
|
stmt.welcome(this);
|
||||||
|
if (stmt.getClass() == VariableAssignment.class || stmt.getClass() == VariableDeclaration.class) {
|
||||||
|
ex.write(";");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ex.subIndent();
|
ex.subIndent();
|
||||||
ex.nl();
|
ex.nl();
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ public interface Visitor<R> {
|
|||||||
R visit(IfStatement e);
|
R visit(IfStatement e);
|
||||||
R visit(WhileLoop e);
|
R visit(WhileLoop e);
|
||||||
R visit(DoWhileLoop e);
|
R visit(DoWhileLoop e);
|
||||||
|
R visit(ForLoop 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);
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
#include "loop.h"
|
#include "loop.h"
|
||||||
|
|
||||||
void printLoopSuccess(char* name, int x, int expected, int result) {
|
void printLoopSuccess(char* name, int x, int expected, int result) {
|
||||||
printf("SUCCESS:\t%s(%d)\tGOT: %d\tExpected: %d\n", name, x, result, expected);
|
printf("\033[0;32mSUCCESS:\t%s(%d)\tGOT: %d\tExpected: %d\033[0;0m\n", name, x, result, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printLoopError(char* name, int x, int expected, int result) {
|
void printLoopError(char* name, int x, int expected, int result) {
|
||||||
printf("ERROR:\t\t%s(%d)\tGOT: %d\tExpected: %d\n", name, x, result, expected);
|
printf("\033[0;31mERROR:\t\t%s(%d)\tGOT: %d\tExpected: %d\033[0;0m\n", name, x, result, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
int loopTest(char* name, int x, int expected, int result) {
|
int loopTest(char* name, int x, int expected, int result) {
|
||||||
@@ -25,6 +25,8 @@ int runLoopTests() {
|
|||||||
failed += loopTest("while", 5, 5, myWhile(5));
|
failed += loopTest("while", 5, 5, myWhile(5));
|
||||||
failed += loopTest("doWhile", 0, 1, myDoWhile(0));
|
failed += loopTest("doWhile", 0, 1, myDoWhile(0));
|
||||||
failed += loopTest("doWhile", 1, 1, myDoWhile(1));
|
failed += loopTest("doWhile", 1, 1, myDoWhile(1));
|
||||||
|
failed += loopTest("for", 5, 5, myFor(5));
|
||||||
|
failed += loopTest("for", 0, 0, myFor(0));
|
||||||
|
|
||||||
return failed;
|
return failed;
|
||||||
}
|
}
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
int myWhile(int x);
|
int myWhile(int x);
|
||||||
int myDoWhile(int x);
|
int myDoWhile(int x);
|
||||||
|
int myFor(int x);
|
||||||
@@ -154,4 +154,12 @@ function myDoWhile(end) {
|
|||||||
return cond;
|
return cond;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function myFor(end) {
|
||||||
|
let x = 0;
|
||||||
|
for (let i = 0; (i < end); i = (i + 1)) {
|
||||||
|
x = (x + 1);
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
add(1, 1);
|
add(1, 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user