From 79fc3dd706b968a9249dfd2db6b5175e4e4a85d4 Mon Sep 17 00:00:00 2001 From: Elias Haugsbakk Date: Sun, 20 Sep 2026 21:07:25 +0200 Subject: update IRGeneration generates records. Variables implemented. --- .../IRGeneration/IRGenerationException.java | 7 +++ .../kompilator/IRGeneration/IRGenerator.java | 60 ++++++++++++++++++---- .../kompilator/IRGeneration/Instr.java | 33 ++++++++++++ .../kompilator/IRGeneration/IRGeneratorTest.java | 17 +++--- 4 files changed, 97 insertions(+), 20 deletions(-) create mode 100644 src/main/java/no/eliashaugsbakk/kompilator/IRGeneration/IRGenerationException.java create mode 100644 src/main/java/no/eliashaugsbakk/kompilator/IRGeneration/Instr.java (limited to 'src') diff --git a/src/main/java/no/eliashaugsbakk/kompilator/IRGeneration/IRGenerationException.java b/src/main/java/no/eliashaugsbakk/kompilator/IRGeneration/IRGenerationException.java new file mode 100644 index 0000000..ab881a0 --- /dev/null +++ b/src/main/java/no/eliashaugsbakk/kompilator/IRGeneration/IRGenerationException.java @@ -0,0 +1,7 @@ +package no.eliashaugsbakk.kompilator.IRGeneration; + +public class IRGenerationException extends RuntimeException { + public IRGenerationException(String message) { + super(message); + } +} diff --git a/src/main/java/no/eliashaugsbakk/kompilator/IRGeneration/IRGenerator.java b/src/main/java/no/eliashaugsbakk/kompilator/IRGeneration/IRGenerator.java index ffbccb6..1c42673 100644 --- a/src/main/java/no/eliashaugsbakk/kompilator/IRGeneration/IRGenerator.java +++ b/src/main/java/no/eliashaugsbakk/kompilator/IRGeneration/IRGenerator.java @@ -6,49 +6,87 @@ import no.eliashaugsbakk.kompilator.parsing.AST; import no.eliashaugsbakk.kompilator.parsing.node.Program; import no.eliashaugsbakk.kompilator.parsing.node.expression.Expression; import no.eliashaugsbakk.kompilator.parsing.node.expression.FunctionCall; +import no.eliashaugsbakk.kompilator.parsing.node.expression.Identifier; import no.eliashaugsbakk.kompilator.parsing.node.expression.literal.StringLiteral; +import no.eliashaugsbakk.kompilator.parsing.node.statement.Assignment; import no.eliashaugsbakk.kompilator.parsing.node.statement.ExpressionStatement; +import no.eliashaugsbakk.kompilator.parsing.node.statement.IdentifierDeclaration; import no.eliashaugsbakk.kompilator.parsing.node.statement.Statement; public class IRGenerator { private final AST ast; - private final List ir = new ArrayList<>(); - private int tempVarCounter = 0; + private final List ir = new ArrayList<>(); + private int tempCounter = 0; public IRGenerator(AST ast) { this.ast = ast; } - public List generate() { + public List generate() { Program program = (Program) ast.getRoot(); for (Statement stmt : program.statements) { generateStatement(stmt); } - return ir; } private void generateStatement(Statement stmt) { if (stmt instanceof ExpressionStatement exprStmt) { generateExpression(exprStmt.expression); + } else if (stmt instanceof Assignment assignment) { + generateAssignment(assignment); + } else if (stmt instanceof IdentifierDeclaration identifierDecl) { + generateIdentifierDecl(identifierDecl); + } + } + + private void generateAssignment(Assignment assignment) { + String value; + if (assignment.expression instanceof StringLiteral stringLiteral) { + value = stringLiteral.value; + } else { + throw new IRGenerationException("Only strings are implemented"); } + ir.add(new Assign(assignment.identifier, value)); + } + + private void generateIdentifierDecl(IdentifierDeclaration identifierDecl) { + String value; + if (identifierDecl.initializer instanceof StringLiteral stringLiteral) { + value = stringLiteral.value; + } else { + throw new IRGenerationException("Unknown function: " + identifierDecl.initializer); + } + ir.add(new Alloc(identifierDecl.identifier, identifierDecl.type.type, identifierDecl.mutable, + value)); } private void generateExpression(Expression expr) { if (expr instanceof FunctionCall call) { generateFunctionCall(call); + } else { + throw new IRGenerationException("Only expression which can stand alone are functions"); } } - private void generateFunctionCall(FunctionCall call) { - for (Expression arg : call.arguments) { - if (arg instanceof StringLiteral stringLit) { - String tempVar = "t" + (tempVarCounter++); - ir.add(tempVar + ": string = \"" + stringLit.value + "\""); - ir.add(String.format("print(%s)", tempVar)); + + private void generateFunctionCall(FunctionCall fnCall) { + List arguments = new ArrayList<>(); + + fnCall.arguments.forEach(arg -> { + if (arg instanceof StringLiteral stringLiteral) { + String temp = "t" + tempCounter++; + ir.add(new Alloc(temp, "string", false, stringLiteral.value)); + arguments.add(temp); + } else if (arg instanceof Identifier identifier) { + arguments.add(identifier.name); + } else { + throw new IRGenerationException("Unknown function: " + arg); } - } + }); + + ir.add(new Call(fnCall.functionName, arguments)); } } diff --git a/src/main/java/no/eliashaugsbakk/kompilator/IRGeneration/Instr.java b/src/main/java/no/eliashaugsbakk/kompilator/IRGeneration/Instr.java new file mode 100644 index 0000000..09ed4f6 --- /dev/null +++ b/src/main/java/no/eliashaugsbakk/kompilator/IRGeneration/Instr.java @@ -0,0 +1,33 @@ +package no.eliashaugsbakk.kompilator.IRGeneration; + +import java.util.List; + +public sealed interface Instr permits Alloc, Assign, Call { +} + + +// allocate a new variable: set x: string = "Hello"; mut y: string?; +// +// Alloc("x", "string", false, "Hello") // Alloc("y", "string", true, "null") +record Alloc(String name, String type, boolean mutable, String initializer) implements Instr { + @Override + public String toString() { + return "Alloc[name=" + name + ", type=" + type + ", mutable=" + mutable + ", initializer=\"" + initializer + "\"]"; + } +} + + +// assign a value to a variable: x = "Hello"; +// Assign("x", "Hello") +record Assign(String name, String value) implements Instr { + @Override + public String toString() { + return "Assign[name=" + name + ", value=\"" + value + "\"]"; + } +} + + +// call a function: skriv("hello"); +// Call("skriv", ["t1"]) +record Call(String fn, List args) implements Instr { +} diff --git a/src/test/java/no/eliashaugsbakk/kompilator/IRGeneration/IRGeneratorTest.java b/src/test/java/no/eliashaugsbakk/kompilator/IRGeneration/IRGeneratorTest.java index fdaab26..232b8f3 100644 --- a/src/test/java/no/eliashaugsbakk/kompilator/IRGeneration/IRGeneratorTest.java +++ b/src/test/java/no/eliashaugsbakk/kompilator/IRGeneration/IRGeneratorTest.java @@ -15,11 +15,11 @@ class IRGeneratorTest { @Test void singlePrintStatementGeneratesCorrectIR() { AST ast = buildAST("skriv", "hello"); - List ir = new IRGenerator(ast).generate(); + List ir = new IRGenerator(ast).generate(); assertEquals(2, ir.size()); - assertEquals("t0: string = \"hello\"", ir.get(0)); - assertEquals("print(t0)", ir.get(1)); + assertEquals(new Alloc("t0", "string", false, "hello"), ir.get(0)); + assertEquals(new Call("skriv", List.of("t0")), ir.get(1)); } @Test @@ -28,14 +28,13 @@ class IRGeneratorTest { program.addStatement(buildStatement("skriv", "hello")); program.addStatement(buildStatement("skriv", "world")); - AST ast = new AST(program); - List ir = new IRGenerator(ast).generate(); + List ir = new IRGenerator(new AST(program)).generate(); assertEquals(4, ir.size()); - assertEquals("t0: string = \"hello\"", ir.get(0)); - assertEquals("print(t0)", ir.get(1)); - assertEquals("t1: string = \"world\"", ir.get(2)); - assertEquals("print(t1)", ir.get(3)); + assertEquals(new Alloc("t0", "string", false, "hello"), ir.get(0)); + assertEquals(new Call("skriv", List.of("t0")), ir.get(1)); + assertEquals(new Alloc("t1", "string", false, "world"), ir.get(2)); + assertEquals(new Call("skriv", List.of("t1")), ir.get(3)); } private AST buildAST(String functionName, String argument) { -- cgit v1.2.3