From 76fc235449f03fd76ab9a5bd96d9e8f2aec025c3 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Fri, 14 Jul 2023 21:27:24 +0100 Subject: Add if instruction --- .../compiler/backends/llvm/LlvmCodeGen.java | 3 +++ .../compiler/backends/wasm/WasmCodeGen.java | 3 +++ .../compiler/stackir/InstructionSerializer.java | 27 ++++++++++++-------- .../stackir/instructions/IfInstruction.java | 18 ++++++++++++++ .../compiler/stackir/instructions/Instruction.java | 2 +- .../stackir/InstructionSerializerTests.java | 29 ++++++++++++++++++++++ .../stackir/instructions/Instructions.java | 7 ++++++ 7 files changed, 78 insertions(+), 11 deletions(-) create mode 100644 src/main/java/org/shedlang/compiler/stackir/instructions/IfInstruction.java (limited to 'src') diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGen.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGen.java index e2236dcc..2f20e55b 100644 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGen.java +++ b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmCodeGen.java @@ -147,6 +147,9 @@ public class LlvmCodeGen { yield context.push(fieldValue); } + case IfInstruction if_ -> + throw new UnsupportedOperationException("TODO"); + case IntAddInstruction intAdd -> generateBinaryOperation( (target, left, right, operationContext) -> diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGen.java b/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGen.java index a9ee98ac..e7ebff16 100644 --- a/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGen.java +++ b/src/main/java/org/shedlang/compiler/backends/wasm/WasmCodeGen.java @@ -179,6 +179,9 @@ public class WasmCodeGen { ); } + case IfInstruction if_ -> + throw new UnsupportedOperationException("TODO"); + case IntAddInstruction intAdd -> context.addInstruction(new WasmI32Add()); diff --git a/src/main/java/org/shedlang/compiler/stackir/InstructionSerializer.java b/src/main/java/org/shedlang/compiler/stackir/InstructionSerializer.java index baaf4b49..17d778df 100644 --- a/src/main/java/org/shedlang/compiler/stackir/InstructionSerializer.java +++ b/src/main/java/org/shedlang/compiler/stackir/InstructionSerializer.java @@ -12,11 +12,7 @@ public class InstructionSerializer { } public static void serializeInstructions(List instructions, StringBuilder builder) { - var tree = treeListIndented( - instructions.stream() - .map(instruction -> toTree(instruction)) - .toList() - ); + var tree = instructionsToTree(instructions); serializeTree(tree, builder, 0); } @@ -25,6 +21,14 @@ public class InstructionSerializer { serializeTree(tree, builder, 0); } + private static Tree instructionsToTree(List instructions) { + return treeListIndented( + instructions.stream() + .map(instruction -> toTree(instruction)) + .toList() + ); + } + private static Tree toTree(Instruction instruction) { return switch (instruction) { case CallInstruction callInstruction -> @@ -63,11 +67,7 @@ public class InstructionSerializer { .map(freeVariable -> treeString(freeVariable.name())) .toList() )), - treeNamed("body", treeListIndented( - defineFunctionInstruction.body().stream() - .map(bodyInstruction -> toTree(bodyInstruction)) - .toList() - )) + treeNamed("body", instructionsToTree(defineFunctionInstruction.body())) ); case DiscardInstruction discardInstruction -> @@ -82,6 +82,13 @@ public class InstructionSerializer { treeString(fieldLoad.fieldName()) ); + case IfInstruction if_ -> + treeListIndented( + treeIdentifier("if"), + instructionsToTree(if_.trueBody()), + instructionsToTree(if_.falseBody()) + ); + case IntAddInstruction intAdd -> treeList(treeIdentifier("int-add")); diff --git a/src/main/java/org/shedlang/compiler/stackir/instructions/IfInstruction.java b/src/main/java/org/shedlang/compiler/stackir/instructions/IfInstruction.java new file mode 100644 index 00000000..df09859f --- /dev/null +++ b/src/main/java/org/shedlang/compiler/stackir/instructions/IfInstruction.java @@ -0,0 +1,18 @@ +package org.shedlang.compiler.stackir.instructions; + + +import org.shedlang.compiler.sources.Source; + +import java.util.List; + +/** + * Pop a value from a stack, and assume it is a Bool. If it is true, execute the + * instructions in the "true" body, otherwise execute the instructions in the + * "false" body. + */ +public record IfInstruction( + List trueBody, + List falseBody, + Source source +) implements Instruction { +} diff --git a/src/main/java/org/shedlang/compiler/stackir/instructions/Instruction.java b/src/main/java/org/shedlang/compiler/stackir/instructions/Instruction.java index a1ab0a39..80593264 100644 --- a/src/main/java/org/shedlang/compiler/stackir/instructions/Instruction.java +++ b/src/main/java/org/shedlang/compiler/stackir/instructions/Instruction.java @@ -3,7 +3,7 @@ package org.shedlang.compiler.stackir.instructions; import org.shedlang.compiler.sources.Source; public sealed interface Instruction - permits CallInstruction, DefineFunctionInstruction, DiscardInstruction, FieldLoadInstruction, IntAddInstruction, IntEqualsInstruction, IntNotEqualInstruction, IntSubInstruction, LocalLoadInstruction, LocalStoreInstruction, NamespaceFieldStoreInstruction, NamespaceImportInstruction, PushBoolInstruction, PushIntInstruction, PushStringInstruction, PushUnitInstruction, ReturnInstruction, StringAddInstruction { + permits CallInstruction, DefineFunctionInstruction, DiscardInstruction, FieldLoadInstruction, IfInstruction, IntAddInstruction, IntEqualsInstruction, IntNotEqualInstruction, IntSubInstruction, LocalLoadInstruction, LocalStoreInstruction, NamespaceFieldStoreInstruction, NamespaceImportInstruction, PushBoolInstruction, PushIntInstruction, PushStringInstruction, PushUnitInstruction, ReturnInstruction, StringAddInstruction { Source source(); } diff --git a/src/test/java/org/shedlang/compiler/stackir/InstructionSerializerTests.java b/src/test/java/org/shedlang/compiler/stackir/InstructionSerializerTests.java index 3ce690b2..72056a3e 100644 --- a/src/test/java/org/shedlang/compiler/stackir/InstructionSerializerTests.java +++ b/src/test/java/org/shedlang/compiler/stackir/InstructionSerializerTests.java @@ -75,6 +75,35 @@ public class InstructionSerializerTests { assertThat(string, equalTo("(field-load \"Example/Lib\" \"x\")")); } + @Test + public void canSerializeIf() { + var instruction = Instructions.if_( + List.of( + Instructions.pushUnit() + ), + List.of( + Instructions.localLoad("x"), + Instructions.discard(), + Instructions.pushBool(true) + ) + ); + + var string = serialize(instruction); + + assertThat(string, equalTo(""" + ( + if + ( + (push-unit) + ) + ( + (local-load "x") + (discard) + (push-bool true) + ) + )""")); + } + @Test public void canSerializeIntAdd() { var instruction = Instructions.intAdd(); diff --git a/src/test/java/org/shedlang/compiler/stackir/instructions/Instructions.java b/src/test/java/org/shedlang/compiler/stackir/instructions/Instructions.java index df8b193b..131207b8 100644 --- a/src/test/java/org/shedlang/compiler/stackir/instructions/Instructions.java +++ b/src/test/java/org/shedlang/compiler/stackir/instructions/Instructions.java @@ -22,6 +22,13 @@ public class Instructions { return new FieldLoadInstruction(namespaceName, fieldName, Sources.NULL); } + public static Instruction if_( + List trueBody, + List falseBody + ) { + return new IfInstruction(trueBody, falseBody, Sources.NULL); + } + public static Instruction intAdd() { return new IntAddInstruction(Sources.NULL); } -- cgit v1.2.3