From 63c5f703582028156ae1dd5c90a767377796b664 Mon Sep 17 00:00:00 2001 From: nitrix Date: Mon, 16 Dec 2019 21:46:43 +0100 Subject: [PATCH] add new node types to the visitors --- .../compiler/Klang/visitors/EvalVisitor.java | 42 +- .../hsrm/compiler/Klang/visitors/GenASM.java | 448 +++++++++--------- .../hsrm/compiler/Klang/visitors/GetVars.java | 49 +- .../Klang/visitors/PrettyPrintVisitor.java | 49 +- .../hsrm/compiler/Klang/visitors/Visitor.java | 8 +- 5 files changed, 328 insertions(+), 268 deletions(-) diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java b/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java index 300360f..7142326 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/EvalVisitor.java @@ -21,24 +21,38 @@ public class EvalVisitor implements Visitor { } @Override - public Value visit(MultiplicativeExpression e) { - Value a = e.lhs.welcome(this); - Value b = e.rhs.welcome(this); - return new Value(a.asInteger() * b.asInteger()); + public Value visit(AdditionExpression e) { + Value lhs = e.lhs.welcome(this); + Value rhs = e.rhs.welcome(this); + return new Value(lhs.asInteger() + rhs.asInteger()); } @Override - public Value visit(AdditiveExpression e) { - Value a = e.lhs.welcome(this); - Value b = e.rhs.welcome(this); - return new Value(a.asInteger() + b.asInteger()); + public Value visit(SubstractionExpression e) { + Value lhs = e.lhs.welcome(this); + Value rhs = e.rhs.welcome(this); + return new Value(lhs.asInteger() - rhs.asInteger()); + } + + @Override + public Value visit(MultiplicationExpression e) { + Value lhs = e.lhs.welcome(this); + Value rhs = e.rhs.welcome(this); + return new Value(lhs.asInteger() * rhs.asInteger()); + } + + @Override + public Value visit(DivisionExpression e) { + Value lhs = e.lhs.welcome(this); + Value rhs = e.rhs.welcome(this); + return new Value(lhs.asInteger() / rhs.asInteger()); } @Override public Value visit(ModuloExpression e) { - Value a = e.lhs.welcome(this); - Value b = e.rhs.welcome(this); - return new Value(a.asInteger() % b.asInteger()); + Value lhs = e.lhs.welcome(this); + Value rhs = e.rhs.welcome(this); + return new Value(lhs.asInteger() % rhs.asInteger()); } @Override @@ -52,7 +66,7 @@ public class EvalVisitor implements Visitor { Value result = this.env.get(e.name); if (result == null) { - throw new RuntimeException("Variable with name " +e.name + " not found."); + throw new RuntimeException("Variable with name " + e.name + " not found."); } return result; @@ -123,7 +137,7 @@ public class EvalVisitor implements Visitor { // 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"); + throw new RuntimeException("Error with function call " + e.name + ": Number of parameters wrong"); } // Baue ein neues environment @@ -147,7 +161,7 @@ public class EvalVisitor implements Visitor { public Value visit(Program e) { // Funktionsdefinitionen für die Auswertung // von Funktionsaufrufen speichern - for (var funcDef: e.funcs) { + for (var funcDef : e.funcs) { this.funcs.put(funcDef.name, funcDef); } diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java b/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java index f82e50c..cc01a65 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GenASM.java @@ -6,249 +6,263 @@ import java.util.Map; import java.util.Set; import java.util.TreeSet; -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.AdditiveExpression; -import de.hsrm.compiler.Klang.nodes.expressions.FunctionCall; -import de.hsrm.compiler.Klang.nodes.expressions.IntegerExpression; -import de.hsrm.compiler.Klang.nodes.expressions.ModuloExpression; -import de.hsrm.compiler.Klang.nodes.expressions.MultiplicativeExpression; -import de.hsrm.compiler.Klang.nodes.expressions.NegateExpression; -import de.hsrm.compiler.Klang.nodes.expressions.Variable; -import de.hsrm.compiler.Klang.nodes.statements.IfStatement; -import de.hsrm.compiler.Klang.nodes.statements.PrintStatement; -import de.hsrm.compiler.Klang.nodes.statements.ReturnStatement; -import de.hsrm.compiler.Klang.nodes.statements.VariableAssignment; +import de.hsrm.compiler.Klang.nodes.*; +import de.hsrm.compiler.Klang.nodes.expressions.*; +import de.hsrm.compiler.Klang.nodes.statements.*; public class GenASM implements Visitor { - 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; - Map env = new HashMap<>(); - Set vars; - String[] rs = { "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9" }; - private int lCount = 0; // Invariante: lCount ist benutzt - - public GenASM(ExWriter ex) { - this.ex = ex; + void subIndent() { + indent = indent.substring(2); } - @Override - public Void visit(IntegerExpression e) { - this.ex.write(" movq $" + e.value + ", %rax\n"); - return null; + void nl() { + write("\n" + indent); } - @Override - public Void visit(Variable e) { - this.ex.write(" movq " +this.env.get(e.name) +"(%rbp), %rax\n"); - return null; + int lbl = 0; + + int next() { + return lbl++; } - @Override - public Void visit(MultiplicativeExpression e) { - e.lhs.welcome(this); - this.ex.write(" movq %rax, %rbx\n"); - e.rhs.welcome(this); - this.ex.write(" imulq %rbx, %rax\n"); - return null; + public ExWriter(Writer w) { + this.w = w; } - @Override - public Void visit(AdditiveExpression e) { - e.lhs.welcome(this); - this.ex.write(" movq %rax, %rbx\n"); - e.rhs.welcome(this); - this.ex.write(" addq %rbx, %rax\n"); - return null; + void lnwrite(Object o) { + nl(); + write(o); } - @Override - public Void visit(NegateExpression e) { - e.lhs.welcome(this); - this.ex.write(" neg %rax\n"); - return null; + void write(Object o) { + try { + w.write(o + ""); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + public ExWriter ex; + Map env = new HashMap<>(); + Set vars; + String[] rs = { "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9" }; + private int lCount = 0; // Invariante: lCount ist benutzt + + public GenASM(ExWriter ex) { + this.ex = ex; + } + + @Override + public Void visit(IntegerExpression e) { + this.ex.write(" movq $" + e.value + ", %rax\n"); + return null; + } + + @Override + public Void visit(Variable e) { + this.ex.write(" movq " + this.env.get(e.name) + "(%rbp), %rax\n"); + return null; + } + + @Override + public Void visit(AdditionExpression e) { + e.lhs.welcome(this); + this.ex.write(" pushq %rax\n"); + e.rhs.welcome(this); + this.ex.write(" popq %rbx\n"); + this.ex.write(" addq %rbx, %rax\n"); + return null; + } + + @Override + public Void visit(SubstractionExpression e) { + e.lhs.welcome(this); + this.ex.write(" pushq %rax\n"); + e.rhs.welcome(this); + this.ex.write(" popq %rbx\n"); + this.ex.write(" subq %rbx, %rax\n"); + return null; + } + + @Override + public Void visit(MultiplicationExpression e) { + e.lhs.welcome(this); + this.ex.write(" pushq %rax\n"); + e.rhs.welcome(this); + this.ex.write(" popq %rbx\n"); + this.ex.write(" imulq %rbx, %rax\n"); + return null; + } + + @Override + public Void visit(DivisionExpression e) { + e.lhs.welcome(this); + this.ex.write(" pushq %rax\n"); + e.rhs.welcome(this); + this.ex.write(" movq %rax, %rbx\n"); + this.ex.write(" popq %rax\n"); + this.ex.write(" xor %rdx, %rdx\n"); // clear upper part of division + this.ex.write(" idiv %rbx\n"); // %rax/%rbx, quotient now in %rax + return null; + } + + @Override + public Void visit(ModuloExpression e) { + this.ex.write(" pushq %rax\n"); + e.rhs.welcome(this); + this.ex.write(" movq %rax, %rbx\n"); + this.ex.write(" popq %rax\n"); + this.ex.write(" xor %rdx, %rdx\n"); // clear upper part of division + this.ex.write(" idiv %rbx\n"); // %rax/%rbx, remainder now in %rdx + this.ex.write(" movq %rdx, %rax\n"); + return null; + } + + @Override + public Void visit(NegateExpression e) { + e.lhs.welcome(this); + this.ex.write(" neg %rax\n"); + return null; + } + + @Override + public Void visit(IfStatement e) { + int then = ++lCount; + int end = ++lCount; + + e.cond.welcome(this); + this.ex.write(" cmp $0, %rax\n"); + this.ex.write(" jz .L" + then + "\n"); + // else Part + if (e.alt != null) { + e.alt.welcome(this); + } else if (e.elif != null) { + e.elif.welcome(this); + } + this.ex.write(" jmp .L" + end + "\n"); + // then Part + this.ex.write(".L" + then + ":\n"); + e.then.welcome(this); + this.ex.write(".L" + end + ":\n"); + return null; + } + + @Override + public Void visit(PrintStatement e) { + throw new RuntimeException("Das machen wir mal nicht, ne?!"); + } + + @Override + public Void visit(VariableAssignment e) { + e.expression.welcome(this); + int offset = this.env.get(e.name); + this.ex.write(" movq %rax, " + offset + "(%rbp)\n"); + return null; + } + + @Override + public Void visit(ReturnStatement e) { + e.expression.welcome(this); + this.ex.write(" movq %rbp, %rsp\n"); + this.ex.write(" popq %rbp\n"); + this.ex.write(" ret\n"); + return null; + } + + @Override + public Void visit(Block e) { + for (var statement : e.statements) { + statement.welcome(this); + } + return null; + } + + @Override + public Void visit(FunctionDefinition e) { + this.ex.write(".globl " + e.name + "\n"); + this.ex.write(".type " + e.name + ", @function\n"); + this.ex.write(e.name + ":\n"); + this.ex.write(" pushq %rbp\n"); + this.ex.write(" movq %rsp, %rbp\n"); + + // hole die anzahl der lokalen variablen + this.vars = new TreeSet(); + GetVars getvars = new GetVars(vars); + getvars.visit(e); + + // Erzeuge ein environment + this.env = new HashMap(); + + // Merke dir die offsets der parameter, die direkt auf den stack gelegt wurden + int m = e.parameters.length - this.rs.length; + for (int i = this.rs.length; i < e.parameters.length; i++) { + int j = i - this.rs.length; + this.env.put(e.parameters[i], ((m - j) * 8)); // positiv, liegt über unserem stack frame } - @Override - public Void visit(ModuloExpression e) { - e.rhs.welcome(this); - this.ex.write(" movq %rax, %rbx\n"); - e.lhs.welcome(this); - this.ex.write(" xor %rdx, %rdx\n"); // clear remainder register - this.ex.write(" idiv %ebx\n"); // %rax/%rbx, remainder now in %rdx - this.ex.write(" movq %rdx, %rax\n"); - return null; + // pushe die aufrufparameter aus den Registern wieder auf den Stack + int offset = 0; + for (int i = 0; i < Math.min(this.rs.length, e.parameters.length); i++) { + this.ex.write(" pushq " + this.rs[i] + "\n"); + offset -= 8; + this.env.put(e.parameters[i], offset); // negative, liegt unter aktuellem BP } - @Override - public Void visit(IfStatement e) { - int then = ++lCount; - int end = ++lCount; - - e.cond.welcome(this); - this.ex.write(" cmp $0, %rax\n"); - this.ex.write(" jz .L" + then + "\n"); - // else Part - if (e.alt != null) { - e.alt.welcome(this); - } else if (e.elif != null) { - e.elif.welcome(this); - } - this.ex.write(" jmp .L" + end + "\n"); - // then Part - this.ex.write(".L" + then + ":\n"); - e.then.welcome(this); - this.ex.write(".L" + end + ":\n"); - return null; + // Reserviere Platz auf dem Stack für jede lokale variable + for (String lok_var : vars) { + offset -= 8; + this.ex.write(" pushq $0\n"); + this.env.put(lok_var, offset); } - @Override - public Void visit(PrintStatement e) { - throw new RuntimeException("Das machen wir mal nicht, ne?!"); + e.block.welcome(this); + return null; + } + + @Override + public Void visit(FunctionCall e) { + // Die ersten sechs params in die register schieben + for (int i = 0; i < Math.min(this.rs.length, e.arguments.length); i++) { + e.arguments[i].welcome(this); + this.ex.write(" movq %rax, " + this.rs[i] + "\n"); } - @Override - public Void visit(VariableAssignment e) { - e.expression.welcome(this); - int offset = this.env.get(e.name); - this.ex.write(" movq %rax, " + offset + "(%rbp)\n"); - return null; + // Den Rest auf den stack pushen + for (int i = this.rs.length; i < e.arguments.length; i++) { + e.arguments[i].welcome(this); } - @Override - public Void visit(ReturnStatement e) { - e.expression.welcome(this); - this.ex.write(" movq %rbp, %rsp\n"); - this.ex.write(" popq %rbp\n"); - this.ex.write(" ret\n"); - return null; + this.ex.write(" call " + e.name + "\n"); + return null; + } + + @Override + public Void visit(Program e) { + this.ex.write(".text\n"); + for (var func : e.funcs) { + func.welcome(this); + this.ex.write("\n"); } + this.ex.write(".globl start\n"); + this.ex.write(".type start, @function\n"); + this.ex.write("start:\n"); + this.ex.write(" pushq %rbp\n"); + this.ex.write(" movq %rsp, %rbp\n"); + e.expression.welcome(this); - @Override - public Void visit(Block e) { - for (var statement : e.statements) { - statement.welcome(this); - } - return null; - } - - @Override - public Void visit(FunctionDefinition e) { - this.ex.write(".globl " + e.name + "\n"); - this.ex.write(".type " + e.name + ", @function\n"); - this.ex.write(e.name + ":\n"); - this.ex.write(" pushq %rbp\n"); - this.ex.write(" movq %rsp, %rbp\n"); - - // hole die anzahl der lokalen variablen - this.vars = new TreeSet(); - GetVars getvars = new GetVars(vars); - getvars.visit(e); - - // Erzeuge ein environment - this.env = new HashMap(); - - // Merke dir die offsets der parameter, die direkt auf den stack gelegt wurden - int m = e.parameters.length - this.rs.length; - for (int i = this.rs.length; i < e.parameters.length; i++) { - int j = i - this.rs.length; - this.env.put(e.parameters[i], ((m - j) * 8)); // positiv, liegt über unserem stack frame - } - - // pushe die aufrufparameter aus den Registern wieder auf den Stack - int offset = 0; - for (int i = 0; i < Math.min(this.rs.length, e.parameters.length); i++) { - this.ex.write(" pushq " + this.rs[i] + "\n"); - 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; - this.ex.write(" pushq $0\n"); - this.env.put(lok_var, offset); - } - - e.block.welcome(this); - return null; - } - - @Override - public Void visit(FunctionCall e) { - // Die ersten sechs params in die register schieben - for (int i = 0; i < Math.min(this.rs.length, e.arguments.length); i++) { - e.arguments[i].welcome(this); - this.ex.write(" movq %rax, " + this.rs[i] + "\n"); - } - - // Den Rest auf den stack pushen - for (int i = this.rs.length; i < e.arguments.length; i++) { - e.arguments[i].welcome(this); - } - - this.ex.write(" call " + e.name + "\n"); - return null; - } - - @Override - public Void visit(Program e) { - this.ex.write(".text\n"); - for (var func : e.funcs) { - func.welcome(this); - this.ex.write("\n"); - } - this.ex.write(".globl start\n"); - this.ex.write(".type start, @function\n"); - this.ex.write("start:\n"); - this.ex.write(" pushq %rbp\n"); - this.ex.write(" movq %rsp, %rbp\n"); - e.expression.welcome(this); - - this.ex.write(" movq %rbp, %rsp\n"); - this.ex.write(" popq %rbp\n"); - this.ex.write(" ret\n"); - return null; - } + this.ex.write(" movq %rbp, %rsp\n"); + this.ex.write(" popq %rbp\n"); + this.ex.write(" ret\n"); + return null; + } } \ No newline at end of file diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java b/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java index ebf004f..8c7444d 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/GetVars.java @@ -2,20 +2,9 @@ package de.hsrm.compiler.Klang.visitors; import java.util.Set; -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.AdditiveExpression; -import de.hsrm.compiler.Klang.nodes.expressions.FunctionCall; -import de.hsrm.compiler.Klang.nodes.expressions.IntegerExpression; -import de.hsrm.compiler.Klang.nodes.expressions.ModuloExpression; -import de.hsrm.compiler.Klang.nodes.expressions.MultiplicativeExpression; -import de.hsrm.compiler.Klang.nodes.expressions.NegateExpression; -import de.hsrm.compiler.Klang.nodes.expressions.Variable; -import de.hsrm.compiler.Klang.nodes.statements.IfStatement; -import de.hsrm.compiler.Klang.nodes.statements.PrintStatement; -import de.hsrm.compiler.Klang.nodes.statements.ReturnStatement; -import de.hsrm.compiler.Klang.nodes.statements.VariableAssignment; +import de.hsrm.compiler.Klang.nodes.*; +import de.hsrm.compiler.Klang.nodes.expressions.*; +import de.hsrm.compiler.Klang.nodes.statements.*; class GetVars implements Visitor { @@ -36,14 +25,35 @@ class GetVars implements Visitor { } @Override - public Void visit(MultiplicativeExpression e) { + public Void visit(AdditionExpression e) { e.lhs.welcome(this); e.rhs.welcome(this); return null; } @Override - public Void visit(AdditiveExpression e) { + public Void visit(SubstractionExpression e) { + e.lhs.welcome(this); + e.rhs.welcome(this); + return null; + } + + @Override + public Void visit(MultiplicationExpression e) { + e.lhs.welcome(this); + e.rhs.welcome(this); + return null; + } + + @Override + public Void visit(DivisionExpression e) { + e.lhs.welcome(this); + e.rhs.welcome(this); + return null; + } + + @Override + public Void visit(ModuloExpression e) { e.lhs.welcome(this); e.rhs.welcome(this); return null; @@ -55,13 +65,6 @@ class GetVars implements Visitor { return null; } - @Override - public Void visit(ModuloExpression e) { - e.lhs.welcome(this); - e.rhs.welcome(this); - return null; - } - @Override public Void visit(IfStatement e) { e.cond.welcome(this); diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java b/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java index fed3c01..0e74dc0 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/PrettyPrintVisitor.java @@ -72,33 +72,60 @@ public class PrettyPrintVisitor implements Visitor { } @Override - public Void visit(MultiplicativeExpression e) { - e.lhs.welcome(this); - ex.write(" * "); - e.rhs.welcome(this); - return null; - } - - @Override - public Void visit(AdditiveExpression e) { + 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(NegateExpression e) { - ex.write(" - "); + 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; } diff --git a/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java b/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java index 456c8cd..662500d 100644 --- a/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java +++ b/src/main/java/de/hsrm/compiler/Klang/visitors/Visitor.java @@ -9,10 +9,12 @@ import de.hsrm.compiler.Klang.nodes.statements.*; public interface Visitor { R visit(IntegerExpression e); R visit(Variable e); - R visit(MultiplicativeExpression e); - R visit(AdditiveExpression e); - R visit(NegateExpression e); + R visit(AdditionExpression e); + R visit(SubstractionExpression e); + R visit(MultiplicationExpression e); + R visit(DivisionExpression e); R visit(ModuloExpression e); + R visit(NegateExpression e); R visit(IfStatement e); R visit(PrintStatement e); R visit(VariableAssignment e);