scan builtin; Value and Array conviniance constructors made explicit

This commit is contained in:
Robert Bendun 2022-10-07 17:33:38 +02:00
parent 20bf379332
commit b6b1209014
6 changed files with 44 additions and 14 deletions

View File

@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Added
* Added `scan` builtin, which computes prefix sum of passed values when provided with addition operator
### Fixed
* Prevented accidental recursive construction of Arrays and Values by making convinience constructor `Value::Value(std::vector<Value>&&)` explicit
## [0.1.0] - 2022-09-25 ## [0.1.0] - 2022-09-25
### Added ### Added

View File

@ -564,6 +564,28 @@ static Result<Value> builtin_fold(Interpreter &interpreter, std::vector<Value> a
return init; return init;
} }
/// Scan computes inclusive prefix sum
static Result<Value> builtin_scan(Interpreter &interpreter, std::vector<Value> args)
{
if (args.size()) {
if (auto p = get_if<Function>(args.front())) {
auto xs = Try(flatten(interpreter, std::span(args).subspan(1)));
for (auto i = 1u; i < xs.size(); ++i) {
xs[i] = Try((*p)(interpreter, { xs[i-1], xs[i] }));
}
return xs;
}
}
return errors::Unsupported_Types_For {
.type = errors::Unsupported_Types_For::Function,
.name = "scan",
.possibilities = {
"(callback, ...array) -> any"
}
};
}
/// 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) {
static constexpr auto guard = Guard<2> { static constexpr auto guard = Guard<2> {
@ -997,6 +1019,7 @@ void Interpreter::register_builtin_functions()
global.force_define("reverse", builtin_reverse); global.force_define("reverse", builtin_reverse);
global.force_define("rotate", builtin_rotate); global.force_define("rotate", builtin_rotate);
global.force_define("round", apply_numeric_transform<&Number::round>); global.force_define("round", apply_numeric_transform<&Number::round>);
global.force_define("scan", builtin_scan);
global.force_define("shuffle", builtin_shuffle); global.force_define("shuffle", builtin_shuffle);
global.force_define("sim", builtin_sim); global.force_define("sim", builtin_sim);
global.force_define("sort", builtin_sort); global.force_define("sort", builtin_sort);

View File

@ -89,8 +89,8 @@ static Result<Value> plus_minus_operator(Interpreter &interpreter, std::vector<V
static_assert(std::is_same_v<std::plus<>, Binary_Operation> || std::is_same_v<std::minus<>, Binary_Operation>, static_assert(std::is_same_v<std::plus<>, Binary_Operation> || std::is_same_v<std::minus<>, Binary_Operation>,
"Error message printing only supports operators given above"); "Error message printing only supports operators given above");
return Error {
.details = errors::Unsupported_Types_For { return errors::Unsupported_Types_For {
.type = errors::Unsupported_Types_For::Operator, .type = errors::Unsupported_Types_For::Operator,
.name = std::is_same_v<std::plus<>, Binary_Operation> ? "+" : "-", .name = std::is_same_v<std::plus<>, Binary_Operation> ? "+" : "-",
.possibilities = { .possibilities = {
@ -100,7 +100,6 @@ static Result<Value> plus_minus_operator(Interpreter &interpreter, std::vector<V
"(array, number|music) -> array", "(array, number|music) -> array",
"(number|music, array) -> array", "(number|music, array) -> array",
} }
}
}; };
}); });
} }

View File

@ -7,7 +7,7 @@ Array::Array(Array &&) = default;
Array::~Array() = default; Array::~Array() = default;
Array::Array(std::vector<Value>&& elements) Array::Array(std::vector<Value>&& elements)
: elements{std::move(elements)} : elements(std::move(elements))
{ {
} }

View File

@ -15,7 +15,7 @@ struct Array : Collection
std::vector<Value> elements; std::vector<Value> elements;
Array(); Array();
Array(std::vector<Value>&&); explicit Array(std::vector<Value>&&);
Array(Array const&); Array(Array const&);
Array(Array &&); Array(Array &&);
~Array() override; ~Array() override;

View File

@ -38,7 +38,7 @@ struct Value
Value(char const* s); ///< Create value of type symbol holding provided symbol Value(char const* s); ///< Create value of type symbol holding provided symbol
Value(std::string s); ///< Create value of type symbol holding provided symbol Value(std::string s); ///< Create value of type symbol holding provided symbol
Value(std::string_view s); ///< Create value of type symbol holding provided symbol Value(std::string_view s); ///< Create value of type symbol holding provided symbol
Value(std::vector<Value> &&array); ///< Create value of type array holding provided array explicit Value(std::vector<Value> &&array); ///< Create value of type array holding provided array
// TODO Most strings should not be allocated by Value, but reference to string allocated previously // TODO Most strings should not be allocated by Value, but reference to string allocated previously
// Wrapper for std::string is needed that will allocate only when needed, middle ground between: // Wrapper for std::string is needed that will allocate only when needed, middle ground between: