Skip to content

Commit f764e8e

Browse files
committed
feat: append, concat and pop can be used as values
1 parent 6db2011 commit f764e8e

38 files changed

Lines changed: 270 additions & 4 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ __arkscript__/
1414
/*.ark
1515
*.ark.ir
1616
!tests/unittests/resources/BytecodeReaderSuite/*.arkc
17+
tools/*_hash.py
1718

1819
# Generated files
1920
include/Ark/Constants.hpp

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77

88
### Added
99
- added new macro `$gensym`, to generate a unique symbol identifier to use in macros
10+
- `append`, `concat`, and `pop` can be use as values
1011

1112
### Changed
1213
- all paths inside `if` should return a value, when used as an expression. If an `else` branch is missing, `nil` will be returned
14+
- new compile time error when trying to use `append!`, `concat!`, `pop!`, `@=` and `@@=` as values
1315

1416
### Removed
1517

include/Ark/Builtins/Builtins.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ namespace Ark::internal::Builtins
163163
ARK_BUILTIN(at);
164164
ARK_BUILTIN(atAt);
165165
ARK_BUILTIN(type);
166+
ARK_BUILTIN(append_list);
167+
ARK_BUILTIN(concat_list);
168+
ARK_BUILTIN(pop_list);
166169
}
167170
}
168171

src/arkreactor/Builtins/Builtins.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ namespace Ark::internal::Builtins
134134
{ "head", Value(Operators::head) },
135135
{ "@", Value(Operators::at) },
136136
{ "@@", Value(Operators::atAt) },
137-
{ "type", Value(Operators::type) }
137+
{ "type", Value(Operators::type) },
138+
{ "append", Value(Operators::append_list) },
139+
{ "concat", Value(Operators::concat_list) },
140+
{ "pop", Value(Operators::pop_list) }
138141
};
139142
}

src/arkreactor/Builtins/Operators.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,4 +374,70 @@ namespace Ark::internal::Builtins::Operators
374374

375375
return Value(std::to_string(n[0].valueType()));
376376
}
377+
378+
// cppcheck-suppress constParameterReference
379+
Value append_list(std::vector<Value>& n, VM* vm [[maybe_unused]])
380+
{
381+
if (n.size() < 2 || n[0].valueType() != ValueType::List)
382+
throw types::TypeCheckingError(
383+
"append",
384+
{ { types::Contract {
385+
{ types::Typedef("list", ValueType::List),
386+
types::Typedef("value", ValueType::Any, /* is_variadic= */ true) } } } },
387+
n);
388+
389+
for (Value& e : n | std::ranges::views::drop(1))
390+
n[0].list().push_back(e);
391+
392+
return n[0];
393+
}
394+
395+
// cppcheck-suppress constParameterReference
396+
Value concat_list(std::vector<Value>& n, VM* vm [[maybe_unused]])
397+
{
398+
if (n.size() < 2 || n[0].valueType() != ValueType::List)
399+
throw types::TypeCheckingError(
400+
"concat",
401+
{ { types::Contract {
402+
{ types::Typedef("list", ValueType::List),
403+
types::Typedef("value", ValueType::List, /* is_variadic= */ true) } } } },
404+
n);
405+
406+
for (Value& e : n | std::ranges::views::drop(1))
407+
{
408+
if (e.valueType() != ValueType::List)
409+
throw types::TypeCheckingError(
410+
"concat",
411+
{ { types::Contract {
412+
{ types::Typedef("dst", ValueType::List),
413+
types::Typedef("src", ValueType::List, /* is_variadic= */ true) } } } },
414+
n);
415+
416+
std::ranges::copy(e.list(), std::back_inserter(n[0].list()));
417+
}
418+
419+
return n[0];
420+
}
421+
422+
// cppcheck-suppress constParameterReference
423+
Value pop_list(std::vector<Value>& n, VM* vm [[maybe_unused]])
424+
{
425+
if (!types::check(n, ValueType::List, ValueType::Number))
426+
throw types::TypeCheckingError(
427+
"pop",
428+
{ { types::Contract {
429+
{ types::Typedef("list", ValueType::List),
430+
types::Typedef("index", ValueType::Number) } } } },
431+
n);
432+
433+
long idx = static_cast<long>(n[1].number());
434+
idx = idx < 0 ? static_cast<long>(n[0].list().size()) + idx : idx;
435+
if (std::cmp_greater_equal(idx, n[0].list().size()) || idx < 0)
436+
VM::throwVMError(
437+
ErrorKind::Index,
438+
fmt::format("pop index ({}) out of range (list size: {})", idx, n[0].list().size()));
439+
440+
n[0].list().erase(n[0].list().begin() + idx);
441+
return n[0];
442+
}
377443
}

src/arkreactor/Compiler/Lowerer/ASTLowerer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,10 @@ namespace Ark::internal
320320

321321
if (const auto it_builtin = getBuiltin(name))
322322
page(p).emplace_back(Instruction::BUILTIN, it_builtin.value());
323+
else if (std::ranges::find(Language::UpdateRef, name) != Language::UpdateRef.end())
324+
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);
325+
else if (name == Language::And || name == Language::Or)
326+
buildAndThrowError(fmt::format("`{}' can not be used as a value like `+', where (let add +) (add 1 2) would be valid", name), x);
323327
else if (getOperator(name).has_value())
324328
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);
325329
else
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
(let a and)
2+
(a 1 2)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
In file tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_and.ark:1
2+
1 | (let a and)
3+
| ^~~
4+
2 | (a 1 2)
5+
3 |
6+
`and' can not be used as a value like `+', where (let add +) (add 1 2) would be valid
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
(let a append!)
2+
(mut b [])
3+
(a b 5)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
In file tests/unittests/resources/DiagnosticsSuite/compileTime/let_a_append_in_place.ark:1
2+
1 | (let a append!)
3+
| ^~~~~~~
4+
2 | (mut b [])
5+
3 | (a b 5)
6+
`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

0 commit comments

Comments
 (0)