renamings

This commit is contained in:
ChUrl
2021-01-28 13:08:44 +01:00
parent fd483811b9
commit c29c807861
11 changed files with 217 additions and 229 deletions

View File

@ -1,4 +1,5 @@
import codegen.CodeGenerator; import codegen.sourcegraph.SourceGraph;
import codegen.sourcegraph.SourceGraphGenerator;
import lexer.StupsLexer; import lexer.StupsLexer;
import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.Lexer; import org.antlr.v4.runtime.Lexer;
@ -78,11 +79,11 @@ public final class StupsCompiler {
// Codegeneration + Output // Codegeneration + Output
final String outputName = filename.replaceFirst("stups", "j"); final String outputName = filename.replaceFirst("stups", "j");
final CodeGenerator gen = CodeGenerator.fromAST(tree, nodeTable); final SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, filename);
final StringBuilder jasmin = gen.generateCode(filename); final SourceGraph graph = gen.generateCode();
try { try {
final Path outputFile = Paths.get(System.getProperty("user.dir") + "/" + outputName); final Path outputFile = Paths.get(System.getProperty("user.dir") + "/" + outputName);
Files.writeString(outputFile, jasmin.toString()); Files.writeString(outputFile, graph.toString());
} catch (IOException e) { } catch (IOException e) {
System.out.println("Datei konnte nicht geschrieben werden."); System.out.println("Datei konnte nicht geschrieben werden.");
return; return;

View File

@ -1,39 +0,0 @@
package codegen.analysis.flowgraph;
import java.util.List;
import java.util.stream.Collectors;
public class FlowGraph {
private final FlowGraphHead head;
private final List<FlowGraphBlock> blocks;
private final FlowGraphTail tail;
public FlowGraph(FlowGraphHead head, List<FlowGraphBlock> blocks, FlowGraphTail tail) {
this.head = head;
this.blocks = blocks;
this.tail = tail;
}
public void print() {
final String blocksString = this.blocks.stream()
.map(FlowGraphBlock::toString)
.map(string -> string + "-".repeat(50))
.collect(Collectors.joining());
System.out.println(this.head + "-".repeat(100)
+ blocksString + "-".repeat(100)
+ this.tail);
}
@Override
public String toString() {
final String blocksString = this.blocks.stream()
.map(FlowGraphBlock::toString)
.collect(Collectors.joining());
return this.head
+ blocksString
+ this.tail;
}
}

View File

@ -1,25 +0,0 @@
package codegen.analysis.flowgraph;
import java.util.List;
import java.util.stream.Collectors;
public class FlowGraphBlock {
private final String label;
private final List<FlowGraphLine> lines;
public FlowGraphBlock(String label, List<FlowGraphLine> lines) {
this.label = label;
this.lines = lines;
}
@Override
public String toString() {
final String linesString = this.lines.stream()
.map(FlowGraphLine::toString)
.collect(Collectors.joining());
return this.label + ":\n"
+ linesString;
}
}

View File

@ -1,10 +0,0 @@
package codegen.analysis.flowgraph;
public class FlowGraphTail {
@Override
public String toString() {
return "\t\treturn\n"
+ ".end method";
}
}

View File

@ -0,0 +1,63 @@
package codegen.sourcegraph;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class SourceGraph {
private final SourceGraphHead head;
private final List<SourceGraphBlock> blocks;
private final SourceGraphTail tail;
public SourceGraph(String bytecodeVersion, String source, String clazz, int stackSize, int localCount) {
this.head = new SourceGraphHead(bytecodeVersion, source, clazz, stackSize, localCount);
this.blocks = new ArrayList<>();
this.tail = new SourceGraphTail();
}
public void addLabel(String label) {
if (this.blocks.get(this.blocks.size() - 1).isEmpty()) {
// Replace empty blocks, we don't need them
this.blocks.set(this.blocks.size() - 1, new SourceGraphBlock(label));
} else {
this.blocks.add(new SourceGraphBlock(label));
}
}
public void addInst(String instruction, String... args) {
if (this.blocks.isEmpty()) {
this.blocks.add(new SourceGraphBlock());
}
this.blocks.get(this.blocks.size() - 1).addLine(instruction, args);
}
public void addJump(String instruction, String label) {
this.addInst(instruction, label);
this.blocks.add(new SourceGraphBlock());
}
public String print() {
final String blocksString = this.blocks.stream()
.map(SourceGraphBlock::toString)
.map(string -> string + "-".repeat(50) + "\n")
.collect(Collectors.joining());
return this.head + "-".repeat(100) + "\n"
+ "-".repeat(50) + "\n" + blocksString + "-".repeat(100) + "\n"
+ this.tail;
}
@Override
public String toString() {
final String blocksString = this.blocks.stream()
.map(SourceGraphBlock::toString)
.collect(Collectors.joining());
return this.head
+ blocksString
+ this.tail;
}
}

View File

@ -0,0 +1,44 @@
package codegen.sourcegraph;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class SourceGraphBlock {
private final String label;
private final List<SourceGraphInst> lines;
public SourceGraphBlock(String label) {
this.label = label;
this.lines = new ArrayList<>();
}
public SourceGraphBlock() {
this.label = "";
this.lines = new ArrayList<>();
}
public boolean isEmpty() {
return this.label.isEmpty() && this.lines.isEmpty();
}
@Override
public String toString() {
final String linesString = this.lines.stream()
.map(SourceGraphInst::toString)
.map(line -> line + "\n")
.collect(Collectors.joining());
if (this.label.isBlank()) {
return linesString;
}
return this.label + ":\n"
+ linesString;
}
public void addLine(String instruction, String... args) {
this.lines.add(new SourceGraphInst(instruction, args));
}
}

View File

@ -1,5 +1,6 @@
package codegen; package codegen.sourcegraph;
import codegen.CodeGenerationException;
import codegen.analysis.StackSizeAnalyzer; import codegen.analysis.StackSizeAnalyzer;
import parser.ast.AST; import parser.ast.AST;
import parser.ast.ASTNode; import parser.ast.ASTNode;
@ -15,23 +16,23 @@ import java.util.Map;
import static java.util.Map.entry; import static java.util.Map.entry;
import static util.Logger.log; import static util.Logger.log;
public final class CodeGenerator { public final class SourceGraphGenerator {
private static final Map<String, Method> methodMap; private static final Map<String, Method> methodMap;
static { static {
Map<String, Method> map; Map<String, Method> map;
try { try {
final Class<?> gen = CodeGenerator.class; final Class<?> gen = SourceGraphGenerator.class;
map = Map.ofEntries( map = Map.ofEntries(
entry("cond", gen.getDeclaredMethod("cond", ASTNode.class)), entry("cond", gen.getDeclaredMethod("cond", ASTNode.class)),
entry("loop", gen.getDeclaredMethod("loop", ASTNode.class)), entry("loop", gen.getDeclaredMethod("loop", ASTNode.class)),
entry("assignment", gen.getDeclaredMethod("assign", ASTNode.class)), entry("assignment", gen.getDeclaredMethod("assign", ASTNode.class)),
entry("expr", gen.getDeclaredMethod("expr", ASTNode.class)), entry("expr", gen.getDeclaredMethod("expr", ASTNode.class)),
// Leafs // Leafs
entry("INTEGER_LIT", gen.getDeclaredMethod("intLiteral", ASTNode.class)), entry("INTEGER_LIT", gen.getDeclaredMethod("intStringLiteral", ASTNode.class)),
entry("BOOLEAN_LIT", gen.getDeclaredMethod("boolLiteral", ASTNode.class)), entry("BOOLEAN_LIT", gen.getDeclaredMethod("boolLiteral", ASTNode.class)),
entry("STRING_LIT", gen.getDeclaredMethod("stringLiteral", ASTNode.class)), entry("STRING_LIT", gen.getDeclaredMethod("intStringLiteral", ASTNode.class)),
entry("IDENTIFIER", gen.getDeclaredMethod("identifier", ASTNode.class)), entry("IDENTIFIER", gen.getDeclaredMethod("identifier", ASTNode.class)),
entry("print", gen.getDeclaredMethod("println", ASTNode.class)) entry("print", gen.getDeclaredMethod("println", ASTNode.class))
); );
@ -44,20 +45,34 @@ public final class CodeGenerator {
private final Map<String, Integer> varMap; private final Map<String, Integer> varMap;
private final Map<ASTNode, String> nodeTypeMap; private final Map<ASTNode, String> nodeTypeMap;
private final StringBuilder jasmin; private final String source;
private final AST tree; private final AST tree;
private final SourceGraph graph;
private int labelCounter; private int labelCounter;
private CodeGenerator(Map<String, Integer> varMap, AST tree, Map<ASTNode, String> nodeTypeMap) { private SourceGraphGenerator(Map<String, Integer> varMap, AST tree, Map<ASTNode, String> nodeTypeMap, SourceGraph graph, String source) {
this.varMap = varMap; this.varMap = varMap;
this.tree = tree; this.tree = tree;
this.nodeTypeMap = nodeTypeMap; this.nodeTypeMap = nodeTypeMap;
this.jasmin = new StringBuilder(); this.graph = graph;
this.source = source;
} }
public static CodeGenerator fromAST(AST tree, Map<ASTNode, String> nodeTypeMap) { public static SourceGraphGenerator fromAST(AST tree, Map<ASTNode, String> nodeTypeMap, String source) {
return new CodeGenerator(varMapFromAST(tree), tree, nodeTypeMap); if (!tree.getRoot().hasChildren()) {
throw new CodeGenerationException("Empty File can't be compiled");
}
final Map<String, Integer> varMap = varMapFromAST(tree);
final String bytecodeVersion = "49.0";
final String clazz = tree.getRoot().getChildren().get(1).getValue();
final int stackSize = StackSizeAnalyzer.runStackModel(tree);
final int localCount = varMap.size() + 1;
final SourceGraph graph = new SourceGraph(bytecodeVersion, source, clazz, stackSize, localCount);
return new SourceGraphGenerator(varMap, tree, nodeTypeMap, graph, source);
} }
private static Map<String, Integer> varMapFromAST(AST tree) { private static Map<String, Integer> varMapFromAST(AST tree) {
@ -84,69 +99,16 @@ public final class CodeGenerator {
return Collections.unmodifiableMap(varMap); return Collections.unmodifiableMap(varMap);
} }
private static String genComparisonInst(String inst, String labelPre, int currentLabel) { public SourceGraph generateCode() {
return inst + " " + labelPre + "true" + currentLabel // If not equal jump to NEtrue
+ "\n\t\tldc 0" // If false load 0
+ "\n\t\tgoto " + labelPre + "end" + currentLabel // If false skip true branch
+ "\n" + labelPre + "true" + currentLabel + ":"
+ "\n\t\tldc 1" // if true load 1
+ "\n" + labelPre + "end" + currentLabel + ":";
}
private void generateHeader(String source) {
final String clazz = this.tree.getRoot().getChildren().get(1).getValue();
this.jasmin.append(".bytecode 49.0\n") // 55.0 has stricter verification => stackmap frames missing
.append(".source ").append(source).append("\n")
.append(".class public ").append(clazz).append("\n")
.append(".super java/lang/Object\n");
log("Generated Jasmin Header.");
}
private void generateConstructor() {
this.jasmin.append(".method public <init>()V\n")
.append("\t.limit stack 1\n")
.append("\t.limit locals 1\n")
.append("\t.line 1\n")
.append("\t\taload_0\n")
.append("\t\tinvokespecial java/lang/Object/<init>()V\n")
.append("\t\treturn\n")
.append(".end method\n\n");
log("Generated Jasmin Constructor.");
}
public StringBuilder generateCode(String source) {
System.out.println(" - Generating Jasmin assembler..."); System.out.println(" - Generating Jasmin assembler...");
if (!this.tree.getRoot().hasChildren()) {
throw new CodeGenerationException("Empty File can't be compiled");
}
this.generateHeader(source);
this.generateConstructor();
this.generateMain();
log("Jasmin Assembler:\n" + "-".repeat(100) + "\n" + this.jasmin + "-".repeat(100));
System.out.println("Code-generation successful.");
return this.jasmin;
}
private void generateMain() {
this.jasmin.append(".method public static main([Ljava/lang/String;)V\n")
.append("\t.limit stack ").append(StackSizeAnalyzer.runStackModel(this.tree)).append("\n")
.append("\t.limit locals ").append(this.varMap.size() + 1).append("\n");
log("\nGenerating main method code");
// Needs to be skipped to not trigger generation for IDENTIFIER: args or IDENTIFIER: ClassName
this.generateNode(this.tree.getRoot().getChildren().get(3).getChildren().get(11)); this.generateNode(this.tree.getRoot().getChildren().get(3).getChildren().get(11));
this.jasmin.append("\t\treturn\n") log("\n\nJasmin Assembler from FlowGraph:\n" + "-".repeat(100) + "\n" + this.graph + "-".repeat(100));
.append(".end method\n"); log("\n\nFlowGraph print:\n" + "-".repeat(100) + "\n" + this.graph.print() + "-".repeat(100));
System.out.println("Code-generation successful.");
log("Generated Jasmin Main.\n"); return this.graph;
} }
private void generateNode(ASTNode node) { private void generateNode(ASTNode node) {
@ -171,14 +133,14 @@ public final class CodeGenerator {
this.generateNode(node.getChildren().get(0)); this.generateNode(node.getChildren().get(0));
// Jump // Jump
this.jasmin.append("\t\tifeq IFfalse").append(currentLabel).append("\n"); // ifeq: == 0 => false this.graph.addJump("ifeq", "IFfalse" + currentLabel);
// IFtrue branch // IFtrue branch
this.generateNode(node.getChildren().get(1)); this.generateNode(node.getChildren().get(1));
this.jasmin.append("\t\tgoto IFend").append(currentLabel).append("\n"); this.graph.addJump("goto", "IFend" + currentLabel);
// IFfalse branch // IFfalse branch
this.jasmin.append("IFfalse").append(currentLabel).append(":\n"); this.graph.addLabel("IFfalse" + currentLabel);
if (node.getChildren().size() == 3) { if (node.getChildren().size() == 3) {
// Else exists // Else exists
@ -186,27 +148,27 @@ public final class CodeGenerator {
} }
// IFend branch // IFend branch
this.jasmin.append("IFend").append(currentLabel).append(":\n"); this.graph.addLabel("IFend" + currentLabel);
} }
private void loop(ASTNode node) { private void loop(ASTNode node) {
final int currentLabel = this.labelCounter; final int currentLabel = this.labelCounter;
this.labelCounter++; this.labelCounter++;
this.jasmin.append("LOOPstart").append(currentLabel).append(":\n"); this.graph.addLabel("LOOPstart" + currentLabel);
// Condition // Condition
this.generateNode(node.getChildren().get(0).getChildren().get(1)); this.generateNode(node.getChildren().get(0).getChildren().get(1));
// Jump // Jump
this.jasmin.append("\t\tifeq LOOPend").append(currentLabel).append("\n"); // ifeq: == 0 => Loop stopped this.graph.addJump("ifeq", "LOOPend" + currentLabel);
// Loop body // Loop body
this.generateNode(node.getChildren().get(1)); this.generateNode(node.getChildren().get(1));
this.jasmin.append("\t\tgoto LOOPstart").append(currentLabel).append("\n"); // Jump to Loop start this.graph.addJump("goto", "LOOPstart" + currentLabel);
// Loop end // Loop end
this.jasmin.append("LOOPend").append(currentLabel).append(":\n"); this.graph.addLabel("LOOPend" + currentLabel);
} }
private void assign(ASTNode node) { //! Stack - 1 private void assign(ASTNode node) { //! Stack - 1
@ -221,10 +183,7 @@ public final class CodeGenerator {
log("assign(): " + node.getName() + ": " + node.getValue() + " => " + inst); log("assign(): " + node.getName() + ": " + node.getValue() + " => " + inst);
this.jasmin.append("\t\t") this.graph.addInst(inst, this.varMap.get(node.getValue()).toString());
.append(inst)
.append(this.varMap.get(node.getValue()))
.append("\n");
} }
private void expr(ASTNode node) { private void expr(ASTNode node) {
@ -266,14 +225,10 @@ public final class CodeGenerator {
log("intExpr(): " + node.getName() + ": " + node.getValue() + " => " + inst); log("intExpr(): " + node.getName() + ": " + node.getValue() + " => " + inst);
this.jasmin.append("\t\t") this.graph.addInst(inst);
.append(inst)
.append("\n");
} }
private void boolExpr(ASTNode node) { private void boolExpr(ASTNode node) {
String inst = "";
if (node.getChildren().size() == 1) { //! Stack + 1 if (node.getChildren().size() == 1) { //! Stack + 1
// Unary operator // Unary operator
@ -284,7 +239,9 @@ public final class CodeGenerator {
this.generateNode(node.getChildren().get(0)); this.generateNode(node.getChildren().get(0));
inst = "ldc 1\n\t\tixor"; // 0 ^1 = 1, 1 ^1 = 0 // 0 ^1 = 1, 1 ^1 = 0
this.graph.addInst("ldc", "1");
this.graph.addInst("ixor");
} else if (node.getChildren().size() == 2) { //! Stack - 1 } else if (node.getChildren().size() == 2) { //! Stack - 1
// Binary operator // Binary operator
@ -307,44 +264,36 @@ public final class CodeGenerator {
default -> throw new IllegalStateException("Unexpected value: " + type); default -> throw new IllegalStateException("Unexpected value: " + type);
}; };
inst = switch (node.getValue()) { switch (node.getValue()) {
case "AND" -> "iand"; // Boolean case "AND" -> this.graph.addInst("iand"); // Boolean
case "OR" -> "ior"; case "OR" -> this.graph.addInst("ior");
case "EQUAL" -> genComparisonInst(cmpeq, "EQ", currentLabel); case "EQUAL" -> this.genComparisonInst(cmpeq, "EQ", currentLabel);
case "NOT_EQUAL" -> genComparisonInst(cmpne, "NE", currentLabel); case "NOT_EQUAL" -> this.genComparisonInst(cmpne, "NE", currentLabel);
case "LESS" -> genComparisonInst("if_icmplt", "LT", currentLabel); case "LESS" -> this.genComparisonInst("if_icmplt", "LT", currentLabel);
case "LESS_EQUAL" -> genComparisonInst("if_icmple", "LE", currentLabel); case "LESS_EQUAL" -> this.genComparisonInst("if_icmple", "LE", currentLabel);
case "GREATER" -> genComparisonInst("if_icmpgt", "GT", currentLabel); case "GREATER" -> this.genComparisonInst("if_icmpgt", "GT", currentLabel);
case "GREATER_EQUAL" -> genComparisonInst("if_icmpge", "GE", currentLabel); case "GREATER_EQUAL" -> this.genComparisonInst("if_icmpge", "GE", currentLabel);
default -> throw new IllegalStateException("Unexpected value: " + node.getValue()); default -> throw new IllegalStateException("Unexpected value: " + node.getValue());
}; }
}
} }
log("boolExpr(): " + node.getName() + ": " + node.getValue() + " => \n\t\t" + inst); private void genComparisonInst(String cmpInst, String labelPre, int currentLabel) {
this.graph.addJump(cmpInst, labelPre + "true" + currentLabel); // If not equal jump to NEtrue
this.jasmin.append("\t\t") this.graph.addInst("ldc", "0"); // If false load 0
.append(inst) this.graph.addJump("goto", labelPre + "end" + currentLabel); // If false skip to true
.append("\n"); this.graph.addLabel(labelPre + "true" + currentLabel);
this.graph.addInst("ldc", "1"); // If true load 1
this.graph.addLabel(labelPre + "end" + currentLabel);
} }
// Leafs // Leafs
private void intLiteral(ASTNode node) { //! Stack + 1 private void intStringLiteral(ASTNode node) { //! Stack + 1
log("literal(): " + node.getName() + ": " + node.getValue() + " => ldc"); log("literal(): " + node.getName() + ": " + node.getValue() + " => ldc");
// bipush only pushes 1 byte as int // bipush only pushes 1 byte as int
this.jasmin.append("\t\tldc ") this.graph.addInst("ldc", node.getValue());
.append(node.getValue())
.append("\n");
}
private void stringLiteral(ASTNode node) { //! Stack + 1
log("literal(): " + node.getName() + ": " + node.getValue() + " => ldc");
// bipush only pushes 1 byte as int
this.jasmin.append("\t\tldc ")
.append(node.getValue())
.append("\n");
} }
private void boolLiteral(ASTNode node) { //! Stack + 1 private void boolLiteral(ASTNode node) { //! Stack + 1
@ -352,9 +301,7 @@ public final class CodeGenerator {
final String val = "true".equals(node.getValue()) ? "1" : "0"; final String val = "true".equals(node.getValue()) ? "1" : "0";
this.jasmin.append("\t\tldc ") this.graph.addInst("ldc", val);
.append(val)
.append("\n");
} }
private void identifier(ASTNode node) { //! Stack + 1 private void identifier(ASTNode node) { //! Stack + 1
@ -367,14 +314,11 @@ public final class CodeGenerator {
log("identifier(): " + node.getName() + ": " + node.getValue() + " => " + inst); log("identifier(): " + node.getName() + ": " + node.getValue() + " => " + inst);
this.jasmin.append("\t\t") this.graph.addInst(inst, this.varMap.get(node.getValue()).toString());
.append(inst)
.append(this.varMap.get(node.getValue()))
.append("\n");
} }
private void println(ASTNode node) { //! Stack + 1 private void println(ASTNode node) { //! Stack + 1
this.jasmin.append("\t\tgetstatic java/lang/System/out Ljava/io/PrintStream;\n"); // Push System.out to stack this.graph.addInst("getstatic", "java/lang/System/out", "Ljava/io/PrintStream;");
final ASTNode expr = node.getChildren().get(1).getChildren().get(1); final ASTNode expr = node.getChildren().get(1).getChildren().get(1);
final String type = switch (this.nodeTypeMap.get(expr)) { final String type = switch (this.nodeTypeMap.get(expr)) {
@ -388,8 +332,6 @@ public final class CodeGenerator {
log("println(): " + expr.getName() + ": " + expr.getValue() + " => " + type); log("println(): " + expr.getName() + ": " + expr.getValue() + " => " + type);
this.jasmin.append("\t\tinvokevirtual java/io/PrintStream/println(") this.graph.addInst("invokevirtual", "java/io/PrintStream/println(" + type + ")V");
.append(type)
.append(")V\n");
} }
} }

View File

@ -1,6 +1,6 @@
package codegen.analysis.flowgraph; package codegen.sourcegraph;
public class FlowGraphHead { public class SourceGraphHead {
private final String bytecodeVersion; private final String bytecodeVersion;
private final String source; private final String source;
@ -8,7 +8,7 @@ public class FlowGraphHead {
private final int stackSize; private final int stackSize;
private final int localCount; private final int localCount;
public FlowGraphHead(String bytecodeVersion, String source, String clazz, int stackSize, int localCount) { public SourceGraphHead(String bytecodeVersion, String source, String clazz, int stackSize, int localCount) {
this.bytecodeVersion = bytecodeVersion; this.bytecodeVersion = bytecodeVersion;
this.source = source; this.source = source;
this.clazz = clazz; this.clazz = clazz;

View File

@ -1,11 +1,11 @@
package codegen.analysis.flowgraph; package codegen.sourcegraph;
public class FlowGraphLine { public class SourceGraphInst {
private final String instruction; private final String instruction;
private final String[] args; private final String[] args;
public FlowGraphLine(String instruction, String... args) { public SourceGraphInst(String instruction, String... args) {
this.instruction = instruction; this.instruction = instruction;
this.args = args; this.args = args;
} }

View File

@ -0,0 +1,10 @@
package codegen.sourcegraph;
public class SourceGraphTail {
@Override
public String toString() {
return "\t\treturn\n"
+ ".end method\n";
}
}

View File

@ -1,5 +1,7 @@
package codegen; package codegen;
import codegen.sourcegraph.SourceGraph;
import codegen.sourcegraph.SourceGraphGenerator;
import lexer.StupsLexer; import lexer.StupsLexer;
import org.antlr.v4.runtime.CharStreams; import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.Lexer; import org.antlr.v4.runtime.Lexer;
@ -27,14 +29,14 @@ import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatThrownBy;
class CodeGeneratorTest { class SourceGraphGeneratorTest {
private static StupsParser parser; private static StupsParser parser;
private static Grammar stupsGrammar; private static Grammar stupsGrammar;
@BeforeAll @BeforeAll
static void init() throws IOException, URISyntaxException { static void init() throws IOException, URISyntaxException {
final Path path = Paths.get(CodeGeneratorTest.class.getClassLoader().getResource("exampleGrammars/Grammar.grammar").toURI()); final Path path = Paths.get(SourceGraphGeneratorTest.class.getClassLoader().getResource("exampleGrammars/Grammar.grammar").toURI());
final Grammar grammar = Grammar.fromFile(path); final Grammar grammar = Grammar.fromFile(path);
parser = StupsParser.fromGrammar(grammar); parser = StupsParser.fromGrammar(grammar);
stupsGrammar = grammar; stupsGrammar = grammar;
@ -42,7 +44,7 @@ class CodeGeneratorTest {
private static String readProgram(String prog) { private static String readProgram(String prog) {
try { try {
final Path progPath = Paths.get(CodeGeneratorTest.class.getClassLoader().getResource("examplePrograms/" + prog).toURI()); final Path progPath = Paths.get(SourceGraphGeneratorTest.class.getClassLoader().getResource("examplePrograms/" + prog).toURI());
return Files.readString(progPath); return Files.readString(progPath);
} catch (URISyntaxException | IOException e) { } catch (URISyntaxException | IOException e) {
e.printStackTrace(); e.printStackTrace();
@ -240,8 +242,8 @@ class CodeGeneratorTest {
final AST tree = lexParseProgram(program); final AST tree = lexParseProgram(program);
final Map<ASTNode, String> nodeTable = TypeChecker.validate(tree); final Map<ASTNode, String> nodeTable = TypeChecker.validate(tree);
final CodeGenerator gen = CodeGenerator.fromAST(tree, nodeTable); final SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, "TestOutpu");
final StringBuilder srcProg = gen.generateCode("TestOutput"); final SourceGraph srcProg = gen.generateCode();
compileJasmin(srcProg.toString()); compileJasmin(srcProg.toString());
assertThat(Integer.parseInt(executeCompiledProgram())).isEqualTo(result); assertThat(Integer.parseInt(executeCompiledProgram())).isEqualTo(result);
@ -255,8 +257,8 @@ class CodeGeneratorTest {
final AST tree = lexParseProgram(program); final AST tree = lexParseProgram(program);
final Map<ASTNode, String> nodeTable = TypeChecker.validate(tree); final Map<ASTNode, String> nodeTable = TypeChecker.validate(tree);
final CodeGenerator gen = CodeGenerator.fromAST(tree, nodeTable); final SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, "TestOutput");
final StringBuilder srcProg = gen.generateCode("TestOutput"); final SourceGraph srcProg = gen.generateCode();
compileJasmin(srcProg.toString()); compileJasmin(srcProg.toString());
assertThat(Integer.parseInt(executeCompiledProgram())).isEqualTo(result); assertThat(Integer.parseInt(executeCompiledProgram())).isEqualTo(result);
@ -270,8 +272,8 @@ class CodeGeneratorTest {
final AST tree = lexParseProgram(program); final AST tree = lexParseProgram(program);
final Map<ASTNode, String> nodeTable = TypeChecker.validate(tree); final Map<ASTNode, String> nodeTable = TypeChecker.validate(tree);
final CodeGenerator gen = CodeGenerator.fromAST(tree, nodeTable); final SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, "TestOutput");
final StringBuilder srcProg = gen.generateCode("TestOutput"); final SourceGraph srcProg = gen.generateCode();
compileJasmin(srcProg.toString()); compileJasmin(srcProg.toString());
assertThat(Boolean.parseBoolean(executeCompiledProgram())).isEqualTo(result); assertThat(Boolean.parseBoolean(executeCompiledProgram())).isEqualTo(result);
@ -285,8 +287,8 @@ class CodeGeneratorTest {
final AST tree = lexParseProgram(program); final AST tree = lexParseProgram(program);
final Map<ASTNode, String> nodeTable = TypeChecker.validate(tree); final Map<ASTNode, String> nodeTable = TypeChecker.validate(tree);
final CodeGenerator gen = CodeGenerator.fromAST(tree, nodeTable); final SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, "TestOutput");
final StringBuilder srcProg = gen.generateCode("TestOutput"); final SourceGraph srcProg = gen.generateCode();
compileJasmin(srcProg.toString()); compileJasmin(srcProg.toString());
assertThat(executeCompiledProgram()).isEqualTo(result); assertThat(executeCompiledProgram()).isEqualTo(result);
@ -300,8 +302,8 @@ class CodeGeneratorTest {
final AST tree = lexParseProgram(program); final AST tree = lexParseProgram(program);
final Map<ASTNode, String> nodeTable = TypeChecker.validate(tree); final Map<ASTNode, String> nodeTable = TypeChecker.validate(tree);
final CodeGenerator gen = CodeGenerator.fromAST(tree, nodeTable); final SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, "TestOutput");
final StringBuilder srcProg = gen.generateCode("TestOutput"); final SourceGraph srcProg = gen.generateCode();
compileJasmin(srcProg.toString()); compileJasmin(srcProg.toString());
assertThat(executeCompiledProgram()).isEqualTo(result); assertThat(executeCompiledProgram()).isEqualTo(result);
@ -313,8 +315,8 @@ class CodeGeneratorTest {
final AST tree = lexParseProgram(program); final AST tree = lexParseProgram(program);
final Map<ASTNode, String> nodeTable = TypeChecker.validate(tree); final Map<ASTNode, String> nodeTable = TypeChecker.validate(tree);
final CodeGenerator gen = CodeGenerator.fromAST(tree, nodeTable);
assertThatThrownBy(() -> gen.generateCode("TestOutput")).isInstanceOf(CodeGenerationException.class); assertThatThrownBy(() -> SourceGraphGenerator.fromAST(tree, nodeTable, "TestOutput"))
.isInstanceOf(CodeGenerationException.class);
} }
} }