Range function for Musique language

This commit is contained in:
Robert Bendun 2022-08-21 13:45:34 +02:00
parent da1ac0dcf7
commit e3164395de
2 changed files with 46 additions and 1 deletions

View File

@ -1023,6 +1023,11 @@ struct Shape
static inline auto move_from(std::vector<Value>& args) { return ::move_from<Types...>(args); }
static inline auto typecheck(std::vector<Value>& args) { return ::typecheck(args, Types...); }
static inline auto typecheck_front(std::vector<Value>& args) { return ::typecheck_front(args, Types...); }
static inline auto typecheck_and_move(std::vector<Value>& args)
{
return typecheck(args) ? std::optional { move_from(args) } : std::nullopt;
}
};
/// Returns if type can be indexed

View File

@ -173,6 +173,42 @@ invalid_argument_type:
};
}
enum class Range_Direction { Up, Down };
template<Range_Direction dir>
Result<Value> builtin_range(Interpreter&, std::vector<Value> args)
{
using N = Shape<Value::Type::Number>;
using NN = Shape<Value::Type::Number, Value::Type::Number>;
using NNN = Shape<Value::Type::Number, Value::Type::Number, Value::Type::Number>;
auto start = Number(0), stop = Number(0), step = Number(1);
if (0) {}
else if (auto a = N::typecheck_and_move(args)) { std::tie(stop) = *a; }
else if (auto a = NN::typecheck_and_move(args)) { std::tie(start, stop) = *a; }
else if (auto a = NNN::typecheck_and_move(args)) { std::tie(start, stop, step) = *a; }
else {
return Error {
.details = errors::Unsupported_Types_For {
.type = errors::Unsupported_Types_For::Function,
.name = "range",
.possibilities = {
"(stop: number) -> array of number",
"(start: number, stop: number) -> array of number",
"(start: number, stop: number, step: number) -> array of number",
}
},
.location = {}
};
}
Array array;
for (; start < stop; start += step) {
array.elements.push_back(Value::from(start));
}
return Value::from(std::move(array));
}
void Interpreter::register_builtin_functions()
{
auto &global = *Env::global;
@ -462,7 +498,7 @@ error:
return Error {
.details = errors::Unsupported_Types_For {
.type = errors::Unsupported_Types_For::Function,
.name = "note_off",
.name = "program_change",
.possibilities = {
"(number) -> nil",
"(number, number) -> nil",
@ -480,4 +516,8 @@ error:
global.force_define("ceil", apply_numeric_transform<&Number::ceil>);
global.force_define("floor", apply_numeric_transform<&Number::floor>);
global.force_define("round", apply_numeric_transform<&Number::round>);
global.force_define("range", builtin_range<Range_Direction::Up>);
global.force_define("up", builtin_range<Range_Direction::Up>);
global.force_define("down", builtin_range<Range_Direction::Down>);
}