From 1e586f72afa17fc6a956f96c1b163c7a3ac6c2a1 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Mon, 12 Feb 2024 19:23:47 +0000 Subject: Remove reliance on exit code for Patio tests --- .../compiler/backends/llvm/PatioToLlvmTests.java | 26 +-- .../compiler/backends/wasm/PatioToWasmTests.java | 22 +- .../shedlang/compiler/patio/PatioExampleTests.java | 238 +++++++++++++-------- .../shedlang/compiler/patio/PatioTestOutput.java | 9 + 4 files changed, 174 insertions(+), 121 deletions(-) create mode 100644 src/test/java/org/shedlang/compiler/patio/PatioTestOutput.java (limited to 'src/test/java') diff --git a/src/test/java/org/shedlang/compiler/backends/llvm/PatioToLlvmTests.java b/src/test/java/org/shedlang/compiler/backends/llvm/PatioToLlvmTests.java index 2873a855..802287ce 100644 --- a/src/test/java/org/shedlang/compiler/backends/llvm/PatioToLlvmTests.java +++ b/src/test/java/org/shedlang/compiler/backends/llvm/PatioToLlvmTests.java @@ -6,11 +6,11 @@ import org.shedlang.compiler.backends.llvm.ir.ast.LlvmBasicBlock; import org.shedlang.compiler.backends.llvm.ir.ast.LlvmFunctionDefinition; import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmCall; import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmReturn; -import org.shedlang.compiler.backends.llvm.ir.ast.instructions.LlvmTrunc; +import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmOperandInt; import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmVariableGlobal; -import org.shedlang.compiler.backends.llvm.ir.ast.operands.LlvmVariableLocal; import org.shedlang.compiler.backends.llvm.ir.ast.types.LlvmTypes; import org.shedlang.compiler.backends.paths.PartialTargetPath; +import org.shedlang.compiler.filesystem.ShedCompilerFiles; import org.shedlang.compiler.patio.PatioCompilationUnit; import org.shedlang.compiler.patio.PatioExampleTests; import org.shedlang.compiler.testing.ExecutionResult; @@ -24,7 +24,7 @@ import java.util.Optional; public abstract class PatioToLlvmTests extends PatioExampleTests { @Override - protected ExecutionResult run(PatioCompilationUnit patio) throws IOException, InterruptedException { + protected ExecutionResult executeCompilationUnit(PatioCompilationUnit patio) throws IOException, InterruptedException { var llvmModuleResult = PatioToLlvm.generateCompilationUnit( patio, PatioToLlvmGlobalContext.empty(this.llvmTarget()) @@ -40,19 +40,13 @@ public abstract class PatioToLlvmTests extends PatioExampleTests { Optional.empty(), List.of( new LlvmCall( - new LlvmVariableLocal("exitCode"), - LlvmTypes.INT_64, + Optional.empty(), + LlvmTypes.VOID, new LlvmVariableGlobal(FUNCTION_NAME), List.of() - ), - new LlvmTrunc( - new LlvmVariableLocal("exitCode32"), - LlvmTypes.INT_64, - new LlvmVariableLocal("exitCode"), - LlvmTypes.INT_32 ) ), - new LlvmReturn(LlvmTypes.INT_32, new LlvmVariableLocal("exitCode32")) + new LlvmReturn(LlvmTypes.INT_32, new LlvmOperandInt(0)) ) ) )); @@ -69,7 +63,13 @@ public abstract class PatioToLlvmTests extends PatioExampleTests { var executablePath = workingDirectory.resolve("main"); LlvmBackend.forTarget(this.llvmTarget()).link( - List.of(objectFilePath), + List.of( + objectFilePath, + ShedCompilerFiles.getRoot() + .resolve("runtime/target") + .resolve(this.llvmTarget().targetName()) + .resolve("libpatio_test.a") + ), executablePath ); diff --git a/src/test/java/org/shedlang/compiler/backends/wasm/PatioToWasmTests.java b/src/test/java/org/shedlang/compiler/backends/wasm/PatioToWasmTests.java index d3a929e8..ed0380ea 100644 --- a/src/test/java/org/shedlang/compiler/backends/wasm/PatioToWasmTests.java +++ b/src/test/java/org/shedlang/compiler/backends/wasm/PatioToWasmTests.java @@ -3,14 +3,9 @@ package org.shedlang.compiler.backends.wasm; import org.shedlang.compiler.backends.wasm.structure.WasmBinaryFormat; import org.shedlang.compiler.backends.wasm.structure.ast.instructions.WasmCall; import org.shedlang.compiler.backends.wasm.structure.ast.instructions.WasmExpression; -import org.shedlang.compiler.backends.wasm.structure.ast.instructions.WasmI32WrapI64; import org.shedlang.compiler.backends.wasm.structure.ast.instructions.WasmInstruction; import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmFuncName; import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmFunction; -import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmImport; -import org.shedlang.compiler.backends.wasm.structure.ast.modules.WasmImportDescriptor; -import org.shedlang.compiler.backends.wasm.structure.ast.types.WasmFuncType; -import org.shedlang.compiler.backends.wasm.structure.ast.types.WasmValueType; import org.shedlang.compiler.backends.wasm.structure.binary.WasmBinaryFormatTesting; import org.shedlang.compiler.patio.PatioCompilationUnit; import org.shedlang.compiler.patio.PatioExampleTests; @@ -27,19 +22,13 @@ import java.util.List; public abstract class PatioToWasmTests extends PatioExampleTests { @Override - protected ExecutionResult run(PatioCompilationUnit patio) throws IOException, InterruptedException { + protected ExecutionResult executeCompilationUnit(PatioCompilationUnit patio) throws IOException, InterruptedException { var wasmModule = PatioToWasm.generateCompilationUnit(patio, wasmTarget()); wasmModule = WasmBackend.generateNativeRuntime(wasmModule); var body = P.vector(new WasmCall(new WasmFuncName(FUNCTION_NAME))); - if (wasmTarget() == WasmTarget.WASM64) { - body = body.plus(new WasmI32WrapI64()); - } - - body = body.plus(new WasmCall(new WasmFuncName("proc_exit"))); - wasmModule = wasmModule.addFunction(new WasmFunction( "_start", List.of(), @@ -48,15 +37,6 @@ public abstract class PatioToWasmTests extends PatioExampleTests { new WasmExpression(body) )); - wasmModule = wasmModule.addImport(new WasmImport( - "wasi_snapshot_preview1", - "proc_exit", - new WasmImportDescriptor.Func("proc_exit", new WasmFuncType( - List.of(WasmValueType.I32), - List.of() - )) - )); - Files.createDirectories(Path.of("tests-tmp")); var workingDirectory = Files.createTempDirectory(Path.of("tests-tmp"), "PatioToWasmTests"); diff --git a/src/test/java/org/shedlang/compiler/patio/PatioExampleTests.java b/src/test/java/org/shedlang/compiler/patio/PatioExampleTests.java index bc44f2ea..b55755d4 100644 --- a/src/test/java/org/shedlang/compiler/patio/PatioExampleTests.java +++ b/src/test/java/org/shedlang/compiler/patio/PatioExampleTests.java @@ -2,15 +2,19 @@ package org.shedlang.compiler.patio; import org.junit.jupiter.api.Test; import org.shedlang.compiler.patio.instructions.Patio; +import org.shedlang.compiler.patio.instructions.PatioInstruction; +import org.shedlang.compiler.patio.operands.PatioOperand; import org.shedlang.compiler.patio.types.PatioDataLayouts; import org.shedlang.compiler.patio.types.PatioDataValues; import org.shedlang.compiler.patio.types.PatioTypes; import org.shedlang.compiler.sources.Sources; import org.shedlang.compiler.testing.ExecutionResult; +import org.shedlang.compiler.util.Lists; import org.zwobble.precisely.Matcher; import java.io.IOException; import java.util.List; +import java.util.Optional; import static org.zwobble.precisely.AssertThat.assertThat; import static org.zwobble.precisely.Matchers.*; @@ -28,7 +32,7 @@ public abstract class PatioExampleTests { ); var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addBodyInstruction(Patio.memoryLoad( Patio.localRef("x"), @@ -36,9 +40,10 @@ public abstract class PatioExampleTests { PatioDataLayouts.INT, List.of() )) - .addBodyInstruction(Patio.return_( + .addBodyInstruction(emitInt( Patio.localRef("x") )) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of( patioDataElement, @@ -47,7 +52,9 @@ public abstract class PatioExampleTests { var result = run(patio); - assertThat(result, isSilentExit(42)); + assertThat(result, isSequence( + isInt(42) + )); } @Test @@ -64,7 +71,7 @@ public abstract class PatioExampleTests { ); var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addBodyInstruction(Patio.memoryLoad( Patio.localRef("x"), @@ -76,9 +83,8 @@ public abstract class PatioExampleTests { )), List.of(1) )) - .addBodyInstruction(Patio.return_( - Patio.localRef("x") - )) + .addBodyInstruction(emitInt(Patio.localRef("x"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of( patioDataElement, @@ -87,14 +93,16 @@ public abstract class PatioExampleTests { var result = run(patio); - assertThat(result, isSilentExit(42)); + assertThat(result, isSequence( + isInt(42) + )); } @Test public void allocStack() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.DATA_PTR)) .addLocal(Patio.val("y", PatioTypes.INT)) .addLocal(Patio.val("z", PatioTypes.INT)) @@ -129,22 +137,23 @@ public abstract class PatioExampleTests { PatioDataLayouts.INT, List.of() )) - .addBodyInstruction(Patio.return_( - Patio.localRef("r") - )) + .addBodyInstruction(emitInt(Patio.localRef("r"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of(patioFunction)); var result = run(patio); - assertThat(result, isSilentExit(47)); + assertThat(result, isSequence( + isInt(47) + )); } @Test public void block() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addBodyInstruction(Patio.block( List.of( @@ -155,20 +164,23 @@ public abstract class PatioExampleTests { ), List.of(Patio.localRef("x")) )) - .addBodyInstruction(Patio.return_(Patio.localRef("x"))) + .addBodyInstruction(emitInt(Patio.localRef("x"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of(patioFunction)); var result = run(patio); - assertThat(result, isSilentExit(42)); + assertThat(result, isSequence( + isInt(42) + )); } @Test public void boolToIntToBoolIsIdentityForFalse() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.BOOL)) .addLocal(Patio.val("y", PatioTypes.INT)) .addLocal(Patio.val("z", PatioTypes.BOOL)) @@ -191,20 +203,23 @@ public abstract class PatioExampleTests { Patio.block(List.of(), List.of(Patio.intConst(42))), Patio.block(List.of(), List.of(Patio.intConst(47))) )) - .addBodyInstruction(Patio.return_(Patio.localRef("r"))) + .addBodyInstruction(emitInt(Patio.localRef("r"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of(patioFunction)); var result = run(patio); - assertThat(result, isSilentExit(47)); + assertThat(result, isSequence( + isInt(47) + )); } @Test public void boolToIntToBoolIsIdentityForTrue() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.BOOL)) .addLocal(Patio.val("y", PatioTypes.INT)) .addLocal(Patio.val("z", PatioTypes.BOOL)) @@ -227,20 +242,23 @@ public abstract class PatioExampleTests { Patio.block(List.of(), List.of(Patio.intConst(42))), Patio.block(List.of(), List.of(Patio.intConst(47))) )) - .addBodyInstruction(Patio.return_(Patio.localRef("r"))) + .addBodyInstruction(emitInt(Patio.localRef("r"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of(patioFunction)); var result = run(patio); - assertThat(result, isSilentExit(42)); + assertThat(result, isSequence( + isInt(42) + )); } @Test public void intAdd() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addLocal(Patio.val("y", PatioTypes.INT)) .addLocal(Patio.val("z", PatioTypes.INT)) @@ -257,20 +275,23 @@ public abstract class PatioExampleTests { Patio.localRef("x"), Patio.localRef("y") )) - .addBodyInstruction(Patio.return_(Patio.localRef("z"))) + .addBodyInstruction(emitInt(Patio.localRef("z"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of(patioFunction)); var result = run(patio); - assertThat(result, isSilentExit(47)); + assertThat(result, isSequence( + isInt(47) + )); } @Test public void switchWithUnreachableDefault() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addLocal(Patio.val("x1", PatioTypes.INT)) .addLocal(Patio.val("x2", PatioTypes.INT)) @@ -302,20 +323,23 @@ public abstract class PatioExampleTests { List.of() ) )) - .addBodyInstruction(Patio.return_(Patio.localRef("x"))) + .addBodyInstruction(emitInt(Patio.localRef("x"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of(patioFunction)); var result = run(patio); - assertThat(result, isSilentExit(47)); + assertThat(result, isSequence( + isInt(47) + )); } @Test public void switchWithReachableDefault() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addLocal(Patio.val("x1", PatioTypes.INT)) .addLocal(Patio.val("x2", PatioTypes.INT)) @@ -340,20 +364,23 @@ public abstract class PatioExampleTests { List.of(Patio.localRef("x2")) ) )) - .addBodyInstruction(Patio.return_(Patio.localRef("x"))) + .addBodyInstruction(emitInt(Patio.localRef("x"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of(patioFunction)); var result = run(patio); - assertThat(result, isSilentExit(47)); + assertThat(result, isSequence( + isInt(47) + )); } @Test public void whenExceptionIsNotThrownThenTryReturnsFromBody() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("r1", PatioTypes.INT)) .addLocal(Patio.val("r2", PatioTypes.INT)) .addLocal(Patio.val("e1", PatioTypes.INT)) @@ -375,9 +402,8 @@ public abstract class PatioExampleTests { List.of(Patio.intConst(0)) ) )) - .addBodyInstruction(Patio.return_( - Patio.localRef("r1") - )) + .addBodyInstruction(emitInt(Patio.localRef("r1"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of( Patio.exceptionTypeDefinition("Error", PatioTypes.INT), @@ -386,14 +412,16 @@ public abstract class PatioExampleTests { var result = run(patio); - assertThat(result, isSilentExit(0)); + assertThat(result, isSequence( + isInt(0) + )); } @Test public void whenExceptionIsThrownThenFirstMatchingExceptionHandlerIsUsed() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("r1", PatioTypes.INT)) .addLocal(Patio.val("r2", PatioTypes.INT)) .addLocal(Patio.val("e1", PatioTypes.INT)) @@ -435,9 +463,8 @@ public abstract class PatioExampleTests { List.of(Patio.localRef("r2")) ) )) - .addBodyInstruction(Patio.return_( - Patio.localRef("r1") - )) + .addBodyInstruction(emitInt(Patio.localRef("r1"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of( Patio.exceptionTypeDefinition("Error", PatioTypes.INT), @@ -446,14 +473,16 @@ public abstract class PatioExampleTests { var result = run(patio); - assertThat(result, isSilentExit(2)); + assertThat(result, isSequence( + isInt(2) + )); } @Test public void multipleCatchClausesCanBeAttachedToSameTry() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("r1", PatioTypes.INT)) .addLocal(Patio.val("r2", PatioTypes.INT)) .addLocal(Patio.val("e1", PatioTypes.INT)) @@ -485,9 +514,8 @@ public abstract class PatioExampleTests { List.of(Patio.intConst(0)) ) )) - .addBodyInstruction(Patio.return_( - Patio.localRef("r1") - )) + .addBodyInstruction(emitInt(Patio.localRef("r1"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of( Patio.exceptionTypeDefinition("Error1", PatioTypes.INT), @@ -497,14 +525,16 @@ public abstract class PatioExampleTests { var result = run(patio); - assertThat(result, isSilentExit(2)); + assertThat(result, isSequence( + isInt(2) + )); } @Test public void whenExceptionIsThrownThenExceptionHandlerForOtherExceptionsIsIgnored() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("r1", PatioTypes.INT)) .addLocal(Patio.val("r2", PatioTypes.INT)) .addLocal(Patio.val("e1", PatioTypes.INT)) @@ -546,9 +576,8 @@ public abstract class PatioExampleTests { List.of(Patio.localRef("r2")) ) )) - .addBodyInstruction(Patio.return_( - Patio.localRef("r1") - )) + .addBodyInstruction(emitInt(Patio.localRef("r1"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of( Patio.exceptionTypeDefinition("Error", PatioTypes.INT), @@ -558,14 +587,16 @@ public abstract class PatioExampleTests { var result = run(patio); - assertThat(result, isSilentExit(1)); + assertThat(result, isSequence( + isInt(1) + )); } @Test public void catchClauseCanThrow() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("r1", PatioTypes.INT)) .addLocal(Patio.val("r2", PatioTypes.INT)) .addLocal(Patio.val("e1", PatioTypes.INT)) @@ -609,9 +640,8 @@ public abstract class PatioExampleTests { List.of(Patio.localRef("r2")) ) )) - .addBodyInstruction(Patio.return_( - Patio.localRef("r1") - )) + .addBodyInstruction(emitInt(Patio.localRef("r1"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of( Patio.exceptionTypeDefinition("Error", PatioTypes.INT), @@ -620,14 +650,16 @@ public abstract class PatioExampleTests { var result = run(patio); - assertThat(result, isSilentExit(1)); + assertThat(result, isSequence( + isInt(1) + )); } @Test public void exceptionHandlerIsDiscardedAfterTry() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("r1", PatioTypes.INT)) .addLocal(Patio.val("r2", PatioTypes.INT)) .addLocal(Patio.val("e1", PatioTypes.INT)) @@ -668,9 +700,8 @@ public abstract class PatioExampleTests { List.of(Patio.localRef("r2")) ) )) - .addBodyInstruction(Patio.return_( - Patio.localRef("r1") - )) + .addBodyInstruction(emitInt(Patio.localRef("r1"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of( Patio.exceptionTypeDefinition("Error", PatioTypes.INT), @@ -679,14 +710,16 @@ public abstract class PatioExampleTests { var result = run(patio); - assertThat(result, isSilentExit(1)); + assertThat(result, isSequence( + isInt(1) + )); } @Test public void thrownValueIsPassedToCatchClause() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("r", PatioTypes.INT)) .addLocal(Patio.val("e", PatioTypes.INT)) .addBodyInstruction(Patio.try_( @@ -708,9 +741,8 @@ public abstract class PatioExampleTests { List.of(Patio.intConst(0)) ) )) - .addBodyInstruction(Patio.return_( - Patio.localRef("r") - )) + .addBodyInstruction(emitInt(Patio.localRef("r"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of( Patio.exceptionTypeDefinition("Error", PatioTypes.INT), @@ -719,14 +751,16 @@ public abstract class PatioExampleTests { var result = run(patio); - assertThat(result, isSilentExit(1)); + assertThat(result, isSequence( + isInt(1) + )); } @Test public void vars() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.var("x", PatioTypes.INT)) .addLocal(Patio.val("y", PatioTypes.INT)) .addLocal(Patio.val("z", PatioTypes.INT)) @@ -752,22 +786,23 @@ public abstract class PatioExampleTests { Patio.localRef("r"), Patio.localRef("x") )) - .addBodyInstruction(Patio.return_( - Patio.localRef("r") - )) + .addBodyInstruction(emitInt(Patio.localRef("r"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of(patioFunction)); var result = run(patio); - assertThat(result, isSilentExit(47)); + assertThat(result, isSequence( + isInt(47) + )); } @Test public void canGetByteOffsetOf() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addBodyInstruction(Patio.localStore( Patio.localRef("x"), @@ -788,9 +823,8 @@ public abstract class PatioExampleTests { List.of(1, 2) )) )) - .addBodyInstruction(Patio.return_( - Patio.localRef("x") - )) + .addBodyInstruction(emitInt(Patio.localRef("x"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of( patioFunction @@ -798,14 +832,16 @@ public abstract class PatioExampleTests { var result = run(patio); - assertThat(result, isSilentExit(4)); + assertThat(result, isSequence( + isInt(4) + )); } @Test public void canGetByteSizeOf() throws IOException, InterruptedException { var patioFunction = PatioFunctionDefinition.builder() .withName(FUNCTION_NAME) - .withReturnType(PatioTypes.INT) + .withReturnType(PatioTypes.VOID) .addLocal(Patio.val("x", PatioTypes.INT)) .addBodyInstruction(Patio.localStore( Patio.localRef("x"), @@ -825,9 +861,8 @@ public abstract class PatioExampleTests { )) )) )) - .addBodyInstruction(Patio.return_( - Patio.localRef("x") - )) + .addBodyInstruction(emitInt(Patio.localRef("x"))) + .addBodyInstruction(Patio.returnVoid()) .build(); var patio = Patio.compilationUnit(List.of( patioFunction @@ -835,16 +870,45 @@ public abstract class PatioExampleTests { var result = run(patio); - assertThat(result, isSilentExit(7)); + assertThat(result, isSequence( + isInt(7) + )); + } + + private PatioInstruction emitInt(PatioOperand value) { + return Patio.call(Optional.empty(), "patio__test__emit_int", List.of(value)); } - private Matcher isSilentExit(int exitCode) { - return allOf( - has("stderr", x -> x.stderr(), equalTo("")), - has("stdout", x -> x.stdout(), equalTo("")), - has("exitCode", x -> x.exitCode(), equalTo(exitCode)) + private Matcher isInt(int value) { + return instanceOf( + PatioTestOutput.Int.class, + has("value", PatioTestOutput.Int::value, equalTo(value)) ); } - protected abstract ExecutionResult run(PatioCompilationUnit patio) throws IOException, InterruptedException; + private List run(PatioCompilationUnit patio) throws IOException, InterruptedException { + var emitIntDeclaration = PatioFunctionDeclaration.builder() + .withName("patio__test__emit_int") + .addParam(PatioLocal.param("value", PatioTypes.INT)) + .withReturnType(PatioTypes.VOID) + .build(); + + var result = executeCompilationUnit(new PatioCompilationUnit( + Lists.concat(patio.elements(), List.of(emitIntDeclaration)), + patio.source() + )); + assertThat(result.stderr(), equalTo("")); + assertThat(result.exitCode(), equalTo(0)); + return parseTestOutput(result.stdout()); + } + + private List parseTestOutput(String stdout) { + return stdout.lines() + .map(line -> PatioTestOutput.int_(Integer.parseInt(line))) + .toList(); + } + + protected abstract ExecutionResult executeCompilationUnit( + PatioCompilationUnit patio + ) throws IOException, InterruptedException; } diff --git a/src/test/java/org/shedlang/compiler/patio/PatioTestOutput.java b/src/test/java/org/shedlang/compiler/patio/PatioTestOutput.java new file mode 100644 index 00000000..8f7956a9 --- /dev/null +++ b/src/test/java/org/shedlang/compiler/patio/PatioTestOutput.java @@ -0,0 +1,9 @@ +package org.shedlang.compiler.patio; + +public sealed interface PatioTestOutput { + static PatioTestOutput int_(int value) { + return new Int(value); + } + + record Int(int value) implements PatioTestOutput {} +} -- cgit v1.2.3