diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-11-26 16:45:51 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-11-26 16:45:51 +0000 |
| commit | aa13c97dac536bd1c4bf2f4e5c6ee505a487c634 (patch) | |
| tree | 61fe8650b0579aa5dc5b55fb50b41eff6c3470d6 /src/main/java | |
| parent | ee02a8cd9af3b2ae723cbba9a910fc159fe75a7c (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.java | 109 |
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)) + ); + } + } } |
