Logical short-circuting operators
This commit is contained in:
parent
946d4b96b1
commit
4d88ca7e40
@ -492,6 +492,19 @@ Result<Value> Interpreter::eval(Ast &&ast)
|
|||||||
std::vector<Value> values;
|
std::vector<Value> values;
|
||||||
values.reserve(ast.arguments.size());
|
values.reserve(ast.arguments.size());
|
||||||
|
|
||||||
|
if (ast.token.source == "and" || ast.token.source == "or") {
|
||||||
|
assert(ast.arguments.size() == 2, "Expected arguments of binary operation to be 2 long");
|
||||||
|
auto lhs = std::move(ast.arguments.front());
|
||||||
|
auto rhs = std::move(ast.arguments.back());
|
||||||
|
|
||||||
|
auto result = Try(eval(std::move(lhs)));
|
||||||
|
if (ast.token.source == "or" ? result.truthy() : result.falsy()) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return eval(std::move(rhs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto op = operators.find(std::string(ast.token.source));
|
auto op = operators.find(std::string(ast.token.source));
|
||||||
|
|
||||||
if (op == operators.end()) {
|
if (op == operators.end()) {
|
||||||
|
@ -14,9 +14,13 @@ constexpr auto Keywords = std::array {
|
|||||||
"false"sv,
|
"false"sv,
|
||||||
"nil"sv,
|
"nil"sv,
|
||||||
"true"sv,
|
"true"sv,
|
||||||
"var"sv
|
"var"sv,
|
||||||
|
"and"sv,
|
||||||
|
"or"sv
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static_assert(Keywords.size() == Keywords_Count, "Table above should contain all the tokens for lexing");
|
||||||
|
|
||||||
void Lexer::skip_whitespace_and_comments()
|
void Lexer::skip_whitespace_and_comments()
|
||||||
{
|
{
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -124,8 +128,6 @@ auto Lexer::next_token() -> Result<std::variant<Token, End_Of_File>>
|
|||||||
Token t = { Token::Type::Symbol, finish(), token_location };
|
Token t = { Token::Type::Symbol, finish(), token_location };
|
||||||
if (std::find(Keywords.begin(), Keywords.end(), t.source) != Keywords.end()) {
|
if (std::find(Keywords.begin(), Keywords.end(), t.source) != Keywords.end()) {
|
||||||
t.type = Token::Type::Keyword;
|
t.type = Token::Type::Keyword;
|
||||||
} else if (t.source == "v") {
|
|
||||||
t.type = Token::Type::Operator;
|
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
@ -382,6 +382,8 @@ struct Token
|
|||||||
Location location;
|
Location location;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static constexpr auto Keywords_Count = 6;
|
||||||
|
|
||||||
std::string_view type_name(Token::Type type);
|
std::string_view type_name(Token::Type type);
|
||||||
|
|
||||||
/// Token debug printing
|
/// Token debug printing
|
||||||
|
@ -21,6 +21,15 @@ constexpr auto Literal_Keywords = std::array {
|
|||||||
"true"sv,
|
"true"sv,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static_assert(Keywords_Count == Literal_Keywords.size() + 3, "Ensure that all literal keywords are listed");
|
||||||
|
|
||||||
|
constexpr auto Operator_Keywords = std::array {
|
||||||
|
"and"sv,
|
||||||
|
"or"sv
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(Keywords_Count == Operator_Keywords.size() + 4, "Ensure that all keywords that are operators are listed here");
|
||||||
|
|
||||||
enum class At_Least : bool
|
enum class At_Least : bool
|
||||||
{
|
{
|
||||||
Zero,
|
Zero,
|
||||||
@ -113,7 +122,7 @@ Result<Ast> Parser::parse_infix_expression()
|
|||||||
auto atomics = Try(parse_many(*this, &Parser::parse_atomic_expression, std::nullopt, At_Least::One));
|
auto atomics = Try(parse_many(*this, &Parser::parse_atomic_expression, std::nullopt, At_Least::One));
|
||||||
auto lhs = wrap_if_several(std::move(atomics), Ast::call);
|
auto lhs = wrap_if_several(std::move(atomics), Ast::call);
|
||||||
|
|
||||||
if (expect(Token::Type::Operator)) {
|
if (expect(Token::Type::Operator) || expect(Token::Type::Keyword, "and") || expect(Token::Type::Keyword, "or")) {
|
||||||
auto op = consume();
|
auto op = consume();
|
||||||
return parse_expression().map([&](Ast rhs) {
|
return parse_expression().map([&](Ast rhs) {
|
||||||
return Ast::binary(std::move(op), std::move(lhs), std::move(rhs));
|
return Ast::binary(std::move(op), std::move(lhs), std::move(rhs));
|
||||||
|
Loading…
Reference in New Issue
Block a user