Separated blocks from lambdas
This commit is contained in:
parent
52ef323284
commit
8025e9bd0f
@ -321,8 +321,9 @@ struct Ast
|
||||
{
|
||||
// Named constructors of AST structure
|
||||
static Ast binary(Token, Ast lhs, Ast rhs);
|
||||
static Ast block(Location location, Ast seq = sequence({}), std::vector<Ast> parameters = {});
|
||||
static Ast block(Location location, Ast seq = sequence({}));
|
||||
static Ast call(std::vector<Ast> call);
|
||||
static Ast lambda(Location location, Ast seq = sequence({}), std::vector<Ast> parameters = {});
|
||||
static Ast literal(Token);
|
||||
static Ast sequence(std::vector<Ast> call);
|
||||
static Ast variable_declaration(Location loc, std::vector<Ast> lvalues, std::optional<Ast> rvalue);
|
||||
@ -331,6 +332,7 @@ struct Ast
|
||||
{
|
||||
Binary, // Binary operator application like `1` + `2`
|
||||
Block, // Block expressions like `[42; hello]`
|
||||
Lambda, // Block expression beeing functions like `[i|i+1]`
|
||||
Call, // Function call application like `print 42`
|
||||
Literal, // Compile time known constant like `c` or `1`
|
||||
Sequence, // Several expressions sequences like `42`, `42; 32`
|
||||
@ -418,9 +420,19 @@ struct Number
|
||||
std::ostream& operator<<(std::ostream& os, Number const& num);
|
||||
|
||||
struct Value;
|
||||
struct Interpreter;
|
||||
|
||||
using Function = std::function<Result<Value>(std::vector<Value>)>;
|
||||
|
||||
struct Lambda
|
||||
{
|
||||
Location location;
|
||||
std::vector<std::string> parameters;
|
||||
Ast body;
|
||||
|
||||
Result<Value> operator()(Interpreter &i, std::vector<Value> params);
|
||||
};
|
||||
|
||||
template<typename T, typename ...XS>
|
||||
constexpr auto is_one_of = (std::is_same_v<T, XS> || ...);
|
||||
|
||||
|
@ -102,18 +102,30 @@ Result<Ast> Parser::parse_atomic_expression()
|
||||
|
||||
auto start = token_id;
|
||||
std::vector<Ast> parameters;
|
||||
bool is_lambda = false;
|
||||
|
||||
if (auto p = parse_many(*this, &Parser::parse_identifier_with_trailing_separators, std::nullopt, At_Least::One); p && expect(Token::Type::Parameter_Separator)) {
|
||||
if (expect(Token::Type::Parameter_Separator)) {
|
||||
consume();
|
||||
parameters = std::move(p).value();
|
||||
is_lambda = true;
|
||||
} else {
|
||||
token_id = start;
|
||||
auto p = parse_many(*this, &Parser::parse_identifier_with_trailing_separators, std::nullopt, At_Least::One);
|
||||
if (p && expect(Token::Type::Parameter_Separator)) {
|
||||
consume();
|
||||
parameters = std::move(p).value();
|
||||
is_lambda = true;
|
||||
} else {
|
||||
token_id = start;
|
||||
}
|
||||
}
|
||||
|
||||
return parse_sequence().and_then([&](Ast &&ast) -> Result<Ast> {
|
||||
Try(ensure(Token::Type::Close_Block));
|
||||
consume();
|
||||
return Ast::block(opening.location, std::move(ast), std::move(parameters));
|
||||
if (is_lambda) {
|
||||
return Ast::lambda(opening.location, std::move(ast), std::move(parameters));
|
||||
} else {
|
||||
return Ast::block(opening.location, std::move(ast));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -253,16 +265,25 @@ Ast Ast::sequence(std::vector<Ast> expressions)
|
||||
return ast;
|
||||
}
|
||||
|
||||
Ast Ast::block(Location location, Ast seq, std::vector<Ast> parameters)
|
||||
Ast Ast::block(Location location, Ast seq)
|
||||
{
|
||||
Ast ast;
|
||||
ast.type = Type::Block;
|
||||
ast.location = location;
|
||||
ast.arguments = std::move(parameters);
|
||||
ast.arguments.push_back(std::move(seq));
|
||||
return ast;
|
||||
}
|
||||
|
||||
Ast Ast::lambda(Location location, Ast body, std::vector<Ast> parameters)
|
||||
{
|
||||
Ast ast;
|
||||
ast.type = Type::Lambda;
|
||||
ast.location = location;
|
||||
ast.arguments = std::move(parameters);
|
||||
ast.arguments.push_back(std::move(body));
|
||||
return ast;
|
||||
}
|
||||
|
||||
Ast Ast::variable_declaration(Location loc, std::vector<Ast> lvalues, std::optional<Ast> rvalue)
|
||||
{
|
||||
Ast ast;
|
||||
@ -300,6 +321,7 @@ bool operator==(Ast const& lhs, Ast const& rhs)
|
||||
|
||||
case Ast::Type::Block:
|
||||
case Ast::Type::Call:
|
||||
case Ast::Type::Lambda:
|
||||
case Ast::Type::Sequence:
|
||||
case Ast::Type::Variable_Declaration:
|
||||
return lhs.arguments.size() == rhs.arguments.size()
|
||||
@ -315,6 +337,7 @@ std::ostream& operator<<(std::ostream& os, Ast::Type type)
|
||||
case Ast::Type::Binary: return os << "BINARY";
|
||||
case Ast::Type::Block: return os << "BLOCK";
|
||||
case Ast::Type::Call: return os << "CALL";
|
||||
case Ast::Type::Lambda: return os << "LAMBDA";
|
||||
case Ast::Type::Literal: return os << "LITERAL";
|
||||
case Ast::Type::Sequence: return os << "SEQUENCE";
|
||||
case Ast::Type::Variable_Declaration: return os << "VAR";
|
||||
|
@ -139,9 +139,9 @@ suite parser_test = [] {
|
||||
Ast::literal({ Token::Type::Symbol, "i", {} }),
|
||||
Ast::literal({ Token::Type::Symbol, "j", {} }),
|
||||
Ast::literal({ Token::Type::Symbol, "k", {} })
|
||||
}), {}));
|
||||
})));
|
||||
|
||||
expect_ast("[ i j k | i + j + k ]", Ast::block({}, Ast::binary(
|
||||
expect_ast("[ i j k | i + j + k ]", Ast::lambda({}, Ast::binary(
|
||||
{ Token::Type::Operator, "+", {} },
|
||||
Ast::literal({ Token::Type::Symbol, "i", {} }),
|
||||
Ast::binary(
|
||||
@ -155,7 +155,7 @@ suite parser_test = [] {
|
||||
Ast::literal({ Token::Type::Symbol, "k", {} })
|
||||
}));
|
||||
|
||||
expect_ast("[ i; j; k | i + j + k ]", Ast::block({}, Ast::binary(
|
||||
expect_ast("[ i; j; k | i + j + k ]", Ast::lambda({}, Ast::binary(
|
||||
{ Token::Type::Operator, "+", {} },
|
||||
Ast::literal({ Token::Type::Symbol, "i", {} }),
|
||||
Ast::binary(
|
||||
@ -168,6 +168,8 @@ suite parser_test = [] {
|
||||
Ast::literal({ Token::Type::Symbol, "j", {} }),
|
||||
Ast::literal({ Token::Type::Symbol, "k", {} })
|
||||
}));
|
||||
|
||||
expect_ast("[|1]", Ast::lambda({}, Ast::literal({ Token::Type::Numeric, "1", {} }), {}));
|
||||
};
|
||||
|
||||
"Variable declarations"_test = [] {
|
||||
|
Loading…
Reference in New Issue
Block a user