fixed index operation; unified builtin operators naming convention

This commit is contained in:
Robert Bendun 2022-10-23 00:08:06 +02:00
parent f10eb5c2ad
commit b924f7dff2

View File

@ -60,7 +60,7 @@ inline std::optional<Value> symetric(Value &lhs, Value &rhs, auto binary)
/// n: number, m: music -> music /// n: number, m: music -> music
/// m: music, n: number -> music moves m by n semitones (+ goes up, - goes down) /// m: music, n: number -> music moves m by n semitones (+ goes up, - goes down)
template<typename Binary_Operation> template<typename Binary_Operation>
static Result<Value> plus_minus_operator(Interpreter &interpreter, std::vector<Value> args) static Result<Value> builtin_operator_add_subtract(Interpreter &interpreter, std::vector<Value> args)
{ {
if (args.empty()) { if (args.empty()) {
return Number(0); return Number(0);
@ -86,7 +86,7 @@ static Result<Value> plus_minus_operator(Interpreter &interpreter, std::vector<V
} }
if (holds_alternative<Collection>(lhs) != holds_alternative<Collection>(rhs)) { if (holds_alternative<Collection>(lhs) != holds_alternative<Collection>(rhs)) {
return vectorize(plus_minus_operator<Binary_Operation>, interpreter, std::move(lhs), std::move(rhs)); return vectorize(builtin_operator_add_subtract<Binary_Operation>, interpreter, std::move(lhs), std::move(rhs));
} }
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>,
@ -107,7 +107,7 @@ static Result<Value> plus_minus_operator(Interpreter &interpreter, std::vector<V
} }
template<typename Binary_Operation, char ...Chars> template<typename Binary_Operation, char ...Chars>
static Result<Value> binary_operator(Interpreter& interpreter, std::vector<Value> args) static Result<Value> builtin_operator_arithmetic(Interpreter& interpreter, std::vector<Value> args)
{ {
static constexpr char Name[] = { Chars..., '\0' }; static constexpr char Name[] = { Chars..., '\0' };
if (args.empty()) { if (args.empty()) {
@ -121,7 +121,7 @@ static Result<Value> binary_operator(Interpreter& interpreter, std::vector<Value
} }
if (holds_alternative<Collection>(lhs) != holds_alternative<Collection>(rhs)) { if (holds_alternative<Collection>(lhs) != holds_alternative<Collection>(rhs)) {
return vectorize(binary_operator<Binary_Operation, Chars...>, interpreter, std::move(lhs), std::move(rhs)); return vectorize(builtin_operator_arithmetic<Binary_Operation, Chars...>, interpreter, std::move(lhs), std::move(rhs));
} }
return errors::Unsupported_Types_For { return errors::Unsupported_Types_For {
@ -138,7 +138,7 @@ static Result<Value> binary_operator(Interpreter& interpreter, std::vector<Value
} }
template<typename Binary_Predicate> template<typename Binary_Predicate>
static Result<Value> comparison_operator(Interpreter &interpreter, std::vector<Value> args) static Result<Value> builtin_operator_compare(Interpreter &interpreter, std::vector<Value> args)
{ {
if (args.size() != 2) { if (args.size() != 2) {
return algo::pairwise_all(std::move(args), Binary_Predicate{}); return algo::pairwise_all(std::move(args), Binary_Predicate{});
@ -167,7 +167,7 @@ static Result<Value> comparison_operator(Interpreter &interpreter, std::vector<V
return Binary_Predicate{}(std::move(args.front()), std::move(args.back())); return Binary_Predicate{}(std::move(args.front()), std::move(args.back()));
} }
static Result<Value> multiplication_operator(Interpreter &i, std::vector<Value> args) static Result<Value> builtin_operator_multiply(Interpreter &i, std::vector<Value> args)
{ {
if (args.empty()) { if (args.empty()) {
return Number(1); return Number(1);
@ -185,9 +185,9 @@ static Result<Value> multiplication_operator(Interpreter &i, std::vector<Value>
} }
} }
// If binary_operator returns an error that lists all possible overloads // If builtin_operator_arithmetic returns an error that lists all possible overloads
// of this operator we must inject overloads that we provided above // of this operator we must inject overloads that we provided above
auto result = binary_operator<std::multiplies<>, '*'>(i, { std::move(lhs), std::move(rhs) }); auto result = builtin_operator_arithmetic<std::multiplies<>, '*'>(i, { std::move(lhs), std::move(rhs) });
if (!result.has_value()) { if (!result.has_value()) {
auto &details = result.error().details; auto &details = result.error().details;
if (auto p = std::get_if<errors::Unsupported_Types_For>(&details)) { if (auto p = std::get_if<errors::Unsupported_Types_For>(&details)) {
@ -200,38 +200,20 @@ static Result<Value> multiplication_operator(Interpreter &i, std::vector<Value>
}); });
} }
using Operator_Entry = std::tuple<char const*, Intrinsic::Function_Pointer>; static Result<Value> builtin_operator_index(Interpreter &interpreter, std::vector<Value> args)
{
using power = decltype([](Number lhs, Number rhs) -> Result<Number> {
return lhs.pow(rhs);
});
/// Operators definition table
static constexpr auto Operators = std::array {
Operator_Entry { "+", plus_minus_operator<std::plus<>> },
Operator_Entry { "-", plus_minus_operator<std::minus<>> },
Operator_Entry { "*", multiplication_operator },
Operator_Entry { "/", binary_operator<std::divides<>, '/'> },
Operator_Entry { "%", binary_operator<std::modulus<>, '%'> },
Operator_Entry { "**", binary_operator<power, '*', '*'> },
Operator_Entry { "!=", comparison_operator<std::not_equal_to<>> },
Operator_Entry { "<", comparison_operator<std::less<>> },
Operator_Entry { "<=", comparison_operator<std::less_equal<>> },
Operator_Entry { "==", comparison_operator<std::equal_to<>> },
Operator_Entry { ">", comparison_operator<std::greater<>> },
Operator_Entry { ">=", comparison_operator<std::greater_equal<>> },
Operator_Entry { ".",
+[](Interpreter &interpreter, std::vector<Value> args) -> Result<Value> {
if (auto a = match<Collection, Number>(args)) { if (auto a = match<Collection, Number>(args)) {
auto& [coll, pos] = *a; auto& [coll, pos] = *a;
return coll.index(interpreter, pos.as_int()); return coll.index(interpreter, pos.as_int());
} }
if (auto a = match<Collection, Bool>(args)) { if (auto a = match<Collection, Bool>(args)) {
auto& [coll, pos] = *a; if (auto& [coll, pos] = *a; pos) {
return coll.index(interpreter, pos ? 1 : 0); return coll.index(interpreter, 0);
} }
return Value{};
}
if (auto a = match<Collection, Collection>(args)) { if (auto a = match<Collection, Collection>(args)) {
auto& [source, positions] = *a; auto& [source, positions] = *a;
@ -241,7 +223,7 @@ static constexpr auto Operators = std::array {
auto index = std::visit(Overloaded { auto index = std::visit(Overloaded {
[](Number n) -> std::optional<size_t> { return n.floor().as_int(); }, [](Number n) -> std::optional<size_t> { return n.floor().as_int(); },
[](Bool b) -> std::optional<size_t> { return b ? 1 : 0; }, [n](Bool b) -> std::optional<size_t> { return b ? std::optional(n) : std::nullopt; },
[](auto &&) -> std::optional<size_t> { return std::nullopt; } [](auto &&) -> std::optional<size_t> { return std::nullopt; }
}, v.data); }, v.data);
@ -263,11 +245,10 @@ static constexpr auto Operators = std::array {
}, },
}, },
}; };
} }
},
Operator_Entry { "&", static Result<Value> builtin_operator_join(Interpreter &interpreter, std::vector<Value> args)
+[](Interpreter& i, std::vector<Value> args) -> Result<Value> { {
constexpr auto guard = Guard<2> { constexpr auto guard = Guard<2> {
.name = "&", .name = "&",
.possibilities = { .possibilities = {
@ -296,12 +277,37 @@ static constexpr auto Operators = std::array {
for (auto&& a : args) { for (auto&& a : args) {
auto &array = *Try(guard.match<Collection>(a)); auto &array = *Try(guard.match<Collection>(a));
for (auto n = 0u; n < array.size(); ++n) { for (auto n = 0u; n < array.size(); ++n) {
result.elements.push_back(Try(array.index(i, n))); result.elements.push_back(Try(array.index(interpreter, n)));
} }
} }
return result; return result;
} }
},
using Operator_Entry = std::tuple<char const*, Intrinsic::Function_Pointer>;
using power = decltype([](Number lhs, Number rhs) -> Result<Number> {
return lhs.pow(rhs);
});
/// Operators definition table
static constexpr auto Operators = std::array {
Operator_Entry { "+", builtin_operator_add_subtract<std::plus<>> },
Operator_Entry { "-", builtin_operator_add_subtract<std::minus<>> },
Operator_Entry { "*", builtin_operator_multiply },
Operator_Entry { "/", builtin_operator_arithmetic<std::divides<>, '/'> },
Operator_Entry { "%", builtin_operator_arithmetic<std::modulus<>, '%'> },
Operator_Entry { "**", builtin_operator_arithmetic<power, '*', '*'> },
Operator_Entry { "!=", builtin_operator_compare<std::not_equal_to<>> },
Operator_Entry { "<", builtin_operator_compare<std::less<>> },
Operator_Entry { "<=", builtin_operator_compare<std::less_equal<>> },
Operator_Entry { "==", builtin_operator_compare<std::equal_to<>> },
Operator_Entry { ">", builtin_operator_compare<std::greater<>> },
Operator_Entry { ">=", builtin_operator_compare<std::greater_equal<>> },
Operator_Entry { ".", builtin_operator_index },
Operator_Entry { "&", builtin_operator_join },
}; };
// All operators should be defined here except 'and' and 'or' which handle evaluation differently // All operators should be defined here except 'and' and 'or' which handle evaluation differently