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`
|
- Printing version number on non-quiet launch, or when provided `--version` or `:version`
|
||||||
- Builtin function documentation generation from C++ Musique implementation source code
|
- Builtin function documentation generation from C++ Musique implementation source code
|
||||||
|
- New builtins: digits
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
@ -1147,6 +1147,62 @@ static Result<Value> builtin_mix(Interpreter &i, std::vector<Value> args)
|
|||||||
return result;
|
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
|
/// Call operator. Calls first argument with remaining arguments
|
||||||
static Result<Value> builtin_call(Interpreter &i, std::vector<Value> args)
|
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("call", builtin_call);
|
||||||
global.force_define("ceil", builtin_ceil);
|
global.force_define("ceil", builtin_ceil);
|
||||||
global.force_define("chord", builtin_chord);
|
global.force_define("chord", builtin_chord);
|
||||||
|
global.force_define("digits", builtin_digits);
|
||||||
global.force_define("down", builtin_down);
|
global.force_define("down", builtin_down);
|
||||||
global.force_define("duration", builtin_duration);
|
global.force_define("duration", builtin_duration);
|
||||||
global.force_define("flat", builtin_flat);
|
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,6 +200,22 @@
|
|||||||
"10"
|
"10"
|
||||||
],
|
],
|
||||||
"stderr_lines": []
|
"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