From 8decaba8f75d16550d5f0e6caf9ddaff18dad38a Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sun, 3 Dec 2023 18:13:30 +0000 Subject: Support exception handler method break --- .../compiler/backends/llvm/LlvmPatioCodeGen.java | 3 + .../org/shedlang/compiler/patio/PatioCodeGen.java | 25 ++++++++- .../compiler/patio/PatioCodeGenContext.java | 6 ++ .../compiler/patio/PatioCodeGenEffects.java | 64 +++++++++++++++++++--- .../patio/ast/instructions/PatioBlock.java | 8 +++ 5 files changed, 97 insertions(+), 9 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmPatioCodeGen.java b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmPatioCodeGen.java index 37cda648..097eb2d8 100644 --- a/src/main/java/org/shedlang/compiler/backends/llvm/LlvmPatioCodeGen.java +++ b/src/main/java/org/shedlang/compiler/backends/llvm/LlvmPatioCodeGen.java @@ -633,6 +633,9 @@ public class LlvmPatioCodeGen { ) )); + // TODO: construct a test for this in PatioExampleTests + context = context.addTerminatorInstruction(new LlvmUnreachable()); + yield context; } diff --git a/src/main/java/org/shedlang/compiler/patio/PatioCodeGen.java b/src/main/java/org/shedlang/compiler/patio/PatioCodeGen.java index 733152b4..a555d181 100644 --- a/src/main/java/org/shedlang/compiler/patio/PatioCodeGen.java +++ b/src/main/java/org/shedlang/compiler/patio/PatioCodeGen.java @@ -309,7 +309,18 @@ public class PatioCodeGen { } case ShedEffectHandlerBreak effectHandlerBreak -> { - throw new UnsupportedOperationException("TODO"); + var valueResult = context.temporaryPop(); + var value = valueResult.value(); + context = valueResult.context(); + + context = PatioCodeGenEffects.break_( + effectHandlerBreak.effect(), + value, + effectHandlerBreak.source(), + context + ); + + yield context; } case ShidFieldLoad fieldLoad -> { @@ -668,15 +679,25 @@ public class PatioCodeGen { handlerMethodsByName.put(handlerMethodName, handlerMethod); } + var targetResult = context.allocateVal( + PatioCodeGenLocalSpace.TEMPORARY, + PatioCodeGenTypes.VALUE_TYPE + ); + var target = targetResult.value(); + context = targetResult.context(); + context = PatioCodeGenEffects.try_( + target, try_.handledEffect(), handlerMethodsByName, bodyContext -> - generateInstructions(try_.body(), bodyContext), + generateBlock(1, try_.body(), try_.source(), bodyContext), try_.source(), context ); + context = context.temporaryPush(target); + yield context; } diff --git a/src/main/java/org/shedlang/compiler/patio/PatioCodeGenContext.java b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenContext.java index 219f9ec1..5dcd91eb 100644 --- a/src/main/java/org/shedlang/compiler/patio/PatioCodeGenContext.java +++ b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenContext.java @@ -708,6 +708,12 @@ public record PatioCodeGenContext( return this.functionContext.stashedEffectHandlerOrThrow(); } + @CheckReturnValue + public String exceptionTypeName(UserDefinedEffect effect) { + // TODO: Allocate properly + return "shed__effect__exception__" + String.join("_", effect.namespaceName().parts()) + "__" + effect.name(); + } + @CheckReturnValue private PatioCodeGenContext withCompilationUnitContext(CompilationUnitContext compilationUnitContext) { return new PatioCodeGenContext(this.globalContext, compilationUnitContext, this.blockStack, this.functionContext); diff --git a/src/main/java/org/shedlang/compiler/patio/PatioCodeGenEffects.java b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenEffects.java index 74073b2f..4dbb7438 100644 --- a/src/main/java/org/shedlang/compiler/patio/PatioCodeGenEffects.java +++ b/src/main/java/org/shedlang/compiler/patio/PatioCodeGenEffects.java @@ -1,6 +1,7 @@ package org.shedlang.compiler.patio; import org.shedlang.compiler.ast.typed.FreeVariables; +import org.shedlang.compiler.patio.ast.PatioExceptionTypeDefinition; import org.shedlang.compiler.patio.ast.PatioFunctionDeclaration; import org.shedlang.compiler.patio.ast.PatioLocal; import org.shedlang.compiler.patio.ast.PatioVisibility; @@ -13,9 +14,9 @@ import org.shedlang.compiler.patio.ast.types.PatioDataLayout; import org.shedlang.compiler.patio.ast.types.PatioDataLayouts; import org.shedlang.compiler.patio.ast.types.PatioType; import org.shedlang.compiler.patio.ast.types.PatioTypes; +import org.shedlang.compiler.shid.instructions.ShidDefineFunction; import org.shedlang.compiler.sources.Source; import org.shedlang.compiler.sources.Sources; -import org.shedlang.compiler.shid.instructions.ShidDefineFunction; import org.shedlang.compiler.types.UserDefinedEffect; import org.shedlang.compiler.util.Lists; @@ -116,6 +117,12 @@ public class PatioCodeGenEffects { Source source, PatioCodeGenContext context ) { + context = context.addCompilationUnitElement(new PatioExceptionTypeDefinition( + context.exceptionTypeName(effect), + PatioCodeGenTypes.VALUE_TYPE, + source + )); + var effectPointerResult = context.allocateVal( PatioCodeGenLocalSpace.USER_DEFINED_EFFECT_POINTER, effect.name(), @@ -264,9 +271,10 @@ public class PatioCodeGenEffects { } public static PatioCodeGenContext try_( + PatioLocalRef target, UserDefinedEffect effect, Map handlerMethodsByName, - Function generateBody, + Function> generateBody, Source source, PatioCodeGenContext context ) { @@ -307,12 +315,37 @@ public class PatioCodeGenEffects { )); } - context = generateBody.apply(context); + var bodyResult = generateBody.apply(context); + var body = bodyResult.value(); + context = bodyResult.context(); - context = context.addInstruction(new PatioCall( - Optional.empty(), - POP_HANDLER_DECLARATION.name(), - List.of(), + var exceptionValueResult = context.allocateVal( + PatioCodeGenLocalSpace.TEMPORARY, + PatioCodeGenTypes.VALUE_TYPE + ); + var exceptionValue = exceptionValueResult.value(); + context = exceptionValueResult.context(); + + context = context.addInstruction(new PatioTry( + List.of(target), + List.of( + new PatioCatchClause( + context.exceptionTypeName(effect), + exceptionValue, + new PatioBlock( + List.of(), + List.of(exceptionValue), + source + ), + source + ) + ), + body.addInstruction(new PatioCall( + Optional.empty(), + POP_HANDLER_DECLARATION.name(), + List.of(), + source + )), source )); @@ -472,6 +505,23 @@ public class PatioCodeGenEffects { return context; } + public static PatioCodeGenContext break_( + UserDefinedEffect effect, + PatioOperand value, + Source source, + PatioCodeGenContext context + ) { + var exceptionTypeName = context.exceptionTypeName(effect); + + context = context.addInstruction(new PatioThrow( + exceptionTypeName, + value, + source + )); + + return context; + } + private static PatioCodeGenContext getCurrentEffectHandler( PatioLocalRef target, Source source, diff --git a/src/main/java/org/shedlang/compiler/patio/ast/instructions/PatioBlock.java b/src/main/java/org/shedlang/compiler/patio/ast/instructions/PatioBlock.java index 8eecfa84..50c59fbf 100644 --- a/src/main/java/org/shedlang/compiler/patio/ast/instructions/PatioBlock.java +++ b/src/main/java/org/shedlang/compiler/patio/ast/instructions/PatioBlock.java @@ -2,6 +2,7 @@ package org.shedlang.compiler.patio.ast.instructions; import org.shedlang.compiler.patio.ast.operands.PatioOperand; import org.shedlang.compiler.sources.Source; +import org.shedlang.compiler.util.Lists; import java.util.List; @@ -10,4 +11,11 @@ public record PatioBlock( List results, Source source ) { + public PatioBlock addInstruction(PatioInstruction instruction) { + return new PatioBlock( + Lists.concat(this.body, List.of(instruction)), + this.results, + this.source + ); + } } -- cgit v1.2.3