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