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;
|
||||
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));
|
||||
|
||||
if (op == operators.end()) {
|
||||
|
@ -14,9 +14,13 @@ constexpr auto Keywords = std::array {
|
||||
"false"sv,
|
||||
"nil"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()
|
||||
{
|
||||
for (;;) {
|
||||
@ -124,8 +128,6 @@ auto Lexer::next_token() -> Result<std::variant<Token, End_Of_File>>
|
||||
Token t = { Token::Type::Symbol, finish(), token_location };
|
||||
if (std::find(Keywords.begin(), Keywords.end(), t.source) != Keywords.end()) {
|
||||
t.type = Token::Type::Keyword;
|
||||
} else if (t.source == "v") {
|
||||
t.type = Token::Type::Operator;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
@ -382,6 +382,8 @@ struct Token
|
||||
Location location;
|
||||
};
|
||||
|
||||
static constexpr auto Keywords_Count = 6;
|
||||
|
||||
std::string_view type_name(Token::Type type);
|
||||
|
||||
/// Token debug printing
|
||||
|
@ -21,6 +21,15 @@ constexpr auto Literal_Keywords = std::array {
|
||||
"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
|
||||
{
|
||||
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 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();
|
||||
return parse_expression().map([&](Ast rhs) {
|
||||
return Ast::binary(std::move(op), std::move(lhs), std::move(rhs));
|
||||
|
Loading…
Reference in New Issue
Block a user