builtin try: should be switched to macro with if or for

This commit is contained in:
Robert Bendun 2023-01-09 09:58:31 +01:00
parent d85c29427d
commit b39e1c4a0f

View File

@ -849,30 +849,31 @@ static Result<Value> builtin_while(Interpreter &i, std::span<Ast> args) {
//: TODO //: TODO
//: ``` //: ```
/// Try executing all but last block and if it fails execute last one /// Try executing all but last block and if it fails execute last one
static Result<Value> builtin_try(Interpreter &interpreter, std::vector<Value> args) static Result<Value> builtin_try(Interpreter &interpreter, std::span<Ast> args)
{ {
constexpr auto guard = Guard<1> {
.name = "try",
.possibilities = {
"(...function) -> any"
}
};
if (args.size() == 1) { if (args.size() == 1) {
auto callable = Try(guard.match<Function>(args[0])); // TODO This should be abstracted
return std::move(*callable)(interpreter, {}).value_or(Value{}); auto result = (args[0].type == Ast::Type::Block)
? interpreter.eval((Ast)args[0].arguments.front())
: interpreter.eval((Ast)args[0]);
return result.value_or(Value{});
} }
Value success; Value success;
for (usize i = 0; i+1 < args.size(); ++i) { for (auto const& node : args.subspan(0, args.size()-1)) {
auto callable = Try(guard.match<Function>(args[i])); auto result = (node.type == Ast::Type::Block)
if (auto result = std::move(*callable)(interpreter, {})) { ? interpreter.eval((Ast)node.arguments.front())
success = *std::move(result); : interpreter.eval((Ast)node);
} else {
auto callable = Try(guard.match<Function>(args.back())); if (result.has_value()) {
return std::move(*callable)(interpreter, {}); success = *result;
continue;
} }
return (args.back().type == Ast::Type::Block)
? interpreter.eval((Ast)args.back().arguments.front())
: interpreter.eval((Ast)args.back());
} }
return success; return success;