add CodeGenerator

This commit is contained in:
ChUrl
2021-01-28 16:49:22 +01:00
parent c29c807861
commit 5cc40964b6
5 changed files with 60 additions and 39 deletions

6
.idea/discord.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="PROJECT" />
</component>
</project>

View File

@ -1,5 +1,4 @@
import codegen.sourcegraph.SourceGraph; import codegen.CodeGenerator;
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,12 +77,11 @@ public final class StupsCompiler {
final Map<ASTNode, String> nodeTable = TypeChecker.validate(tree); final Map<ASTNode, String> nodeTable = TypeChecker.validate(tree);
// Codegeneration + Output // Codegeneration + Output
final String outputName = filename.replaceFirst("stups", "j"); final String outputName = filename.replaceFirst("\\.stups", ".j");
final SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, filename); final String sourceCode = CodeGenerator.generateCode(tree, nodeTable, 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, graph.toString()); Files.writeString(outputFile, sourceCode);
} 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

@ -0,0 +1,20 @@
package codegen;
import codegen.sourcegraph.SourceGraph;
import codegen.sourcegraph.SourceGraphGenerator;
import parser.ast.AST;
import parser.ast.ASTNode;
import java.util.Map;
public final class CodeGenerator {
private CodeGenerator() {}
public static String generateCode(AST tree, Map<ASTNode, String> nodeTypeMap, String source) {
final SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTypeMap, source);
final SourceGraph graph = gen.generateGraph();
return graph.toString();
}
}

View File

@ -25,16 +25,16 @@ public final class SourceGraphGenerator {
try { try {
final Class<?> gen = SourceGraphGenerator.class; final Class<?> gen = SourceGraphGenerator.class;
map = Map.ofEntries( map = Map.ofEntries(
entry("cond", gen.getDeclaredMethod("cond", ASTNode.class)), entry("cond", gen.getDeclaredMethod("condNode", ASTNode.class)),
entry("loop", gen.getDeclaredMethod("loop", ASTNode.class)), entry("loop", gen.getDeclaredMethod("loopNode", ASTNode.class)),
entry("assignment", gen.getDeclaredMethod("assign", ASTNode.class)), entry("assignment", gen.getDeclaredMethod("assignNode", ASTNode.class)),
entry("expr", gen.getDeclaredMethod("expr", ASTNode.class)), entry("expr", gen.getDeclaredMethod("exprNode", ASTNode.class)),
// Leafs // Leafs
entry("INTEGER_LIT", gen.getDeclaredMethod("intStringLiteral", ASTNode.class)), entry("INTEGER_LIT", gen.getDeclaredMethod("intStringLiteralNode", ASTNode.class)),
entry("BOOLEAN_LIT", gen.getDeclaredMethod("boolLiteral", ASTNode.class)), entry("BOOLEAN_LIT", gen.getDeclaredMethod("boolLiteralNode", ASTNode.class)),
entry("STRING_LIT", gen.getDeclaredMethod("intStringLiteral", ASTNode.class)), entry("STRING_LIT", gen.getDeclaredMethod("intStringLiteralNode", ASTNode.class)),
entry("IDENTIFIER", gen.getDeclaredMethod("identifier", ASTNode.class)), entry("IDENTIFIER", gen.getDeclaredMethod("identifierNode", ASTNode.class)),
entry("print", gen.getDeclaredMethod("println", ASTNode.class)) entry("print", gen.getDeclaredMethod("printlnNode", ASTNode.class))
); );
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
map = null; map = null;
@ -43,20 +43,18 @@ public final class SourceGraphGenerator {
methodMap = map; methodMap = map;
} }
private final AST tree;
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 String source;
private final AST tree;
private final SourceGraph graph; private final SourceGraph graph;
private int labelCounter; private int labelCounter;
private SourceGraphGenerator(Map<String, Integer> varMap, AST tree, Map<ASTNode, String> nodeTypeMap, SourceGraph graph, String source) { private SourceGraphGenerator(Map<String, Integer> varMap, AST tree, Map<ASTNode, String> nodeTypeMap, SourceGraph graph) {
this.varMap = varMap; this.varMap = varMap;
this.tree = tree; this.tree = tree;
this.nodeTypeMap = nodeTypeMap; this.nodeTypeMap = nodeTypeMap;
this.graph = graph; this.graph = graph;
this.source = source;
} }
public static SourceGraphGenerator fromAST(AST tree, Map<ASTNode, String> nodeTypeMap, String source) { public static SourceGraphGenerator fromAST(AST tree, Map<ASTNode, String> nodeTypeMap, String source) {
@ -72,7 +70,7 @@ public final class SourceGraphGenerator {
final int localCount = varMap.size() + 1; final int localCount = varMap.size() + 1;
final SourceGraph graph = new SourceGraph(bytecodeVersion, source, clazz, stackSize, localCount); final SourceGraph graph = new SourceGraph(bytecodeVersion, source, clazz, stackSize, localCount);
return new SourceGraphGenerator(varMap, tree, nodeTypeMap, graph, source); return new SourceGraphGenerator(varMap, tree, nodeTypeMap, graph);
} }
private static Map<String, Integer> varMapFromAST(AST tree) { private static Map<String, Integer> varMapFromAST(AST tree) {
@ -99,14 +97,13 @@ public final class SourceGraphGenerator {
return Collections.unmodifiableMap(varMap); return Collections.unmodifiableMap(varMap);
} }
public SourceGraph generateCode() { public SourceGraph generateGraph() {
System.out.println(" - Generating Jasmin assembler..."); System.out.println(" - Generating Source Graph...");
this.generateNode(this.tree.getRoot().getChildren().get(3).getChildren().get(11)); this.generateNode(this.tree.getRoot().getChildren().get(3).getChildren().get(11));
log("\n\nJasmin Assembler from FlowGraph:\n" + "-".repeat(100) + "\n" + this.graph + "-".repeat(100)); log("\n\nSourceGraph print:\n" + "-".repeat(100) + "\n" + this.graph.print() + "-".repeat(100));
log("\n\nFlowGraph print:\n" + "-".repeat(100) + "\n" + this.graph.print() + "-".repeat(100)); System.out.println("Graph-generation successful.");
System.out.println("Code-generation successful.");
return this.graph; return this.graph;
} }
@ -125,7 +122,7 @@ public final class SourceGraphGenerator {
// ifeq - if value is 0 // ifeq - if value is 0
// ifne - if value is not 0 // ifne - if value is not 0
private void cond(ASTNode node) { private void condNode(ASTNode node) {
final int currentLabel = this.labelCounter; final int currentLabel = this.labelCounter;
this.labelCounter++; this.labelCounter++;
@ -151,7 +148,7 @@ public final class SourceGraphGenerator {
this.graph.addLabel("IFend" + currentLabel); this.graph.addLabel("IFend" + currentLabel);
} }
private void loop(ASTNode node) { private void loopNode(ASTNode node) {
final int currentLabel = this.labelCounter; final int currentLabel = this.labelCounter;
this.labelCounter++; this.labelCounter++;
@ -171,7 +168,7 @@ public final class SourceGraphGenerator {
this.graph.addLabel("LOOPend" + currentLabel); this.graph.addLabel("LOOPend" + currentLabel);
} }
private void assign(ASTNode node) { //! Stack - 1 private void assignNode(ASTNode node) { //! Stack - 1
this.generateNode(node.getChildren().get(0)); this.generateNode(node.getChildren().get(0));
final String type = this.nodeTypeMap.get(node.getChildren().get(0)); final String type = this.nodeTypeMap.get(node.getChildren().get(0));
@ -186,7 +183,7 @@ public final class SourceGraphGenerator {
this.graph.addInst(inst, this.varMap.get(node.getValue()).toString()); this.graph.addInst(inst, this.varMap.get(node.getValue()).toString());
} }
private void expr(ASTNode node) { private void exprNode(ASTNode node) {
if ("INTEGER_TYPE".equals(this.nodeTypeMap.get(node))) { if ("INTEGER_TYPE".equals(this.nodeTypeMap.get(node))) {
this.intExpr(node); this.intExpr(node);
} else if ("BOOLEAN_TYPE".equals(this.nodeTypeMap.get(node))) { } else if ("BOOLEAN_TYPE".equals(this.nodeTypeMap.get(node))) {
@ -289,14 +286,14 @@ public final class SourceGraphGenerator {
// Leafs // Leafs
private void intStringLiteral(ASTNode node) { //! Stack + 1 private void intStringLiteralNode(ASTNode node) { //! Stack + 1
log("literal(): " + node.getName() + ": " + node.getValue() + " => ldc"); log("intStringLiteral(): " + node.getName() + ": " + node.getValue() + " => ldc");
// bipush only pushes 1 byte as int // bipush only pushes 1 byte as int
this.graph.addInst("ldc", node.getValue()); this.graph.addInst("ldc", node.getValue());
} }
private void boolLiteral(ASTNode node) { //! Stack + 1 private void boolLiteralNode(ASTNode node) { //! Stack + 1
log("booleanLiteral(): " + node.getName() + ": " + node.getValue() + " => ldc"); log("booleanLiteral(): " + node.getName() + ": " + node.getValue() + " => ldc");
final String val = "true".equals(node.getValue()) ? "1" : "0"; final String val = "true".equals(node.getValue()) ? "1" : "0";
@ -304,7 +301,7 @@ public final class SourceGraphGenerator {
this.graph.addInst("ldc", val); this.graph.addInst("ldc", val);
} }
private void identifier(ASTNode node) { //! Stack + 1 private void identifierNode(ASTNode node) { //! Stack + 1
final String type = this.nodeTypeMap.get(node); final String type = this.nodeTypeMap.get(node);
final String inst = switch (type) { final String inst = switch (type) {
case "INTEGER_TYPE", "BOOLEAN_TYPE" -> "iload"; case "INTEGER_TYPE", "BOOLEAN_TYPE" -> "iload";
@ -317,7 +314,7 @@ public final class SourceGraphGenerator {
this.graph.addInst(inst, this.varMap.get(node.getValue()).toString()); this.graph.addInst(inst, this.varMap.get(node.getValue()).toString());
} }
private void println(ASTNode node) { //! Stack + 1 private void printlnNode(ASTNode node) { //! Stack + 1
this.graph.addInst("getstatic", "java/lang/System/out", "Ljava/io/PrintStream;"); 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);

View File

@ -243,7 +243,7 @@ class SourceGraphGeneratorTest {
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 SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, "TestOutpu"); final SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, "TestOutpu");
final SourceGraph srcProg = gen.generateCode(); final SourceGraph srcProg = gen.generateGraph();
compileJasmin(srcProg.toString()); compileJasmin(srcProg.toString());
assertThat(Integer.parseInt(executeCompiledProgram())).isEqualTo(result); assertThat(Integer.parseInt(executeCompiledProgram())).isEqualTo(result);
@ -258,7 +258,7 @@ class SourceGraphGeneratorTest {
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 SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, "TestOutput"); final SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, "TestOutput");
final SourceGraph srcProg = gen.generateCode(); final SourceGraph srcProg = gen.generateGraph();
compileJasmin(srcProg.toString()); compileJasmin(srcProg.toString());
assertThat(Integer.parseInt(executeCompiledProgram())).isEqualTo(result); assertThat(Integer.parseInt(executeCompiledProgram())).isEqualTo(result);
@ -273,7 +273,7 @@ class SourceGraphGeneratorTest {
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 SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, "TestOutput"); final SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, "TestOutput");
final SourceGraph srcProg = gen.generateCode(); final SourceGraph srcProg = gen.generateGraph();
compileJasmin(srcProg.toString()); compileJasmin(srcProg.toString());
assertThat(Boolean.parseBoolean(executeCompiledProgram())).isEqualTo(result); assertThat(Boolean.parseBoolean(executeCompiledProgram())).isEqualTo(result);
@ -288,7 +288,7 @@ class SourceGraphGeneratorTest {
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 SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, "TestOutput"); final SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, "TestOutput");
final SourceGraph srcProg = gen.generateCode(); final SourceGraph srcProg = gen.generateGraph();
compileJasmin(srcProg.toString()); compileJasmin(srcProg.toString());
assertThat(executeCompiledProgram()).isEqualTo(result); assertThat(executeCompiledProgram()).isEqualTo(result);
@ -303,7 +303,7 @@ class SourceGraphGeneratorTest {
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 SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, "TestOutput"); final SourceGraphGenerator gen = SourceGraphGenerator.fromAST(tree, nodeTable, "TestOutput");
final SourceGraph srcProg = gen.generateCode(); final SourceGraph srcProg = gen.generateGraph();
compileJasmin(srcProg.toString()); compileJasmin(srcProg.toString());
assertThat(executeCompiledProgram()).isEqualTo(result); assertThat(executeCompiledProgram()).isEqualTo(result);