Added O_EXPAND operator, to handle macros
This commit is contained in:
parent
713f308d0f
commit
d5f8c3bc57
2 changed files with 50 additions and 3 deletions
52
src/op.cc
52
src/op.cc
|
|
@ -38,6 +38,37 @@
|
||||||
|
|
||||||
namespace ledger {
|
namespace ledger {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
value_t split_cons_expr(expr_t::ptr_op_t op, scope_t& scope,
|
||||||
|
std::vector<expr_t>& exprs)
|
||||||
|
{
|
||||||
|
value_t seq;
|
||||||
|
|
||||||
|
if (op->kind == expr_t::op_t::O_CONS) {
|
||||||
|
exprs.push_back(expr_t(op->left(), &scope));
|
||||||
|
seq.push_back(value_t(exprs.back()));
|
||||||
|
|
||||||
|
expr_t::ptr_op_t next = op->right();
|
||||||
|
while (next) {
|
||||||
|
expr_t::ptr_op_t value_op;
|
||||||
|
if (next->kind == expr_t::op_t::O_CONS) {
|
||||||
|
value_op = next->left();
|
||||||
|
next = next->right();
|
||||||
|
} else {
|
||||||
|
value_op = next;
|
||||||
|
next = NULL;
|
||||||
|
}
|
||||||
|
exprs.push_back(expr_t(value_op, &scope));
|
||||||
|
seq.push_back(value_t(exprs.back()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
exprs.push_back(expr_t(op, &scope));
|
||||||
|
seq.push_back(value_t(exprs.back()));
|
||||||
|
}
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth)
|
expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth)
|
||||||
{
|
{
|
||||||
if (is_ident()) {
|
if (is_ident()) {
|
||||||
|
|
@ -190,11 +221,24 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
|
||||||
_("Failed to lookup member '%1'") << right()->as_ident());
|
_("Failed to lookup member '%1'") << right()->as_ident());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case O_CALL: {
|
case O_CALL:
|
||||||
|
case O_EXPAND: {
|
||||||
call_scope_t call_args(scope);
|
call_scope_t call_args(scope);
|
||||||
|
// When evaluating a macro call, these expressions have to live beyond the
|
||||||
|
// call to calc() below.
|
||||||
|
optional<std::vector<expr_t> > args_expr;
|
||||||
|
|
||||||
if (has_right())
|
if (has_right()) {
|
||||||
call_args.set_args(right()->calc(scope, locus, depth + 1));
|
if (kind == O_CALL) {
|
||||||
|
call_args.set_args(right()->calc(scope, locus, depth + 1));
|
||||||
|
} else {
|
||||||
|
// macros defer calculation to the callee
|
||||||
|
args_expr = std::vector<expr_t>();
|
||||||
|
call_args.set_args(split_cons_expr(right()->kind == O_SEQ ?
|
||||||
|
right()->left() : right(),
|
||||||
|
scope, *args_expr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ptr_op_t func = left();
|
ptr_op_t func = left();
|
||||||
const string& name(func->as_ident());
|
const string& name(func->as_ident());
|
||||||
|
|
@ -592,6 +636,7 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case O_CALL:
|
case O_CALL:
|
||||||
|
case O_EXPAND:
|
||||||
if (left() && left()->print(out, context))
|
if (left() && left()->print(out, context))
|
||||||
found = true;
|
found = true;
|
||||||
if (has_right()) {
|
if (has_right()) {
|
||||||
|
|
@ -663,6 +708,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_CALL: out << "O_CALL"; break;
|
case O_CALL: out << "O_CALL"; break;
|
||||||
|
case O_EXPAND: out << "O_EXPAND"; break;
|
||||||
case O_MATCH: out << "O_MATCH"; break;
|
case O_MATCH: out << "O_MATCH"; break;
|
||||||
|
|
||||||
case O_NOT: out << "O_NOT"; break;
|
case O_NOT: out << "O_NOT"; break;
|
||||||
|
|
|
||||||
1
src/op.h
1
src/op.h
|
|
@ -105,6 +105,7 @@ public:
|
||||||
O_DEFINE,
|
O_DEFINE,
|
||||||
O_LOOKUP,
|
O_LOOKUP,
|
||||||
O_CALL,
|
O_CALL,
|
||||||
|
O_EXPAND,
|
||||||
O_MATCH,
|
O_MATCH,
|
||||||
|
|
||||||
BINARY_OPERATORS,
|
BINARY_OPERATORS,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue