Started builtins refactoring and testing
This commit is contained in:
parent
548b29d897
commit
bc5736bf35
@ -31,6 +31,28 @@ concept Iterable = (With_Index_Method<T> || With_Index_Operator<T>) && requires
|
|||||||
{ t.size() } -> std::convertible_to<usize>;
|
{ t.size() } -> std::convertible_to<usize>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Result<std::vector<Value>> deep_flat(Interpreter &interpreter, Iterable auto const& array)
|
||||||
|
{
|
||||||
|
std::vector<Value> result;
|
||||||
|
|
||||||
|
for (auto i = 0u; i < array.size(); ++i) {
|
||||||
|
Value element;
|
||||||
|
if constexpr (With_Index_Method<decltype(array)>) {
|
||||||
|
element = Try(array.index(interpreter, i));
|
||||||
|
} else {
|
||||||
|
element = std::move(array[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto collection = get_if<Collection>(element)) {
|
||||||
|
std::ranges::move(Try(deep_flat(interpreter, *collection)), std::back_inserter(result));
|
||||||
|
} else {
|
||||||
|
result.push_back(std::move(element));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/// Create chord out of given notes
|
/// Create chord out of given notes
|
||||||
template<Iterable T>
|
template<Iterable T>
|
||||||
static inline std::optional<Error> create_chord(std::vector<Note> &chord, Interpreter &interpreter, T&& args)
|
static inline std::optional<Error> create_chord(std::vector<Note> &chord, Interpreter &interpreter, T&& args)
|
||||||
@ -543,7 +565,7 @@ static Result<Value> builtin_fold(Interpreter &interpreter, std::vector<Value> a
|
|||||||
|
|
||||||
/// Execute blocks depending on condition
|
/// Execute blocks depending on condition
|
||||||
static Result<Value> builtin_if(Interpreter &i, std::vector<Value> args) {
|
static Result<Value> builtin_if(Interpreter &i, std::vector<Value> args) {
|
||||||
constexpr auto guard = Guard<2> {
|
static constexpr auto guard = Guard<2> {
|
||||||
.name = "if",
|
.name = "if",
|
||||||
.possibilities = {
|
.possibilities = {
|
||||||
"(any, function) -> any",
|
"(any, function) -> any",
|
||||||
@ -656,7 +678,7 @@ static Result<Value> builtin_shuffle(Interpreter &i, std::vector<Value> args)
|
|||||||
{
|
{
|
||||||
static std::mt19937 rnd{std::random_device{}()};
|
static std::mt19937 rnd{std::random_device{}()};
|
||||||
auto array = Try(flatten(i, std::move(args)));
|
auto array = Try(flatten(i, std::move(args)));
|
||||||
std::shuffle(array.begin(), array.end(), rnd);
|
std::ranges::shuffle(array, rnd);
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -664,7 +686,7 @@ static Result<Value> builtin_shuffle(Interpreter &i, std::vector<Value> args)
|
|||||||
static Result<Value> builtin_permute(Interpreter &i, std::vector<Value> args)
|
static Result<Value> builtin_permute(Interpreter &i, std::vector<Value> args)
|
||||||
{
|
{
|
||||||
auto array = Try(flatten(i, std::move(args)));
|
auto array = Try(flatten(i, std::move(args)));
|
||||||
std::next_permutation(array.begin(), array.end());
|
std::ranges::next_permutation(array);
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -672,7 +694,7 @@ static Result<Value> builtin_permute(Interpreter &i, std::vector<Value> args)
|
|||||||
static Result<Value> builtin_sort(Interpreter &i, std::vector<Value> args)
|
static Result<Value> builtin_sort(Interpreter &i, std::vector<Value> args)
|
||||||
{
|
{
|
||||||
auto array = Try(flatten(i, std::move(args)));
|
auto array = Try(flatten(i, std::move(args)));
|
||||||
std::sort(array.begin(), array.end());
|
std::ranges::sort(array);
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -680,28 +702,26 @@ static Result<Value> builtin_sort(Interpreter &i, std::vector<Value> args)
|
|||||||
static Result<Value> builtin_reverse(Interpreter &i, std::vector<Value> args)
|
static Result<Value> builtin_reverse(Interpreter &i, std::vector<Value> args)
|
||||||
{
|
{
|
||||||
auto array = Try(flatten(i, std::move(args)));
|
auto array = Try(flatten(i, std::move(args)));
|
||||||
std::reverse(array.begin(), array.end());
|
std::ranges::reverse(array);
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get minimum of arguments
|
/// Get minimum of arguments
|
||||||
static Result<Value> builtin_min(Interpreter &i, std::vector<Value> args)
|
static Result<Value> builtin_min(Interpreter &i, std::vector<Value> args)
|
||||||
{
|
{
|
||||||
auto array = Try(flatten(i, std::move(args)));
|
auto array = Try(deep_flat(i, std::move(args)));
|
||||||
auto min = std::min_element(array.begin(), array.end());
|
if (auto min = std::ranges::min_element(array); min != array.end())
|
||||||
if (min == array.end())
|
return *min;
|
||||||
return Value{};
|
return Value{};
|
||||||
return *min;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get maximum of arguments
|
/// Get maximum of arguments
|
||||||
static Result<Value> builtin_max(Interpreter &i, std::vector<Value> args)
|
static Result<Value> builtin_max(Interpreter &i, std::vector<Value> args)
|
||||||
{
|
{
|
||||||
auto array = Try(flatten(i, std::move(args)));
|
auto array = Try(deep_flat(i, std::move(args)));
|
||||||
auto max = std::max_element(array.begin(), array.end());
|
if (auto max = std::ranges::max_element(array); max != array.end())
|
||||||
if (max == array.end())
|
return *max;
|
||||||
return Value{};
|
return Value{};
|
||||||
return *max;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parition arguments into 2 arrays based on predicate
|
/// Parition arguments into 2 arrays based on predicate
|
||||||
@ -935,7 +955,8 @@ static Result<Value> builtin_call(Interpreter &i, std::vector<Value> args)
|
|||||||
return guard.yield_error();
|
return guard.yield_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &callable = *Try(guard.match<Function>(args.front()));
|
auto fst = std::move(args.front());
|
||||||
|
auto &callable = *Try(guard.match<Function>(fst));
|
||||||
args.erase(args.begin());
|
args.erase(args.begin());
|
||||||
return callable(i, std::move(args));
|
return callable(i, std::move(args));
|
||||||
}
|
}
|
||||||
|
@ -205,6 +205,8 @@ Result<Value> Interpreter::eval(Ast &&ast)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << ast.type << std::endl;
|
||||||
|
std::cout << ast.token.type << std::endl;
|
||||||
unreachable();
|
unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ struct Intrinsic : Function
|
|||||||
constexpr ~Intrinsic() = default;
|
constexpr ~Intrinsic() = default;
|
||||||
|
|
||||||
/// Calls underlying function pointer
|
/// Calls underlying function pointer
|
||||||
Result<Value> operator()(Interpreter&, std::vector<Value>) const;
|
Result<Value> operator()(Interpreter&, std::vector<Value>) const override;
|
||||||
|
|
||||||
/// Compares if function pointers are equal
|
/// Compares if function pointers are equal
|
||||||
bool operator==(Intrinsic const&) const = default;
|
bool operator==(Intrinsic const&) const = default;
|
||||||
|
8
regression-tests/builtin/call.mq
Normal file
8
regression-tests/builtin/call.mq
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
-- Call executes blocks without parameters
|
||||||
|
say (call [42]);
|
||||||
|
|
||||||
|
-- Call executes block passing parameters
|
||||||
|
say (call [n | n + 1] 10);
|
||||||
|
|
||||||
|
-- Call executes builtin functions
|
||||||
|
call say 43;
|
13
regression-tests/builtin/if.mq
Normal file
13
regression-tests/builtin/if.mq
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
-- If executes then first block when condition is true
|
||||||
|
if true [say 1];
|
||||||
|
if true [say 2] [say 3];
|
||||||
|
|
||||||
|
-- If executes second block when condition is false
|
||||||
|
if false [say 4] [say 5];
|
||||||
|
|
||||||
|
-- If returns nil when without else block
|
||||||
|
say (if false [say 6]);
|
||||||
|
|
||||||
|
-- If returns block execution value
|
||||||
|
say (if true [7]);
|
||||||
|
say (if false [say 100; 8] [say 200; 9]);
|
6
regression-tests/builtin/max.mq
Normal file
6
regression-tests/builtin/max.mq
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
say (max 1 2 5 4 3);
|
||||||
|
say (max (200 + up 10));
|
||||||
|
say (max (100 + down 10));
|
||||||
|
|
||||||
|
-- Max should do deep search
|
||||||
|
say (max 1 2 [3; 4; [5; 10; 8]; 1] 2);
|
6
regression-tests/builtin/min.mq
Normal file
6
regression-tests/builtin/min.mq
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
say (min 1 2 5 4 3);
|
||||||
|
say (min (200 + up 10));
|
||||||
|
say (min (100 + down 10));
|
||||||
|
|
||||||
|
-- Min should do deep search
|
||||||
|
say (min 1 2 [3; 4; [5; 0; 8]; 1] 2);
|
4
regression-tests/builtin/reverse.mq
Normal file
4
regression-tests/builtin/reverse.mq
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
say (reverse []);
|
||||||
|
say (reverse (up 10));
|
||||||
|
say (reverse (reverse (up 10)));
|
||||||
|
say (reverse [[1; 2; 3]; 4; 5] 6 7 [[8; 9]]);
|
Loading…
Reference in New Issue
Block a user