implemented variables and function call evaluation

This commit is contained in:
2019-11-18 18:02:10 +01:00
parent 13caee0667
commit b38369b7a5
6 changed files with 127 additions and 45 deletions

View File

@@ -52,6 +52,7 @@ arguments
atom
: INTEGER_LITERAL #intAtom
| IDENT # variable
;
PRINT: 'print';

View File

@@ -87,6 +87,11 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
return result;
}
@Override
public Node visitVariable(KlangParser.VariableContext ctx) {
return new Variable(ctx.IDENT().getText());
}
@Override
public Node visitAtomExpression(KlangParser.AtomExpressionContext ctx) {
return this.visit(ctx.atom());

View File

@@ -0,0 +1,18 @@
package de.hsrm.compiler.Klang.nodes.expressions;
import de.hsrm.compiler.Klang.visitors.Visitor;
public class Variable extends Expression {
public String name;
public Variable(String name) {
this.name = name;
}
@Override
public <R> R welcome(Visitor<R> v) {
return v.visit(this);
}
}

View File

@@ -1,13 +1,20 @@
package de.hsrm.compiler.Klang.visitors;
import java.util.HashMap;
import java.util.Map;
import de.hsrm.compiler.Klang.Value;
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.statements.*;
public class EvalVisitor implements Visitor<Value> {
Map<String, FunctionDefinition> funcs = new HashMap<>();
Map<String, Value> env = new HashMap<>();
@Override
public Value visit(IntegerExpression e) {
return new Value(e.value);
@@ -40,6 +47,17 @@ public class EvalVisitor implements Visitor<Value> {
return new Value(-a.asInteger());
}
@Override
public Value visit(Variable e) {
Value result = this.env.get(e.name);
if (result == null) {
throw new RuntimeException("Variable with name " +e.name + " not found.");
}
return result;
}
@Override
public Value visit(IfStatement e) {
// In the future we have to make sure that the
@@ -69,22 +87,55 @@ public class EvalVisitor implements Visitor<Value> {
@Override
public Value visit(Block e) {
Value result = null;
for (var stmt : e.statements) {
stmt.welcome(this);
result = stmt.welcome(this);
}
return null;
return result;
}
@Override
public Value visit(FunctionDefinition e) {
// TODO Auto-generated method stub
return null;
// Ein Eval über eine FunDef macht keinen Sinn
throw new RuntimeException("Wir sind im Eval und visiten eine Funktionsdefinition.. WUT?!");
}
@Override
public Value visit(FunctionCall e) {
// TODO Auto-generated method stub
return null;
// Die funktionsdefinition speichern
FunctionDefinition func = this.funcs.get(e.name);
// Stelle sicher, dass die Länge der argumente und parameter übereinstimmen
if (e.arguments.length != func.parameters.length) {
throw new RuntimeException("Error with function call " +e.name + ": Number of parameters wrong");
}
// Baue ein neues environment
Map<String, Value> newEnv = new HashMap<>();
for (int i = 0; i < func.parameters.length; i++) {
newEnv.put(func.parameters[i], e.arguments[i].welcome(this));
}
var oldEnv = this.env;
this.env = newEnv;
// Execute
Value result = func.block.welcome(this);
// Das alte env wiederherstellen
this.env = oldEnv;
return result;
}
@Override
public Value visit(Program e) {
// Funktionsdefinitionen für die Auswertung
// von Funktionsaufrufen speichern
for (var funcDef: e.funcs) {
this.funcs.put(funcDef.name, funcDef);
}
return e.expression.welcome(this);
}
}

View File

@@ -55,13 +55,13 @@ public class PrettyPrintVisitor implements Visitor<Void> {
@Override
public Void visit(Program e) {
for (var funcDef : e.funcs) {
funcDef.welcome(this);
ex.nl();
ex.nl();
}
e.expression.welcome(this);
return null;
for (var funcDef : e.funcs) {
funcDef.welcome(this);
ex.nl();
ex.nl();
}
e.expression.welcome(this);
return null;
}
@Override
@@ -139,40 +139,46 @@ public class PrettyPrintVisitor implements Visitor<Void> {
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);
@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;
}
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);
@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;
}
ex.write(");");
return null;
}
}

View File

@@ -8,6 +8,7 @@ import de.hsrm.compiler.Klang.nodes.statements.*;
public interface Visitor<R> {
R visit(IntegerExpression e);
R visit(Variable e);
R visit(MultiplicativeExpression e);
R visit(AdditiveExpression e);
R visit(NegateExpression e);