digits builtin
This commit is contained in:
parent
bda1e503c7
commit
d7c26e5858
@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
- Printing version number on non-quiet launch, or when provided `--version` or `:version`
|
||||
- Builtin function documentation generation from C++ Musique implementation source code
|
||||
- New builtins: digits
|
||||
|
||||
### Removed
|
||||
|
||||
|
@ -1147,6 +1147,62 @@ static Result<Value> builtin_mix(Interpreter &i, std::vector<Value> args)
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void append_digits(std::vector<uint8_t> &digits, usize base, Number number)
|
||||
{
|
||||
auto start = digits.size();
|
||||
|
||||
number.simplify_inplace();
|
||||
|
||||
auto integer_part = number.num / number.den;
|
||||
number.num -= integer_part * number.den;
|
||||
|
||||
do {
|
||||
digits.push_back(integer_part % base);
|
||||
integer_part /= base;
|
||||
} while (integer_part != 0);
|
||||
std::reverse(digits.begin() + start, digits.end());
|
||||
|
||||
if (number.den != 1) {
|
||||
std::unordered_set<Number> repeats;
|
||||
|
||||
do {
|
||||
repeats.insert(number);
|
||||
number.num *= base;
|
||||
|
||||
auto const digit = number.floor().as_int();
|
||||
digits.push_back(digit);
|
||||
|
||||
number.num = number.num - digit * number.den;
|
||||
number.simplify_inplace();
|
||||
} while (number.num != 0 && !repeats.contains(number));
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts number to array of its digits
|
||||
static Result<Value> builtin_digits(Interpreter &interpreter, std::vector<Value> args)
|
||||
{
|
||||
// For now it's a constant. It waits on some kind of keyword parameters
|
||||
// so base can be provided nicely
|
||||
auto const base = 10;
|
||||
|
||||
std::vector<uint8_t> digits;
|
||||
|
||||
auto args_flattened = Try(deep_flat(interpreter, args));
|
||||
for (auto const& arg : args_flattened) {
|
||||
if (auto num = get_if<Number>(arg)) {
|
||||
append_digits(digits, base, *num);
|
||||
} else {
|
||||
// TODO This may be an error. Currently we fail silently
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Value> result;
|
||||
result.reserve(digits.size());
|
||||
std::transform(digits.begin(), digits.end(), std::back_inserter(result), [](auto digit) { return Number(digit); });
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Call operator. Calls first argument with remaining arguments
|
||||
static Result<Value> builtin_call(Interpreter &i, std::vector<Value> args)
|
||||
{
|
||||
@ -1175,6 +1231,7 @@ void Interpreter::register_builtin_functions()
|
||||
global.force_define("call", builtin_call);
|
||||
global.force_define("ceil", builtin_ceil);
|
||||
global.force_define("chord", builtin_chord);
|
||||
global.force_define("digits", builtin_digits);
|
||||
global.force_define("down", builtin_down);
|
||||
global.force_define("duration", builtin_duration);
|
||||
global.force_define("flat", builtin_flat);
|
||||
|
8
regression-tests/builtin/digits.mq
Normal file
8
regression-tests/builtin/digits.mq
Normal file
@ -0,0 +1,8 @@
|
||||
say (digits 3456),
|
||||
say (digits (100/10)),
|
||||
say (digits 0),
|
||||
say (digits (0 - 1234)),
|
||||
say (digits 0 0 0 0),
|
||||
say (digits (4/3)),
|
||||
say (digits 0.5),
|
||||
say (digits 1234.5678),
|
@ -200,7 +200,23 @@
|
||||
"10"
|
||||
],
|
||||
"stderr_lines": []
|
||||
},
|
||||
{
|
||||
"name": "digits.mq",
|
||||
"exit_code": 0,
|
||||
"stdin_lines": [],
|
||||
"stdout_lines": [
|
||||
"(3, 4, 5, 6)",
|
||||
"(1, 0)",
|
||||
"(0)",
|
||||
"(1, 8, 4, 4, 6, 7, 4, 4, 0, 7, 3, 7, 0, 9, 5, 5, 0, 3, 8, 2)",
|
||||
"(0, 0, 0, 0)",
|
||||
"(1, 3)",
|
||||
"(0, 5)",
|
||||
"(1, 2, 3, 4, 5, 6, 7, 8)"
|
||||
],
|
||||
"stderr_lines": []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
Loading…
Reference in New Issue
Block a user