From ffcf99fabf00f21ee48f82c913e2ad06b3b0c395 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Tue, 7 Apr 2026 19:58:08 +0100 Subject: Return multiple values from Patio functions --- .../cranelift/PatioToCraneliftAmd64Tests.java | 2 +- .../shedlang/compiler/patio/PatioExampleTests.java | 43 ++-------------------- .../compiler/patio/PatioSerializerTests.java | 31 +++------------- .../compiler/patio/instructions/Patio.java | 4 +- .../serialization/PatioSerializationTests.java | 16 +------- 5 files changed, 14 insertions(+), 82 deletions(-) (limited to 'src/test/java') diff --git a/src/test/java/org/shedlang/compiler/backends/cranelift/PatioToCraneliftAmd64Tests.java b/src/test/java/org/shedlang/compiler/backends/cranelift/PatioToCraneliftAmd64Tests.java index 3d258e0f..f8814ba7 100644 --- a/src/test/java/org/shedlang/compiler/backends/cranelift/PatioToCraneliftAmd64Tests.java +++ b/src/test/java/org/shedlang/compiler/backends/cranelift/PatioToCraneliftAmd64Tests.java @@ -29,7 +29,7 @@ public class PatioToCraneliftAmd64Tests extends PatioExampleTests { "main", PatioVisibility.PUBLIC, List.of(), - PatioTypes.INT32, + List.of(PatioTypes.INT32), List.of( Patio.call( Optional.empty(), diff --git a/src/test/java/org/shedlang/compiler/patio/PatioExampleTests.java b/src/test/java/org/shedlang/compiler/patio/PatioExampleTests.java index 8267a13a..eed0e9f3 100644 --- a/src/test/java/org/shedlang/compiler/patio/PatioExampleTests.java +++ b/src/test/java/org/shedlang/compiler/patio/PatioExampleTests.java @@ -26,7 +26,6 @@ public abstract class PatioExampleTests { public void intConstCreatesConstantIntValue() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addBodyInstruction(emitInt(Patio.intConst(42))) .addBodyInstruction(Patio.returnVoid()) .build(); @@ -45,7 +44,6 @@ public abstract class PatioExampleTests { public void localsAreStoredByName() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(PatioLocal.val("a", PatioTypes.INT)) .addLocal(PatioLocal.val("b", PatioTypes.INT)) .addBodyInstruction(Patio.localStore(Patio.localRef("a"), Patio.intConst(42))) @@ -76,7 +74,6 @@ public abstract class PatioExampleTests { ); var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addBodyInstruction(Patio.memoryLoad( Patio.localRef("x"), @@ -115,7 +112,6 @@ public abstract class PatioExampleTests { ); var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addBodyInstruction(Patio.memoryLoad( Patio.localRef("x"), @@ -152,7 +148,6 @@ public abstract class PatioExampleTests { ); var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addBodyInstruction(Patio.memoryStore( Patio.dataPtrConst("answer"), @@ -192,7 +187,6 @@ public abstract class PatioExampleTests { ); var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addBodyInstruction(Patio.memoryLoad( Patio.localRef("x"), @@ -226,7 +220,6 @@ public abstract class PatioExampleTests { Patio.localRef("x"), Patio.dataPtrConst(Patio.dataPtrValueNull()) )) - .withReturnType(PatioTypes.VOID) .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of( @@ -248,7 +241,6 @@ public abstract class PatioExampleTests { ); var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addLocal(Patio.val("ptr_int", PatioTypes.INT)) .addLocal(Patio.val("ptr", PatioTypes.DATA_PTR)) @@ -281,7 +273,6 @@ public abstract class PatioExampleTests { public void blockSingleResult() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addBodyInstruction(Patio.block( List.of( @@ -308,7 +299,6 @@ public abstract class PatioExampleTests { public void blockMultipleResults() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addLocal(Patio.val("y", PatioTypes.INT)) .addBodyInstruction(Patio.block( @@ -342,7 +332,6 @@ public abstract class PatioExampleTests { public void ifCanHaveOneResult() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addBodyInstruction(Patio.if_( List.of(Patio.localRef("x")), @@ -366,7 +355,6 @@ public abstract class PatioExampleTests { public void ifCanHaveMultipleResults() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addLocal(Patio.val("y", PatioTypes.INT)) .addBodyInstruction(Patio.if_( @@ -393,7 +381,6 @@ public abstract class PatioExampleTests { public void loopRunsUntilEndIsReachedWithoutContinue() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("c", PatioTypes.BOOL)) .addLocal(Patio.var("x_var", PatioTypes.INT)) .addLocal(Patio.val("x_current", PatioTypes.INT)) @@ -428,7 +415,6 @@ public abstract class PatioExampleTests { public void loopCanExitEarlyWithBreak() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("c", PatioTypes.BOOL)) .addLocal(Patio.var("x_var", PatioTypes.INT)) .addLocal(Patio.val("x_current", PatioTypes.INT)) @@ -464,7 +450,6 @@ public abstract class PatioExampleTests { public void boolToIntToBoolIsIdentityForFalse() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.BOOL)) .addLocal(Patio.val("y", PatioTypes.INT)) .addLocal(Patio.val("z", PatioTypes.BOOL)) @@ -503,7 +488,6 @@ public abstract class PatioExampleTests { public void boolToIntToBoolIsIdentityForTrue() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.BOOL)) .addLocal(Patio.val("y", PatioTypes.INT)) .addLocal(Patio.val("z", PatioTypes.BOOL)) @@ -542,7 +526,6 @@ public abstract class PatioExampleTests { public void intAdd() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addLocal(Patio.val("y", PatioTypes.INT)) .addLocal(Patio.val("z", PatioTypes.INT)) @@ -584,7 +567,6 @@ public abstract class PatioExampleTests { ) throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addLocal(Patio.val("y", PatioTypes.INT)) .addLocal(Patio.val("z_bool", PatioTypes.BOOL)) @@ -631,7 +613,6 @@ public abstract class PatioExampleTests { ) throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addLocal(Patio.val("y", PatioTypes.INT)) .addLocal(Patio.val("z_bool", PatioTypes.BOOL)) @@ -669,7 +650,6 @@ public abstract class PatioExampleTests { public void intSub() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addLocal(Patio.val("y", PatioTypes.INT)) .addLocal(Patio.val("z", PatioTypes.INT)) @@ -702,7 +682,6 @@ public abstract class PatioExampleTests { public void switchWithUnreachableDefault() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addLocal(Patio.val("x1", PatioTypes.INT)) .addLocal(Patio.val("x2", PatioTypes.INT)) @@ -750,7 +729,6 @@ public abstract class PatioExampleTests { public void switchWithReachableDefault() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addLocal(Patio.val("x1", PatioTypes.INT)) .addLocal(Patio.val("x2", PatioTypes.INT)) @@ -791,13 +769,12 @@ public abstract class PatioExampleTests { public void canCallFunctionWithoutArgsDefinedInModule() throws IOException, InterruptedException { var calledFunction = PatioFunctionDefinition.builder() .withName("get") - .withReturnType(PatioTypes.INT) + .addReturnType(PatioTypes.INT) .addBodyInstruction(Patio.return_(Patio.intConst(42))) .build(); var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addBodyInstruction(Patio.call( Optional.of(Patio.localRef("x")), @@ -821,13 +798,12 @@ public abstract class PatioExampleTests { var calledFunction = PatioFunctionDefinition.builder() .withName("identity") .addLocal(PatioLocal.param("x", PatioTypes.INT)) - .withReturnType(PatioTypes.INT) + .addReturnType(PatioTypes.INT) .addBodyInstruction(Patio.return_(Patio.localRef("x"))) .build(); var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addBodyInstruction(Patio.call( Optional.of(Patio.localRef("x")), @@ -850,13 +826,12 @@ public abstract class PatioExampleTests { public void canCallPointerToFunctionDefinedInModule() throws IOException, InterruptedException { var calledFunction = PatioFunctionDefinition.builder() .withName("get") - .withReturnType(PatioTypes.INT) + .addReturnType(PatioTypes.INT) .addBodyInstruction(Patio.return_(Patio.intConst(42))) .build(); var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addBodyInstruction(Patio.callPointer( Patio.localRef("x"), @@ -879,7 +854,6 @@ public abstract class PatioExampleTests { public void whenExceptionIsNotThrownThenTryReturnsFromBody() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("r1", PatioTypes.INT)) .addLocal(Patio.val("r2", PatioTypes.INT)) .addLocal(Patio.val("e1", PatioTypes.INT)) @@ -920,7 +894,6 @@ public abstract class PatioExampleTests { public void whenExceptionIsThrownThenFirstMatchingExceptionHandlerIsUsed() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("r1", PatioTypes.INT)) .addLocal(Patio.val("r2", PatioTypes.INT)) .addLocal(Patio.val("e1", PatioTypes.INT)) @@ -981,7 +954,6 @@ public abstract class PatioExampleTests { public void multipleCatchClausesCanBeAttachedToSameTry() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("r1", PatioTypes.INT)) .addLocal(Patio.val("r2", PatioTypes.INT)) .addLocal(Patio.val("e1", PatioTypes.INT)) @@ -1033,7 +1005,6 @@ public abstract class PatioExampleTests { public void whenExceptionIsThrownThenExceptionHandlerForOtherExceptionsIsIgnored() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("r1", PatioTypes.INT)) .addLocal(Patio.val("r2", PatioTypes.INT)) .addLocal(Patio.val("e1", PatioTypes.INT)) @@ -1095,7 +1066,6 @@ public abstract class PatioExampleTests { public void catchClauseCanThrow() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("r1", PatioTypes.INT)) .addLocal(Patio.val("r2", PatioTypes.INT)) .addLocal(Patio.val("e1", PatioTypes.INT)) @@ -1158,7 +1128,6 @@ public abstract class PatioExampleTests { public void exceptionHandlerIsDiscardedAfterTry() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("r1", PatioTypes.INT)) .addLocal(Patio.val("r2", PatioTypes.INT)) .addLocal(Patio.val("e1", PatioTypes.INT)) @@ -1218,7 +1187,6 @@ public abstract class PatioExampleTests { public void thrownValueIsPassedToCatchClause() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("r", PatioTypes.INT)) .addLocal(Patio.val("e", PatioTypes.INT)) .addBodyInstruction(Patio.try_( @@ -1259,7 +1227,6 @@ public abstract class PatioExampleTests { public void tryCanHaveMultipleResults() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("r1", PatioTypes.INT)) .addLocal(Patio.val("r2", PatioTypes.INT)) .addLocal(Patio.val("e1", PatioTypes.INT)) @@ -1302,7 +1269,6 @@ public abstract class PatioExampleTests { public void vars() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.var("x", PatioTypes.INT)) .addLocal(Patio.val("y", PatioTypes.INT)) .addLocal(Patio.val("z", PatioTypes.INT)) @@ -1344,7 +1310,6 @@ public abstract class PatioExampleTests { public void canGetByteOffsetOf() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addBodyInstruction(Patio.localStore( Patio.localRef("x"), @@ -1383,7 +1348,6 @@ public abstract class PatioExampleTests { public void canGetByteSizeOf() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addBodyInstruction(Patio.localStore( Patio.localRef("x"), @@ -1432,7 +1396,6 @@ public abstract class PatioExampleTests { var emitIntDeclaration = PatioFunctionDeclaration.builder() .withName("patio__test__emit_int") .addParam(PatioLocal.param("value", PatioTypes.INT)) - .withReturnType(PatioTypes.VOID) .build(); var result = executeCompilationUnit(new PatioCompilationUnit( diff --git a/src/test/java/org/shedlang/compiler/patio/PatioSerializerTests.java b/src/test/java/org/shedlang/compiler/patio/PatioSerializerTests.java index 5cf44a1a..76b336ea 100644 --- a/src/test/java/org/shedlang/compiler/patio/PatioSerializerTests.java +++ b/src/test/java/org/shedlang/compiler/patio/PatioSerializerTests.java @@ -19,7 +19,6 @@ public class PatioSerializerTests { public void canSerializeCompilationUnit() { var element = PatioFunctionDefinition.builder() .withName("f") - .withReturnType(PatioTypes.VOID) .build(); var compilationUnit = Patio.compilationUnit(List.of(element)); @@ -32,7 +31,7 @@ public class PatioSerializerTests { "f" visibility=private locals=() - return-type=void + return-types=() body=( ) ) @@ -106,7 +105,7 @@ public class PatioSerializerTests { .withName("f") .addParam(Patio.param("param1", PatioTypes.INT)) .addParam(Patio.param("param2", PatioTypes.DATA_PTR)) - .withReturnType(PatioTypes.VOID) + .addReturnType(PatioTypes.INT32) .build(); var string = PatioTesting.serializeCompilationUnitElement(element); @@ -116,7 +115,7 @@ public class PatioSerializerTests { function-decl "f" params=((param "param1" int) (param "param2" data-ptr)) - return-type=void + return-types=(int32) )""" )); } @@ -130,7 +129,7 @@ public class PatioSerializerTests { .addLocal(Patio.param("param2", PatioTypes.DATA_PTR)) .addLocal(Patio.val("local1", PatioTypes.FUNCTION_PTR)) .addLocal(Patio.val("local2", PatioTypes.INT)) - .withReturnType(PatioTypes.VOID) + .addReturnType(PatioTypes.INT32) .addBodyInstruction(Patio.localStore(Patio.localRef("local2"), Patio.intConst(2))) .build(); @@ -142,7 +141,7 @@ public class PatioSerializerTests { "f" visibility=private locals=((param "param1" int) (param "param2" data-ptr) (val "local1" function-ptr) (val "local2" int)) - return-type=void + return-types=(int32) body=( (local-store (local "local2") (int-const 2)) ) @@ -479,16 +478,7 @@ public class PatioSerializerTests { var string = PatioTesting.serializeInstruction(instruction); - assertThat(string, equalTo("(return (local \"value\"))")); - } - - @Test - public void canSerializeReturnVoid() { - var instruction = Patio.returnVoid(); - - var string = PatioTesting.serializeInstruction(instruction); - - assertThat(string, equalTo("(return-void)")); + assertThat(string, equalTo("(return ((local \"value\")))")); } @Test @@ -889,15 +879,6 @@ public class PatioSerializerTests { assertThat(string, equalTo("int32")); } - @Test - public void canSerializeVoidType() { - var type = PatioTypes.VOID; - - var string = PatioTesting.serializeType(type); - - assertThat(string, equalTo("void")); - } - // == Data layouts == @Test diff --git a/src/test/java/org/shedlang/compiler/patio/instructions/Patio.java b/src/test/java/org/shedlang/compiler/patio/instructions/Patio.java index 5bdd24df..0c0de429 100644 --- a/src/test/java/org/shedlang/compiler/patio/instructions/Patio.java +++ b/src/test/java/org/shedlang/compiler/patio/instructions/Patio.java @@ -299,11 +299,11 @@ public class Patio { } public static PatioInstruction return_(PatioOperand value) { - return new PatioReturn(value, Sources.NULL); + return new PatioReturn(List.of(value), Sources.NULL); } public static PatioInstruction returnVoid() { - return new PatioReturnVoid(Sources.NULL); + return new PatioReturn(List.of(), Sources.NULL); } public static PatioInstruction switch_( diff --git a/src/test/java/org/shedlang/compiler/patio/serialization/PatioSerializationTests.java b/src/test/java/org/shedlang/compiler/patio/serialization/PatioSerializationTests.java index be71c7ce..2f2990bb 100644 --- a/src/test/java/org/shedlang/compiler/patio/serialization/PatioSerializationTests.java +++ b/src/test/java/org/shedlang/compiler/patio/serialization/PatioSerializationTests.java @@ -28,7 +28,6 @@ public abstract class PatioSerializationTests { public void canSerializeCompilationUnit() { var element = PatioFunctionDefinition.builder() .withName("f") - .withReturnType(PatioTypes.VOID) .build(); var compilationUnit = Patio.compilationUnit(List.of(element)); @@ -112,7 +111,7 @@ public abstract class PatioSerializationTests { .withName("f") .addParam(Patio.param("param1", PatioTypes.INT)) .addParam(Patio.param("param2", PatioTypes.DATA_PTR)) - .withReturnType(PatioTypes.VOID) + .addReturnType(PatioTypes.INT32) .build(); var deserializedElement = deserializeCompilationUnitElement( @@ -132,7 +131,7 @@ public abstract class PatioSerializationTests { .addLocal(Patio.param("param2", PatioTypes.DATA_PTR)) .addLocal(Patio.val("local1", PatioTypes.FUNCTION_PTR)) .addLocal(Patio.val("local2", PatioTypes.INT)) - .withReturnType(PatioTypes.VOID) + .addReturnType(PatioTypes.INT32) .addBodyInstruction(Patio.localStore(Patio.localRef("local2"), Patio.intConst(2))) .build(); @@ -868,17 +867,6 @@ public abstract class PatioSerializationTests { assertThat(deserializedType, equalTo(type)); } - @Test - public void canSerializeVoidType() { - var type = PatioTypes.VOID; - - var deserializedType = deserializeType( - serializeType(type) - ); - - assertThat(deserializedType, equalTo(type)); - } - // == Data layouts == protected abstract PatioDataLayout deserializeDataLayout(byte[] buffer); -- cgit v1.2.3