fold
buultin. Operators can be quoted
By prepending ' to operator you can use it as function
This commit is contained in:
parent
9b846d8115
commit
96c96ef2b0
@ -402,6 +402,43 @@ static Result<Value> builtin_for(Interpreter &i, std::vector<Value> args)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fold container
|
||||||
|
static Result<Value> builtin_fold(Interpreter &interpreter, std::vector<Value> args) {
|
||||||
|
constexpr auto guard = Guard<2> {
|
||||||
|
.name = "fold",
|
||||||
|
.possibilities = {
|
||||||
|
"(array, callback) -> any",
|
||||||
|
"(array, init, callback) -> any"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Value array, init, callback;
|
||||||
|
switch (args.size()) {
|
||||||
|
break; case 2:
|
||||||
|
array = std::move(args[0]);
|
||||||
|
callback = std::move(args[1]);
|
||||||
|
if (array.size() != 0) {
|
||||||
|
init = Try(array.index(interpreter, 0));
|
||||||
|
}
|
||||||
|
break; case 3:
|
||||||
|
array = std::move(args[0]);
|
||||||
|
init = std::move(args[1]);
|
||||||
|
callback = std::move(args[2]);
|
||||||
|
break; default:
|
||||||
|
return guard.yield_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
Try(guard(is_indexable, array));
|
||||||
|
Try(guard(is_callable, callback));
|
||||||
|
|
||||||
|
for (auto i = 0u; i < array.size(); ++i) {
|
||||||
|
auto element = Try(array.index(interpreter, i));
|
||||||
|
init = Try(callback(interpreter, { std::move(init), std::move(element) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
return init;
|
||||||
|
}
|
||||||
|
|
||||||
/// 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) {
|
||||||
constexpr auto guard = Guard<2> {
|
constexpr auto guard = Guard<2> {
|
||||||
@ -790,6 +827,7 @@ void Interpreter::register_builtin_functions()
|
|||||||
global.force_define("down", builtin_range<Range_Direction::Down>);
|
global.force_define("down", builtin_range<Range_Direction::Down>);
|
||||||
global.force_define("flat", builtin_flat);
|
global.force_define("flat", builtin_flat);
|
||||||
global.force_define("floor", apply_numeric_transform<&Number::floor>);
|
global.force_define("floor", apply_numeric_transform<&Number::floor>);
|
||||||
|
global.force_define("fold", builtin_fold);
|
||||||
global.force_define("for", builtin_for);
|
global.force_define("for", builtin_for);
|
||||||
global.force_define("hash", builtin_hash);
|
global.force_define("hash", builtin_hash);
|
||||||
global.force_define("if", builtin_if);
|
global.force_define("if", builtin_if);
|
||||||
|
@ -55,8 +55,12 @@ Result<Value> Interpreter::eval(Ast &&ast)
|
|||||||
case Token::Type::Symbol:
|
case Token::Type::Symbol:
|
||||||
{
|
{
|
||||||
if (ast.token.source.starts_with('\'')) {
|
if (ast.token.source.starts_with('\'')) {
|
||||||
|
if (auto op = operators.find(std::string(ast.token.source.substr(1))); op != operators.end()) {
|
||||||
|
return Value(op->second);
|
||||||
|
} else {
|
||||||
return Value::from(std::move(ast.token.source).substr(1));
|
return Value::from(std::move(ast.token.source).substr(1));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto name = std::string(ast.token.source);
|
auto name = std::string(ast.token.source);
|
||||||
|
|
||||||
|
12
src/lexer.cc
12
src/lexer.cc
@ -135,8 +135,18 @@ auto Lexer::next_token() -> Result<std::variant<Token, End_Of_File>>
|
|||||||
return Token { Token::Type::Chord, finish(), token_location };
|
return Token { Token::Type::Chord, finish(), token_location };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lex symbol
|
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
|
||||||
|
// Lex quoted symbol
|
||||||
|
if (consume_if('\'')) {
|
||||||
|
for (auto predicate = std::bind(unicode::is_identifier, _1, unicode::First_Character::No);
|
||||||
|
consume_if(predicate) || consume_if(Valid_Operator_Chars);) {}
|
||||||
|
|
||||||
|
Token t = { Token::Type::Symbol, finish(), token_location };
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lex symbol
|
||||||
if (consume_if(std::bind(unicode::is_identifier, _1, unicode::First_Character::Yes))) {
|
if (consume_if(std::bind(unicode::is_identifier, _1, unicode::First_Character::Yes))) {
|
||||||
symbol_lexing:
|
symbol_lexing:
|
||||||
for (auto predicate = std::bind(unicode::is_identifier, _1, unicode::First_Character::No);
|
for (auto predicate = std::bind(unicode::is_identifier, _1, unicode::First_Character::No);
|
||||||
|
Loading…
Reference in New Issue
Block a user