From 3f86a16360679fd3e530ebb9b8f06de2373d407f Mon Sep 17 00:00:00 2001 From: mike Date: Sat, 1 Feb 2025 20:49:58 +0100 Subject: [PATCH 1/4] Added err outport for Println. --- e2e/99_bottles_verbose/main/main.neva | 32 +++++++++---------- e2e/add_nums_from_stdin_naive/main/main.neva | 2 +- .../main/main.neva | 7 ++-- .../main/main.neva | 4 ++- .../main/main.neva | 10 +++--- .../main/main.neva | 10 +++--- e2e/add_nums_verbose/main/main.neva | 2 ++ .../arithmetic/add_floats/main/main.neva | 5 ++- .../arithmetic/add_ints/main/main.neva | 5 ++- .../arithmetic/add_strings/main/main.neva | 5 ++- .../arithmetic/divide_floats/main/main.neva | 5 ++- .../arithmetic/divide_ints/main/main.neva | 5 ++- .../arithmetic/modulo/main/main.neva | 5 ++- .../arithmetic/multiply_floats/main/main.neva | 5 ++- .../arithmetic/multiply_ints/main/main.neva | 5 ++- .../arithmetic/power/main/main.neva | 5 ++- .../arithmetic/subtract_floats/main/main.neva | 5 ++- .../arithmetic/subtract_ints/main/main.neva | 5 ++- .../bitwise/and/main/main.neva | 5 ++- .../bitwise/left_shift/main/main.neva | 5 ++- .../bitwise/or/main/main.neva | 5 ++- .../bitwise/right_shift/main/main.neva | 5 ++- .../bitwise/xor/main/main.neva | 5 ++- .../comparison/equal/main/main.neva | 5 ++- .../comparison/greater_int/main/main.neva | 5 ++- .../greater_or_equal_int/main/main.neva | 5 ++- .../comparison/less_int/main/main.neva | 5 ++- .../less_or_equal_int/main/main.neva | 5 ++- .../comparison/not_equal/main/main.neva | 5 ++- .../logical/and/main/main.neva | 5 ++- .../logical/or/main/main.neva | 5 ++- e2e/classify_int/src/main.neva | 4 ++- e2e/comments/main/main.neva | 2 ++ e2e/compare_ints/main/main.neva | 5 ++- e2e/compare_ints_lt_equal/main/main.neva | 5 ++- e2e/compare_strings/main/main.neva | 5 ++- .../main/main.neva | 12 ++++--- e2e/const_refs_verbose/main/main.neva | 2 ++ e2e/div_test/main/main.neva | 5 ++- e2e/duplicate_receiver/e2e_test.go | 2 +- e2e/duplicate_receiver/main/main.neva | 7 ++-- e2e/duplicate_sender/main/main.neva | 1 + e2e/echo_verbose/main/main.neva | 2 ++ e2e/enums_verbose/main/main.neva | 6 ++-- e2e/hello_world_verbose/main/main.neva | 2 ++ .../main/main.neva | 2 ++ .../main/main.neva | 2 ++ .../main/main.neva | 2 ++ .../main/main.neva | 2 ++ .../main/main.neva | 2 ++ e2e/inc_test/main/main.neva | 5 ++- .../main/main.neva | 12 ++++--- e2e/interface_anonymous/main/main.neva | 8 +++-- e2e/interface_verbose/main/main.neva | 8 +++-- e2e/interface_with_imports/main/main.neva | 8 +++-- e2e/interface_with_imports/neva.yml | 2 +- e2e/list_with_neg_nums/main/main.neva | 2 ++ e2e/local_imports/foo/bar/bar.neva | 7 ++-- e2e/local_imports/foo/foo.neva | 7 ++-- e2e/local_imports/main/main.neva | 6 +++- e2e/logic_gate_and/main/main.neva | 5 ++- e2e/logic_gate_or/main/main.neva | 5 ++- e2e/map_list_verbose/main/main.neva | 5 ++- e2e/multiply_numbers/main/main.neva | 5 ++- .../main/main.neva | 5 ++- e2e/print_float/main/main.neva | 2 ++ e2e/regex_submatch_verbose/main/main.neva | 2 +- .../foo/bar/main.neva | 5 ++- e2e/simple_fan_out/main/main.neva | 6 ++-- e2e/slow_iteration_with_for/main/main.neva | 5 ++- e2e/slow_iteration_with_map/main/main.neva | 5 ++- e2e/struct_builder_verbose/main/main.neva | 2 ++ e2e/struct_builder_with_sugar/main/main.neva | 2 ++ .../main/main.neva | 3 +- e2e/struct_selector_verbose/main/main.neva | 2 ++ .../main/main.neva | 6 ++-- e2e/struct_selector_with_sugar/main/main.neva | 3 +- examples/99_bottles/main.neva | 8 ++--- examples/add_numbers/main.neva | 3 ++ examples/add_numbers_from_stdin/main.neva | 14 ++++---- examples/advanced_error_handling/main.neva | 5 +-- examples/compare_values/main.neva | 5 ++- examples/const_refs/main.neva | 6 ++-- examples/delayed_echo/main.neva | 8 +++-- examples/dict/main.neva | 6 ++-- examples/echo/main.neva | 6 ++-- examples/enums/main.neva | 13 +++++--- examples/file_read_all/main.neva | 6 ++-- examples/file_write_all/main.neva | 6 ++-- examples/hello_world/main.neva | 6 ++-- examples/http_get/main.neva | 5 +-- examples/image_png/main.neva | 4 ++- examples/interfaces/main.neva | 11 ++++--- examples/list_index/main.neva | 6 ++-- examples/list_len/main.neva | 6 ++-- examples/map_list/main.neva | 5 ++- examples/neva.yml | 2 +- examples/push_to_list/main.neva | 6 ++-- examples/reduce_list/main.neva | 5 ++- examples/regex_submatch/main.neva | 6 ++-- examples/split_join_string/main.neva | 6 ++-- examples/stream_to_list/main.neva | 5 ++- examples/struct_builder/main.neva | 6 ++-- examples/struct_selector/main.neva | 6 ++-- examples/switch/main.neva | 9 ++++-- examples/switch_fan_out/main.neva | 9 ++++-- examples/wait_group/main.neva | 4 ++- internal/runtime/funcs/println.go | 10 +++++- std/fmt/fmt.neva | 2 +- 109 files changed, 418 insertions(+), 177 deletions(-) diff --git a/e2e/99_bottles_verbose/main/main.neva b/e2e/99_bottles_verbose/main/main.neva index e2912cd8..6c0880d2 100644 --- a/e2e/99_bottles_verbose/main/main.neva +++ b/e2e/99_bottles_verbose/main/main.neva @@ -7,18 +7,20 @@ def Main(start any) (stop any) { s Switch print_next_2_lines PrintNext2Lines lock Lock + panic Panic --- :start -> lock:sig 99 -> lock:data [lock:data, s:else] -> print_next_2_lines - print_next_2_lines -> s:data + print_next_2_lines:n -> s:data -1 -> s:case[0] -> :stop + print_next_2_lines:err -> panic } -def PrintNext2Lines(n int) (n int) { +def PrintNext2Lines(n int) (n int, err error) { dec Dec - print_first_line PrintFirstLine - print_second_line PrintSecondLine + print_first_line PrintFirstLine? + print_second_line PrintSecondLine? --- // print_first_line and print_second_line won't work in parallel // because they are in the loop at the level of Main @@ -34,13 +36,12 @@ const firstLine1 string = '$0 bottles of beer on the wall, $0 bottles of beer.\n const firstLine2 string = '1 bottle of beer on the wall, 1 bottle of beer.' const firstLine3 string = 'No more bottles of beer on the wall, no more bottles of beer.' -def PrintFirstLine(n int) (n int) { +def PrintFirstLine(n int) (n int, err error) { s Switch - p1 fmt.Println - p2 fmt.Println - printf fmt.Printf + p1 fmt.Println? + p2 fmt.Println? + printf fmt.Printf? lock Lock - panic Panic --- :n -> [s:data, lock:data] @@ -55,7 +56,6 @@ def PrintFirstLine(n int) (n int) { ] [p1:res, p2:res, printf:sig] -> lock:sig - printf:err -> panic lock:data -> :n } @@ -66,14 +66,13 @@ const secondLine2 string = 'Take one down and pass it around, 1 bottle of beer o const secondLine3 string = 'Take one down and pass it around, no more bottles of beer on the wall.\n' const secondLine4 string = 'Go to the store and buy some more, 99 bottles of beer on the wall.' -def PrintSecondLine(n int) (n int) { +def PrintSecondLine(n int) (n int, err error) { s Switch - p1 fmt.Println - p2 fmt.Println - p3 fmt.Println - printf fmt.Printf + p1 fmt.Println? + p2 fmt.Println? + p3 fmt.Println? + printf fmt.Printf? lock Lock - panic Panic --- :n -> [s:data, lock:data] @@ -91,6 +90,5 @@ def PrintSecondLine(n int) (n int) { ] [p1:res, p2:res, p3:res, printf:sig] -> lock:sig - printf:err -> panic lock:data -> :n } \ No newline at end of file diff --git a/e2e/add_nums_from_stdin_naive/main/main.neva b/e2e/add_nums_from_stdin_naive/main/main.neva index 2ccac3bc..e504b22a 100644 --- a/e2e/add_nums_from_stdin_naive/main/main.neva +++ b/e2e/add_nums_from_stdin_naive/main/main.neva @@ -16,5 +16,5 @@ def Main(start any) (stop any) { parser2:res -> add:right add:res -> println:data println:res -> :stop - [parser1:err, parser2:err] -> panic + [parser1:err, parser2:err, println:err] -> panic } diff --git a/e2e/add_nums_from_stdin_with_default_any/main/main.neva b/e2e/add_nums_from_stdin_with_default_any/main/main.neva index e59316a9..dd26ec01 100644 --- a/e2e/add_nums_from_stdin_with_default_any/main/main.neva +++ b/e2e/add_nums_from_stdin_with_default_any/main/main.neva @@ -7,18 +7,17 @@ def Main(start any) (stop any) { --- :start -> aux:sig aux:res -> println:data - aux:err -> panic println:res -> :stop + [aux:err, println:err] -> panic } def Aux(sig any) (res int, err error) { - reader1 IntReader - reader2 IntReader + reader1 IntReader? + reader2 IntReader? add Add --- :sig -> reader1:sig reader1:num -> [add:left, reader2:sig] - [reader1:err, reader2:err] -> :err reader2:num -> add:right add:res -> :res } diff --git a/e2e/add_nums_from_stdin_with_err_handling/main/main.neva b/e2e/add_nums_from_stdin_with_err_handling/main/main.neva index a18e8f96..ed1e95ba 100644 --- a/e2e/add_nums_from_stdin_with_err_handling/main/main.neva +++ b/e2e/add_nums_from_stdin_with_err_handling/main/main.neva @@ -7,12 +7,14 @@ def Main(start any) (stop any) { parser2 strconv.ParseNum add Add println fmt.Println + panic Panic --- :start -> scanner1:sig scanner1:res -> parser1:data parser1:res -> [add:left, scanner2:sig] scanner2:res -> parser2:data parser2:res -> add:right + add:res -> println:data println:res -> :stop - [parser1:err, parser2:err, add:res] -> println:data + [parser1:err, parser2:err, println:err] -> panic } diff --git a/e2e/add_nums_from_stdin_with_multuple_senders/main/main.neva b/e2e/add_nums_from_stdin_with_multuple_senders/main/main.neva index fd362d36..42404ed8 100644 --- a/e2e/add_nums_from_stdin_with_multuple_senders/main/main.neva +++ b/e2e/add_nums_from_stdin_with_multuple_senders/main/main.neva @@ -3,30 +3,30 @@ import { strconv, fmt } def Main(start any) (stop any) { aux Aux, println fmt.Println + panic Panic --- :start -> aux:sig [aux:res, aux:err] -> println:data println:res -> :stop + println:err -> panic } def Aux(sig any) (res int, err error) { - reader1 IntReader - reader2 IntReader + reader1 IntReader? + reader2 IntReader? add Add --- :sig -> reader1:sig reader1:num -> [add:left, reader2:sig] - [reader1:err, reader2:err] -> :err reader2:num -> add:right add:res -> :res } def IntReader(sig any) (num int, err error) { scanln fmt.Scanln - parse_num strconv.ParseNum + parse_num strconv.ParseNum? --- :sig -> scanln:sig scanln:res -> parse_num:data parse_num:res -> :num - parse_num:err -> :err } diff --git a/e2e/add_nums_from_stdin_with_sub_components/main/main.neva b/e2e/add_nums_from_stdin_with_sub_components/main/main.neva index 21f64033..75b4a633 100644 --- a/e2e/add_nums_from_stdin_with_sub_components/main/main.neva +++ b/e2e/add_nums_from_stdin_with_sub_components/main/main.neva @@ -3,30 +3,30 @@ import { strconv, fmt } def Main(start any) (stop any) { aux Aux println fmt.Println + panic Panic --- :start -> aux:sig [aux:res, aux:err] -> println:data println:res -> :stop + println:err -> panic } def Aux(sig any) (res int, err error) { - reader1 IntReader - reader2 IntReader + reader1 IntReader? + reader2 IntReader? add Add --- :sig -> reader1:sig reader1:num -> [add:left, reader2:sig] - [reader1:err, reader2:err] -> :err reader2:num -> add:right add:res -> :res } def IntReader(sig any) (num int, err error) { scanln fmt.Scanln - parse_num strconv.ParseNum + parse_num strconv.ParseNum? --- :sig -> scanln:sig scanln:res -> parse_num:data parse_num:res -> :num - parse_num:err -> :err } diff --git a/e2e/add_nums_verbose/main/main.neva b/e2e/add_nums_verbose/main/main.neva index 6789cd43..9a2aecb2 100644 --- a/e2e/add_nums_verbose/main/main.neva +++ b/e2e/add_nums_verbose/main/main.neva @@ -3,6 +3,7 @@ import { fmt } def Main(start any) (stop any) { adder Add println fmt.Println + panic Panic --- :start -> [ 1 -> adder:left, @@ -10,4 +11,5 @@ def Main(start any) (stop any) { ] adder:res -> println:data println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/add_floats/main/main.neva b/e2e/binary_operators/arithmetic/add_floats/main/main.neva index 4ce0638a..88a1f063 100644 --- a/e2e/binary_operators/arithmetic/add_floats/main/main.neva +++ b/e2e/binary_operators/arithmetic/add_floats/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { println fmt.Println + panic Panic --- - :start -> { (21.5 + 20.5) -> println -> :stop } + :start -> { (21.5 + 20.5) -> println:data } + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/add_ints/main/main.neva b/e2e/binary_operators/arithmetic/add_ints/main/main.neva index f207ddb2..c15c544b 100644 --- a/e2e/binary_operators/arithmetic/add_ints/main/main.neva +++ b/e2e/binary_operators/arithmetic/add_ints/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { println fmt.Println + panic Panic --- - :start -> { (5 + 3) -> println -> :stop } + :start -> { (5 + 3) -> println:data } + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/add_strings/main/main.neva b/e2e/binary_operators/arithmetic/add_strings/main/main.neva index 21274143..30bd6c13 100644 --- a/e2e/binary_operators/arithmetic/add_strings/main/main.neva +++ b/e2e/binary_operators/arithmetic/add_strings/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { println fmt.Println + panic Panic --- - :start -> { ('Hello, ' + 'World!') -> println -> :stop } + :start -> { ('Hello, ' + 'World!') -> println:data } + println:res -> :stop + println:err -> panic } diff --git a/e2e/binary_operators/arithmetic/divide_floats/main/main.neva b/e2e/binary_operators/arithmetic/divide_floats/main/main.neva index a571af52..b7e14795 100644 --- a/e2e/binary_operators/arithmetic/divide_floats/main/main.neva +++ b/e2e/binary_operators/arithmetic/divide_floats/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (15.0 / 3.0) -> println -> :stop } + :start -> { (15.0 / 3.0) -> println:data } + println:res -> :stop + println:err -> panic } diff --git a/e2e/binary_operators/arithmetic/divide_ints/main/main.neva b/e2e/binary_operators/arithmetic/divide_ints/main/main.neva index 586ab076..9fa91ae7 100644 --- a/e2e/binary_operators/arithmetic/divide_ints/main/main.neva +++ b/e2e/binary_operators/arithmetic/divide_ints/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (6 / 2) -> println -> :stop } + :start -> { (6 / 2) -> println:data } + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/modulo/main/main.neva b/e2e/binary_operators/arithmetic/modulo/main/main.neva index 2b48f329..cbae03f4 100644 --- a/e2e/binary_operators/arithmetic/modulo/main/main.neva +++ b/e2e/binary_operators/arithmetic/modulo/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (7 % 3) -> println -> :stop } + :start -> { (7 % 3) -> println:data } + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/multiply_floats/main/main.neva b/e2e/binary_operators/arithmetic/multiply_floats/main/main.neva index e81e6350..b53481c6 100644 --- a/e2e/binary_operators/arithmetic/multiply_floats/main/main.neva +++ b/e2e/binary_operators/arithmetic/multiply_floats/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (5.5 * 3.3) -> println -> :stop } + :start -> { (5.5 * 3.3) -> println:data } + println:res -> :stop + println:err -> panic } diff --git a/e2e/binary_operators/arithmetic/multiply_ints/main/main.neva b/e2e/binary_operators/arithmetic/multiply_ints/main/main.neva index 323fc5fe..cea2a09d 100644 --- a/e2e/binary_operators/arithmetic/multiply_ints/main/main.neva +++ b/e2e/binary_operators/arithmetic/multiply_ints/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (5 * 3) -> println -> :stop } + :start -> { (5 * 3) -> println:data } + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/binary_operators/arithmetic/power/main/main.neva b/e2e/binary_operators/arithmetic/power/main/main.neva index 55904dde..523f9ae8 100644 --- a/e2e/binary_operators/arithmetic/power/main/main.neva +++ b/e2e/binary_operators/arithmetic/power/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (2 ** 3) -> println -> :stop } + :start -> { (2 ** 3) -> println:data } + println:res -> :stop + println:err -> panic } diff --git a/e2e/binary_operators/arithmetic/subtract_floats/main/main.neva b/e2e/binary_operators/arithmetic/subtract_floats/main/main.neva index 140c1cda..146c67b4 100644 --- a/e2e/binary_operators/arithmetic/subtract_floats/main/main.neva +++ b/e2e/binary_operators/arithmetic/subtract_floats/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { println fmt.Println + panic Panic --- - :start -> { (21.5 - 20.5) -> println -> :stop } + :start -> { (21.5 - 20.5) -> println:data } + println:res -> :stop + println:err -> panic } diff --git a/e2e/binary_operators/arithmetic/subtract_ints/main/main.neva b/e2e/binary_operators/arithmetic/subtract_ints/main/main.neva index c43ef010..e4420893 100644 --- a/e2e/binary_operators/arithmetic/subtract_ints/main/main.neva +++ b/e2e/binary_operators/arithmetic/subtract_ints/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (5 - 3) -> println -> :stop } + :start -> { (5 - 3) -> println:data } + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/binary_operators/bitwise/and/main/main.neva b/e2e/binary_operators/bitwise/and/main/main.neva index 29df750f..6abec092 100644 --- a/e2e/binary_operators/bitwise/and/main/main.neva +++ b/e2e/binary_operators/bitwise/and/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (5 & 3) -> println -> :stop } + :start -> { (5 & 3) -> println:data } + println:res -> :stop + println:err -> panic } diff --git a/e2e/binary_operators/bitwise/left_shift/main/main.neva b/e2e/binary_operators/bitwise/left_shift/main/main.neva index 26b2bc96..d9beee95 100644 --- a/e2e/binary_operators/bitwise/left_shift/main/main.neva +++ b/e2e/binary_operators/bitwise/left_shift/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (5 << 1) -> println -> :stop } + :start -> { (5 << 1) -> println:data } + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/binary_operators/bitwise/or/main/main.neva b/e2e/binary_operators/bitwise/or/main/main.neva index ae690fca..1279a24b 100644 --- a/e2e/binary_operators/bitwise/or/main/main.neva +++ b/e2e/binary_operators/bitwise/or/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (5 | 3) -> println -> :stop } + :start -> { (5 | 3) -> println:data } + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/binary_operators/bitwise/right_shift/main/main.neva b/e2e/binary_operators/bitwise/right_shift/main/main.neva index 6a1d61b7..2d66c0b7 100644 --- a/e2e/binary_operators/bitwise/right_shift/main/main.neva +++ b/e2e/binary_operators/bitwise/right_shift/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (8 >> 1) -> println -> :stop } + :start -> { (8 >> 1) -> println:data } + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/binary_operators/bitwise/xor/main/main.neva b/e2e/binary_operators/bitwise/xor/main/main.neva index 133eea3a..50fbe1df 100644 --- a/e2e/binary_operators/bitwise/xor/main/main.neva +++ b/e2e/binary_operators/bitwise/xor/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (5 ^ 3) -> println -> :stop } + :start -> { (5 ^ 3) -> println:data } + println:res -> :stop + println:err -> panic } diff --git a/e2e/binary_operators/comparison/equal/main/main.neva b/e2e/binary_operators/comparison/equal/main/main.neva index 63b1489a..95e4d45f 100644 --- a/e2e/binary_operators/comparison/equal/main/main.neva +++ b/e2e/binary_operators/comparison/equal/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (5 == 5) -> println -> :stop } + :start -> { (5 == 5) -> println:data } + println:res -> :stop + println:err -> panic } diff --git a/e2e/binary_operators/comparison/greater_int/main/main.neva b/e2e/binary_operators/comparison/greater_int/main/main.neva index 5e75eb96..7030afda 100644 --- a/e2e/binary_operators/comparison/greater_int/main/main.neva +++ b/e2e/binary_operators/comparison/greater_int/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (5 > 3) -> println -> :stop } + :start -> { (5 > 3) -> println:data } + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/binary_operators/comparison/greater_or_equal_int/main/main.neva b/e2e/binary_operators/comparison/greater_or_equal_int/main/main.neva index 6140ca09..05078c55 100644 --- a/e2e/binary_operators/comparison/greater_or_equal_int/main/main.neva +++ b/e2e/binary_operators/comparison/greater_or_equal_int/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (5 >= 5) -> println -> :stop } + :start -> { (5 >= 5) -> println:data } + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/binary_operators/comparison/less_int/main/main.neva b/e2e/binary_operators/comparison/less_int/main/main.neva index 7e20fe57..e6f9539c 100644 --- a/e2e/binary_operators/comparison/less_int/main/main.neva +++ b/e2e/binary_operators/comparison/less_int/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (5 < 8) -> println -> :stop } + :start -> { (5 < 8) -> println:data } + println:res -> :stop + println:err -> panic } diff --git a/e2e/binary_operators/comparison/less_or_equal_int/main/main.neva b/e2e/binary_operators/comparison/less_or_equal_int/main/main.neva index f4538f1c..c1ae89d9 100644 --- a/e2e/binary_operators/comparison/less_or_equal_int/main/main.neva +++ b/e2e/binary_operators/comparison/less_or_equal_int/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (5 <= 8) -> println -> :stop } + :start -> { (5 <= 8) -> println:data } + println:res -> :stop + println:err -> panic } diff --git a/e2e/binary_operators/comparison/not_equal/main/main.neva b/e2e/binary_operators/comparison/not_equal/main/main.neva index 023bafa1..10797103 100644 --- a/e2e/binary_operators/comparison/not_equal/main/main.neva +++ b/e2e/binary_operators/comparison/not_equal/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (5 != 3) -> println -> :stop } + :start -> { (5 != 3) -> println:data } + println:res -> :stop + println:err -> panic } diff --git a/e2e/binary_operators/logical/and/main/main.neva b/e2e/binary_operators/logical/and/main/main.neva index 0c26d744..e6995e8a 100644 --- a/e2e/binary_operators/logical/and/main/main.neva +++ b/e2e/binary_operators/logical/and/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (true && true) -> println -> :stop } + :start -> { (true && true) -> println:data } + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/binary_operators/logical/or/main/main.neva b/e2e/binary_operators/logical/or/main/main.neva index 3a775a7a..2a8bf0a2 100644 --- a/e2e/binary_operators/logical/or/main/main.neva +++ b/e2e/binary_operators/logical/or/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (true || false) -> println -> :stop } + :start -> { (true || false) -> println:data } + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/classify_int/src/main.neva b/e2e/classify_int/src/main.neva index 93b4cbf2..7169392f 100644 --- a/e2e/classify_int/src/main.neva +++ b/e2e/classify_int/src/main.neva @@ -7,9 +7,11 @@ def Main(start any) (stop any) { classify utils.ClassifyInt println1 fmt.Println println2 fmt.Println + panic Panic --- :start -> -42 -> classify classify:pos -> 'positive :)' -> println1 classify:neg -> 'negative :(' -> println2 - [println1, println2] -> :stop + [println1:res, println2:res] -> :stop + [println1:err, println2:err] -> panic } diff --git a/e2e/comments/main/main.neva b/e2e/comments/main/main.neva index b0632dd7..4d169ed9 100644 --- a/e2e/comments/main/main.neva +++ b/e2e/comments/main/main.neva @@ -6,10 +6,12 @@ def Main(start any) (stop any) { // comment inside nodes 1 fmt.Println // comment inside nodes 2 + panic Panic --- // comment inside def 2 :start -> println:data println:res -> :stop // comment inside def 3 + println:err -> panic } // top-level comment 2 \ No newline at end of file diff --git a/e2e/compare_ints/main/main.neva b/e2e/compare_ints/main/main.neva index 13748f6f..f1482d88 100644 --- a/e2e/compare_ints/main/main.neva +++ b/e2e/compare_ints/main/main.neva @@ -2,6 +2,7 @@ import { fmt } def Main(start any) (stop any) { fmt.Println, Gt, Ternary + panic Panic --- :start -> [ 50 -> gt:left, @@ -10,5 +11,7 @@ def Main(start any) (stop any) { gt:res -> ternary:if 'Actual is greater' -> ternary:then 'Actual is lower' -> ternary:else - ternary:res -> println -> :stop + ternary:res -> println:data + println:res -> :stop + println:err -> panic } diff --git a/e2e/compare_ints_lt_equal/main/main.neva b/e2e/compare_ints_lt_equal/main/main.neva index 153ed716..2046e48a 100644 --- a/e2e/compare_ints_lt_equal/main/main.neva +++ b/e2e/compare_ints_lt_equal/main/main.neva @@ -2,10 +2,13 @@ import { fmt } def Main(start any) (stop any) { fmt.Println, Lt + panic Panic --- :start -> [ 20 -> lt:right, 20 -> lt:left ] - lt:res -> println -> :stop + lt:res -> println:data + println:res -> :stop + println:err -> panic } diff --git a/e2e/compare_strings/main/main.neva b/e2e/compare_strings/main/main.neva index f5cf2504..7cce15fd 100644 --- a/e2e/compare_strings/main/main.neva +++ b/e2e/compare_strings/main/main.neva @@ -2,6 +2,7 @@ import { fmt } def Main(start any) (stop any) { fmt.Println, Gt, Ternary + panic Panic --- :start -> [ 'Z' -> gt:left, @@ -10,5 +11,7 @@ def Main(start any) (stop any) { gt:res -> ternary:if 'Actual is greater' -> ternary:then 'Actual is lower' -> ternary:else - ternary -> println -> :stop + ternary -> println:data + println:res -> :stop + println:err -> panic } diff --git a/e2e/compiler_error_unused_outport/main/main.neva b/e2e/compiler_error_unused_outport/main/main.neva index a179e4ea..39af1c20 100644 --- a/e2e/compiler_error_unused_outport/main/main.neva +++ b/e2e/compiler_error_unused_outport/main/main.neva @@ -3,13 +3,17 @@ import { fmt } def Main(start any) (stop any) { sub1 SubComponent sub2 SubComponent + panic Panic --- - :start -> 'Hi, Neva!' -> sub1 -> :stop + :start -> 'Hi, Neva!' -> sub1:data + sub1:stop-> :stop '1' -> sub2 + [sub1:err, sub2:err] -> panic } -def SubComponent(data string) (stop any) { - println fmt.Println +def SubComponent(data string) (stop any, err error) { + println fmt.Println? --- - :data -> println -> :stop + :data -> println:data + println:res -> :stop } diff --git a/e2e/const_refs_verbose/main/main.neva b/e2e/const_refs_verbose/main/main.neva index 48ca25ab..f07cccc2 100644 --- a/e2e/const_refs_verbose/main/main.neva +++ b/e2e/const_refs_verbose/main/main.neva @@ -17,7 +17,9 @@ const numsStruct NumsStruct = { def Main(start any) (stop any) { fmt.Println + panic Panic --- :start -> $numsStruct -> println:data println:res -> :stop + println:err -> panic } diff --git a/e2e/div_test/main/main.neva b/e2e/div_test/main/main.neva index d7ea319b..d46147ef 100644 --- a/e2e/div_test/main/main.neva +++ b/e2e/div_test/main/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> { (12 / 3) -> println -> :stop } + :start -> { (12 / 3) -> println:data } + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/duplicate_receiver/e2e_test.go b/e2e/duplicate_receiver/e2e_test.go index 573d5c2e..9a952df8 100644 --- a/e2e/duplicate_receiver/e2e_test.go +++ b/e2e/duplicate_receiver/e2e_test.go @@ -16,6 +16,6 @@ func Test(t *testing.T) { require.Contains( t, string(out), - "main/main.neva:7:1: port 'println:res' is used twice\n", + "main/main.neva:9:1: port 'println:res' is used twice\n", ) } diff --git a/e2e/duplicate_receiver/main/main.neva b/e2e/duplicate_receiver/main/main.neva index 8dc9fea3..1dc986b4 100644 --- a/e2e/duplicate_receiver/main/main.neva +++ b/e2e/duplicate_receiver/main/main.neva @@ -2,7 +2,10 @@ import { io, fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> println -> :stop - println -> println + :start -> println:data + println:res -> :stop + println:res -> println:data + println:err -> panic } \ No newline at end of file diff --git a/e2e/duplicate_sender/main/main.neva b/e2e/duplicate_sender/main/main.neva index 8a3cf57b..4ee1ed88 100644 --- a/e2e/duplicate_sender/main/main.neva +++ b/e2e/duplicate_sender/main/main.neva @@ -5,5 +5,6 @@ def Main(start any) (stop any) { --- :start -> println :start -> panic + println:err -> panic println:res -> :stop } \ No newline at end of file diff --git a/e2e/echo_verbose/main/main.neva b/e2e/echo_verbose/main/main.neva index ab667b56..4eb52b13 100644 --- a/e2e/echo_verbose/main/main.neva +++ b/e2e/echo_verbose/main/main.neva @@ -3,8 +3,10 @@ import { fmt } def Main(start any) (stop any) { scanln fmt.Scanln println fmt.Println + panic Panic --- :start -> scanln:sig scanln:res -> println:data println:res -> :stop + println:err -> panic } diff --git a/e2e/enums_verbose/main/main.neva b/e2e/enums_verbose/main/main.neva index 87e227cd..3f9935d2 100644 --- a/e2e/enums_verbose/main/main.neva +++ b/e2e/enums_verbose/main/main.neva @@ -2,9 +2,11 @@ import { fmt } def Main(start any) (stop any) { DayPrinter + panic Panic --- :start -> { Day::Friday -> dayPrinter:day } dayPrinter:sig -> :stop + dayPrinter:err -> panic } type Day enum { @@ -17,8 +19,8 @@ type Day enum { Sunday } -def DayPrinter(day Day) (sig any) { - fmt.Println +def DayPrinter(day Day) (sig any, err error) { + fmt.Println? --- :day -> println:data println:res -> :sig diff --git a/e2e/hello_world_verbose/main/main.neva b/e2e/hello_world_verbose/main/main.neva index 8122381d..cfb5067e 100644 --- a/e2e/hello_world_verbose/main/main.neva +++ b/e2e/hello_world_verbose/main/main.neva @@ -7,6 +7,7 @@ def Main(start any) (stop any) { greeting New println fmt.Println lock Lock + panic Panic --- @@ -14,4 +15,5 @@ def Main(start any) (stop any) { greeting:res -> lock:data lock:data -> println:data println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/hello_world_with_const_sender/main/main.neva b/e2e/hello_world_with_const_sender/main/main.neva index 70a6fa3f..66b265cf 100644 --- a/e2e/hello_world_with_const_sender/main/main.neva +++ b/e2e/hello_world_with_const_sender/main/main.neva @@ -5,9 +5,11 @@ const greeting string = 'Hello, World!' def Main(start any) (stop any) { println fmt.Println lock Lock + panic Panic --- :start -> lock:sig $greeting -> lock:data lock:data -> println:data println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/hello_world_with_implicit_any/main/main.neva b/e2e/hello_world_with_implicit_any/main/main.neva index 4c0fa8a0..c2493559 100644 --- a/e2e/hello_world_with_implicit_any/main/main.neva +++ b/e2e/hello_world_with_implicit_any/main/main.neva @@ -2,7 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- :start -> 'Hello, World!' -> println:data println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/hello_world_with_literal_sender/main/main.neva b/e2e/hello_world_with_literal_sender/main/main.neva index 5f7b7301..2beced2e 100644 --- a/e2e/hello_world_with_literal_sender/main/main.neva +++ b/e2e/hello_world_with_literal_sender/main/main.neva @@ -2,7 +2,9 @@ import { fmt } def Main(start any) (stop any) { println fmt.Println + panic Panic --- :start -> 'Hello, World!' -> println:data println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/hello_world_with_then_connection/main/main.neva b/e2e/hello_world_with_then_connection/main/main.neva index 004daa61..cfec4ce5 100644 --- a/e2e/hello_world_with_then_connection/main/main.neva +++ b/e2e/hello_world_with_then_connection/main/main.neva @@ -4,7 +4,9 @@ const greeting string = 'Hello, World!' def Main(start any) (stop any) { println fmt.Println + panic Panic --- :start -> $greeting -> println:data println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/hello_world_with_unnamed_node/main/main.neva b/e2e/hello_world_with_unnamed_node/main/main.neva index fb154bf5..8dc2394e 100644 --- a/e2e/hello_world_with_unnamed_node/main/main.neva +++ b/e2e/hello_world_with_unnamed_node/main/main.neva @@ -2,7 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- :start -> 'Hello, World!' -> println:data println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/inc_test/main/main.neva b/e2e/inc_test/main/main.neva index 510932b2..e8cc6a60 100644 --- a/e2e/inc_test/main/main.neva +++ b/e2e/inc_test/main/main.neva @@ -2,7 +2,10 @@ import { fmt } def Main(start any) (stop any) { Inc, fmt.Println + panic Panic --- :start -> 41 -> inc - inc -> println -> :stop + inc -> println:data + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/incompat_types_with_untyped_port/main/main.neva b/e2e/incompat_types_with_untyped_port/main/main.neva index ae13a5ea..1eb2c7a4 100644 --- a/e2e/incompat_types_with_untyped_port/main/main.neva +++ b/e2e/incompat_types_with_untyped_port/main/main.neva @@ -2,12 +2,16 @@ import { fmt } def Main(start any) (stop any) { PrintAny + panic Panic --- - :start -> 42 -> printAny -> :stop + :start -> 42 -> printAny + printAny:sig -> :stop + printAny:err -> panic } -def PrintAny(data any) (sig any) { - fmt.Println +def PrintAny(data any) (sig any, err error) { + fmt.Println? --- - :data -> println -> :sig + :data -> println + println:res -> :sig } diff --git a/e2e/interface_anonymous/main/main.neva b/e2e/interface_anonymous/main/main.neva index 2d670d69..8b2d9fef 100644 --- a/e2e/interface_anonymous/main/main.neva +++ b/e2e/interface_anonymous/main/main.neva @@ -2,16 +2,18 @@ import { fmt } def Main(start any) (stop any) { second_flow Secondflow{fmt.Println} + panic Panic --- :start -> second_flow:data second_flow:res -> :stop + second_flow:err -> panic } -def Secondflow (data any) (res any) { - printer IPrinter +def Secondflow (data any) (res any, err error) { + printer IPrinter? --- :data -> printer:data printer:res -> :res } -interface IPrinter(data T) (res T) +interface IPrinter(data T) (res T, err error) diff --git a/e2e/interface_verbose/main/main.neva b/e2e/interface_verbose/main/main.neva index 4fa45f0f..3b81e62a 100644 --- a/e2e/interface_verbose/main/main.neva +++ b/e2e/interface_verbose/main/main.neva @@ -4,16 +4,18 @@ def Main(start any) (stop any) { second_flow Secondflow { printer fmt.Println } + panic Panic --- :start -> second_flow:data second_flow:res -> :stop + second_flow:err -> panic } -def Secondflow (data any) (res any) { - printer IPrinter +def Secondflow (data any) (res any, err error) { + printer IPrinter? --- :data -> printer:data printer:res -> :res } -interface IPrinter(data T) (res T) +interface IPrinter(data T) (res T, err error) diff --git a/e2e/interface_with_imports/main/main.neva b/e2e/interface_with_imports/main/main.neva index 189027fa..b4429d58 100644 --- a/e2e/interface_with_imports/main/main.neva +++ b/e2e/interface_with_imports/main/main.neva @@ -2,16 +2,18 @@ import { github.com/nevalang/x:main } def Main(start any) (stop any) { sub_component SubComponent{main.Println} + panic Panic --- :start -> sub_component:data sub_component:res -> :stop + sub_component:err -> panic } -def SubComponent(data any) (res any) { - printer IPrinter +def SubComponent(data any) (res any, err error) { + printer IPrinter? --- :data -> printer:data printer:res -> :res } -interface IPrinter(data T) (res T) +interface IPrinter(data T) (res T, err error) diff --git a/e2e/interface_with_imports/neva.yml b/e2e/interface_with_imports/neva.yml index fe07c0aa..736d0326 100644 --- a/e2e/interface_with_imports/neva.yml +++ b/e2e/interface_with_imports/neva.yml @@ -2,4 +2,4 @@ neva: 0.30.2 deps: github.com/nevalang/x: path: github.com/nevalang/x - version: 0.0.16 + version: 0.0.17 diff --git a/e2e/list_with_neg_nums/main/main.neva b/e2e/list_with_neg_nums/main/main.neva index 0cfe78bb..cfbadba2 100644 --- a/e2e/list_with_neg_nums/main/main.neva +++ b/e2e/list_with_neg_nums/main/main.neva @@ -4,7 +4,9 @@ const l list = [-215] def Main(start any) (stop any) { fmt.Println + panic Panic --- :start -> $l -> println:data println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/local_imports/foo/bar/bar.neva b/e2e/local_imports/foo/bar/bar.neva index ff8092b8..12054bef 100644 --- a/e2e/local_imports/foo/bar/bar.neva +++ b/e2e/local_imports/foo/bar/bar.neva @@ -1,7 +1,8 @@ import { fmt } -pub def Println(data any) (sig any) { - fmt.Println +pub def Println(data any) (sig any, err error) { + fmt.Println? --- - :data -> println -> :sig + :data -> println:data + println:res -> :sig } \ No newline at end of file diff --git a/e2e/local_imports/foo/foo.neva b/e2e/local_imports/foo/foo.neva index ff8092b8..12054bef 100644 --- a/e2e/local_imports/foo/foo.neva +++ b/e2e/local_imports/foo/foo.neva @@ -1,7 +1,8 @@ import { fmt } -pub def Println(data any) (sig any) { - fmt.Println +pub def Println(data any) (sig any, err error) { + fmt.Println? --- - :data -> println -> :sig + :data -> println:data + println:res -> :sig } \ No newline at end of file diff --git a/e2e/local_imports/main/main.neva b/e2e/local_imports/main/main.neva index f7a463bd..fe838884 100644 --- a/e2e/local_imports/main/main.neva +++ b/e2e/local_imports/main/main.neva @@ -6,6 +6,10 @@ import { def Main(start any) (stop any) { foo foo.Println bar bar.Println + panic Panic --- - :start -> 42 -> foo -> bar -> :stop + :start -> 42 -> foo:data + foo:sig -> bar:data + bar:sig -> :stop + [foo:err, bar:err] -> panic } diff --git a/e2e/logic_gate_and/main/main.neva b/e2e/logic_gate_and/main/main.neva index c71b5696..bd393805 100644 --- a/e2e/logic_gate_and/main/main.neva +++ b/e2e/logic_gate_and/main/main.neva @@ -2,10 +2,13 @@ import { fmt } def Main(start any) (stop any) { fmt.Println, And + panic Panic --- :start -> [ { true -> and:left }, { true -> and:right } ] - and -> println -> :stop + and -> println:data + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/logic_gate_or/main/main.neva b/e2e/logic_gate_or/main/main.neva index 8ec5160c..bba6b41f 100644 --- a/e2e/logic_gate_or/main/main.neva +++ b/e2e/logic_gate_or/main/main.neva @@ -2,10 +2,13 @@ import { fmt } def Main(start any) (stop any) { fmt.Println, Or + panic Panic --- :start -> [ { false -> or:left }, { false -> or:right } ] - or -> println -> :stop + or -> println:data + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/map_list_verbose/main/main.neva b/e2e/map_list_verbose/main/main.neva index 5722b17c..d9de28a1 100644 --- a/e2e/map_list_verbose/main/main.neva +++ b/e2e/map_list_verbose/main/main.neva @@ -9,6 +9,9 @@ def Main(start any) (stop any) { s2l StreamToList println fmt.Println> l2s ListToStream + panic Panic --- - :start -> $lst -> l2s -> map_decr -> s2l -> println -> :stop + :start -> $lst -> l2s -> map_decr -> s2l -> println:data + println:res -> :stop + println:err -> panic } diff --git a/e2e/multiply_numbers/main/main.neva b/e2e/multiply_numbers/main/main.neva index 0a6532f9..79293bb2 100644 --- a/e2e/multiply_numbers/main/main.neva +++ b/e2e/multiply_numbers/main/main.neva @@ -6,8 +6,11 @@ def Main(start any) (stop any) { fmt.Println Reduce{Mul} ListToStream + panic Panic --- :start -> $l -> listToStream -> reduce:data 1 -> reduce:init - reduce -> println -> :stop + reduce -> println:data + println:res -> :stop + println:err -> panic } diff --git a/e2e/order_dependend_with_arr_inport/main/main.neva b/e2e/order_dependend_with_arr_inport/main/main.neva index 196b2437..cb92ead7 100644 --- a/e2e/order_dependend_with_arr_inport/main/main.neva +++ b/e2e/order_dependend_with_arr_inport/main/main.neva @@ -6,8 +6,11 @@ def Main(start any) (stop any) { fmt.Println Reduce{Sub} ListToStream + panic Panic --- :start -> $l -> listToStream -> reduce:data 0 -> reduce:init - reduce -> println -> :stop + reduce -> println:data + println:res -> :stop + println:err -> panic } diff --git a/e2e/print_float/main/main.neva b/e2e/print_float/main/main.neva index 1ede436c..b331622b 100644 --- a/e2e/print_float/main/main.neva +++ b/e2e/print_float/main/main.neva @@ -4,7 +4,9 @@ const x float = 42 def Main(start any) (stop any) { fmt.Println + panic Panic --- :start -> $x -> println:data println:res -> :stop + println:err -> panic } diff --git a/e2e/regex_submatch_verbose/main/main.neva b/e2e/regex_submatch_verbose/main/main.neva index ef8056cf..08a87caa 100644 --- a/e2e/regex_submatch_verbose/main/main.neva +++ b/e2e/regex_submatch_verbose/main/main.neva @@ -9,5 +9,5 @@ def Main(start any) (stop any) { ] submatch:res -> println:data println:res -> :stop - submatch:err -> panic + [submatch:err, println:err] -> panic } diff --git a/e2e/run_cli_not_from_module_root/foo/bar/main.neva b/e2e/run_cli_not_from_module_root/foo/bar/main.neva index 9d985e05..73892a22 100644 --- a/e2e/run_cli_not_from_module_root/foo/bar/main.neva +++ b/e2e/run_cli_not_from_module_root/foo/bar/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + panic Panic --- - :start -> 42 -> println -> :stop + :start -> 42 -> println:data + println:res -> :stop + println:err -> panic } diff --git a/e2e/simple_fan_out/main/main.neva b/e2e/simple_fan_out/main/main.neva index 7243812c..3b5d39f3 100644 --- a/e2e/simple_fan_out/main/main.neva +++ b/e2e/simple_fan_out/main/main.neva @@ -3,7 +3,9 @@ import { time, fmt } def Main(start any) (stop any) { p1 fmt.Println p2 fmt.Println + panic Panic --- - :start -> [p1, p2] - p1 -> { p2 -> :stop } + :start -> [p1:data, p2:data] + p1:res -> { p2:res -> :stop } + [p1:err, p2:err] -> panic } diff --git a/e2e/slow_iteration_with_for/main/main.neva b/e2e/slow_iteration_with_for/main/main.neva index 52a84f36..62d02ee6 100644 --- a/e2e/slow_iteration_with_for/main/main.neva +++ b/e2e/slow_iteration_with_for/main/main.neva @@ -15,8 +15,11 @@ def Main(start any) (stop any) { def Slow(data int) (sig any) { time.Delay fmt.Println + panic Panic --- :data -> delay:data $time.second -> delay:dur - delay -> println -> :sig + delay -> println:data + println:res -> :sig + println:err -> panic } diff --git a/e2e/slow_iteration_with_map/main/main.neva b/e2e/slow_iteration_with_map/main/main.neva index 1ce061ed..7b0f19ee 100644 --- a/e2e/slow_iteration_with_map/main/main.neva +++ b/e2e/slow_iteration_with_map/main/main.neva @@ -11,8 +11,11 @@ def Main(start any) (stop any) { map Map{Slow} s2l StreamToList println fmt.Println> + panic Panic --- - :start -> $lst -> l2s -> map -> s2l -> println -> :stop + :start -> $lst -> l2s -> map -> s2l -> println:data + println:res -> :stop + println:err -> panic } def Slow(data int) (res int) { diff --git a/e2e/struct_builder_verbose/main/main.neva b/e2e/struct_builder_verbose/main/main.neva index 6906a198..06fc234c 100644 --- a/e2e/struct_builder_verbose/main/main.neva +++ b/e2e/struct_builder_verbose/main/main.neva @@ -12,6 +12,7 @@ def MyStructBuilder(age int, name string) (res User) def Main(start any) (stop any) { println fmt.Println builder MyStructBuilder + panic Panic --- :start -> [ 'John' -> builder:name, @@ -19,4 +20,5 @@ def Main(start any) (stop any) { ] builder:res -> println:data println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/e2e/struct_builder_with_sugar/main/main.neva b/e2e/struct_builder_with_sugar/main/main.neva index adc6ce06..25852cf9 100644 --- a/e2e/struct_builder_with_sugar/main/main.neva +++ b/e2e/struct_builder_with_sugar/main/main.neva @@ -6,6 +6,7 @@ type User struct { def Main(start any) (stop any) { println fmt.Println builder Struct // FIXME - cannot use 'struct' as a node name + panic Panic --- :start -> [ 'John' -> builder:name, @@ -13,4 +14,5 @@ def Main(start any) (stop any) { ] builder:res -> println:data println:res -> :stop + println:err -> panic } diff --git a/e2e/struct_selector_on_port_addr/main/main.neva b/e2e/struct_selector_on_port_addr/main/main.neva index 5ccd7bc1..5ad3f5ec 100644 --- a/e2e/struct_selector_on_port_addr/main/main.neva +++ b/e2e/struct_selector_on_port_addr/main/main.neva @@ -1,11 +1,12 @@ import { fmt } def Main(start any) (stop any) { - Foo, fmt.Println + Foo, fmt.Println, Panic --- :start -> foo:sig foo:res -> .a -> println:data println:res -> :stop + println:err -> panic } const s struct { a int } = { a: 42 } diff --git a/e2e/struct_selector_verbose/main/main.neva b/e2e/struct_selector_verbose/main/main.neva index 7d811897..910a6267 100644 --- a/e2e/struct_selector_verbose/main/main.neva +++ b/e2e/struct_selector_verbose/main/main.neva @@ -21,6 +21,7 @@ const path list = ['pet', 'name'] def Main(start any) (stop any) { fmt.Println + Panic #bind(path) Field @@ -30,4 +31,5 @@ def Main(start any) (stop any) { :start -> $user -> field:data field:res -> println:data println:res -> :stop + println:err -> panic } diff --git a/e2e/struct_selector_with_more_sugar/main/main.neva b/e2e/struct_selector_with_more_sugar/main/main.neva index 71e73f78..4dadea0a 100644 --- a/e2e/struct_selector_with_more_sugar/main/main.neva +++ b/e2e/struct_selector_with_more_sugar/main/main.neva @@ -11,10 +11,12 @@ type User struct { type Pet struct { name string } def Main(start any) (stop any) { - UserSender, fmt.Println + UserSender, fmt.Println, Panic --- :start -> userSender:sig - userSender -> .pet.name -> println -> :stop + userSender -> .pet.name -> println:data + println:res -> :stop + println:err -> panic } const user User = { diff --git a/e2e/struct_selector_with_sugar/main/main.neva b/e2e/struct_selector_with_sugar/main/main.neva index 68dc94b7..55d6b570 100644 --- a/e2e/struct_selector_with_sugar/main/main.neva +++ b/e2e/struct_selector_with_sugar/main/main.neva @@ -11,11 +11,12 @@ type User struct { type Pet struct { name string } def Main(start any) (stop any) { - UserSender, fmt.Println + UserSender, fmt.Println, Panic --- :start -> userSender:sig userSender:u -> .pet.name -> println:data println:res -> :stop + println:err -> panic } const user User = { diff --git a/examples/99_bottles/main.neva b/examples/99_bottles/main.neva index d7a3d451..470f8835 100644 --- a/examples/99_bottles/main.neva +++ b/examples/99_bottles/main.neva @@ -29,8 +29,8 @@ def FirstLine(data int) (sig any) { '$0 bottles of beer on the wall, $0 bottles of beer.\n' -> p3:tpl ] } - [p1, p2, p3:sig] -> :sig - p3:err -> panic + [p1:res, p2:res, p3:sig] -> :sig + [p1:err, p2:err, p3:err] -> panic } def SecondLine(data int) (sig any) { @@ -49,6 +49,6 @@ def SecondLine(data int) (sig any) { 'Take one down and pass it around, $0 bottles of beer on the wall.\n\n' -> p4:tpl ] } - [p1, p2, p3, p4:sig] -> :sig - p4:err -> panic + [p1:res, p2:res, p3:res, p4:sig] -> :sig + [p1:err, p2:err, p3:err, p4:err] -> panic } diff --git a/examples/add_numbers/main.neva b/examples/add_numbers/main.neva index 3fbe94ad..f1146265 100644 --- a/examples/add_numbers/main.neva +++ b/examples/add_numbers/main.neva @@ -2,6 +2,9 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + Panic --- :start -> { (1 + 2) -> println -> :stop } + //println:res -> :stop + println:err -> panic } diff --git a/examples/add_numbers_from_stdin/main.neva b/examples/add_numbers_from_stdin/main.neva index 8e6e5d8d..6163e48b 100644 --- a/examples/add_numbers_from_stdin/main.neva +++ b/examples/add_numbers_from_stdin/main.neva @@ -1,28 +1,28 @@ import { strconv, fmt } def Main(start any) (stop any) { - App, fmt.Println + App, fmt.Println, Panic --- :start -> app - [app:res, app:err] -> println -> :stop + [app:res, app:err] -> println:data + println:res -> :stop + println:err -> panic } def App(sig any) (res int, err error) { - readFirstInt ReadIntFromStdin - readSecondInt ReadIntFromStdin + readFirstInt ReadIntFromStdin? + readSecondInt ReadIntFromStdin? add Add --- :sig -> readFirstInt readFirstInt:num -> [add:left, readSecondInt] readSecondInt:num -> add:right - [readFirstInt:err, readSecondInt:err] -> :err add -> :res } def ReadIntFromStdin(sig any) (num int, err error) { - fmt.Scanln, strconv.ParseNum + fmt.Scanln, strconv.ParseNum? --- :sig -> scanln -> parseNum parseNum:res -> :num - parseNum:err -> :err } diff --git a/examples/advanced_error_handling/main.neva b/examples/advanced_error_handling/main.neva index 3b996625..5f17a323 100644 --- a/examples/advanced_error_handling/main.neva +++ b/examples/advanced_error_handling/main.neva @@ -4,8 +4,9 @@ def Main(start any) (stop any) { App, fmt.Println, Panic // `Panic` will terminate the program --- :start -> app:sig - app:err -> panic // we only handle `:err` at this lvl - app:data -> println -> :stop + [app:err, println:err] -> panic // we only handle `:err` at this lvl + app:data -> println:data + println:res -> :stop } def App(sig any) (data string, err error) { diff --git a/examples/compare_values/main.neva b/examples/compare_values/main.neva index 27166d73..5be5eef3 100644 --- a/examples/compare_values/main.neva +++ b/examples/compare_values/main.neva @@ -2,8 +2,11 @@ import { fmt } def Main(start any) (stop any) { fmt.Println + Panic --- :start -> { - ((2 == 2) ? 'They match' : 'They do not match') -> println -> :stop + ((2 == 2) ? 'They match' : 'They do not match') -> println:data } + println:res -> :stop + println:err -> panic } diff --git a/examples/const_refs/main.neva b/examples/const_refs/main.neva index 485e4048..731ef247 100644 --- a/examples/const_refs/main.neva +++ b/examples/const_refs/main.neva @@ -16,7 +16,9 @@ const numsStruct NumsStruct = { } def Main(start any) (stop any) { - fmt.Println + fmt.Println, Panic --- - :start -> $numsStruct -> println -> :stop + :start -> $numsStruct -> println:data + println:res -> :stop + println:err -> panic } diff --git a/examples/delayed_echo/main.neva b/examples/delayed_echo/main.neva index f021ec4e..3340e2e2 100644 --- a/examples/delayed_echo/main.neva +++ b/examples/delayed_echo/main.neva @@ -13,6 +13,7 @@ def Main(start any) (stop any) { w5 Worker w6 Worker wg sync.WaitGroup + panic Panic --- :start -> [ 'Hello' -> println, @@ -24,13 +25,14 @@ def Main(start any) (stop any) { 'World' -> w6 ] 6 -> wg:count - [w1, w2, w3, w4, w5, w6, println] -> wg:sig + [w1:sig, w2:sig, w3:sig, w4:sig, w5:sig, w6:sig, println:res] -> wg:sig wg -> :stop + [w1:err, w2:err, w3:err, w4:err, w5:err, w6:err, println:err] -> panic } -def Worker(data any) (sig any) { +def Worker(data any) (sig any, err error) { delay time.Delay - println fmt.Println + println fmt.Println? --- :data -> delay:data $time.second -> delay:dur diff --git a/examples/dict/main.neva b/examples/dict/main.neva index 580b3143..28b5451b 100644 --- a/examples/dict/main.neva +++ b/examples/dict/main.neva @@ -6,9 +6,11 @@ const d dict = { } def Main(start any) (stop any) { - Get, fmt.Println + Get, fmt.Println, Panic --- :start -> 'name' -> get:key $d -> get:dict - [get:res, get:err] -> println -> :stop + [get:res, get:err] -> println:data + println:res -> :stop + println:err -> panic } diff --git a/examples/echo/main.neva b/examples/echo/main.neva index a1b43c48..381e6d1e 100644 --- a/examples/echo/main.neva +++ b/examples/echo/main.neva @@ -1,7 +1,9 @@ import { fmt } def Main(start any) (stop any) { - fmt.Scanln, fmt.Println + fmt.Scanln, fmt.Println, Panic --- - :start -> scanln -> println -> :stop + :start -> scanln -> println:data + println:res -> :stop + println:err -> panic } diff --git a/examples/enums/main.neva b/examples/enums/main.neva index 32b71ac6..c9fcc2af 100644 --- a/examples/enums/main.neva +++ b/examples/enums/main.neva @@ -1,9 +1,11 @@ import { fmt } def Main(start any) (stop any) { - PrintDay + PrintDay, Panic --- - :start -> { Day::Friday -> printDay -> :stop } + :start -> { Day::Friday -> printDay:day } + printDay:sig -> :stop + printDay:err -> panic } type Day enum { @@ -16,8 +18,9 @@ type Day enum { Sunday } -def PrintDay(day Day) (sig any) { - fmt.Println +def PrintDay(day Day) (sig any, err error) { + fmt.Println? --- - :day -> println -> :sig + :day -> println:data + println:res -> :sig } diff --git a/examples/file_read_all/main.neva b/examples/file_read_all/main.neva index 2d042a5e..89901285 100644 --- a/examples/file_read_all/main.neva +++ b/examples/file_read_all/main.neva @@ -1,8 +1,10 @@ import { io, fmt } def Main(start any) (stop any) { - io.ReadAll, fmt.Println + io.ReadAll, fmt.Println, Panic --- :start -> 'file_read_all/main.neva' -> readAll:filename - [readAll:res, readAll:err] -> println -> :stop + readAll:res -> println:data + println:res -> :stop + [readAll:err, println:err] -> panic } diff --git a/examples/file_write_all/main.neva b/examples/file_write_all/main.neva index 5b8ca546..ee897962 100644 --- a/examples/file_write_all/main.neva +++ b/examples/file_write_all/main.neva @@ -1,12 +1,12 @@ import { io, fmt } def Main(start any) (stop any) { - io.WriteAll, fmt.Println + io.WriteAll, Panic --- :start -> [ 'file_writer_example.txt' -> writeAll:filename, 'Hello, io.WriteAll!' -> writeAll:data ] - writeAll:err -> println - [writeAll:sig, println] -> :stop + writeAll:err -> panic + writeAll:sig -> :stop } diff --git a/examples/hello_world/main.neva b/examples/hello_world/main.neva index 971802cd..53624ab9 100644 --- a/examples/hello_world/main.neva +++ b/examples/hello_world/main.neva @@ -1,7 +1,9 @@ import { fmt } def Main(start any) (stop any) { - fmt.Println + fmt.Println, Panic --- - :start -> 'Hello, World!' -> println -> :stop + :start -> 'Hello, World!' -> println:data + println:res -> :stop + println:err -> panic } diff --git a/examples/http_get/main.neva b/examples/http_get/main.neva index 5346102a..0184139b 100644 --- a/examples/http_get/main.neva +++ b/examples/http_get/main.neva @@ -4,6 +4,7 @@ def Main(start any) (stop any) { http.Get, fmt.Println, Panic --- :start -> 'http://www.example.com' -> get - get:res -> .body -> println -> :stop - get:err -> panic + get:res -> .body -> println:data + println:res -> :stop + [get:err, println:err] -> panic } \ No newline at end of file diff --git a/examples/image_png/main.neva b/examples/image_png/main.neva index dd2aecbe..1769415b 100644 --- a/examples/image_png/main.neva +++ b/examples/image_png/main.neva @@ -32,6 +32,7 @@ def Main(start any) (stop any) { image.New, image.Encode NewPixel, NewColor, NewStream, io.WriteAll, printErr fmt.Println + Panic --- :start -> [ 0 -> [newColor:r, newColor:g, newColor:b, newColor:a], @@ -44,5 +45,6 @@ def Main(start any) (stop any) { new:img -> encode:img encode:data -> writeAll:data [new:err, encode:err, writeAll:err] -> printErr - [writeAll:sig, printErr] -> :stop + [writeAll:sig, printErr:res] -> :stop + printErr:err -> panic } diff --git a/examples/interfaces/main.neva b/examples/interfaces/main.neva index df922560..0c211406 100644 --- a/examples/interfaces/main.neva +++ b/examples/interfaces/main.neva @@ -2,14 +2,17 @@ import { fmt } def Main(start any) (stop any) { wrapper Wrapper{fmt.Println} + panic Panic --- - :start -> wrapper -> :stop + :start -> wrapper:data + wrapper:res -> :stop + wrapper:err -> panic } -def Wrapper(data any) (res any) { - printer IPrinter +def Wrapper(data any) (res any, err error) { + printer IPrinter? --- :data -> printer -> :res } -interface IPrinter(T) (T) +interface IPrinter(T) (T, err error) diff --git a/examples/list_index/main.neva b/examples/list_index/main.neva index 3d634f62..7ed33f46 100644 --- a/examples/list_index/main.neva +++ b/examples/list_index/main.neva @@ -3,11 +3,13 @@ import { lists, fmt } const lst list = [1, 1, 5, 112, 69, 420] def Main(start any) (stop any) { - lists.At, fmt.Println + lists.At, fmt.Println, Panic --- :start -> [ $lst -> at:data, 4 -> at:idx ] - [at:res, at:err] -> println -> :stop + [at:res, at:err] -> println:data + println:res -> :stop + println:err -> panic } diff --git a/examples/list_len/main.neva b/examples/list_len/main.neva index 9cf5dd34..3711c5e9 100644 --- a/examples/list_len/main.neva +++ b/examples/list_len/main.neva @@ -3,7 +3,9 @@ import { fmt } const lst list = [4, 123, 22, 1121, 215] def Main(start any) (stop any) { - fmt.Println, Len> + fmt.Println, Len>, Panic --- - :start -> $lst -> len -> println -> :stop + :start -> $lst -> len -> println:data + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/examples/map_list/main.neva b/examples/map_list/main.neva index 2ea6842a..d14e0911 100644 --- a/examples/map_list/main.neva +++ b/examples/map_list/main.neva @@ -7,6 +7,9 @@ def Main(start any) (stop any) { map_dec Map{Dec} println fmt.Println> l2s ListToStream + panic Panic --- - :start -> $lst -> l2s -> map_dec -> s2l -> println -> :stop + :start -> $lst -> l2s -> map_dec -> s2l -> println:data + println:res -> :stop + println:err -> panic } diff --git a/examples/neva.yml b/examples/neva.yml index fe07c0aa..736d0326 100644 --- a/examples/neva.yml +++ b/examples/neva.yml @@ -2,4 +2,4 @@ neva: 0.30.2 deps: github.com/nevalang/x: path: github.com/nevalang/x - version: 0.0.16 + version: 0.0.17 diff --git a/examples/push_to_list/main.neva b/examples/push_to_list/main.neva index 8ff1a32f..07a7c917 100644 --- a/examples/push_to_list/main.neva +++ b/examples/push_to_list/main.neva @@ -4,11 +4,13 @@ const f int = 69 const l list = [320, 420, 100, -100, 0, 5] def Main(start any) (stop any) { - Push, fmt.Println + Push, fmt.Println, Panic --- :start -> [ $l -> push:lst, $f -> push:data ] - push -> println -> :stop + push -> println:data + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/examples/reduce_list/main.neva b/examples/reduce_list/main.neva index 5435ee6d..c2244715 100644 --- a/examples/reduce_list/main.neva +++ b/examples/reduce_list/main.neva @@ -6,8 +6,11 @@ def Main(start any) (stop any) { l2s ListToStream reduce Reduce{Add} println fmt.Println + panic Panic --- :start -> $lst -> l2s -> reduce:data 0 -> reduce:init - reduce -> println -> :stop + reduce -> println:data + println:res -> :stop + println:err -> panic } diff --git a/examples/regex_submatch/main.neva b/examples/regex_submatch/main.neva index dd491a26..a90ec21a 100644 --- a/examples/regex_submatch/main.neva +++ b/examples/regex_submatch/main.neva @@ -1,11 +1,13 @@ import { regexp, fmt } def Main(start any) (stop any) { - fmt.Println, regexp.Submatch + fmt.Println, regexp.Submatch, Panic --- :start -> [ 'a(x*)b(y|z)c' -> submatch:regexp, '-axxxbyc-' -> submatch:data ] - [submatch:res, submatch:err] -> println -> :stop + submatch:res -> println:data + println:res -> :stop + [submatch:err, println:err] -> panic } \ No newline at end of file diff --git a/examples/split_join_string/main.neva b/examples/split_join_string/main.neva index e6ae4879..ff167dce 100644 --- a/examples/split_join_string/main.neva +++ b/examples/split_join_string/main.neva @@ -1,12 +1,14 @@ import { strings, fmt } def Main(start any) (stop any) { - fmt.Println, strings.Split, strings.Join + fmt.Println, strings.Split, strings.Join, Panic --- :start -> [ 'neva' -> split:data, '' -> split:delim ] - split -> join -> println -> :stop + split -> join -> println:data + println:res -> :stop + println:err -> panic } diff --git a/examples/stream_to_list/main.neva b/examples/stream_to_list/main.neva index 700f2dbf..92fdc019 100644 --- a/examples/stream_to_list/main.neva +++ b/examples/stream_to_list/main.neva @@ -3,6 +3,9 @@ import { fmt } def Main(start any) (stop any) { s2l StreamToList println fmt.Println + panic Panic --- - :start -> 1..11 -> s2l -> println -> :stop + :start -> 1..11 -> s2l -> println:data + println:res -> :stop + println:err -> panic } diff --git a/examples/struct_builder/main.neva b/examples/struct_builder/main.neva index 472c9275..1232bfa9 100644 --- a/examples/struct_builder/main.neva +++ b/examples/struct_builder/main.neva @@ -8,12 +8,14 @@ type User struct { // FIXME:grammar - cannot use 'struct' as a node name def Main(start any) (stop any) { - fmt.Println + fmt.Println, Panic builder Struct --- :start -> [ 'John' -> builder:name, 32 -> builder:age ] - builder -> println -> :stop + builder -> println:data + println:res -> :stop + println:err -> panic } \ No newline at end of file diff --git a/examples/struct_selector/main.neva b/examples/struct_selector/main.neva index b5216e5d..6746e6ed 100644 --- a/examples/struct_selector/main.neva +++ b/examples/struct_selector/main.neva @@ -8,9 +8,11 @@ type User struct { type Pet struct { name string } def Main(start any) (stop any) { - GetUser, fmt.Println + GetUser, fmt.Println, Panic --- - :start -> getUser -> .pet.name -> println -> :stop + :start -> getUser -> .pet.name -> println:data + println:res -> :stop + println:err -> panic } const user User = { diff --git a/examples/switch/main.neva b/examples/switch/main.neva index c4455c53..7ef18531 100644 --- a/examples/switch/main.neva +++ b/examples/switch/main.neva @@ -9,12 +9,15 @@ def Main(start any) (stop any) { upper strings.ToUpper lower strings.ToLower println fmt.Println - panic Panic + panic1 Panic + panic2 Panic --- :start -> 'Enter the name: ' -> print -> scanln -> switch { 'Alice' -> upper 'Bob' -> lower - _ -> panic + _ -> panic1 } - [upper, lower] -> println -> :stop + [upper, lower] -> println:data + println:res -> :stop + println:err -> panic2 } diff --git a/examples/switch_fan_out/main.neva b/examples/switch_fan_out/main.neva index c5b187b2..05ee8087 100644 --- a/examples/switch_fan_out/main.neva +++ b/examples/switch_fan_out/main.neva @@ -9,11 +9,14 @@ def Main(start any) (stop any) { upper strings.ToUpper lower strings.ToLower println fmt.Println - panic Panic + panic1 Panic + panic2 Panic --- :start -> 'Enter the name: ' -> print -> scanln -> switch { 'Alice' -> [upper, lower] - _ -> panic + _ -> panic1 } - (upper + lower) -> println -> :stop + (upper + lower) -> println:data + println:res -> :stop + println:err -> panic2 } diff --git a/examples/wait_group/main.neva b/examples/wait_group/main.neva index 48b667e2..0a6b9b3e 100644 --- a/examples/wait_group/main.neva +++ b/examples/wait_group/main.neva @@ -5,13 +5,15 @@ def Main(start any) (stop any) { p2 fmt.Println p3 fmt.Println wg sync.WaitGroup + panic Panic --- :start -> [ 'Hello' -> p1, 'Neva' -> p2, 'World!' -> p3 ] - [p1, p2, p3] -> wg:sig + [p1:res, p2:res, p3:res] -> wg:sig 3 -> wg:count wg -> :stop + [p1:err, p2:err, p3:err] -> panic } diff --git a/internal/runtime/funcs/println.go b/internal/runtime/funcs/println.go index 0b284721..3f209245 100644 --- a/internal/runtime/funcs/println.go +++ b/internal/runtime/funcs/println.go @@ -20,6 +20,11 @@ func (p println) Create(io runtime.IO, _ runtime.Msg) (func(ctx context.Context) return nil, err } + errOut, err := io.Out.Single("err") + if err != nil { + return nil, err + } + return func(ctx context.Context) { for { dataMsg, ok := dataIn.Receive(ctx) @@ -28,7 +33,10 @@ func (p println) Create(io runtime.IO, _ runtime.Msg) (func(ctx context.Context) } if _, err := fmt.Println(dataMsg); err != nil { - panic(err) + if !errOut.Send(ctx, errFromErr(err)) { + return + } + continue } if !resOut.Send(ctx, dataMsg) { diff --git a/std/fmt/fmt.neva b/std/fmt/fmt.neva index 900a5c25..4f0a756e 100644 --- a/std/fmt/fmt.neva +++ b/std/fmt/fmt.neva @@ -1,6 +1,6 @@ // Println prints to stdout with newline and then sends message further. #extern(println) -pub def Println(data T) (res T) +pub def Println(data T) (res T, err error) // Print prints to stdout without newline and then sends message further. #extern(print) From db64efb7f1198b8a84ce5143976e49239f5262e8 Mon Sep 17 00:00:00 2001 From: mike Date: Mon, 3 Feb 2025 20:53:00 +0100 Subject: [PATCH 2/4] Changed For component and the interface for the handler to return an error. Adjusted testcases for changed For implementation. --- e2e/for_loop_over_list_verbose/main/main.neva | 6 ++-- e2e/for_with_range_and_if/main/main.neva | 6 ++-- e2e/slow_iteration_with_for/main/main.neva | 14 ++++---- examples/99_bottles/main.neva | 33 +++++++++---------- examples/add_numbers/main.neva | 4 +-- examples/filter_list/main.neva | 5 ++- examples/fizzbuzz/main.neva | 5 ++- examples/for_loop_over_list/main.neva | 6 ++-- examples/get_args/main.neva | 6 ++-- examples/match/main.neva | 10 +++--- examples/select/main.neva | 5 ++- examples/stream_product/main.neva | 5 ++- examples/stream_zip/main.neva | 6 ++-- std/builtin/core.neva | 4 +-- std/builtin/streams.neva | 7 ++-- 15 files changed, 73 insertions(+), 49 deletions(-) diff --git a/e2e/for_loop_over_list_verbose/main/main.neva b/e2e/for_loop_over_list_verbose/main/main.neva index f29137c2..a10e8541 100644 --- a/e2e/for_loop_over_list_verbose/main/main.neva +++ b/e2e/for_loop_over_list_verbose/main/main.neva @@ -3,7 +3,9 @@ import { fmt } const lst list = [50, 30, 20, 100] def Main(start any) (stop any) { - ListToStream, For{fmt.Println}, Wait + ListToStream, For{fmt.Println}, Wait, Panic --- - :start -> $lst -> listToStream -> for -> wait -> :stop + :start -> $lst -> listToStream -> for + for:res -> wait -> :stop + for:err -> panic } diff --git a/e2e/for_with_range_and_if/main/main.neva b/e2e/for_with_range_and_if/main/main.neva index a2023bba..c1b185b9 100644 --- a/e2e/for_with_range_and_if/main/main.neva +++ b/e2e/for_with_range_and_if/main/main.neva @@ -3,9 +3,11 @@ import { lists, fmt } const lst list = [true, false] def Main(start any) (stop any) { - ListToStream, For{PrintAsNum}, Wait + ListToStream, For{PrintAsNum}, Wait, Panic --- - :start -> $lst -> listToStream -> for -> wait -> :stop + :start -> $lst -> listToStream -> for + for:res -> wait -> :stop + for:err -> panic } def PrintAsNum(data bool) (sig any) { diff --git a/e2e/slow_iteration_with_for/main/main.neva b/e2e/slow_iteration_with_for/main/main.neva index 62d02ee6..385ac427 100644 --- a/e2e/slow_iteration_with_for/main/main.neva +++ b/e2e/slow_iteration_with_for/main/main.neva @@ -1,25 +1,25 @@ // this e2e test must prove that this issue is fixed: // https://github.com/nevalang/neva/issues/575 -// all elements of the array must be printed befofe program terminate +// all elements of the array must be printed before program terminate import { time, fmt } const lst list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] def Main(start any) (stop any) { - ListToStream, For{Slow}, Wait + ListToStream, For{Slow}, Wait, Panic --- - :start -> $lst -> listToStream -> for -> wait -> :stop + :start -> $lst -> listToStream -> for + for:res -> wait -> :stop + for:err -> panic } -def Slow(data int) (sig any) { +def Slow(data int) (sig any, err error) { time.Delay - fmt.Println - panic Panic + fmt.Println? --- :data -> delay:data $time.second -> delay:dur delay -> println:data println:res -> :sig - println:err -> panic } diff --git a/examples/99_bottles/main.neva b/examples/99_bottles/main.neva index 470f8835..214dc450 100644 --- a/examples/99_bottles/main.neva +++ b/examples/99_bottles/main.neva @@ -3,23 +3,25 @@ import { fmt } def Main(start any) (stop any) { print For{Next2Lines} wait Wait + panic Panic --- - :start -> 99..-1 -> print -> wait -> :stop + :start -> 99..-1 -> print + print:res -> wait -> :stop + print:err -> panic } -def Next2Lines(data int) (sig any) { - first Tap{FirstLine} +def Next2Lines(data int) (sig any, err error) { + first Tap{FirstLine}? dec Dec - second SecondLine + second SecondLine? --- :data -> first -> dec -> second -> :sig } -def FirstLine(data int) (sig any) { - p1 fmt.Println - p2 fmt.Println - p3 fmt.Printf - panic Panic +def FirstLine(data int) (sig any, err error) { + p1 fmt.Println? + p2 fmt.Println? + p3 fmt.Printf? --- :data -> switch { 0 -> 'No more bottles of beer on the wall, no more bottles of beer.' -> p1 @@ -30,15 +32,13 @@ def FirstLine(data int) (sig any) { ] } [p1:res, p2:res, p3:sig] -> :sig - [p1:err, p2:err, p3:err] -> panic } -def SecondLine(data int) (sig any) { - p1 fmt.Println - p2 fmt.Println - p3 fmt.Println - p4 fmt.Printf - panic Panic +def SecondLine(data int) (sig any, err error) { + p1 fmt.Println? + p2 fmt.Println? + p3 fmt.Println? + p4 fmt.Printf? --- :data -> switch { -1 -> 'Go to the store and buy some more, 99 bottles of beer on the wall.' -> p1 @@ -50,5 +50,4 @@ def SecondLine(data int) (sig any) { ] } [p1:res, p2:res, p3:res, p4:sig] -> :sig - [p1:err, p2:err, p3:err, p4:err] -> panic } diff --git a/examples/add_numbers/main.neva b/examples/add_numbers/main.neva index f1146265..14dcc000 100644 --- a/examples/add_numbers/main.neva +++ b/examples/add_numbers/main.neva @@ -4,7 +4,7 @@ def Main(start any) (stop any) { fmt.Println Panic --- - :start -> { (1 + 2) -> println -> :stop } - //println:res -> :stop + :start -> { (1 + 2) -> println } + println:res -> :stop println:err -> panic } diff --git a/examples/filter_list/main.neva b/examples/filter_list/main.neva index 3495b4f7..1148d22d 100644 --- a/examples/filter_list/main.neva +++ b/examples/filter_list/main.neva @@ -7,8 +7,11 @@ def Main(start any) (stop any) { filter_even Filter{predicate Even} for_print For{fmt.Println} wait Wait + panic Panic --- - :start -> $numbers -> list_to_stream1-> filter_even -> for_print -> wait -> :stop + :start -> $numbers -> list_to_stream1-> filter_even -> for_print + for_print:res -> wait -> :stop + for_print:err -> panic } def Even(data int) (res bool) { diff --git a/examples/fizzbuzz/main.neva b/examples/fizzbuzz/main.neva index b1f3eb57..2880a8f4 100644 --- a/examples/fizzbuzz/main.neva +++ b/examples/fizzbuzz/main.neva @@ -4,8 +4,11 @@ def Main(start any) (stop any) { Map{FizzBuzz} For{fmt.Println} Wait + Panic --- - :start -> 1..101 -> map -> for -> wait -> :stop + :start -> 1..101 -> map -> for + for:res -> wait -> :stop + for:err -> panic } def FizzBuzz(data int) (res string | int) { diff --git a/examples/for_loop_over_list/main.neva b/examples/for_loop_over_list/main.neva index b431d6e6..4243e3cf 100644 --- a/examples/for_loop_over_list/main.neva +++ b/examples/for_loop_over_list/main.neva @@ -3,7 +3,9 @@ import { fmt } const lst list = [1, 2, 3] def Main(start any) (stop any) { - ListToStream, For{fmt.Println}, Wait + ListToStream, For{fmt.Println}, Wait, Panic --- - :start -> $lst -> listToStream -> for -> wait -> :stop + :start -> $lst -> listToStream -> for + for:res -> wait -> :stop + for:err -> panic } diff --git a/examples/get_args/main.neva b/examples/get_args/main.neva index e00739f5..d927a520 100644 --- a/examples/get_args/main.neva +++ b/examples/get_args/main.neva @@ -1,7 +1,9 @@ import { os, fmt } def Main(start any) (stop any) { - os.Args, ListToStream, For{fmt.Println}, Wait + os.Args, ListToStream, For{fmt.Println}, Wait, Panic --- - :start -> args -> listToStream -> for -> wait -> :stop + :start -> args -> listToStream -> for + for:res -> wait -> :stop + for:err -> panic } \ No newline at end of file diff --git a/examples/match/main.neva b/examples/match/main.neva index 71aac8b2..b692eb7c 100644 --- a/examples/match/main.neva +++ b/examples/match/main.neva @@ -1,13 +1,15 @@ import { fmt } def Main(start any) (stop any) { - For{Handler}, Wait + For{Handler}, Wait, Panic --- - :start -> 1..5 -> for -> wait -> :stop + :start -> 1..5 -> for + for:res -> wait -> :stop + for:err -> panic } -def Handler(data int) (sig any) { - Match, fmt.Println +def Handler(data int) (sig any, err error) { + Match, fmt.Println? --- diff --git a/examples/select/main.neva b/examples/select/main.neva index 7eed2e64..7ac78fc6 100644 --- a/examples/select/main.neva +++ b/examples/select/main.neva @@ -6,8 +6,11 @@ def Main(start any) (stop any) { Map{Handler} For{fmt.Println} Wait + Panic --- - :start -> 1..5 -> map -> for -> wait -> :stop + :start -> 1..5 -> map -> for + for:res -> wait -> :stop + for:err -> panic } def Handler(data int) (res string) { diff --git a/examples/stream_product/main.neva b/examples/stream_product/main.neva index 95f74058..60b5c436 100644 --- a/examples/stream_product/main.neva +++ b/examples/stream_product/main.neva @@ -6,10 +6,13 @@ def Main(start any) (stop any) { streams.Product For{fmt.Println} Wait + Panic --- :start -> [ 0..3 -> product:first, 0..3 -> product:second ] - product -> for -> wait -> :stop + product -> for + for:res -> wait -> :stop + for:err -> panic } diff --git a/examples/stream_zip/main.neva b/examples/stream_zip/main.neva index 4f0b81a1..5cec9414 100644 --- a/examples/stream_zip/main.neva +++ b/examples/stream_zip/main.neva @@ -4,9 +4,11 @@ const strings list = ['a', 'b', 'c'] def Main(start any) (stop any) { ListToStream, streams.Zip - For{fmt.Println}, Wait + For{fmt.Println}, Wait, Panic --- :start -> 0..10 -> zip:first $strings -> listToStream -> zip:second - zip -> for -> wait -> :stop + zip -> for + for:res -> wait -> :stop + for:err -> panic } \ No newline at end of file diff --git a/std/builtin/core.neva b/std/builtin/core.neva index ddb87e15..3c04f144 100644 --- a/std/builtin/core.neva +++ b/std/builtin/core.neva @@ -60,10 +60,10 @@ pub def Pass(data T) (res T) { // more, it leads to need for explicit locks. Deferred connections do not cover // this case. Explicit lock make network harder to reason about. // `Tap` is a higher-order component, that implements this logic for you. -// All you need to do, is to provide dependency node, thar receives data and +// All you need to do, is to provide dependency node, that receives data and // sends a signal when finishes. Signal could be of any type, so no need for // dealing with locks manually. Handler can send error, in that case `Tap` will -// propogate it up to parent node. +// propagate it up to parent node. pub def Tap(data T) (res T) { lock Lock handler ITapHandler diff --git a/std/builtin/streams.neva b/std/builtin/streams.neva index 85f8b4f7..b777ddb1 100644 --- a/std/builtin/streams.neva +++ b/std/builtin/streams.neva @@ -112,7 +112,7 @@ pub def Accumulator(init T, upd T, last bool) (cur T, res T) // // Like other iterators, it processes items one at a time without blocking the stream. // To wait for all items to be processed, use with `Wait`. -pub def For(data stream) (res stream) { +pub def For(data stream) (res stream, err error) { first First // to check if current msg is the first lock1 Lock> // to lock current msg before sending to handler lock2 Lock> // to lock current msg before sending downstream @@ -128,10 +128,11 @@ pub def For(data stream) (res stream) { [first:then, pass1] -> lock1:sig pass2 -> lock2:sig - handler -> [pass1, pass2] + handler:res -> [pass1, pass2] + handler:err -> :err } -pub interface ISideEffector(T) (any) +pub interface ISideEffector(T) (res any, err error) // `First` is a helper that allows to check if given stream item is the first one. def First(data stream) (then stream, else stream) { From 678b7c869c18d040c7ae164a43691fb2858289ba Mon Sep 17 00:00:00 2001 From: mike Date: Thu, 6 Feb 2025 21:57:06 +0100 Subject: [PATCH 3/4] Skipped e2e-test for_with_range_and_if. Adjusted neva new template for new println syntax. Updated documentation with new println syntax. --- README.md | 8 ++- docs/book/components.md | 15 +++-- docs/book/directives.md | 4 +- docs/book/networks.md | 28 +++++---- docs/book/program_structure.md | 3 +- docs/tutorial.md | 91 +++++++++++++++------------ e2e/for_with_range_and_if/e2e_test.go | 1 + internal/cli/new.go | 3 +- 8 files changed, 89 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index f2c09225..fa9d10e8 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,8 @@ import { fmt } def Main(start any) (stop any) { println fmt.Println --- - :start -> 'Hello, World!' -> println -> :stop + :start -> 'Hello, World!' -> println + [println:res, println:err] -> :stop } ``` @@ -58,7 +59,10 @@ What's happening here: - `import { fmt }` loads the `fmt` package for printing - `def Main` defines the main component with input port `start` and output port `stop` of type `any` (it's safe since it's only used as a signal) -- `:start -> 'Hello, World!' -> println -> :stop` defines a connection that sends the string to `println` when program starts and terminates after printing (runtime sends a message to `Main:start` at startup and waits for `Main:stop` to terminate) +- `:start -> 'Hello, World!' -> println` defines a connection that sends the string to `println` when the program starts +- The runtime sends a message to `Main:start` at startup and waits for `Main:stop` to terminate +- `[println:res, println:err] -> :stop` defines a connection that sends either println:res or println:err as the termination signal, depending on which case returned from println. +- As in Go, errors need to be handled. Removing `println:err` from this example would result in a compiler error. ## 🔥 Features diff --git a/docs/book/components.md b/docs/book/components.md index 36c0ea9b..f8610046 100644 --- a/docs/book/components.md +++ b/docs/book/components.md @@ -54,7 +54,8 @@ Normal component `Main` with a `println` node (instance of `Println`): def Main(start any) (stop any) { Println --- - :start -> { 42 -> println -> :stop } + :start -> { 42 -> println } + [println:res, println:err] -> :stop } ``` @@ -65,7 +66,9 @@ def Main(start any) (stop any) { p1 Println p2 Println --- - :start -> { 42 -> p1 -> p2 -> :stop } + :start -> { 42 -> p1 } + [p1:res, p1:err] -> p2 + [p2:res, p2:err] -> :stop } ``` @@ -101,7 +104,7 @@ def App(data any, prod bool) (sig any) { This not only makes the code more complex but also means we have to initialize both implementations: `ProdLogger` in the test environment and `MockLogger` in the production environment, even though they are not needed in those respective contexts. What if you need to read environment variables to initialize a component? For example, your logger might need to send requests to a third-party service to collect errors. And finally, imagine if it were not a boolean flag but an enum with several possible states. The complexity would increase dramatically. -> As you can see it's possible to write nodes in a single line, separated by comma: `Cond, Logic, Println, Mock`. Don't abuse this style - Nevalang is not about clever one-liners. +> As you can see it's possible to write nodes in a single line, separated by comma: `Cond, Logic, Mock`. Don't abuse this style - Nevalang is not about clever one-liners, as you can see with `Println`. Let's implement this using dependency injection. First, define an interface: @@ -182,9 +185,11 @@ Components can pass type parameters from their interface to node expressions: ```neva def Bar(data T) (sig any) { - Println + Println, Panic --- - :data -> println -> :sig + :data -> println + println:res -> :sig + println:err -> panic } ``` diff --git a/docs/book/directives.md b/docs/book/directives.md index 2afe92fe..7a051bd4 100644 --- a/docs/book/directives.md +++ b/docs/book/directives.md @@ -8,7 +8,7 @@ Tells compiler a component lacks source code implementation and requires a runti ```neva #extern(println) -pub def Println(data T) (sig T) +pub def Println(data T) (res T, err error) ``` ### Overloading @@ -36,7 +36,7 @@ def Main(start any) (stop any) { :start -> lock:sig greeting:res -> lock:data lock:data -> println:data - println:res -> :stop + [println:res, println:err] -> :stop } ``` diff --git a/docs/book/networks.md b/docs/book/networks.md index 91f0c337..eaa2c953 100644 --- a/docs/book/networks.md +++ b/docs/book/networks.md @@ -323,7 +323,8 @@ type Person struct { age int } def Foo(person Person) (sig any) { fmt.Println --- - :person -> .age -> println -> :sig + :person -> .age -> println + [println:res, println:err] -> :sig } ``` @@ -426,17 +427,17 @@ Here's an example using this feature: ```neva def Foo(data) (sig) { - Println + Print --- - :data -> println -> :sig + :data -> print -> :sig } ``` -`:data -> println -> :sig` combines port-address on the sender-side and chained connection on the receiver-side. `println -> :stop` is chained to `:data ->`. Here's a desugared version: +`:data -> print -> :sig` combines port-address on the sender-side and chained connection on the receiver-side. `print -> :stop` is chained to `:data ->`. Here's a desugared version: ```neva -:data -> println -println -> :sig +:data -> print +print -> :sig ``` Components don't need matching inport and outport names. Chained connections require one port per side. Both `def Foo(bar) (bar)` and `def Foo (bar) (baz)` are valid. @@ -462,20 +463,20 @@ In controlflow programming, instructions execute sequentially. In Nevalang's dat Let's say we want to print 42 and then terminate. ```neva -42 -> println -> :stop +42 -> print -> :stop ``` -Turns out, this program is indeterministic and could give different outputs. The problem is that `42 ->` acts like an emitter sending messages in an infinite loop. Therefore, `42` might reach `println` twice if the program doesn't terminate quickly enough: +Turns out, this program is indeterministic and could give different outputs. The problem is that `42 ->` acts like an emitter sending messages in an infinite loop. Therefore, `42` might reach `print` twice if the program doesn't terminate quickly enough: -1. `42` received and printed by `println` -2. signal sent from `println` to `:stop` +1. `42` received and printed by `print` +2. signal sent from `print` to `:stop` 3. new `42` sent and printed again 4. runtime processed `:stop` signal and terminated the program To ensure `42` is printed once, synchronize it with `:start` using "defer". Here's the fix: ```neva -:start -> { 42 -> println -> :stop } +:start -> { 42 -> print -> :stop } ``` This syntax sugar inserts a `Lock` node between `:start` and `42`. Here's the desugared version: @@ -486,7 +487,7 @@ def Main(start any) (stop any) { --- :start -> lock:sig 42 -> lock:data - lock:data -> println -> :stop + lock:data -> print -> :stop } ``` @@ -705,7 +706,8 @@ def Main() () { 1 -> wrap[0] 2 -> wrap[1] 3 -> wrap[2] - wrap -> println -> :stop + wrap -> println + [println:res, println:err] -> :stop } ``` diff --git a/docs/book/program_structure.md b/docs/book/program_structure.md index 85419a82..d3b470aa 100644 --- a/docs/book/program_structure.md +++ b/docs/book/program_structure.md @@ -300,7 +300,8 @@ import { def Main(start any) (stop any) { bar.AddP, Println --- - :start -> { $foo.p -> addP:right -> println -> :stop } + :start -> { $foo.p -> addP:right -> println } + [println:res, println:err] -> :stop } ``` diff --git a/docs/tutorial.md b/docs/tutorial.md index 402e0d04..b37044bd 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -107,7 +107,8 @@ import { fmt } def Main(start any) (stop any) { println fmt.Println --- - :start -> 'Hello, World!' -> println -> :stop + :start -> 'Hello, World!' -> println + [println:res, println:err] -> :stop } ``` @@ -163,7 +164,8 @@ import { fmt } def Main(start any) (stop any) { println fmt.Println --- - :start -> println -> :stop + :start -> println + [println:res, println:err] -> :stop } ``` @@ -188,7 +190,8 @@ import { fmt } def Main(start any) (stop any) { println fmt.Println --- - :start -> 'Hello, World!' -> println -> :stop + :start -> 'Hello, World!' -> println + [println:res, println:err] -> :stop } ``` @@ -234,7 +237,8 @@ const greeting string = 'Hello!' def Main(start any) (stop any) { println fmt.Println --- - :start -> $greeting -> println -> :stop + :start -> $greeting -> println + [println:res, println:err] -> :stop } ``` @@ -271,7 +275,8 @@ import { fmt } def Main(start any) (stop any) { println fmt.Println --- - :start -> 'Hello, World!' -> println -> :stop + :start -> 'Hello, World!' -> println + [println:res, println:err] -> :stop } ``` @@ -308,7 +313,8 @@ def Main(start any) (stop any) { greet utils.Greet // new node println fmt.Println --- - :start -> 'World' -> greet -> println -> :stop // new connection + :start -> 'World' -> greet -> println + [println:res, println:err] -> :stop // new connection } ``` @@ -365,7 +371,8 @@ def Main(start any) (stop any) { exclaim AddExclamation // same package, no import needed println fmt.Println --- - :start -> 'World' -> greet -> exclaim -> println -> :stop + :start -> 'World' -> greet -> exclaim -> println + [println:res, println:err] -> :stop } ``` @@ -397,17 +404,10 @@ pub def Greet(data string) (res string) { } ``` -Same true for `fmt.Println`: - -```neva -// fmt package -pub def Println(data T) (sig struct{}) -``` - This allowed us to chain nodes together: ```neva -:start -> 'World' -> greet -> println -> :stop +:start -> 'World' -> greet -> println ``` When chaining nodes, we actually reference their ports implicitly. The chain could be written more verbosely as: @@ -415,7 +415,6 @@ When chaining nodes, we actually reference their ports implicitly. The chain cou ```neva :start -> 'World' -> greet:data greet:res -> println:data -println:res -> :stop ``` Both versions are equivalent, but the chained syntax is preferred for readability. @@ -452,14 +451,12 @@ def Main(start any) (stop any) { --- :start -> 'Hello, ' -> concat:prefix 'World' -> concat:suffix - concat -> println -> :stop + concat -> println + [println:res, println:err] -> :stop } ``` -Notice that: - -1. We can omit `concat:res ->` and write just `concat ->` since `Concat` has one outport -2. We can chain `-> println ->` since it still has a single port +Notice that we can omit `concat:res ->` and write just `concat ->` since `Concat` has one outport. Let's add a `debug` outport to `Concat`: @@ -484,7 +481,8 @@ def Main(start any) (stop any) { --- :start -> 'Hello, ' -> concat:prefix 'World' -> concat:suffix - concat:res -> println -> :stop // concat:debug is not used + concat:res -> println + [println:res, println:err] -> :stop // concat:debug is not used } ``` @@ -503,7 +501,7 @@ Let's explore this using `strconv.ParseNum` from the standard library, which con pub def ParseNum(data string) (res T, err error) ``` -Note that it has an `err` outport of type `error`. While we can usually ignore node outports as long as we use at least one, the `err` port is special - we must always handle potential errors. +Note that it has an `err` outport of type `error`. While we can usually ignore node outports as long as we use at least one, the `err` port is special - we must always handle potential errors. You may have already seen the fan-in pattern with `Println` earlier, since it also may return an error. But let's take a look into another example. Let's try converting `'42'` to `42` and print both the result and any potential errors: @@ -518,7 +516,8 @@ def Main(start any) (stop any) { println fmt.Println --- :start -> '42' -> parse - [parse:res, parse:err] -> println -> :stop // fan-in + [parse:res, parse:err] -> println + [println:res, println:err] -> :stop // fan-in } ``` @@ -534,7 +533,7 @@ If we try an invalid number: ```neva :start -> 'forty two' -> parse -[parse:res, parse:err] -> println -> :stop +[parse:res, parse:err] -> println ``` We'll see: @@ -585,7 +584,8 @@ def Main(start any) (stop any) { println fmt.Println --- :start -> '21' -> [add:left, add:right] // chain + fan-out - [add:res, add:err] -> println -> :stop // fan-in + chain + [add:res, add:err] -> println //fan-in + [println:res, println:err] -> :stop // fan-in } ``` @@ -648,7 +648,8 @@ def Main(start any) (stop any) { 10 -> area:b, 20 -> area:h ] - area -> println -> :stop + area -> println + [println:res, println:err] -> :stop } ``` @@ -715,7 +716,8 @@ def Main(start any) (stop any) { 10 -> area:h ] (area > 50) -> format - ((format == 'true') ? 'Big' : 'Small') -> println -> :stop + ((format == 'true') ? 'Big' : 'Small') -> println + [println:res, println:err] -> :stop } ``` @@ -764,14 +766,16 @@ def Main(start any) (stop any) { upper strings.ToUpper lower strings.ToLower println fmt.Println - panic Panic + panic1, panic2 Panic --- :start -> 'Enter the name: ' -> print -> scanln -> switch { 'Alice' -> upper 'Bob' -> lower - _ -> panic + _ -> panic1 } - [upper, lower] -> println -> :stop + [upper, lower] -> println + println:res -> :stop + println:err -> panic2 } ``` @@ -779,7 +783,7 @@ We used several new things here. First, the `strings` package from the standard The `fmt` package is used again - `fmt.Print` works like `Println` but without adding `\n` at the end, and `fmt.Scanln` waits for keyboard input followed by Enter. -Finally, there's the builtin `Panic` component. It immediately terminates the program with a non-zero status code when its node receives a message. +Finally, there's the builtin `Panic` component. It immediately terminates the program with a non-zero status code when its node receives a message. We use it to 'panic', when println fails (e. g. couldn't print to stdout). The program prompts for a name, converts it to uppercase for "Alice" or lowercase for "Bob" (panicking for any other input), then prints the result. @@ -799,13 +803,15 @@ def Main(start any) (stop any) { upper strings.ToUpper lower strings.ToLower println fmt.Println - panic Panic + panic1, panic2 Panic --- :start -> 'Enter the name: ' -> print -> scanln -> switch { 'Alice' -> [upper, lower] - _ -> panic + _ -> panic1 } - (upper + lower) -> println -> :stop + (upper + lower) -> println + println:res -> :stop + println:err -> panic2 } ``` @@ -846,11 +852,13 @@ def Main(start any) (stop any) { classify utils.ClassifyInt println1 fmt.Println println2 fmt.Println + panic Panic --- :start -> -42 -> classify classify:pos -> 'positive :)' -> println1 classify:neg -> 'negative :(' -> println2 - [println1, println2] -> :stop + [println1:res, println2:res] -> :stop + [println1:err, println2:err] -> panic } ``` @@ -874,7 +882,7 @@ import { // ...existing code... -pub def CommentOnUser(name string, age int) (sig any) { +pub def CommentOnUser(name string, age int) (sig any, err error) { println1 fmt.Println println2 fmt.Println panic Panic @@ -882,9 +890,10 @@ pub def CommentOnUser(name string, age int) (sig any) { true -> switch { (:name == 'Bob') -> 'Beautiful name!' -> println1 (:age < 18) -> 'Young fellow!' -> println2 - _ -> panic + _ -> panic1 } - [println1, println2] -> :sig + [println1:res, println2:res] -> :sig + [println1:err, println2:err] -> :err } ``` @@ -898,12 +907,14 @@ import { def Main(start any) (stop any) { comment utils.CommentOnUser + panic Panic --- :start -> [ 'Bob' -> comment:name, 17 -> comment:age ] - comment -> :stop + comment:sig -> :stop + comment:err -> panic } ``` diff --git a/e2e/for_with_range_and_if/e2e_test.go b/e2e/for_with_range_and_if/e2e_test.go index 0c6a693f..f9219b7d 100644 --- a/e2e/for_with_range_and_if/e2e_test.go +++ b/e2e/for_with_range_and_if/e2e_test.go @@ -8,6 +8,7 @@ import ( ) func Test(t *testing.T) { + t.Skip("Remove this skip, until errors.Lift has been implemented.") for i := 0; i < 10; i++ { t.Run("", func(t *testing.T) { cmd := exec.Command("neva", "run", "main") diff --git a/internal/cli/new.go b/internal/cli/new.go index a4e84dd8..4b8cbd20 100644 --- a/internal/cli/new.go +++ b/internal/cli/new.go @@ -55,7 +55,8 @@ func createNevaMod(path string) error { def Main(start any) (stop any) { fmt.Println --- - :start -> 'Hello, World!' -> println -> :stop + :start -> 'Hello, World!' -> println + [println:res, println:err] -> :stop }` if err := os.WriteFile( From 52db95fe46348807e552bb84a27581850cd7e182 Mon Sep 17 00:00:00 2001 From: mike Date: Fri, 14 Feb 2025 18:56:24 +0100 Subject: [PATCH 4/4] Changed Tap implementation to fix possible deadlocks. Adjusted for_with_range_and_if test to use errors.Lift. Changed errors_lift test to not print out a number anymore. Adjusted examples and other tests for new println implementation. --- e2e/cli/build_windows/neva.yml | 2 +- e2e/cli/new_and_run/neva.yml | 2 +- e2e/compiler_error_unused_outport/main/main.neva | 8 ++++---- e2e/errors_lift/e2e_test.go | 2 +- e2e/errors_lift/main/main.neva | 4 +--- e2e/errors_must/main/main.neva | 7 +++++-- e2e/for_with_range_and_if/e2e_test.go | 1 - e2e/for_with_range_and_if/main/main.neva | 6 ++++-- e2e/slow_iteration_with_for/main/main.neva | 4 ++-- examples/99_bottles/main.neva | 13 +++++++------ examples/file_write_all/main.neva | 5 +++-- examples/image_png/main.neva | 4 +++- std/builtin/core.neva | 14 ++++++++++---- 13 files changed, 42 insertions(+), 30 deletions(-) diff --git a/e2e/cli/build_windows/neva.yml b/e2e/cli/build_windows/neva.yml index 5d36b277..b3a5c1a2 100644 --- a/e2e/cli/build_windows/neva.yml +++ b/e2e/cli/build_windows/neva.yml @@ -1 +1 @@ -neva: 0.31.0 \ No newline at end of file +neva: 0.31.2 \ No newline at end of file diff --git a/e2e/cli/new_and_run/neva.yml b/e2e/cli/new_and_run/neva.yml index 5d36b277..b3a5c1a2 100644 --- a/e2e/cli/new_and_run/neva.yml +++ b/e2e/cli/new_and_run/neva.yml @@ -1 +1 @@ -neva: 0.31.0 \ No newline at end of file +neva: 0.31.2 \ No newline at end of file diff --git a/e2e/compiler_error_unused_outport/main/main.neva b/e2e/compiler_error_unused_outport/main/main.neva index 39af1c20..5b4ff8f8 100644 --- a/e2e/compiler_error_unused_outport/main/main.neva +++ b/e2e/compiler_error_unused_outport/main/main.neva @@ -3,17 +3,17 @@ import { fmt } def Main(start any) (stop any) { sub1 SubComponent sub2 SubComponent - panic Panic --- :start -> 'Hi, Neva!' -> sub1:data sub1:stop-> :stop '1' -> sub2 - [sub1:err, sub2:err] -> panic } -def SubComponent(data string) (stop any, err error) { - println fmt.Println? +def SubComponent(data string) (stop any) { + println fmt.Println + panic Panic --- :data -> println:data println:res -> :stop + println:err -> panic } diff --git a/e2e/errors_lift/e2e_test.go b/e2e/errors_lift/e2e_test.go index fbc169a6..7692fcfe 100644 --- a/e2e/errors_lift/e2e_test.go +++ b/e2e/errors_lift/e2e_test.go @@ -14,7 +14,7 @@ func Test(t *testing.T) { require.NoError(t, err) require.Equal( t, - "42\n", + "", string(out), ) diff --git a/e2e/errors_lift/main/main.neva b/e2e/errors_lift/main/main.neva index af637d1c..6ebb5768 100644 --- a/e2e/errors_lift/main/main.neva +++ b/e2e/errors_lift/main/main.neva @@ -15,7 +15,5 @@ def Main(start any) (stop any) { // Handler doesn't have error outport. def Handler(data any) (res any) { - println fmt.Println - --- - :data -> '42' -> println -> :res + :data -> :res } diff --git a/e2e/errors_must/main/main.neva b/e2e/errors_must/main/main.neva index ceb924fd..2c1f7d15 100644 --- a/e2e/errors_must/main/main.neva +++ b/e2e/errors_must/main/main.neva @@ -8,8 +8,11 @@ import { def Main(start any) (stop any) { println fmt.Println must_handle errors.Must{Handler} + panic Panic --- - :start -> 'create_me.txt' -> must_handle -> 'success!' -> println -> :stop + :start -> 'create_me.txt' -> must_handle -> 'success!' -> println + println:res -> :stop + println:err -> panic } // Handler have error outport. @@ -18,5 +21,5 @@ def Handler(data string) (res any, err error) { --- :data -> write_all:filename 'Hello, io.WriteAll!' -> write_all:data - write_all -> :res + write_all:res -> :res } diff --git a/e2e/for_with_range_and_if/e2e_test.go b/e2e/for_with_range_and_if/e2e_test.go index f9219b7d..0c6a693f 100644 --- a/e2e/for_with_range_and_if/e2e_test.go +++ b/e2e/for_with_range_and_if/e2e_test.go @@ -8,7 +8,6 @@ import ( ) func Test(t *testing.T) { - t.Skip("Remove this skip, until errors.Lift has been implemented.") for i := 0; i < 10; i++ { t.Run("", func(t *testing.T) { cmd := exec.Command("neva", "run", "main") diff --git a/e2e/for_with_range_and_if/main/main.neva b/e2e/for_with_range_and_if/main/main.neva index c1b185b9..a4f3cffb 100644 --- a/e2e/for_with_range_and_if/main/main.neva +++ b/e2e/for_with_range_and_if/main/main.neva @@ -10,11 +10,13 @@ def Main(start any) (stop any) { for:err -> panic } -def PrintAsNum(data bool) (sig any) { +def PrintAsNum(data bool) (res any, err error) { Ternary, fmt.Println --- :data -> ternary:if 1 -> ternary:then 0 -> ternary:else - ternary -> println -> :sig + ternary -> println + println:res -> :res + println:err -> :err } diff --git a/e2e/slow_iteration_with_for/main/main.neva b/e2e/slow_iteration_with_for/main/main.neva index 385ac427..b354d1d8 100644 --- a/e2e/slow_iteration_with_for/main/main.neva +++ b/e2e/slow_iteration_with_for/main/main.neva @@ -14,12 +14,12 @@ def Main(start any) (stop any) { for:err -> panic } -def Slow(data int) (sig any, err error) { +def Slow(data int) (res any, err error) { time.Delay fmt.Println? --- :data -> delay:data $time.second -> delay:dur delay -> println:data - println:res -> :sig + println:res -> :res } diff --git a/examples/99_bottles/main.neva b/examples/99_bottles/main.neva index 214dc450..0386d505 100644 --- a/examples/99_bottles/main.neva +++ b/examples/99_bottles/main.neva @@ -10,15 +10,16 @@ def Main(start any) (stop any) { print:err -> panic } -def Next2Lines(data int) (sig any, err error) { +def Next2Lines(data int) (res any, err error) { first Tap{FirstLine}? dec Dec second SecondLine? --- - :data -> first -> dec -> second -> :sig + :data -> first + first:res -> dec -> second -> :res } -def FirstLine(data int) (sig any, err error) { +def FirstLine(data int) (res any, err error) { p1 fmt.Println? p2 fmt.Println? p3 fmt.Printf? @@ -31,10 +32,10 @@ def FirstLine(data int) (sig any, err error) { '$0 bottles of beer on the wall, $0 bottles of beer.\n' -> p3:tpl ] } - [p1:res, p2:res, p3:sig] -> :sig + [p1:res, p2:res, p3:sig] -> :res } -def SecondLine(data int) (sig any, err error) { +def SecondLine(data int) (res any, err error) { p1 fmt.Println? p2 fmt.Println? p3 fmt.Println? @@ -49,5 +50,5 @@ def SecondLine(data int) (sig any, err error) { 'Take one down and pass it around, $0 bottles of beer on the wall.\n\n' -> p4:tpl ] } - [p1:res, p2:res, p3:res, p4:sig] -> :sig + [p1:res, p2:res, p3:res, p4:sig] -> :res } diff --git a/examples/file_write_all/main.neva b/examples/file_write_all/main.neva index 46b6f033..6691a2ea 100644 --- a/examples/file_write_all/main.neva +++ b/examples/file_write_all/main.neva @@ -1,12 +1,13 @@ import { io, fmt } def Main(start any) (stop any) { - io.WriteAll, fmt.Println + io.WriteAll, fmt.Println, Panic --- :start -> [ 'file_writer_example.txt' -> writeAll:filename, 'Hello, io.WriteAll!' -> writeAll:data ] writeAll:err -> println - [writeAll:res, println] -> :stop + [writeAll:res, println:res] -> :stop + println:err -> panic } diff --git a/examples/image_png/main.neva b/examples/image_png/main.neva index c0357710..3d32aae3 100644 --- a/examples/image_png/main.neva +++ b/examples/image_png/main.neva @@ -32,6 +32,7 @@ def Main(start any) (stop any) { image.New, image.Encode NewPixel, NewColor, NewStream, io.WriteAll, printErr fmt.Println + panic Panic --- :start -> [ 0 -> [newColor:r, newColor:g, newColor:b, newColor:a], @@ -44,5 +45,6 @@ def Main(start any) (stop any) { new:img -> encode:img encode:data -> writeAll:data [new:err, encode:err, writeAll:err] -> printErr - [writeAll:res, printErr] -> :stop + [writeAll:res, printErr:res] -> :stop + printErr:err -> panic } diff --git a/std/builtin/core.neva b/std/builtin/core.neva index 3c04f144..10c92488 100644 --- a/std/builtin/core.neva +++ b/std/builtin/core.neva @@ -64,13 +64,19 @@ pub def Pass(data T) (res T) { // sends a signal when finishes. Signal could be of any type, so no need for // dealing with locks manually. Handler can send error, in that case `Tap` will // propagate it up to parent node. -pub def Tap(data T) (res T) { +pub def Tap(data T) (res T, err error) { + proxy1 Pass + proxy2 Pass lock Lock handler ITapHandler --- - :data -> [handler, lock:data] - handler -> lock:sig + :data -> [lock:data, handler] + + handler:res -> proxy1 + handler:err -> [proxy2, :err] + + [proxy1, proxy2] -> lock:sig lock -> :res } -pub interface ITapHandler(T) (any) +pub interface ITapHandler(T) (res any, err error)