diff options
Diffstat (limited to 'src/op.cc')
-rw-r--r-- | src/op.cc | 68 |
1 files changed, 33 insertions, 35 deletions
@@ -39,14 +39,11 @@ namespace ledger { namespace { - value_t split_cons_expr(expr_t::ptr_op_t op, scope_t& scope, - std::vector<expr_t>& exprs) + value_t split_cons_expr(expr_t::ptr_op_t op) { - 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())); + value_t seq; + seq.push_back(expr_value(op->left())); expr_t::ptr_op_t next = op->right(); while (next) { @@ -58,14 +55,24 @@ namespace { value_op = next; next = NULL; } - exprs.push_back(expr_t(value_op, &scope)); - seq.push_back(value_t(exprs.back())); + seq.push_back(expr_value(value_op)); } + return seq; } else { - exprs.push_back(expr_t(op, &scope)); - seq.push_back(value_t(exprs.back())); + return expr_value(op); + } + } + + inline void check_type_context(scope_t& scope, value_t& result) + { + if (scope.type_required() && + scope.type_context() != value_t::VOID && + result.type() != scope.type_context()) { + throw_(calc_error, + _("Expected return of %1, but received %2") + << result.label(scope.type_context()) + << result.label()); } - return seq; } } @@ -150,9 +157,10 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) // Evaluating an identifier is the same as calling its definition // directly, so we create an empty call_scope_t to reflect the scope for // this implicit call. - call_scope_t call_args(scope); + call_scope_t call_args(scope, scope.type_context(), scope.type_required()); result = left()->compile(call_args, depth + 1) ->calc(call_args, locus, depth + 1); + check_type_context(scope, result); break; } @@ -160,8 +168,9 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) // Evaluating a FUNCTION is the same as calling it directly; this happens // when certain functions-that-look-like-variables (such as "amount") are // resolved. - call_scope_t call_args(scope); + call_scope_t call_args(scope, scope.type_context(), scope.type_required()); result = as_function()(call_args); + check_type_context(scope, result); #if defined(DEBUG_ON) skip_debug = true; #endif @@ -200,8 +209,9 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) break; } - case O_LOOKUP: - if (value_t obj = left()->calc(scope, locus, depth + 1)) { + case O_LOOKUP: { + context_scope_t context_scope(scope, value_t::SCOPE); + if (value_t obj = left()->calc(context_scope, locus, depth + 1)) { if (obj.is_scope()) { if (obj.as_scope() == NULL) { throw_(calc_error, _("Left operand of . operator is NULL")); @@ -222,25 +232,13 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) throw_(calc_error, _("Failed to lookup member '%1'") << right()->as_ident()); break; + } - case O_CALL: - case O_EXPAND: { - 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 (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)); - } - } + case O_CALL: { + call_scope_t call_args(scope, scope.type_context(), scope.type_required()); + if (has_right()) + call_args.set_args(split_cons_expr(right()->kind == O_SEQ ? + right()->left() : right())); ptr_op_t func = left(); const string& name(func->as_ident()); @@ -253,6 +251,8 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) result = func->as_function()(call_args); else result = func->calc(call_args, locus, depth + 1); + + check_type_context(scope, result); break; } @@ -638,7 +638,6 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const break; case O_CALL: - case O_EXPAND: if (left() && left()->print(out, context)) found = true; if (has_right()) { @@ -710,7 +709,6 @@ void expr_t::op_t::dump(std::ostream& out, const int depth) const case O_DEFINE: out << "O_DEFINE"; break; case O_LOOKUP: out << "O_LOOKUP"; break; case O_CALL: out << "O_CALL"; break; - case O_EXPAND: out << "O_EXPAND"; break; case O_MATCH: out << "O_MATCH"; break; case O_NOT: out << "O_NOT"; break; |