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 atom
: INTEGER_LITERAL #intAtom : INTEGER_LITERAL #intAtom
| IDENT # variable
; ;
PRINT: 'print'; PRINT: 'print';

View File

@@ -87,6 +87,11 @@ public class ContextAnalysis extends KlangBaseVisitor<Node> {
return result; return result;
} }
@Override
public Node visitVariable(KlangParser.VariableContext ctx) {
return new Variable(ctx.IDENT().getText());
}
@Override @Override
public Node visitAtomExpression(KlangParser.AtomExpressionContext ctx) { public Node visitAtomExpression(KlangParser.AtomExpressionContext ctx) {
return this.visit(ctx.atom()); 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; 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.Value;
import de.hsrm.compiler.Klang.nodes.Block; 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.expressions.*; import de.hsrm.compiler.Klang.nodes.expressions.*;
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> {
Map<String, FunctionDefinition> funcs = new HashMap<>();
Map<String, Value> env = new HashMap<>();
@Override @Override
public Value visit(IntegerExpression e) { public Value visit(IntegerExpression e) {
return new Value(e.value); return new Value(e.value);
@@ -40,6 +47,17 @@ public class EvalVisitor implements Visitor<Value> {
return new Value(-a.asInteger()); 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 @Override
public Value visit(IfStatement e) { public Value visit(IfStatement e) {
// In the future we have to make sure that the // In the future we have to make sure that the
@@ -69,22 +87,55 @@ public class EvalVisitor implements Visitor<Value> {
@Override @Override
public Value visit(Block e) { public Value visit(Block e) {
Value result = null;
for (var stmt : e.statements) { for (var stmt : e.statements) {
stmt.welcome(this); result = stmt.welcome(this);
} }
return null; return result;
} }
@Override @Override
public Value visit(FunctionDefinition e) { public Value visit(FunctionDefinition e) {
// TODO Auto-generated method stub // Ein Eval über eine FunDef macht keinen Sinn
return null; throw new RuntimeException("Wir sind im Eval und visiten eine Funktionsdefinition.. WUT?!");
} }
@Override @Override
public Value visit(FunctionCall e) { public Value visit(FunctionCall e) {
// TODO Auto-generated method stub // Die funktionsdefinition speichern
return null; 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

@@ -175,4 +175,10 @@ public class PrettyPrintVisitor implements Visitor<Void> {
return null; return null;
} }
@Override
public Void visit(Variable e) {
ex.write(e.name);
return null;
}
} }

View File

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