aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-11-26 16:45:51 +0000
committerMichael Williamson <mike@zwobble.org>2023-11-26 16:45:51 +0000
commitaa13c97dac536bd1c4bf2f4e5c6ee505a487c634 (patch)
tree61fe8650b0579aa5dc5b55fb50b41eff6c3470d6 /src/main/java
parentee02a8cd9af3b2ae723cbba9a910fc159fe75a7c (diff)
Support Patio exceptions in Patio Wasm backend
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/org/shedlang/compiler/backends/wasm/WasmPatioCodeGen.java109
1 files changed, 106 insertions, 3 deletions
diff --git a/src/main/java/org/shedlang/compiler/backends/wasm/WasmPatioCodeGen.java b/src/main/java/org/shedlang/compiler/backends/wasm/WasmPatioCodeGen.java
index 1447ee14..585de4e6 100644
--- a/src/main/java/org/shedlang/compiler/backends/wasm/WasmPatioCodeGen.java
+++ b/src/main/java/org/shedlang/compiler/backends/wasm/WasmPatioCodeGen.java
@@ -337,18 +337,36 @@ public class WasmPatioCodeGen {
yield context;
}
- case PatioThrow throw_ ->
- throw new UnsupportedOperationException("TODO");
+ case PatioThrow throw_ -> {
+ context = generateOperand(throw_.value(), context);
+
+ context = context.addInstruction(new WasmThrow(new WasmTagName(throw_.exceptionTypeName())));
+
+ yield context;
+ }
case PatioTry try_ -> {
+ context = context.enterTryInstruction(
+ new WasmBlockType(List.of(WasmValueType.I32))
+ );
+
context = generateBlockBody(try_.body(), context);
+ for (var catchClause : try_.catchClauses()) {
+ context = context.enterCatch(new WasmTagName(catchClause.exceptionTypeName()));
+
+ // TODO: pop into local for catch
+ context = context.addInstruction(new WasmDrop());
+ context = generateBlockBody(catchClause.body(), context);
+ }
+
+ context = context.exitTryInstruction();
+
context = popIntoPatioLocals(try_.targets(), context);
yield context;
}
-
case PatioUnreachable patioUnreachable ->
context.addInstruction(new WasmUnreachable());
@@ -732,6 +750,33 @@ public class WasmPatioCodeGen {
return exitStructuredInstruction();
}
+ public Context enterTryInstruction(WasmBlockType blockType) {
+ return new Context(
+ this.module,
+ P.vector(),
+ this.instructionsStack.plus(this.instructions),
+ this.patioLocalNameToWasmLocalIndex,
+ new WasmTryInstructionBuilder(blockType),
+ this.structuredInstructionBuilderStack.plus(this.structuredInstructionBuilder)
+ );
+ }
+
+ public Context enterCatch(WasmTagName tagName) {
+ return new Context(
+ this.module,
+ P.vector(),
+ this.instructionsStack,
+ this.patioLocalNameToWasmLocalIndex,
+ this.structuredInstructionBuilder.enterCatch(tagName, this.instructions),
+ this.structuredInstructionBuilderStack
+ );
+ }
+
+ public Context exitTryInstruction() {
+ // TODO: verify matching enter/exit?
+ return exitStructuredInstruction();
+ }
+
public Context exitStructuredInstruction() {
var context = new Context(
this.module,
@@ -775,6 +820,13 @@ public class WasmPatioCodeGen {
default WasmStructuredInstructionBuilder enterElse(PVector<WasmInstruction> instructions) {
throw new UnsupportedOperationException();
}
+
+ default WasmStructuredInstructionBuilder enterCatch(
+ WasmTagName tagName,
+ PVector<WasmInstruction> instructions
+ ) {
+ throw new UnsupportedOperationException();
+ }
}
private static class NullStructuredInstructionBuilder implements WasmStructuredInstructionBuilder {
@@ -821,4 +873,55 @@ public class WasmPatioCodeGen {
return new WasmIf(blockType, ifTrue, instructions);
}
}
+
+ private record WasmTryInstructionBuilder(
+ WasmBlockType blockType
+ ) implements WasmStructuredInstructionBuilder {
+ @Override
+ public WasmInstruction exit(PVector<WasmInstruction> instructions) {
+ return new WasmTry(blockType, List.of(), instructions);
+ }
+
+ @Override
+ public WasmStructuredInstructionBuilder enterCatch(
+ WasmTagName tagName,
+ PVector<WasmInstruction> instructions
+ ) {
+ return new WasmTryCatchInstructionBuilder(
+ blockType,
+ instructions,
+ tagName,
+ P.vector()
+ );
+ }
+ }
+
+ private record WasmTryCatchInstructionBuilder(
+ WasmBlockType blockType,
+ List<WasmInstruction> tryBodyInstructions,
+ WasmTagName tagName,
+ PVector<WasmCatchBlock> catchBlocks
+ ) implements WasmStructuredInstructionBuilder {
+ @Override
+ public WasmInstruction exit(PVector<WasmInstruction> instructions) {
+ return new WasmTry(
+ this.blockType,
+ this.catchBlocks.plus(new WasmCatchBlock(this.tagName, instructions)),
+ this.tryBodyInstructions
+ );
+ }
+
+ @Override
+ public WasmStructuredInstructionBuilder enterCatch(
+ WasmTagName tagName,
+ PVector<WasmInstruction> instructions
+ ) {
+ return new WasmTryCatchInstructionBuilder(
+ this.blockType,
+ this.tryBodyInstructions,
+ tagName,
+ this.catchBlocks.plus(new WasmCatchBlock(this.tagName, instructions))
+ );
+ }
+ }
}