From ae8ef1fba47a3a7b1332f175a70427a531a33c5c Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 13 Jan 2025 23:33:19 +0100 Subject: [PATCH 01/18] implemented `Out of Bound` stdlib example --- examples/stdlib/exception/out_of_bounds.check | 2 ++ examples/stdlib/exception/out_of_bounds.effekt | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 examples/stdlib/exception/out_of_bounds.check create mode 100644 examples/stdlib/exception/out_of_bounds.effekt diff --git a/examples/stdlib/exception/out_of_bounds.check b/examples/stdlib/exception/out_of_bounds.check new file mode 100644 index 000000000..442c8f06d --- /dev/null +++ b/examples/stdlib/exception/out_of_bounds.check @@ -0,0 +1,2 @@ +Index Out of Bound +a \ No newline at end of file diff --git a/examples/stdlib/exception/out_of_bounds.effekt b/examples/stdlib/exception/out_of_bounds.effekt new file mode 100644 index 000000000..a40338f16 --- /dev/null +++ b/examples/stdlib/exception/out_of_bounds.effekt @@ -0,0 +1,16 @@ +module examples/pos/exception/out_of_bounds + +import exception + +def main() = { + + val str = "Hallo" + charOrOutOfBounds { str.charAt(10) } + charOrOutOfBounds { str.charAt(1) } + +} + + def charOrOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { + with on[OutOfBounds].default { println("Index Out of Bound") } + println(p().show) + } \ No newline at end of file From 9e02b585cbb086e2ea96c84e53c19fb2744214d3 Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 13 Jan 2025 23:43:12 +0100 Subject: [PATCH 02/18] implemented examples for `wrong_format` and restyled both tests --- examples/stdlib/exception/out_of_bounds.effekt | 12 ++++++------ examples/stdlib/exception/wrong_format.check | 2 ++ examples/stdlib/exception/wrong_format.effekt | 15 +++++++++++++++ 3 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 examples/stdlib/exception/wrong_format.check create mode 100644 examples/stdlib/exception/wrong_format.effekt diff --git a/examples/stdlib/exception/out_of_bounds.effekt b/examples/stdlib/exception/out_of_bounds.effekt index a40338f16..30ca442c6 100644 --- a/examples/stdlib/exception/out_of_bounds.effekt +++ b/examples/stdlib/exception/out_of_bounds.effekt @@ -3,14 +3,14 @@ module examples/pos/exception/out_of_bounds import exception def main() = { - val str = "Hallo" + + def charOrOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { + with on[OutOfBounds].default { println("Index Out of Bound") } + println(p().show) + } + charOrOutOfBounds { str.charAt(10) } charOrOutOfBounds { str.charAt(1) } - } - def charOrOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { - with on[OutOfBounds].default { println("Index Out of Bound") } - println(p().show) - } \ No newline at end of file diff --git a/examples/stdlib/exception/wrong_format.check b/examples/stdlib/exception/wrong_format.check new file mode 100644 index 000000000..898fb6ee2 --- /dev/null +++ b/examples/stdlib/exception/wrong_format.check @@ -0,0 +1,2 @@ +Wrong Format +99 \ No newline at end of file diff --git a/examples/stdlib/exception/wrong_format.effekt b/examples/stdlib/exception/wrong_format.effekt new file mode 100644 index 000000000..616e25b6f --- /dev/null +++ b/examples/stdlib/exception/wrong_format.effekt @@ -0,0 +1,15 @@ +module examples/pos/exception/wrong_format + +import exception + +def main() = { + def intOrWrongFormat { p: => Int / Exception[WrongFormat] }: Unit = { + with on[WrongFormat].default { println("Wrong Format") } + println(p().show) + + } + + intOrWrongFormat { "".toInt } + intOrWrongFormat { "99".toInt } +} + From 847d189aba594edccd94139c430d76b19eb0a031 Mon Sep 17 00:00:00 2001 From: Jakub Date: Tue, 14 Jan 2025 00:00:32 +0100 Subject: [PATCH 03/18] added example for `MissingValue` Exception --- examples/stdlib/exception/missing_value.check | 2 ++ examples/stdlib/exception/missing_value.effekt | 13 +++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 examples/stdlib/exception/missing_value.check create mode 100644 examples/stdlib/exception/missing_value.effekt diff --git a/examples/stdlib/exception/missing_value.check b/examples/stdlib/exception/missing_value.check new file mode 100644 index 000000000..6e354e8af --- /dev/null +++ b/examples/stdlib/exception/missing_value.check @@ -0,0 +1,2 @@ +Value is missing +Valid value \ No newline at end of file diff --git a/examples/stdlib/exception/missing_value.effekt b/examples/stdlib/exception/missing_value.effekt new file mode 100644 index 000000000..d6480ad0c --- /dev/null +++ b/examples/stdlib/exception/missing_value.effekt @@ -0,0 +1,13 @@ +module examples/pos/exception/missing_value + +import exception + +def main() = { + def stringOrMissing { p: => String / Exception[MissingValue] }: Unit = { + with on[MissingValue].default { println("Value is missing") } + println(p().show) + } + + stringOrMissing { missingValue() } + stringOrMissing { "Valid value" } +} From fe509db181c70e3fe8f8afcddfb259728595bb5f Mon Sep 17 00:00:00 2001 From: Jakub Date: Tue, 14 Jan 2025 00:24:42 +0100 Subject: [PATCH 04/18] examples for `runtime-error` --- examples/stdlib/exception/runtime_error.check | 3 +++ .../stdlib/exception/runtime_error.effekt | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 examples/stdlib/exception/runtime_error.check create mode 100644 examples/stdlib/exception/runtime_error.effekt diff --git a/examples/stdlib/exception/runtime_error.check b/examples/stdlib/exception/runtime_error.check new file mode 100644 index 000000000..64f0724bb --- /dev/null +++ b/examples/stdlib/exception/runtime_error.check @@ -0,0 +1,3 @@ +Runtime error encountered +Runtime error encountered +No error, valid string \ No newline at end of file diff --git a/examples/stdlib/exception/runtime_error.effekt b/examples/stdlib/exception/runtime_error.effekt new file mode 100644 index 000000000..338020313 --- /dev/null +++ b/examples/stdlib/exception/runtime_error.effekt @@ -0,0 +1,19 @@ +module examples/pos/exception/runtime_error + +import exception + +def main() = { + def valueOrRuntimeError { p: => String / Exception[RuntimeError] }: Unit = { + with on[RuntimeError].default { println("Runtime error encountered") } + println(p().show) + } + + def divByZero() : String = { + val zero : Double = 2.0 / 0.0 + "bla bla bla" + } + + valueOrRuntimeError { raise("This is a runtime error.") } + valueOrRuntimeError { divByZero() } + valueOrRuntimeError { "No error, valid string" } +} From 771c23d077de1c1deae13f036e6699f2259f9ca4 Mon Sep 17 00:00:00 2001 From: Jakub Date: Tue, 14 Jan 2025 00:35:14 +0100 Subject: [PATCH 05/18] validated runtime error --- examples/stdlib/exception/runtime_error.check | 1 - examples/stdlib/exception/runtime_error.effekt | 6 ------ 2 files changed, 7 deletions(-) diff --git a/examples/stdlib/exception/runtime_error.check b/examples/stdlib/exception/runtime_error.check index 64f0724bb..af9191d57 100644 --- a/examples/stdlib/exception/runtime_error.check +++ b/examples/stdlib/exception/runtime_error.check @@ -1,3 +1,2 @@ Runtime error encountered -Runtime error encountered No error, valid string \ No newline at end of file diff --git a/examples/stdlib/exception/runtime_error.effekt b/examples/stdlib/exception/runtime_error.effekt index 338020313..5438572e4 100644 --- a/examples/stdlib/exception/runtime_error.effekt +++ b/examples/stdlib/exception/runtime_error.effekt @@ -7,13 +7,7 @@ def main() = { with on[RuntimeError].default { println("Runtime error encountered") } println(p().show) } - - def divByZero() : String = { - val zero : Double = 2.0 / 0.0 - "bla bla bla" - } valueOrRuntimeError { raise("This is a runtime error.") } - valueOrRuntimeError { divByZero() } valueOrRuntimeError { "No error, valid string" } } From cd7cd3ceda5bff78e7efa47dc32b72f4a1d558cd Mon Sep 17 00:00:00 2001 From: Jakub <168542356+JakubSchwenkbeck@users.noreply.github.com> Date: Tue, 14 Jan 2025 00:39:54 +0100 Subject: [PATCH 06/18] add missing indentation --- examples/stdlib/exception/out_of_bounds.effekt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/stdlib/exception/out_of_bounds.effekt b/examples/stdlib/exception/out_of_bounds.effekt index 30ca442c6..31f9ff2cf 100644 --- a/examples/stdlib/exception/out_of_bounds.effekt +++ b/examples/stdlib/exception/out_of_bounds.effekt @@ -6,8 +6,8 @@ def main() = { val str = "Hallo" def charOrOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { - with on[OutOfBounds].default { println("Index Out of Bound") } - println(p().show) + with on[OutOfBounds].default { println("Index Out of Bound") } + println(p().show) } charOrOutOfBounds { str.charAt(10) } From 85d47a1f6597acecd09a8dd6462cdbeb8910d049 Mon Sep 17 00:00:00 2001 From: Jakub Date: Tue, 14 Jan 2025 11:32:44 +0100 Subject: [PATCH 07/18] restarted with test/example for `default` and `ignore` combinators --- ...{out_of_bounds.check => combinators.check} | 1 + examples/stdlib/exception/combinators.effekt | 25 +++++++++++++++++++ examples/stdlib/exception/missing_value.check | 2 -- .../stdlib/exception/missing_value.effekt | 13 ---------- .../stdlib/exception/out_of_bounds.effekt | 16 ------------ examples/stdlib/exception/runtime_error.check | 2 -- .../stdlib/exception/runtime_error.effekt | 13 ---------- examples/stdlib/exception/wrong_format.check | 2 -- examples/stdlib/exception/wrong_format.effekt | 15 ----------- 9 files changed, 26 insertions(+), 63 deletions(-) rename examples/stdlib/exception/{out_of_bounds.check => combinators.check} (90%) create mode 100644 examples/stdlib/exception/combinators.effekt delete mode 100644 examples/stdlib/exception/missing_value.check delete mode 100644 examples/stdlib/exception/missing_value.effekt delete mode 100644 examples/stdlib/exception/out_of_bounds.effekt delete mode 100644 examples/stdlib/exception/runtime_error.check delete mode 100644 examples/stdlib/exception/runtime_error.effekt delete mode 100644 examples/stdlib/exception/wrong_format.check delete mode 100644 examples/stdlib/exception/wrong_format.effekt diff --git a/examples/stdlib/exception/out_of_bounds.check b/examples/stdlib/exception/combinators.check similarity index 90% rename from examples/stdlib/exception/out_of_bounds.check rename to examples/stdlib/exception/combinators.check index 442c8f06d..51b201766 100644 --- a/examples/stdlib/exception/out_of_bounds.check +++ b/examples/stdlib/exception/combinators.check @@ -1,2 +1,3 @@ Index Out of Bound +a a \ No newline at end of file diff --git a/examples/stdlib/exception/combinators.effekt b/examples/stdlib/exception/combinators.effekt new file mode 100644 index 000000000..c7a7aed29 --- /dev/null +++ b/examples/stdlib/exception/combinators.effekt @@ -0,0 +1,25 @@ +module examples/pos/exception/combinators + +import exception + +def main() = { + val str = "Hallo" + + // Test for default handling of OutOfBoundsException + def defaultOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { + with on[OutOfBounds].default { println("Index Out of Bound") } + println(p().show) + } + + defaultOutOfBounds { str.charAt(10) } // Index Out of Bound + defaultOutOfBounds { str.charAt(1) } // a + + // Test for ignoring OutOfBoundsException + def ignoreOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { + with on[OutOfBounds].ignore(); + println(p().show) // This will not raise the exception as it will be ignored + } + + ignoreOutOfBounds { str.charAt(10) } // This will ignore the OutOfBoundsException + ignoreOutOfBounds { str.charAt(1) } // 'a' +} diff --git a/examples/stdlib/exception/missing_value.check b/examples/stdlib/exception/missing_value.check deleted file mode 100644 index 6e354e8af..000000000 --- a/examples/stdlib/exception/missing_value.check +++ /dev/null @@ -1,2 +0,0 @@ -Value is missing -Valid value \ No newline at end of file diff --git a/examples/stdlib/exception/missing_value.effekt b/examples/stdlib/exception/missing_value.effekt deleted file mode 100644 index d6480ad0c..000000000 --- a/examples/stdlib/exception/missing_value.effekt +++ /dev/null @@ -1,13 +0,0 @@ -module examples/pos/exception/missing_value - -import exception - -def main() = { - def stringOrMissing { p: => String / Exception[MissingValue] }: Unit = { - with on[MissingValue].default { println("Value is missing") } - println(p().show) - } - - stringOrMissing { missingValue() } - stringOrMissing { "Valid value" } -} diff --git a/examples/stdlib/exception/out_of_bounds.effekt b/examples/stdlib/exception/out_of_bounds.effekt deleted file mode 100644 index 31f9ff2cf..000000000 --- a/examples/stdlib/exception/out_of_bounds.effekt +++ /dev/null @@ -1,16 +0,0 @@ -module examples/pos/exception/out_of_bounds - -import exception - -def main() = { - val str = "Hallo" - - def charOrOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { - with on[OutOfBounds].default { println("Index Out of Bound") } - println(p().show) - } - - charOrOutOfBounds { str.charAt(10) } - charOrOutOfBounds { str.charAt(1) } -} - diff --git a/examples/stdlib/exception/runtime_error.check b/examples/stdlib/exception/runtime_error.check deleted file mode 100644 index af9191d57..000000000 --- a/examples/stdlib/exception/runtime_error.check +++ /dev/null @@ -1,2 +0,0 @@ -Runtime error encountered -No error, valid string \ No newline at end of file diff --git a/examples/stdlib/exception/runtime_error.effekt b/examples/stdlib/exception/runtime_error.effekt deleted file mode 100644 index 5438572e4..000000000 --- a/examples/stdlib/exception/runtime_error.effekt +++ /dev/null @@ -1,13 +0,0 @@ -module examples/pos/exception/runtime_error - -import exception - -def main() = { - def valueOrRuntimeError { p: => String / Exception[RuntimeError] }: Unit = { - with on[RuntimeError].default { println("Runtime error encountered") } - println(p().show) - } - - valueOrRuntimeError { raise("This is a runtime error.") } - valueOrRuntimeError { "No error, valid string" } -} diff --git a/examples/stdlib/exception/wrong_format.check b/examples/stdlib/exception/wrong_format.check deleted file mode 100644 index 898fb6ee2..000000000 --- a/examples/stdlib/exception/wrong_format.check +++ /dev/null @@ -1,2 +0,0 @@ -Wrong Format -99 \ No newline at end of file diff --git a/examples/stdlib/exception/wrong_format.effekt b/examples/stdlib/exception/wrong_format.effekt deleted file mode 100644 index 616e25b6f..000000000 --- a/examples/stdlib/exception/wrong_format.effekt +++ /dev/null @@ -1,15 +0,0 @@ -module examples/pos/exception/wrong_format - -import exception - -def main() = { - def intOrWrongFormat { p: => Int / Exception[WrongFormat] }: Unit = { - with on[WrongFormat].default { println("Wrong Format") } - println(p().show) - - } - - intOrWrongFormat { "".toInt } - intOrWrongFormat { "99".toInt } -} - From bf2a1a7f847c64c7ad7a75cafa3210ca5ea1b0c5 Mon Sep 17 00:00:00 2001 From: Jakub Date: Tue, 14 Jan 2025 12:49:51 +0100 Subject: [PATCH 08/18] implemented test for combinator `report` --- examples/stdlib/exception/combinators.check | 2 ++ examples/stdlib/exception/combinators.effekt | 13 ++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/examples/stdlib/exception/combinators.check b/examples/stdlib/exception/combinators.check index 51b201766..2eb7ab5be 100644 --- a/examples/stdlib/exception/combinators.check +++ b/examples/stdlib/exception/combinators.check @@ -1,3 +1,5 @@ Index Out of Bound a +a +Index out of bounds: 10 in string: 'Hallo' a \ No newline at end of file diff --git a/examples/stdlib/exception/combinators.effekt b/examples/stdlib/exception/combinators.effekt index c7a7aed29..96e432f12 100644 --- a/examples/stdlib/exception/combinators.effekt +++ b/examples/stdlib/exception/combinators.effekt @@ -21,5 +21,16 @@ def main() = { } ignoreOutOfBounds { str.charAt(10) } // This will ignore the OutOfBoundsException - ignoreOutOfBounds { str.charAt(1) } // 'a' + ignoreOutOfBounds { str.charAt(1) } // a + +// Test for reporting OutOfBoundsException + def reportOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { + with on[OutOfBounds].report(); + println(p().show) // If an exception occurs, it will be reported to the console + + } + + reportOutOfBounds { str.charAt(10) } // Will report: "Index out of bounds" + reportOutOfBounds { str.charAt(1) } // Will print: "a" + } From 0bcc826d6403f22a83996bcbf43e84ffc2c5c16b Mon Sep 17 00:00:00 2001 From: Jakub Date: Tue, 14 Jan 2025 13:12:11 +0100 Subject: [PATCH 09/18] first draft of finalize - throws `main cannot have effects` --- examples/stdlib/exception/combinators.effekt | 22 +++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/examples/stdlib/exception/combinators.effekt b/examples/stdlib/exception/combinators.effekt index 96e432f12..893851f2b 100644 --- a/examples/stdlib/exception/combinators.effekt +++ b/examples/stdlib/exception/combinators.effekt @@ -17,20 +17,32 @@ def main() = { // Test for ignoring OutOfBoundsException def ignoreOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { with on[OutOfBounds].ignore(); - println(p().show) // This will not raise the exception as it will be ignored + println(p().show) } ignoreOutOfBounds { str.charAt(10) } // This will ignore the OutOfBoundsException ignoreOutOfBounds { str.charAt(1) } // a -// Test for reporting OutOfBoundsException + // Test for reporting OutOfBoundsException def reportOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { with on[OutOfBounds].report(); - println(p().show) // If an exception occurs, it will be reported to the console + println(p().show) } - reportOutOfBounds { str.charAt(10) } // Will report: "Index out of bounds" - reportOutOfBounds { str.charAt(1) } // Will print: "a" + reportOutOfBounds { str.charAt(10) } // Index out of bounds: 10 in string: 'Hallo' + reportOutOfBounds { str.charAt(1) } // a + + + /*def finalizeOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { + with on[OutOfBounds].finalize { println("Finalizer executed") } + println(p().show) + + } + + finalizeOutOfBounds { str.charAt(10) } // Finalizer executed \n a + finalizeOutOfBounds { str.charAt(1) } // Finalizer will execute even without exception + */ + //!! This somehow causes : Main cannot have effects, but includes effects: { Exception[OutOfBounds] } } From 1407440eafa1cb91383b174dfbb42b63f6a78cf5 Mon Sep 17 00:00:00 2001 From: Jakub Date: Tue, 14 Jan 2025 13:23:53 +0100 Subject: [PATCH 10/18] implemented `finalizer` --- examples/stdlib/exception/combinators.check | 5 ++++- examples/stdlib/exception/combinators.effekt | 15 +++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/examples/stdlib/exception/combinators.check b/examples/stdlib/exception/combinators.check index 2eb7ab5be..5674c187e 100644 --- a/examples/stdlib/exception/combinators.check +++ b/examples/stdlib/exception/combinators.check @@ -2,4 +2,7 @@ Index Out of Bound a a Index out of bounds: 10 in string: 'Hallo' -a \ No newline at end of file +a +Finalizer executed +a +Finalizer executed diff --git a/examples/stdlib/exception/combinators.effekt b/examples/stdlib/exception/combinators.effekt index 893851f2b..4f5847332 100644 --- a/examples/stdlib/exception/combinators.effekt +++ b/examples/stdlib/exception/combinators.effekt @@ -33,16 +33,15 @@ def main() = { reportOutOfBounds { str.charAt(10) } // Index out of bounds: 10 in string: 'Hallo' reportOutOfBounds { str.charAt(1) } // a - - /*def finalizeOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { - with on[OutOfBounds].finalize { println("Finalizer executed") } - println(p().show) - - + // Test for finalizing OutOfBoundsException + def finalizeOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { + try { + with on[OutOfBounds].finalize { println("Finalizer executed") } + println(p().show) // Run the operation that might throw an exception + } with Exception[OutOfBounds] { def raise(exception, msg) = () } // Ignore the exception } finalizeOutOfBounds { str.charAt(10) } // Finalizer executed \n a finalizeOutOfBounds { str.charAt(1) } // Finalizer will execute even without exception - */ - //!! This somehow causes : Main cannot have effects, but includes effects: { Exception[OutOfBounds] } + } From 30da4eb382e23ba0b944f915ffbba46183f20226 Mon Sep 17 00:00:00 2001 From: Jakub Date: Tue, 14 Jan 2025 15:39:15 +0100 Subject: [PATCH 11/18] first draft of implementation with independet `TestException` --- examples/stdlib/exception/combinators.check | 14 ++--- examples/stdlib/exception/combinators.effekt | 57 +++++++++++--------- 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/examples/stdlib/exception/combinators.check b/examples/stdlib/exception/combinators.check index 5674c187e..06d611ba2 100644 --- a/examples/stdlib/exception/combinators.check +++ b/examples/stdlib/exception/combinators.check @@ -1,8 +1,8 @@ -Index Out of Bound -a -a -Index out of bounds: 10 in string: 'Hallo' -a -Finalizer executed -a +Exception handled by default combinator +World +World +Test Exception. +World Finalizer executed +World +Finalizer executed \ No newline at end of file diff --git a/examples/stdlib/exception/combinators.effekt b/examples/stdlib/exception/combinators.effekt index 4f5847332..9726a3d5f 100644 --- a/examples/stdlib/exception/combinators.effekt +++ b/examples/stdlib/exception/combinators.effekt @@ -1,47 +1,52 @@ module examples/pos/exception/combinators import exception +/** + * Used as a type for `Exception` purely for independent testing + */ +record TestException() + +def testException(): Nothing / Exception[TestException] = + do raise(TestException(), "Test Exception.") + -def main() = { - val str = "Hallo" - // Test for default handling of OutOfBoundsException - def defaultOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { - with on[OutOfBounds].default { println("Index Out of Bound") } +def main() = { + // Test for default handling of Test Exception + def defaultTestException { p: => String / Exception[TestException] }: Unit = { + with on[TestException].default { println("Exception handled by default combinator") } println(p().show) } - defaultOutOfBounds { str.charAt(10) } // Index Out of Bound - defaultOutOfBounds { str.charAt(1) } // a + defaultTestException { testException() } // Exception + defaultTestException { "World" } // World - // Test for ignoring OutOfBoundsException - def ignoreOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { - with on[OutOfBounds].ignore(); + // Test for ignoring TestExceptionException + def ignoreTestException { p: => String / Exception[TestException] }: Unit = { + with on[TestException].ignore(); println(p().show) } - - ignoreOutOfBounds { str.charAt(10) } // This will ignore the OutOfBoundsException - ignoreOutOfBounds { str.charAt(1) } // a - // Test for reporting OutOfBoundsException - def reportOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { - with on[OutOfBounds].report(); + ignoreTestException { testException() } // ignored + ignoreTestException { "World" } // World + + // Test for reporting TestExceptionException + def reportTestException { p: => String / Exception[TestException] }: Unit = { + with on[TestException].report(); println(p().show) - } - reportOutOfBounds { str.charAt(10) } // Index out of bounds: 10 in string: 'Hallo' - reportOutOfBounds { str.charAt(1) } // a + reportTestException { testException() } // Test Exception. + reportTestException { "World" } // World - // Test for finalizing OutOfBoundsException - def finalizeOutOfBounds { p: => Char / Exception[OutOfBounds] }: Unit = { + // Test for finalizing TestExceptionException + def finalizeTestException { p: => String / Exception[TestException] }: Unit = { try { - with on[OutOfBounds].finalize { println("Finalizer executed") } + with on[TestException].finalize { println("Finalizer executed") } println(p().show) // Run the operation that might throw an exception - } with Exception[OutOfBounds] { def raise(exception, msg) = () } // Ignore the exception + } with Exception[TestException] { def raise(exception, msg) = () } // Ignore the exception } - finalizeOutOfBounds { str.charAt(10) } // Finalizer executed \n a - finalizeOutOfBounds { str.charAt(1) } // Finalizer will execute even without exception - + finalizeTestException { testException() } // Finalizer executed with exception + finalizeTestException { "World" } // World + Finalizer will execute even without exception } From d527f67582286fd1ba2e6fd691b0395f234310a3 Mon Sep 17 00:00:00 2001 From: Jakub Date: Tue, 14 Jan 2025 20:22:00 +0100 Subject: [PATCH 12/18] first approach for adressing llvm fails --- examples/stdlib/exception/combinators.effekt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/stdlib/exception/combinators.effekt b/examples/stdlib/exception/combinators.effekt index 9726a3d5f..affd72bcf 100644 --- a/examples/stdlib/exception/combinators.effekt +++ b/examples/stdlib/exception/combinators.effekt @@ -1,6 +1,7 @@ module examples/pos/exception/combinators import exception + /** * Used as a type for `Exception` purely for independent testing */ @@ -11,11 +12,11 @@ def testException(): Nothing / Exception[TestException] = -def main() = { +def main() : Unit = { // Test for default handling of Test Exception def defaultTestException { p: => String / Exception[TestException] }: Unit = { with on[TestException].default { println("Exception handled by default combinator") } - println(p().show) + println(p().show) } defaultTestException { testException() } // Exception @@ -44,7 +45,7 @@ def main() = { try { with on[TestException].finalize { println("Finalizer executed") } println(p().show) // Run the operation that might throw an exception - } with Exception[TestException] { def raise(exception, msg) = () } // Ignore the exception + } with exc : Exception[TestException] { def exc::raise(exception, msg) = () } // Ignore the exception } finalizeTestException { testException() } // Finalizer executed with exception From 9df0aae7d4ae97c1df35cb5b664b55e8fbc2f97c Mon Sep 17 00:00:00 2001 From: Jakub Date: Tue, 14 Jan 2025 22:59:37 +0100 Subject: [PATCH 13/18] reworked combinators to an independent and general design --- examples/stdlib/exception/combinators.effekt | 50 ++++++++++---------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/examples/stdlib/exception/combinators.effekt b/examples/stdlib/exception/combinators.effekt index affd72bcf..a2b1a2395 100644 --- a/examples/stdlib/exception/combinators.effekt +++ b/examples/stdlib/exception/combinators.effekt @@ -1,53 +1,55 @@ module examples/pos/exception/combinators import exception - -/** - * Used as a type for `Exception` purely for independent testing - */ record TestException() -def testException(): Nothing / Exception[TestException] = - do raise(TestException(), "Test Exception.") +def generalOperation(str: String, index: Int): String / Exception[TestException] = + if (index > 1) + do raise(TestException(), "TestException with index :" ++ show(index) ) + else + str +def main() = { + val str = "Hallo" -def main() : Unit = { - // Test for default handling of Test Exception + // Test for default handling of TestException def defaultTestException { p: => String / Exception[TestException] }: Unit = { - with on[TestException].default { println("Exception handled by default combinator") } - println(p().show) + with on[TestException].default { println("default handled TestException") } + println(p().show) } - defaultTestException { testException() } // Exception - defaultTestException { "World" } // World + defaultTestException { str.generalOperation(10) } // + defaultTestException { str.generalOperation(1) } // a - // Test for ignoring TestExceptionException + // Test for ignoring TestException def ignoreTestException { p: => String / Exception[TestException] }: Unit = { with on[TestException].ignore(); println(p().show) } + + ignoreTestException { str.generalOperation(10) } // This will ignore the TestException + ignoreTestException { str.generalOperation(1) } // a - ignoreTestException { testException() } // ignored - ignoreTestException { "World" } // World - - // Test for reporting TestExceptionException + // Test for reporting TestException def reportTestException { p: => String / Exception[TestException] }: Unit = { with on[TestException].report(); println(p().show) + } - reportTestException { testException() } // Test Exception. - reportTestException { "World" } // World + reportTestException { str.generalOperation(10) } // Index out of bounds: 10 in string: 'Hallo' + reportTestException { str.generalOperation(1) } // a - // Test for finalizing TestExceptionException + // Test for finalizing TestException def finalizeTestException { p: => String / Exception[TestException] }: Unit = { try { with on[TestException].finalize { println("Finalizer executed") } println(p().show) // Run the operation that might throw an exception - } with exc : Exception[TestException] { def exc::raise(exception, msg) = () } // Ignore the exception + } with Exception[TestException] { def raise(exception, msg) = () } // Ignore the exception } - finalizeTestException { testException() } // Finalizer executed with exception - finalizeTestException { "World" } // World + Finalizer will execute even without exception -} + finalizeTestException { str.generalOperation(10) } // Finalizer executed \n a + finalizeTestException { str.generalOperation(1) } // Finalizer will execute even without exception + +} \ No newline at end of file From 5bf66803e9f25a16b2f6a94fb9c8a93130ab2ca9 Mon Sep 17 00:00:00 2001 From: Jakub Date: Tue, 14 Jan 2025 23:17:23 +0100 Subject: [PATCH 14/18] refined naming and output prints, added comments and fixed style --- examples/stdlib/exception/combinators.check | 16 ++++---- examples/stdlib/exception/combinators.effekt | 41 ++++++++++++-------- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/examples/stdlib/exception/combinators.check b/examples/stdlib/exception/combinators.check index 06d611ba2..0b676b1b5 100644 --- a/examples/stdlib/exception/combinators.check +++ b/examples/stdlib/exception/combinators.check @@ -1,8 +1,8 @@ -Exception handled by default combinator -World -World -Test Exception. -World -Finalizer executed -World -Finalizer executed \ No newline at end of file +Test: Default Handling +hello +hello +Error: Invalid index (0) +hello +Test: Finalizer +hello +Test: Finalizer \ No newline at end of file diff --git a/examples/stdlib/exception/combinators.effekt b/examples/stdlib/exception/combinators.effekt index a2b1a2395..fd35b20a8 100644 --- a/examples/stdlib/exception/combinators.effekt +++ b/examples/stdlib/exception/combinators.effekt @@ -1,26 +1,33 @@ module examples/pos/exception/combinators import exception -record TestException() +/** + * Used as a type for `Exception` purely for independent testing + */ +record TestException() -def generalOperation(str: String, index: Int): String / Exception[TestException] = - if (index > 1) - do raise(TestException(), "TestException with index :" ++ show(index) ) +/** + * Returns the string if index > 0; otherwise raises a TestException. + */ +def generalOperation(str: String, index: Int): String / Exception[TestException] = { + if (index <= 0) + do raise(TestException(), "Error: Invalid index (" ++ show(index) ++ ")") else str +} def main() = { - val str = "Hallo" + val str = "hello" // Test for default handling of TestException def defaultTestException { p: => String / Exception[TestException] }: Unit = { - with on[TestException].default { println("default handled TestException") } + with on[TestException].default { println("Test: Default Handling") } println(p().show) } - defaultTestException { str.generalOperation(10) } // - defaultTestException { str.generalOperation(1) } // a + defaultTestException { str.generalOperation(0) } // Test: Default Handling + defaultTestException { str.generalOperation(1) } // hello // Test for ignoring TestException def ignoreTestException { p: => String / Exception[TestException] }: Unit = { @@ -28,8 +35,8 @@ def main() = { println(p().show) } - ignoreTestException { str.generalOperation(10) } // This will ignore the TestException - ignoreTestException { str.generalOperation(1) } // a + ignoreTestException { str.generalOperation(0) } // *ignores the TestException* + ignoreTestException { str.generalOperation(1) } // hello // Test for reporting TestException def reportTestException { p: => String / Exception[TestException] }: Unit = { @@ -38,18 +45,18 @@ def main() = { } - reportTestException { str.generalOperation(10) } // Index out of bounds: 10 in string: 'Hallo' - reportTestException { str.generalOperation(1) } // a + reportTestException { str.generalOperation(0) } // Error: Invalid index (0) + reportTestException { str.generalOperation(1) } // hello // Test for finalizing TestException def finalizeTestException { p: => String / Exception[TestException] }: Unit = { try { - with on[TestException].finalize { println("Finalizer executed") } - println(p().show) // Run the operation that might throw an exception - } with Exception[TestException] { def raise(exception, msg) = () } // Ignore the exception + with on[TestException].finalize { println("Test: Finalizer") } + println(p().show) + } with Exception[TestException] { def raise(exception, msg) = () } } - finalizeTestException { str.generalOperation(10) } // Finalizer executed \n a - finalizeTestException { str.generalOperation(1) } // Finalizer will execute even without exception + finalizeTestException { str.generalOperation(0) } // Test: Finalizer + finalizeTestException { str.generalOperation(1) } // Test: Finalizer hello } \ No newline at end of file From e67cad85d53070ce027996208f87d4b5153a12b0 Mon Sep 17 00:00:00 2001 From: Jakub Date: Tue, 14 Jan 2025 23:29:55 +0100 Subject: [PATCH 15/18] added `: String` and fixed whitespaces --- examples/stdlib/exception/combinators.check | 1 + examples/stdlib/exception/combinators.effekt | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/stdlib/exception/combinators.check b/examples/stdlib/exception/combinators.check index 0b676b1b5..4a6d49331 100644 --- a/examples/stdlib/exception/combinators.check +++ b/examples/stdlib/exception/combinators.check @@ -2,6 +2,7 @@ Test: Default Handling hello hello Error: Invalid index (0) +Error: Invalid index (-1) hello Test: Finalizer hello diff --git a/examples/stdlib/exception/combinators.effekt b/examples/stdlib/exception/combinators.effekt index fd35b20a8..4c578c4d8 100644 --- a/examples/stdlib/exception/combinators.effekt +++ b/examples/stdlib/exception/combinators.effekt @@ -18,7 +18,7 @@ def generalOperation(str: String, index: Int): String / Exception[TestException] } def main() = { - val str = "hello" + val str : String = "hello" // Test for default handling of TestException def defaultTestException { p: => String / Exception[TestException] }: Unit = { @@ -42,10 +42,10 @@ def main() = { def reportTestException { p: => String / Exception[TestException] }: Unit = { with on[TestException].report(); println(p().show) - } reportTestException { str.generalOperation(0) } // Error: Invalid index (0) + reportTestException { str.generalOperation(-1) }// Error: Invalid index (-1) reportTestException { str.generalOperation(1) } // hello // Test for finalizing TestException From 93b6225d85478b0a5bc42cdd7dc379e40af422b7 Mon Sep 17 00:00:00 2001 From: Jakub Date: Tue, 14 Jan 2025 23:59:25 +0100 Subject: [PATCH 16/18] implemen test for `reifying` an Exception using `Result` --- examples/stdlib/exception/combinators.check | 4 +++- examples/stdlib/exception/combinators.effekt | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/examples/stdlib/exception/combinators.check b/examples/stdlib/exception/combinators.check index 4a6d49331..41969b94c 100644 --- a/examples/stdlib/exception/combinators.check +++ b/examples/stdlib/exception/combinators.check @@ -6,4 +6,6 @@ Error: Invalid index (-1) hello Test: Finalizer hello -Test: Finalizer \ No newline at end of file +Test: Finalizer +Error: Invalid index (0) +Success: hello \ No newline at end of file diff --git a/examples/stdlib/exception/combinators.effekt b/examples/stdlib/exception/combinators.effekt index 4c578c4d8..8d8e3ca56 100644 --- a/examples/stdlib/exception/combinators.effekt +++ b/examples/stdlib/exception/combinators.effekt @@ -1,6 +1,7 @@ module examples/pos/exception/combinators import exception +import result /** * Used as a type for `Exception` purely for independent testing @@ -59,4 +60,16 @@ def main() = { finalizeTestException { str.generalOperation(0) } // Test: Finalizer finalizeTestException { str.generalOperation(1) } // Test: Finalizer hello + // Test for "reifying" an Exception using Result + def resultTestException { p: => String / Exception[TestException] }: Unit = { + val res= result[String, TestException](on[TestException]) { p() } + res match { + case Success(msg) => println("Success: " ++ msg) + case Error(exc, msg) => println(msg) + } + } + + resultTestException { str.generalOperation(0) } // Error: Invalid index (0) + resultTestException { str.generalOperation(1) } // Success: hello + } \ No newline at end of file From e573723616299b406007835a0c18430802e79211 Mon Sep 17 00:00:00 2001 From: Jakub Date: Wed, 15 Jan 2025 14:19:46 +0100 Subject: [PATCH 17/18] adress style knitpicks:) --- examples/stdlib/exception/combinators.effekt | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/examples/stdlib/exception/combinators.effekt b/examples/stdlib/exception/combinators.effekt index 8d8e3ca56..ee44dd791 100644 --- a/examples/stdlib/exception/combinators.effekt +++ b/examples/stdlib/exception/combinators.effekt @@ -3,14 +3,12 @@ module examples/pos/exception/combinators import exception import result -/** - * Used as a type for `Exception` purely for independent testing - */ + +/// Used as a type for `Exception` purely for independent testing record TestException() -/** - * Returns the string if index > 0; otherwise raises a TestException. - */ + +/// Returns the string if index > 0; otherwise raises a TestException. def generalOperation(str: String, index: Int): String / Exception[TestException] = { if (index <= 0) do raise(TestException(), "Error: Invalid index (" ++ show(index) ++ ")") @@ -19,7 +17,7 @@ def generalOperation(str: String, index: Int): String / Exception[TestException] } def main() = { - val str : String = "hello" + val str: String = "hello" // Test for default handling of TestException def defaultTestException { p: => String / Exception[TestException] }: Unit = { @@ -60,9 +58,9 @@ def main() = { finalizeTestException { str.generalOperation(0) } // Test: Finalizer finalizeTestException { str.generalOperation(1) } // Test: Finalizer hello - // Test for "reifying" an Exception using Result + // Test for "reifying" an Exception usix^xng Result def resultTestException { p: => String / Exception[TestException] }: Unit = { - val res= result[String, TestException](on[TestException]) { p() } + val res= result[String, TestException] { p() } res match { case Success(msg) => println("Success: " ++ msg) case Error(exc, msg) => println(msg) From b9c03c7031613262dcbbaaac80d7b2e1e369d5cd Mon Sep 17 00:00:00 2001 From: Jakub Date: Wed, 15 Jan 2025 14:23:52 +0100 Subject: [PATCH 18/18] fixed typo --- examples/stdlib/exception/combinators.effekt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/stdlib/exception/combinators.effekt b/examples/stdlib/exception/combinators.effekt index ee44dd791..cc1be1a80 100644 --- a/examples/stdlib/exception/combinators.effekt +++ b/examples/stdlib/exception/combinators.effekt @@ -58,9 +58,9 @@ def main() = { finalizeTestException { str.generalOperation(0) } // Test: Finalizer finalizeTestException { str.generalOperation(1) } // Test: Finalizer hello - // Test for "reifying" an Exception usix^xng Result + // Test for "reifying" an Exception using Result def resultTestException { p: => String / Exception[TestException] }: Unit = { - val res= result[String, TestException] { p() } + val res = result[String, TestException] { p() } res match { case Success(msg) => println("Success: " ++ msg) case Error(exc, msg) => println(msg)