Added initial support for lambda functions
This commit is contained in:
parent
e162455ebb
commit
84780270f9
6 changed files with 129 additions and 27 deletions
32
src/op.cc
32
src/op.cc
|
|
@ -108,10 +108,15 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth)
|
||||||
scope.define(symbol_t::FUNCTION, left()->as_ident(), right());
|
scope.define(symbol_t::FUNCTION, left()->as_ident(), right());
|
||||||
break;
|
break;
|
||||||
case O_CALL:
|
case O_CALL:
|
||||||
if (left()->left()->is_ident())
|
if (left()->left()->is_ident()) {
|
||||||
scope.define(symbol_t::FUNCTION, left()->left()->as_ident(), this);
|
ptr_op_t node(new op_t(op_t::O_LAMBDA));
|
||||||
else
|
node->set_left(left()->right());
|
||||||
|
node->set_right(right());
|
||||||
|
|
||||||
|
scope.define(symbol_t::FUNCTION, left()->left()->as_ident(), node);
|
||||||
|
} else {
|
||||||
throw_(compile_error, _("Invalid function definition"));
|
throw_(compile_error, _("Invalid function definition"));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw_(compile_error, _("Invalid function definition"));
|
throw_(compile_error, _("Invalid function definition"));
|
||||||
|
|
@ -183,16 +188,12 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case O_DEFINE: {
|
case O_LAMBDA: {
|
||||||
call_scope_t& call_args(downcast<call_scope_t>(scope));
|
call_scope_t& call_args(downcast<call_scope_t>(scope));
|
||||||
std::size_t args_count = call_args.size();
|
std::size_t args_count(call_args.size());
|
||||||
std::size_t args_index = 0;
|
std::size_t args_index(0);
|
||||||
|
|
||||||
assert(left()->kind == O_CALL);
|
|
||||||
|
|
||||||
ptr_op_t sym = left()->right();
|
|
||||||
|
|
||||||
symbol_scope_t call_scope(call_args);
|
symbol_scope_t call_scope(call_args);
|
||||||
|
ptr_op_t sym(left());
|
||||||
|
|
||||||
for (; sym; sym = sym->has_right() ? sym->right() : NULL) {
|
for (; sym; sym = sym->has_right() ? sym->right() : NULL) {
|
||||||
ptr_op_t varname = sym;
|
ptr_op_t varname = sym;
|
||||||
|
|
@ -618,6 +619,14 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case O_LAMBDA:
|
||||||
|
if (left() && left()->print(out, context))
|
||||||
|
found = true;
|
||||||
|
out << " -> ";
|
||||||
|
if (has_right() && right()->print(out, context))
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case O_CALL:
|
case O_CALL:
|
||||||
if (left() && left()->print(out, context))
|
if (left() && left()->print(out, context))
|
||||||
found = true;
|
found = true;
|
||||||
|
|
@ -692,6 +701,7 @@ void expr_t::op_t::dump(std::ostream& out, const int depth) const
|
||||||
|
|
||||||
case O_DEFINE: out << "O_DEFINE"; break;
|
case O_DEFINE: out << "O_DEFINE"; break;
|
||||||
case O_LOOKUP: out << "O_LOOKUP"; break;
|
case O_LOOKUP: out << "O_LOOKUP"; break;
|
||||||
|
case O_LAMBDA: out << "O_LAMBDA"; break;
|
||||||
case O_CALL: out << "O_CALL"; break;
|
case O_CALL: out << "O_CALL"; break;
|
||||||
case O_MATCH: out << "O_MATCH"; break;
|
case O_MATCH: out << "O_MATCH"; break;
|
||||||
|
|
||||||
|
|
|
||||||
1
src/op.h
1
src/op.h
|
|
@ -104,6 +104,7 @@ public:
|
||||||
|
|
||||||
O_DEFINE,
|
O_DEFINE,
|
||||||
O_LOOKUP,
|
O_LOOKUP,
|
||||||
|
O_LAMBDA,
|
||||||
O_CALL,
|
O_CALL,
|
||||||
O_MATCH,
|
O_MATCH,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -238,9 +238,6 @@ expr_t::parser_t::parse_logic_expr(std::istream& in,
|
||||||
bool negate = false;
|
bool negate = false;
|
||||||
|
|
||||||
switch (tok.kind) {
|
switch (tok.kind) {
|
||||||
case token_t::DEFINE:
|
|
||||||
kind = op_t::O_DEFINE;
|
|
||||||
break;
|
|
||||||
case token_t::EQUAL:
|
case token_t::EQUAL:
|
||||||
if (tflags.has_flags(PARSE_NO_ASSIGN))
|
if (tflags.has_flags(PARSE_NO_ASSIGN))
|
||||||
tok.rewind(in);
|
tok.rewind(in);
|
||||||
|
|
@ -422,22 +419,42 @@ expr_t::parser_t::parse_querycolon_expr(std::istream& in,
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_t::ptr_op_t
|
expr_t::ptr_op_t
|
||||||
expr_t::parser_t::parse_value_expr(std::istream& in,
|
expr_t::parser_t::parse_lambda_expr(std::istream& in,
|
||||||
const parse_flags_t& tflags) const
|
const parse_flags_t& tflags) const
|
||||||
{
|
{
|
||||||
ptr_op_t node(parse_querycolon_expr(in, tflags));
|
ptr_op_t node(parse_querycolon_expr(in, tflags));
|
||||||
|
|
||||||
|
if (node && ! tflags.has_flags(PARSE_SINGLE)) {
|
||||||
|
token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
|
||||||
|
|
||||||
|
if (tok.kind == token_t::ARROW) {
|
||||||
|
ptr_op_t prev(node);
|
||||||
|
node = new op_t(op_t::O_LAMBDA);
|
||||||
|
node->set_left(prev);
|
||||||
|
node->set_right(parse_querycolon_expr(in, tflags));
|
||||||
|
} else {
|
||||||
|
push_token(tok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_t::ptr_op_t
|
||||||
|
expr_t::parser_t::parse_comma_expr(std::istream& in,
|
||||||
|
const parse_flags_t& tflags) const
|
||||||
|
{
|
||||||
|
ptr_op_t node(parse_lambda_expr(in, tflags));
|
||||||
|
|
||||||
if (node && ! tflags.has_flags(PARSE_SINGLE)) {
|
if (node && ! tflags.has_flags(PARSE_SINGLE)) {
|
||||||
ptr_op_t next;
|
ptr_op_t next;
|
||||||
while (true) {
|
while (true) {
|
||||||
token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
|
token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
|
||||||
|
|
||||||
if (tok.kind == token_t::COMMA || tok.kind == token_t::SEMI) {
|
if (tok.kind == token_t::COMMA) {
|
||||||
bool comma_op = tok.kind == token_t::COMMA;
|
|
||||||
|
|
||||||
if (! next) {
|
if (! next) {
|
||||||
ptr_op_t prev(node);
|
ptr_op_t prev(node);
|
||||||
node = new op_t(comma_op ? op_t::O_CONS : op_t::O_SEQ);
|
node = new op_t(op_t::O_CONS);
|
||||||
node->set_left(prev);
|
node->set_left(prev);
|
||||||
|
|
||||||
next = node;
|
next = node;
|
||||||
|
|
@ -448,8 +465,65 @@ expr_t::parser_t::parse_value_expr(std::istream& in,
|
||||||
if (ntok.kind == token_t::RPAREN)
|
if (ntok.kind == token_t::RPAREN)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ptr_op_t chain(new op_t(comma_op ? op_t::O_CONS : op_t::O_SEQ));
|
ptr_op_t chain(new op_t(op_t::O_CONS));
|
||||||
chain->set_left(parse_querycolon_expr(in, tflags));
|
chain->set_left(parse_lambda_expr(in, tflags));
|
||||||
|
|
||||||
|
next->set_right(chain);
|
||||||
|
next = chain;
|
||||||
|
} else {
|
||||||
|
push_token(tok);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_t::ptr_op_t
|
||||||
|
expr_t::parser_t::parse_assign_expr(std::istream& in,
|
||||||
|
const parse_flags_t& tflags) const
|
||||||
|
{
|
||||||
|
ptr_op_t node(parse_comma_expr(in, tflags));
|
||||||
|
|
||||||
|
if (node && ! tflags.has_flags(PARSE_SINGLE)) {
|
||||||
|
token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
|
||||||
|
|
||||||
|
if (tok.kind == token_t::ASSIGN) {
|
||||||
|
ptr_op_t prev(node);
|
||||||
|
node = new op_t(op_t::O_DEFINE);
|
||||||
|
node->set_left(prev);
|
||||||
|
node->set_right(parse_comma_expr(in, tflags));
|
||||||
|
} else {
|
||||||
|
push_token(tok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_t::ptr_op_t
|
||||||
|
expr_t::parser_t::parse_value_expr(std::istream& in,
|
||||||
|
const parse_flags_t& tflags) const
|
||||||
|
{
|
||||||
|
ptr_op_t node(parse_assign_expr(in, tflags));
|
||||||
|
|
||||||
|
if (node && ! tflags.has_flags(PARSE_SINGLE)) {
|
||||||
|
ptr_op_t next;
|
||||||
|
while (true) {
|
||||||
|
token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT));
|
||||||
|
|
||||||
|
if (tok.kind == token_t::SEMI) {
|
||||||
|
if (! next) {
|
||||||
|
ptr_op_t prev(node);
|
||||||
|
node = new op_t(op_t::O_SEQ);
|
||||||
|
node->set_left(prev);
|
||||||
|
|
||||||
|
next = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr_op_t chain(new op_t(op_t::O_SEQ));
|
||||||
|
chain->set_left(parse_assign_expr(in, tflags));
|
||||||
|
|
||||||
next->set_right(chain);
|
next->set_right(chain);
|
||||||
next = chain;
|
next = chain;
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,12 @@ class expr_t::parser_t : public noncopyable
|
||||||
const parse_flags_t& flags) const;
|
const parse_flags_t& flags) const;
|
||||||
ptr_op_t parse_querycolon_expr(std::istream& in,
|
ptr_op_t parse_querycolon_expr(std::istream& in,
|
||||||
const parse_flags_t& flags) const;
|
const parse_flags_t& flags) const;
|
||||||
|
ptr_op_t parse_comma_expr(std::istream& in,
|
||||||
|
const parse_flags_t& flags) const;
|
||||||
|
ptr_op_t parse_lambda_expr(std::istream& in,
|
||||||
|
const parse_flags_t& flags) const;
|
||||||
|
ptr_op_t parse_assign_expr(std::istream& in,
|
||||||
|
const parse_flags_t& flags) const;
|
||||||
ptr_op_t parse_value_expr(std::istream& in,
|
ptr_op_t parse_value_expr(std::istream& in,
|
||||||
const parse_flags_t& flags) const;
|
const parse_flags_t& flags) const;
|
||||||
|
|
||||||
|
|
|
||||||
11
src/token.cc
11
src/token.cc
|
|
@ -269,6 +269,15 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
|
||||||
|
|
||||||
case '-':
|
case '-':
|
||||||
in.get(c);
|
in.get(c);
|
||||||
|
c = static_cast<char>(in.peek());
|
||||||
|
if (c == '>') {
|
||||||
|
in.get(c);
|
||||||
|
symbol[1] = c;
|
||||||
|
symbol[2] = '\0';
|
||||||
|
kind = ARROW;
|
||||||
|
length = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
kind = MINUS;
|
kind = MINUS;
|
||||||
break;
|
break;
|
||||||
case '+':
|
case '+':
|
||||||
|
|
@ -329,7 +338,7 @@ void expr_t::token_t::next(std::istream& in, const parse_flags_t& pflags,
|
||||||
length = 2;
|
length = 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
kind = DEFINE;
|
kind = ASSIGN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '<':
|
case '<':
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,8 @@ struct expr_t::token_t : public noncopyable
|
||||||
|
|
||||||
LPAREN, // (
|
LPAREN, // (
|
||||||
RPAREN, // )
|
RPAREN, // )
|
||||||
|
LBRACE, // {
|
||||||
|
RBRACE, // }
|
||||||
|
|
||||||
EQUAL, // ==
|
EQUAL, // ==
|
||||||
NEQUAL, // !=
|
NEQUAL, // !=
|
||||||
|
|
@ -64,7 +66,6 @@ struct expr_t::token_t : public noncopyable
|
||||||
GREATER, // >
|
GREATER, // >
|
||||||
GREATEREQ, // >=
|
GREATEREQ, // >=
|
||||||
|
|
||||||
DEFINE, // :=
|
|
||||||
ASSIGN, // =
|
ASSIGN, // =
|
||||||
MATCH, // =~
|
MATCH, // =~
|
||||||
NMATCH, // !~
|
NMATCH, // !~
|
||||||
|
|
@ -72,6 +73,7 @@ struct expr_t::token_t : public noncopyable
|
||||||
PLUS, // +
|
PLUS, // +
|
||||||
STAR, // *
|
STAR, // *
|
||||||
SLASH, // /
|
SLASH, // /
|
||||||
|
ARROW, // ->
|
||||||
KW_DIV, // div
|
KW_DIV, // div
|
||||||
|
|
||||||
EXCLAM, // !, not
|
EXCLAM, // !, not
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue