make codegen completely static

This commit is contained in:
Christoph
2021-01-21 18:20:32 +01:00
parent 049f2529d4
commit f9eb73630f
2 changed files with 36 additions and 35 deletions

View File

@ -76,8 +76,7 @@ public final class StupsCompiler {
// Codegeneration + Output // Codegeneration + Output
final String outputName = filename.replaceFirst("stups", "j"); final String outputName = filename.replaceFirst("stups", "j");
final CodeGenerator generator = CodeGenerator.fromAST(tree); final StringBuilder jasmin = CodeGenerator.generateCode(tree, filename);
final StringBuilder jasmin = generator.generateCode(tree, filename);
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, jasmin.toString());

View File

@ -23,11 +23,11 @@ public final class CodeGenerator {
try { try {
final Class<?> gen = CodeGenerator.class; final Class<?> gen = CodeGenerator.class;
map = Map.ofEntries( map = Map.ofEntries(
entry("assignment", gen.getDeclaredMethod("assign", ASTNode.class, StringBuilder.class)), entry("assignment", gen.getDeclaredMethod("assign", ASTNode.class, StringBuilder.class, Map.class)),
entry("expr", gen.getDeclaredMethod("expr", ASTNode.class, StringBuilder.class)), entry("expr", gen.getDeclaredMethod("expr", ASTNode.class, StringBuilder.class, Map.class)),
entry("INTEGER_LIT", gen.getDeclaredMethod("literal", ASTNode.class, StringBuilder.class)), entry("INTEGER_LIT", gen.getDeclaredMethod("literal", ASTNode.class, StringBuilder.class, Map.class)),
entry("IDENTIFIER", gen.getDeclaredMethod("identifier", ASTNode.class, StringBuilder.class)), entry("IDENTIFIER", gen.getDeclaredMethod("identifier", ASTNode.class, StringBuilder.class, Map.class)),
entry("print", gen.getDeclaredMethod("println", ASTNode.class, StringBuilder.class)) entry("print", gen.getDeclaredMethod("println", ASTNode.class, StringBuilder.class, Map.class))
); );
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
map = null; map = null;
@ -36,13 +36,9 @@ public final class CodeGenerator {
nodeMap = map; nodeMap = map;
} }
private final Map<String, Integer> varMap; private CodeGenerator() {}
private CodeGenerator(Map<String, Integer> varMap) { private static Map<String, Integer> varMapFromAST(AST tree) {
this.varMap = Collections.unmodifiableMap(varMap);
}
public static CodeGenerator fromAST(AST tree) {
final Map<String, Integer> varMap = new HashMap<>(); final Map<String, Integer> varMap = new HashMap<>();
// Assign variables to map // Assign variables to map
@ -63,7 +59,7 @@ public final class CodeGenerator {
current.getChildren().forEach(stack::push); current.getChildren().forEach(stack::push);
} }
return new CodeGenerator(varMap); return Collections.unmodifiableMap(varMap);
} }
private static void generateHeader(AST ast, String source, StringBuilder jasmin) { private static void generateHeader(AST ast, String source, StringBuilder jasmin) {
@ -91,26 +87,27 @@ public final class CodeGenerator {
Logger.log("Generated Jasmin Init."); Logger.log("Generated Jasmin Init.");
} }
public StringBuilder generateCode(AST ast, String source) { public static StringBuilder generateCode(AST ast, String source) {
final StringBuilder jasmin = new StringBuilder(); final StringBuilder jasmin = new StringBuilder();
final Map<String, Integer> varMap = varMapFromAST(ast);
generateHeader(ast, source, jasmin); generateHeader(ast, source, jasmin);
generateConstructor(jasmin); generateConstructor(jasmin);
this.generateMain(ast, jasmin); generateMain(ast, jasmin, varMap);
Logger.log("Jasmin Assembler:\n" + jasmin); Logger.log("Jasmin Assembler:\n" + jasmin);
return jasmin; return jasmin;
} }
// TODO: Indentation // TODO: Indentation?
// TODO: Stack size // TODO: Stack size
private void generateMain(AST ast, StringBuilder jasmin) { private static void generateMain(AST ast, StringBuilder jasmin, Map<String, Integer> varMap) {
jasmin.append(".method public static main([Ljava/lang/String;)V\n") jasmin.append(".method public static main([Ljava/lang/String;)V\n")
.append(".limit stack 10\n") .append(".limit stack 10\n")
.append(".limit locals ").append(this.varMap.size() + 1).append("\n"); .append(".limit locals ").append(varMap.size() + 1).append("\n");
this.generateNode(ast.getRoot().getChildren().get(3).getChildren().get(11), jasmin); // Skip crap generateNode(ast.getRoot().getChildren().get(3).getChildren().get(11), jasmin, varMap); // Skip crap
jasmin.append("return\n") jasmin.append("return\n")
.append(".end method\n"); .append(".end method\n");
@ -118,32 +115,37 @@ public final class CodeGenerator {
Logger.log("Generated Jasmin Main.\n"); Logger.log("Generated Jasmin Main.\n");
} }
private void generateNode(ASTNode node, StringBuilder jasmin) { private static void generateNode(ASTNode node, StringBuilder jasmin, Map<String, Integer> varMap) {
if (nodeMap.containsKey(node.getName())) { if (nodeMap.containsKey(node.getName())) {
try { try {
nodeMap.get(node.getName()).invoke(this, node, jasmin); nodeMap.get(node.getName()).invoke(null, node, jasmin, varMap);
} catch (IllegalAccessException | InvocationTargetException e) { } catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace(); e.printStackTrace();
} }
} else { } else {
node.getChildren().forEach(child -> this.generateNode(child, jasmin)); node.getChildren().forEach(child -> generateNode(child, jasmin, varMap));
} }
} }
private void assign(ASTNode node, StringBuilder jasmin) { private static void assign(ASTNode node, StringBuilder jasmin, Map<String, Integer> varMap) {
this.generateNode(node.getChildren().get(0), jasmin); generateNode(node.getChildren().get(0), jasmin, varMap);
jasmin.append("istore ") //!: Type dependant jasmin.append("istore ") //!: Type dependant
.append(this.varMap.get(node.getValue())) .append(varMap.get(node.getValue()))
.append("\n"); .append("\n");
} }
private void expr(ASTNode node, StringBuilder jasmin) { // TODO: Unary operators
this.generateNode(node.getChildren().get(0), jasmin); private static void expr(ASTNode node, StringBuilder jasmin, Map<String, Integer> varMap) {
this.generateNode(node.getChildren().get(1), jasmin); generateNode(node.getChildren().get(0), jasmin, varMap);
generateNode(node.getChildren().get(1), jasmin, varMap);
final String inst = switch (node.getValue()) { //!: Type dependant final String inst = switch (node.getValue()) { //!: Type dependant
case "ADD" -> "iadd"; // Integer addition case "ADD" -> "iadd"; // Integer
case "SUB" -> "isub";
case "MUL" -> "imul";
case "DIV" -> "idiv";
case "MOD" -> "irem"; // Remainder operator
default -> throw new IllegalStateException("Unexpected value: " + node.getValue()); default -> throw new IllegalStateException("Unexpected value: " + node.getValue());
}; };
@ -153,24 +155,24 @@ public final class CodeGenerator {
// Leafs // Leafs
private void literal(ASTNode node, StringBuilder jasmin) { private static void literal(ASTNode node, StringBuilder jasmin, Map<String, Integer> varMap) {
jasmin.append("bipush ") //!: Type dependant jasmin.append("bipush ") //!: Type dependant
.append(node.getValue()) .append(node.getValue())
.append("\n"); .append("\n");
} }
private void identifier(ASTNode node, StringBuilder jasmin) { private static void identifier(ASTNode node, StringBuilder jasmin, Map<String, Integer> varMap) {
Logger.log(node.getName() + ": " + node.getValue() + " => iload"); Logger.log(node.getName() + ": " + node.getValue() + " => iload");
jasmin.append("iload ") //!: Type dependent jasmin.append("iload ") //!: Type dependent
.append(this.varMap.get(node.getValue())) .append(varMap.get(node.getValue()))
.append("\n"); .append("\n");
} }
private void println(ASTNode node, StringBuilder jasmin) { private static void println(ASTNode node, StringBuilder jasmin, Map<String, Integer> varMap) {
jasmin.append("getstatic java/lang/System/out Ljava/io/PrintStream;\n"); // Push System.out to stack jasmin.append("getstatic java/lang/System/out Ljava/io/PrintStream;\n"); // Push System.out to stack
this.generateNode(node.getChildren().get(1).getChildren().get(1), jasmin); generateNode(node.getChildren().get(1).getChildren().get(1), jasmin, varMap);
jasmin.append("invokevirtual java/io/PrintStream/println(I)V\n"); //!: Type dependent jasmin.append("invokevirtual java/io/PrintStream/println(I)V\n"); //!: Type dependent
} }