diff --git a/.gitignore b/.gitignore index c60942fd7..3c202a89d 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ __arkscript__/ /*.ark *.ark.ir !tests/unittests/resources/BytecodeReaderSuite/*.arkc +tools/*_hash.py # Generated files include/Ark/Constants.hpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 10c40f1e2..147f1ad5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,11 @@ ### Added - added new macro `$gensym`, to generate a unique symbol identifier to use in macros +- `append`, `concat`, and `pop` can be use as values ### Changed - all paths inside `if` should return a value, when used as an expression. If an `else` branch is missing, `nil` will be returned +- new compile time error when trying to use `append!`, `concat!`, `pop!`, `@=` and `@@=` as values ### Removed diff --git a/include/Ark/Builtins/Builtins.hpp b/include/Ark/Builtins/Builtins.hpp index 2f7f0e151..275468711 100644 --- a/include/Ark/Builtins/Builtins.hpp +++ b/include/Ark/Builtins/Builtins.hpp @@ -163,6 +163,9 @@ namespace Ark::internal::Builtins ARK_BUILTIN(at); ARK_BUILTIN(atAt); ARK_BUILTIN(type); + ARK_BUILTIN(append_list); + ARK_BUILTIN(concat_list); + ARK_BUILTIN(pop_list); } } diff --git a/src/arkreactor/Builtins/Builtins.cpp b/src/arkreactor/Builtins/Builtins.cpp index 809fffa95..5e8dd6c0c 100644 --- a/src/arkreactor/Builtins/Builtins.cpp +++ b/src/arkreactor/Builtins/Builtins.cpp @@ -134,6 +134,9 @@ namespace Ark::internal::Builtins { "head", Value(Operators::head) }, { "@", Value(Operators::at) }, { "@@", Value(Operators::atAt) }, - { "type", Value(Operators::type) } + { "type", Value(Operators::type) }, + { "append", Value(Operators::append_list) }, + { "concat", Value(Operators::concat_list) }, + { "pop", Value(Operators::pop_list) } }; } diff --git a/src/arkreactor/Builtins/Operators.cpp b/src/arkreactor/Builtins/Operators.cpp index e6ccee14b..77ef6cf9d 100644 --- a/src/arkreactor/Builtins/Operators.cpp +++ b/src/arkreactor/Builtins/Operators.cpp @@ -374,4 +374,70 @@ namespace Ark::internal::Builtins::Operators return Value(std::to_string(n[0].valueType())); } + + // cppcheck-suppress constParameterReference + Value append_list(std::vector& n, VM* vm [[maybe_unused]]) + { + if (n.size() < 2 || n[0].valueType() != ValueType::List) + throw types::TypeCheckingError( + "append", + { { types::Contract { + { types::Typedef("list", ValueType::List), + types::Typedef("value", ValueType::Any, /* is_variadic= */ true) } } } }, + n); + + for (Value& e : n | std::ranges::views::drop(1)) + n[0].list().push_back(e); + + return n[0]; + } + + // cppcheck-suppress constParameterReference + Value concat_list(std::vector& n, VM* vm [[maybe_unused]]) + { + if (n.size() < 2 || n[0].valueType() != ValueType::List) + throw types::TypeCheckingError( + "concat", + { { types::Contract { + { types::Typedef("list", ValueType::List), + types::Typedef("value", ValueType::List, /* is_variadic= */ true) } } } }, + n); + + for (Value& e : n | std::ranges::views::drop(1)) + { + if (e.valueType() != ValueType::List) + throw types::TypeCheckingError( + "concat", + { { types::Contract { + { types::Typedef("dst", ValueType::List), + types::Typedef("src", ValueType::List, /* is_variadic= */ true) } } } }, + n); + + std::ranges::copy(e.list(), std::back_inserter(n[0].list())); + } + + return n[0]; + } + + // cppcheck-suppress constParameterReference + Value pop_list(std::vector& n, VM* vm [[maybe_unused]]) + { + if (!types::check(n, ValueType::List, ValueType::Number)) + throw types::TypeCheckingError( + "pop", + { { types::Contract { + { types::Typedef("list", ValueType::List), + types::Typedef("index", ValueType::Number) } } } }, + n); + + long idx = static_cast(n[1].number()); + idx = idx < 0 ? static_cast(n[0].list().size()) + idx : idx; + if (std::cmp_greater_equal(idx, n[0].list().size()) || idx < 0) + VM::throwVMError( + ErrorKind::Index, + fmt::format("pop index ({}) out of range (list size: {})", idx, n[0].list().size())); + + n[0].list().erase(n[0].list().begin() + idx); + return n[0]; + } } diff --git a/src/arkreactor/Compiler/Lowerer/ASTLowerer.cpp b/src/arkreactor/Compiler/Lowerer/ASTLowerer.cpp index 947dc8441..396d60fc5 100644 --- a/src/arkreactor/Compiler/Lowerer/ASTLowerer.cpp +++ b/src/arkreactor/Compiler/Lowerer/ASTLowerer.cpp @@ -320,6 +320,10 @@ namespace Ark::internal if (const auto it_builtin = getBuiltin(name)) page(p).emplace_back(Instruction::BUILTIN, it_builtin.value()); + else if (std::ranges::find(Language::UpdateRef, name) != Language::UpdateRef.end()) + buildAndThrowError(fmt::format("`{}' updates a list in-place, and can not be used as a value. Prefer using their copy alternative (without the `!` at the end) when possible", name), x); + else if (name == Language::And || name == Language::Or) + buildAndThrowError(fmt::format("`{}' can not be used as a value like `+', where (let add +) (add 1 2) would be valid", name), x); else if (getOperator(name).has_value()) buildAndThrowError(fmt::format("Found a freestanding operator: `{}`. It can not be used as value like `+', where (let add +) (add 1 2) would be valid", name), x); else diff --git a/tests/unittests/resources/CompilerSuite/ir/operators.ark b/tests/unittests/resources/CompilerSuite/ir/operators.ark index cb70addcf..4cf1cd6c6 100644 --- a/tests/unittests/resources/CompilerSuite/ir/operators.ark +++ b/tests/unittests/resources/CompilerSuite/ir/operators.ark @@ -23,4 +23,7 @@ (head []) (@ [1 2] 1) (@@ [[1] [2] [3]] 0 0) - (type 12)) + (type 12) + (append [] 1) + (concat [1] [2]) + (pop [1] 0)) diff --git a/tests/unittests/resources/CompilerSuite/ir/operators.expected b/tests/unittests/resources/CompilerSuite/ir/operators.expected index 4854cff50..0c3ee2703 100644 --- a/tests/unittests/resources/CompilerSuite/ir/operators.expected +++ b/tests/unittests/resources/CompilerSuite/ir/operators.expected @@ -66,7 +66,19 @@ page_0 AT_AT 0 LOAD_CONST 3 TYPE 0 - CALL_BUILTIN 9, 22 + LOAD_CONST 0 + LIST 0 + APPEND 1 + LOAD_CONST 1 + LIST 1 + LOAD_CONST 0 + LIST 1 + CONCAT 1 + LOAD_CONST 5 + LOAD_CONST 0 + LIST 1 + POP_LIST 0 + CALL_BUILTIN 9, 25 .L0: POP 0 HALT 0 diff --git a/tests/unittests/resources/CompilerSuite/ir/operators_as_builtins.ark b/tests/unittests/resources/CompilerSuite/ir/operators_as_builtins.ark index 3e683477b..dee89e33a 100644 --- a/tests/unittests/resources/CompilerSuite/ir/operators_as_builtins.ark +++ b/tests/unittests/resources/CompilerSuite/ir/operators_as_builtins.ark @@ -1 +1 @@ -(print + - * / mod toNumber toString < <= > >= = != not len empty? nil? tail head @ @@ type) +(print + - * / mod toNumber toString < <= > >= = != not len empty? nil? tail head @ @@ type append concat pop) diff --git a/tests/unittests/resources/CompilerSuite/ir/operators_as_builtins.expected b/tests/unittests/resources/CompilerSuite/ir/operators_as_builtins.expected index a53fb6aec..e0c95fe03 100644 --- a/tests/unittests/resources/CompilerSuite/ir/operators_as_builtins.expected +++ b/tests/unittests/resources/CompilerSuite/ir/operators_as_builtins.expected @@ -22,7 +22,10 @@ page_0 BUILTIN 88 BUILTIN 89 BUILTIN 90 - CALL_BUILTIN 9, 22 + BUILTIN 91 + BUILTIN 92 + BUILTIN 93 + CALL_BUILTIN 9, 25 .L0: POP 0 HALT 0 diff --git a/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_and.ark b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_and.ark new file mode 100644 index 000000000..e252e1a13 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_and.ark @@ -0,0 +1,2 @@ +(let a and) +(a 1 2) diff --git a/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_and.expected b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_and.expected new file mode 100644 index 000000000..cbe4782aa --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_and.expected @@ -0,0 +1,6 @@ +In file tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_and.ark:1 + 1 | (let a and) + | ^~~ + 2 | (a 1 2) + 3 | + `and' can not be used as a value like `+', where (let add +) (add 1 2) would be valid diff --git a/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_append_in_place.ark b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_append_in_place.ark new file mode 100644 index 000000000..cc1b9450e --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_append_in_place.ark @@ -0,0 +1,3 @@ +(let a append!) +(mut b []) +(a b 5) diff --git a/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_append_in_place.expected b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_append_in_place.expected new file mode 100644 index 000000000..bd0c586ff --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_append_in_place.expected @@ -0,0 +1,6 @@ +In file tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_append_in_place.ark:1 + 1 | (let a append!) + | ^~~~~~~ + 2 | (mut b []) + 3 | (a b 5) + `append!' updates a list in-place, and can not be used as a value. Prefer using their copy alternative (without the `!` at the end) when possible diff --git a/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_at_at_eq.ark b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_at_at_eq.ark new file mode 100644 index 000000000..0910af27f --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_at_at_eq.ark @@ -0,0 +1,3 @@ +(let a @@=) +(mut b [[]]) +(a b 5 6 7) diff --git a/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_at_at_eq.expected b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_at_at_eq.expected new file mode 100644 index 000000000..c7ae8952c --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_at_at_eq.expected @@ -0,0 +1,6 @@ +In file tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_at_at_eq.ark:1 + 1 | (let a @@=) + | ^~~ + 2 | (mut b [[]]) + 3 | (a b 5 6 7) + `@@=' updates a list in-place, and can not be used as a value. Prefer using their copy alternative (without the `!` at the end) when possible diff --git a/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_at_eq.ark b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_at_eq.ark new file mode 100644 index 000000000..5b4b142bb --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_at_eq.ark @@ -0,0 +1,3 @@ +(let a @=) +(mut b []) +(a b 5 6) diff --git a/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_at_eq.expected b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_at_eq.expected new file mode 100644 index 000000000..7ef5cc360 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_at_eq.expected @@ -0,0 +1,6 @@ +In file tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_at_eq.ark:1 + 1 | (let a @=) + | ^~ + 2 | (mut b []) + 3 | (a b 5 6) + `@=' updates a list in-place, and can not be used as a value. Prefer using their copy alternative (without the `!` at the end) when possible diff --git a/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_concat_in_place.ark b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_concat_in_place.ark new file mode 100644 index 000000000..f408fe167 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_concat_in_place.ark @@ -0,0 +1,3 @@ +(let a concat!) +(mut b []) +(a b [5]) diff --git a/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_concat_in_place.expected b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_concat_in_place.expected new file mode 100644 index 000000000..eaf16f843 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_concat_in_place.expected @@ -0,0 +1,6 @@ +In file tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_concat_in_place.ark:1 + 1 | (let a concat!) + | ^~~~~~~ + 2 | (mut b []) + 3 | (a b [5]) + `concat!' updates a list in-place, and can not be used as a value. Prefer using their copy alternative (without the `!` at the end) when possible diff --git a/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_or.ark b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_or.ark new file mode 100644 index 000000000..8f0235833 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_or.ark @@ -0,0 +1,2 @@ +(let a or) +(a 1 2) diff --git a/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_or.expected b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_or.expected new file mode 100644 index 000000000..99d007541 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_or.expected @@ -0,0 +1,6 @@ +In file tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_or.ark:1 + 1 | (let a or) + | ^~ + 2 | (a 1 2) + 3 | + `or' can not be used as a value like `+', where (let add +) (add 1 2) would be valid diff --git a/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_pop_in_place.ark b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_pop_in_place.ark new file mode 100644 index 000000000..d23660fe1 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_pop_in_place.ark @@ -0,0 +1,3 @@ +(let a pop!) +(mut b []) +(a b 5) diff --git a/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_pop_in_place.expected b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_pop_in_place.expected new file mode 100644 index 000000000..48d103142 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_pop_in_place.expected @@ -0,0 +1,6 @@ +In file tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_pop_in_place.ark:1 + 1 | (let a pop!) + | ^~~~ + 2 | (mut b []) + 3 | (a b 5) + `pop!' updates a list in-place, and can not be used as a value. Prefer using their copy alternative (without the `!` at the end) when possible diff --git a/tests/unittests/resources/DiagnosticsSuite/runtime/apply_pop_out_of_range.ark b/tests/unittests/resources/DiagnosticsSuite/runtime/apply_pop_out_of_range.ark new file mode 100644 index 000000000..ce39dba95 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/runtime/apply_pop_out_of_range.ark @@ -0,0 +1 @@ +(apply pop [[1 2 3] 4]) diff --git a/tests/unittests/resources/DiagnosticsSuite/runtime/apply_pop_out_of_range.expected b/tests/unittests/resources/DiagnosticsSuite/runtime/apply_pop_out_of_range.expected new file mode 100644 index 000000000..93d0b121e --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/runtime/apply_pop_out_of_range.expected @@ -0,0 +1,6 @@ +IndexError: pop index (4) out of range (list size: 3) + +In file tests/unittests/resources/DiagnosticsSuite/runtime/apply_pop_out_of_range.ark:1 + 1 | (apply pop [[1 2 3] 4]) + | ^~~~~~~~~~~~~~~~~~~~~~ + 2 | diff --git a/tests/unittests/resources/DiagnosticsSuite/runtime/apply_pop_out_of_range_neg.ark b/tests/unittests/resources/DiagnosticsSuite/runtime/apply_pop_out_of_range_neg.ark new file mode 100644 index 000000000..043dcaee0 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/runtime/apply_pop_out_of_range_neg.ark @@ -0,0 +1 @@ +(apply pop [[1 2 3] -4]) diff --git a/tests/unittests/resources/DiagnosticsSuite/runtime/apply_pop_out_of_range_neg.expected b/tests/unittests/resources/DiagnosticsSuite/runtime/apply_pop_out_of_range_neg.expected new file mode 100644 index 000000000..5823bfbc3 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/runtime/apply_pop_out_of_range_neg.expected @@ -0,0 +1,6 @@ +IndexError: pop index (-1) out of range (list size: 3) + +In file tests/unittests/resources/DiagnosticsSuite/runtime/apply_pop_out_of_range_neg.ark:1 + 1 | (apply pop [[1 2 3] -4]) + | ^~~~~~~~~~~~~~~~~~~~~~~ + 2 | diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_append_list.ark b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_append_list.ark new file mode 100644 index 000000000..f314ce7a9 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_append_list.ark @@ -0,0 +1 @@ +(apply append [[1]]) diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_append_list.expected b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_append_list.expected new file mode 100644 index 000000000..2ea97ec6b --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_append_list.expected @@ -0,0 +1,13 @@ +Function append expected at least 2 arguments but got 1 +Call + ↳ (append [1]) +Signature + ↳ (append list value) +Arguments + → `list' (expected List) ✓ + → variadic `value' (expected any) was not provided + +In file tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_append_list.ark:1 + 1 | (apply append [[1]]) + | ^~~~~~~~~~~~~~~~~~~ + 2 | diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_append_num_num.ark b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_append_num_num.ark new file mode 100644 index 000000000..08c235b21 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_append_num_num.ark @@ -0,0 +1 @@ +(apply append [1 2]) diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_append_num_num.expected b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_append_num_num.expected new file mode 100644 index 000000000..93ee3e325 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_append_num_num.expected @@ -0,0 +1,13 @@ +Function append expected at least 2 arguments and got 2 +Call + ↳ (append 1 2) +Signature + ↳ (append list value) +Arguments + → `list' (expected List), got 1 (Number) + → variadic `value' (expected any) + +In file tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_append_num_num.ark:1 + 1 | (apply append [1 2]) + | ^~~~~~~~~~~~~~~~~~~ + 2 | diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_list.ark b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_list.ark new file mode 100644 index 000000000..1084344ce --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_list.ark @@ -0,0 +1 @@ +(apply concat [[1]]) diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_list.expected b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_list.expected new file mode 100644 index 000000000..ceff106aa --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_list.expected @@ -0,0 +1,13 @@ +Function concat expected at least 2 arguments but got 1 +Call + ↳ (concat [1]) +Signature + ↳ (concat list value) +Arguments + → `list' (expected List) ✓ + → variadic `value' (expected List) was not provided + +In file tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_list.ark:1 + 1 | (apply concat [[1]]) + | ^~~~~~~~~~~~~~~~~~~ + 2 | diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_list_num.ark b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_list_num.ark new file mode 100644 index 000000000..cb24dedc7 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_list_num.ark @@ -0,0 +1 @@ +(apply concat [[1] 1]) diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_list_num.expected b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_list_num.expected new file mode 100644 index 000000000..29fe2fddb --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_list_num.expected @@ -0,0 +1,14 @@ +Function concat expected at least 2 arguments and got 2 +Call + ↳ (concat [1] 1) +Signature + ↳ (concat dst src) +Arguments + → `dst' (expected List) ✓ + → variadic `src' (expected List): 1 argument do not match: + 1 (Number) × + +In file tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_list_num.ark:1 + 1 | (apply concat [[1] 1]) + | ^~~~~~~~~~~~~~~~~~~~~ + 2 | diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_num.ark b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_num.ark new file mode 100644 index 000000000..0b2223261 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_num.ark @@ -0,0 +1 @@ +(apply concat [1]) diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_num.expected b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_num.expected new file mode 100644 index 000000000..246fcabb0 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_num.expected @@ -0,0 +1,13 @@ +Function concat expected at least 2 arguments but got 1 +Call + ↳ (concat 1) +Signature + ↳ (concat list value) +Arguments + → `list' (expected List), got 1 (Number) + → variadic `value' (expected List) was not provided + +In file tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_concat_num.ark:1 + 1 | (apply concat [1]) + | ^~~~~~~~~~~~~~~~~ + 2 | diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_pop_num_num.ark b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_pop_num_num.ark new file mode 100644 index 000000000..b52914ae2 --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_pop_num_num.ark @@ -0,0 +1 @@ +(apply pop [1 1]) diff --git a/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_pop_num_num.expected b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_pop_num_num.expected new file mode 100644 index 000000000..b783dc7ae --- /dev/null +++ b/tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_pop_num_num.expected @@ -0,0 +1,13 @@ +Function pop expected 2 arguments +Call + ↳ (pop 1 1) +Signature + ↳ (pop list index) +Arguments + → `list' (expected List), got 1 (Number) + → `index' (expected Number) ✓ + +In file tests/unittests/resources/DiagnosticsSuite/typeChecking/apply_pop_num_num.ark:1 + 1 | (apply pop [1 1]) + | ^~~~~~~~~~~~~~~~ + 2 | diff --git a/tests/unittests/resources/LangSuite/operators-tests.ark b/tests/unittests/resources/LangSuite/operators-tests.ark index ee4d29eb3..5e89ef5b2 100644 --- a/tests/unittests/resources/LangSuite/operators-tests.ark +++ b/tests/unittests/resources/LangSuite/operators-tests.ark @@ -190,4 +190,18 @@ (test:eq (apply type [1]) (type 1)) (test:eq (apply type [1]) "Number") (test:eq (apply type [nil]) (type nil)) - (test:eq (apply type [nil]) "Nil") })}) + (test:eq (apply type [nil]) "Nil") }) + + (test:case "append" { + (test:eq (apply append [[] 1]) [1]) + (test:eq (apply append [[] 1 2]) [1 2]) + (test:eq (apply append [[] 1 2 3]) [1 2 3]) }) + + (test:case "concat" { + (test:eq (apply concat [[] [1]]) [1]) + (test:eq (apply concat [[] [1] [2 3]]) [1 2 3]) + (test:eq (apply concat [[] [1] [2 3] [] [4 5 6]]) [1 2 3 4 5 6]) }) + + (test:case "pop" { + (test:eq (apply pop [[1 2] 0]) [2]) + (test:eq (apply pop [[1] 0]) []) }) }) diff --git a/tests/unittests/resources/LangSuite/weird-tests.ark b/tests/unittests/resources/LangSuite/weird-tests.ark index da0811b06..e798b61f6 100644 --- a/tests/unittests/resources/LangSuite/weird-tests.ark +++ b/tests/unittests/resources/LangSuite/weird-tests.ark @@ -15,7 +15,7 @@ (test:case "list:map with let" { (mut output []) - (list:map (let a [0 1]) f1) + (list:map (let z [0 1]) f1) (test:eq output [0 1]) }) (test:case "(Q ((let Q f1) 0))" { @@ -63,4 +63,17 @@ (or false (if 0 0)) b })) - (test:eq (g 1 2) 2) }) }) + (test:eq (g 1 2) 2) }) + + (test:case "append, concat, pop as values" { + (let data [1 2 3]) + (let a append) + (let c concat) + (let p pop) + + (test:eq (type a) "CProc") + (test:eq (type c) "CProc") + (test:eq (type p) "CProc") + (test:eq (a data 4) [1 2 3 4]) + (test:eq (c data [4 5]) [1 2 3 4 5]) + (test:eq (p data 1) [1 3]) }) })