diff options
author | John Wiegley <johnw@newartisans.com> | 2008-08-05 13:17:04 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2008-08-05 18:05:49 -0400 |
commit | f6f4a46cf5b14f9a2170cd6475958efbf320caec (patch) | |
tree | 05bc1defcdebc201de3dd10477483d906a842821 /op.cc | |
parent | b7970b29855563e4c67f85af8b31233eda80c22a (diff) | |
download | fork-ledger-f6f4a46cf5b14f9a2170cd6475958efbf320caec.tar.gz fork-ledger-f6f4a46cf5b14f9a2170cd6475958efbf320caec.tar.bz2 fork-ledger-f6f4a46cf5b14f9a2170cd6475958efbf320caec.zip |
Moved around most of the files so that source code is in src/, documentation
is in doc/, etc.
Diffstat (limited to 'op.cc')
-rw-r--r-- | op.cc | 1130 |
1 files changed, 0 insertions, 1130 deletions
@@ -1,1130 +0,0 @@ -/* - * Copyright (c) 2003-2008, John Wiegley. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of New Artisans LLC nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "op.h" -#include "scope.h" -#include "binary.h" - -namespace ledger { - -#if 0 -void expr_t::op_t::compute(value_t& result, - const details_t& details, - ptr_op_t context) const -{ - try { - switch (kind) { - case INDEX: - throw compute_error("Cannot directly compute an argument index"); - - case VALUE: - result = as_value(); - break; - - case F_NOW: - result = terminus; - break; - - case AMOUNT: - if (details.xact) { - if (xact_has_xdata(*details.xact) && - xact_xdata_(*details.xact).dflags & XACT_COMPOUND) - result = xact_xdata_(*details.xact).value; - else - result = details.xact->amount; - } - else if (details.account && account_has_xdata(*details.account)) { - result = account_xdata(*details.account).value; - } - else { - result = 0L; - } - break; - - case PRICE: - if (details.xact) { - bool set = false; - if (xact_has_xdata(*details.xact)) { - xact_xdata_t& xdata(xact_xdata_(*details.xact)); - if (xdata.dflags & XACT_COMPOUND) { - result = xdata.value.value(); - set = true; - } - } - if (! set) { - optional<amount_t> value = details.xact->amount.value(); - if (value) - result = *value; - else - result = 0L; - } - } - else if (details.account && account_has_xdata(*details.account)) { - result = account_xdata(*details.account).value.value(); - } - else { - result = 0L; - } - break; - - case COST: - if (details.xact) { - bool set = false; - if (xact_has_xdata(*details.xact)) { - xact_xdata_t& xdata(xact_xdata_(*details.xact)); - if (xdata.dflags & XACT_COMPOUND) { - result = xdata.value.cost(); - set = true; - } - } - - if (! set) { - if (details.xact->cost) - result = *details.xact->cost; - else - result = details.xact->amount; - } - } - else if (details.account && account_has_xdata(*details.account)) { - result = account_xdata(*details.account).value.cost(); - } - else { - result = 0L; - } - break; - - case TOTAL: - if (details.xact && xact_has_xdata(*details.xact)) - result = xact_xdata_(*details.xact).total; - else if (details.account && account_has_xdata(*details.account)) - result = account_xdata(*details.account).total; - else - result = 0L; - break; - case PRICE_TOTAL: - if (details.xact && xact_has_xdata(*details.xact)) - result = xact_xdata_(*details.xact).total.value(); - else if (details.account && account_has_xdata(*details.account)) - result = account_xdata(*details.account).total.value(); - else - result = 0L; - break; - case COST_TOTAL: - if (details.xact && xact_has_xdata(*details.xact)) - result = xact_xdata_(*details.xact).total.cost(); - else if (details.account && account_has_xdata(*details.account)) - result = account_xdata(*details.account).total.cost(); - else - result = 0L; - break; - - case VALUE_EXPR: - if (value_expr::amount_expr.get()) - value_expr::amount_expr->compute(result, details, context); - else - result = 0L; - break; - case TOTAL_EXPR: - if (value_expr::total_expr.get()) - value_expr::total_expr->compute(result, details, context); - else - result = 0L; - break; - - case DATE: - if (details.xact && xact_has_xdata(*details.xact) && - is_valid(xact_xdata_(*details.xact).date)) - result = xact_xdata_(*details.xact).date; - else if (details.xact) - result = details.xact->date(); - else if (details.entry) - result = details.entry->date(); - else - result = terminus; - break; - - case ACT_DATE: - if (details.xact && xact_has_xdata(*details.xact) && - is_valid(xact_xdata_(*details.xact).date)) - result = xact_xdata_(*details.xact).date; - else if (details.xact) - result = details.xact->actual_date(); - else if (details.entry) - result = details.entry->actual_date(); - else - result = terminus; - break; - - case EFF_DATE: - if (details.xact && xact_has_xdata(*details.xact) && - is_valid(xact_xdata_(*details.xact).date)) - result = xact_xdata_(*details.xact).date; - else if (details.xact) - result = details.xact->effective_date(); - else if (details.entry) - result = details.entry->effective_date(); - else - result = terminus; - break; - - case CLEARED: - if (details.xact) - result = details.xact->state == xact_t::CLEARED; - else - result = false; - break; - case PENDING: - if (details.xact) - result = details.xact->state == xact_t::PENDING; - else - result = false; - break; - - case REAL: - if (details.xact) - result = ! (details.xact->has_flags(XACT_VIRTUAL)); - else - result = true; - break; - - case ACTUAL: - if (details.xact) - result = ! (details.xact->has_flags(XACT_AUTO)); - else - result = true; - break; - - case INDEX: - if (details.xact && xact_has_xdata(*details.xact)) - result = long(xact_xdata_(*details.xact).index + 1); - else if (details.account && account_has_xdata(*details.account)) - result = long(account_xdata(*details.account).count); - else - result = 0L; - break; - - case COUNT: - if (details.xact && xact_has_xdata(*details.xact)) - result = long(xact_xdata_(*details.xact).index + 1); - else if (details.account && account_has_xdata(*details.account)) - result = long(account_xdata(*details.account).total_count); - else - result = 0L; - break; - - case DEPTH: - if (details.account) - result = long(details.account->depth); - else - result = 0L; - break; - - case F_PRICE: { - long arg_index = 0; - ptr_op_t expr = find_leaf(context, 0, arg_index); - expr->compute(result, details, context); - result = result.value(); - break; - } - - case F_DATE: { - long arg_index = 0; - ptr_op_t expr = find_leaf(context, 0, arg_index); - expr->compute(result, details, context); - result = result.as_datetime(); - break; - } - - case F_DATECMP: { - long arg_index = 0; - ptr_op_t expr = find_leaf(context, 0, arg_index); - expr->compute(result, details, context); - result = result.as_datetime(); - if (! result) - break; - - arg_index = 0; - expr = find_leaf(context, 1, arg_index); - value_t moment; - expr->compute(moment, details, context); - if (moment.is_type(value_t::DATETIME)) { - result.cast(value_t::INTEGER); - moment.cast(value_t::INTEGER); - result -= moment; - } else { - add_error_context(expr_context(expr)); - throw compute_error("Invalid date passed to datecmp(value,date)"); - } - break; - } - - case F_YEAR: - case F_MONTH: - case F_DAY: { - long arg_index = 0; - ptr_op_t expr = find_leaf(context, 0, arg_index); - expr->compute(result, details, context); - - if (! result.is_type(value_t::DATETIME)) { - add_error_context(expr_context(expr)); - throw compute_error("Invalid date passed to year|month|day(date)"); - } - - const date_t& moment(result.as_date()); - switch (kind) { - case F_YEAR: - result = (long)moment.year(); - break; - case F_MONTH: - result = (long)moment.month(); - break; - case F_DAY: - result = (long)moment.day(); - break; - default: - break; - } - break; - } - - case F_ARITH_MEAN: { - long arg_index = 0; - ptr_op_t expr = find_leaf(context, 0, arg_index); - if (details.xact && xact_has_xdata(*details.xact)) { - expr->compute(result, details, context); - result /= amount_t(long(xact_xdata_(*details.xact).index + 1)); - } - else if (details.account && account_has_xdata(*details.account) && - account_xdata(*details.account).total_count) { - expr->compute(result, details, context); - result /= amount_t(long(account_xdata(*details.account).total_count)); - } - else { - result = 0L; - } - break; - } - - case F_PARENT: - if (details.account && details.account->parent) - left()->compute(result, details_t(*details.account->parent), context); - break; - - case F_ABS: { - long arg_index = 0; - ptr_op_t expr = find_leaf(context, 0, arg_index); - expr->compute(result, details, context); - result.abs(); - break; - } - - case F_ROUND: { - long arg_index = 0; - ptr_op_t expr = find_leaf(context, 0, arg_index); - expr->compute(result, details, context); - result.round(); - break; - } - - case F_COMMODITY: { - long arg_index = 0; - ptr_op_t expr = find_leaf(context, 0, arg_index); - expr->compute(result, details, context); - if (! result.is_type(value_t::AMOUNT)) { - add_error_context(expr_context(expr)); - throw compute_error("Argument to commodity() must be a commoditized amount"); - } - amount_t temp("1"); - temp.set_commodity(result.as_amount().commodity()); - result = temp; - break; - } - - case F_SET_COMMODITY: { - long arg_index = 0; - ptr_op_t expr = find_leaf(context, 0, arg_index); - value_t temp; - expr->compute(temp, details, context); - - arg_index = 0; - expr = find_leaf(context, 1, arg_index); - expr->compute(result, details, context); - if (! result.is_type(value_t::AMOUNT)) { - add_error_context(expr_context(expr)); - throw compute_error("Second argument to set_commodity() must be a commoditized amount"); - } - amount_t one("1"); - one.set_commodity(result.as_amount().commodity()); - result = one; - - result *= temp; - break; - } - - case F_QUANTITY: { - long arg_index = 0; - ptr_op_t expr = find_leaf(context, 0, arg_index); - expr->compute(result, details, context); - - const balance_t * bal = NULL; - switch (result.type()) { - case value_t::BALANCE_PAIR: - bal = &(result.as_balance_pair().quantity()); - // fall through... - - case value_t::BALANCE: - if (! bal) - bal = &result.as_balance(); - - if (bal->amounts.size() < 2) { - result.cast(value_t::AMOUNT); - } else { - value_t temp; - for (balance_t::amounts_map::value_type pair, bal->amounts) { - amount_t x = pair.second; - x.clear_commodity(); - temp += x; - } - result = temp; - assert(temp.is_type(value_t::AMOUNT)); - } - // fall through... - - case value_t::AMOUNT: - result.as_amount_lval().clear_commodity(); - break; - - default: - break; - } - break; - } - - case O_ARG: { - long arg_index = 0; - assert(left()->kind == INDEX); - ptr_op_t expr = find_leaf(context, left()->as_long(), arg_index); - if (expr) - expr->compute(result, details, context); - else - result = 0L; - break; - } - - case O_COMMA: - if (! left()) { - add_error_context(expr_context(*this)); - throw compute_error("Comma operator missing left operand"); - } - if (! right()) { - add_error_context(expr_context(*this)); - throw compute_error("Comma operator missing right operand"); - } - right()->compute(result, details, context); - break; - - case O_DEF: - result = 0L; - break; - - case O_REF: { - assert(left()); - if (right()) { - value_expr args(reduce_leaves(right(), details, context)); - left()->compute(result, details, args.get()); - } else { - left()->compute(result, details, context); - } - break; - } - - case F_VALUE: { - long arg_index = 0; - ptr_op_t expr = find_leaf(context, 0, arg_index); - expr->compute(result, details, context); - - arg_index = 0; - expr = find_leaf(context, 1, arg_index); - value_t moment; - expr->compute(moment, details, context); - if (! moment.is_type(value_t::DATETIME)) { - add_error_context(expr_context(expr)); - throw compute_error("Invalid date passed to P(value,date)"); - } - result = result.value(moment.as_datetime()); - break; - } - - case O_NOT: - left()->compute(result, details, context); - if (result.strip_annotations()) - result = false; - else - result = true; - break; - - case O_QUES: { - assert(left()); - assert(right()); - assert(right()->kind == O_COL); - left()->compute(result, details, context); - if (result.strip_annotations()) - right()->left()->compute(result, details, context); - else - right()->right()->compute(result, details, context); - break; - } - - case O_AND: - assert(left()); - assert(right()); - left()->compute(result, details, context); - result = result.strip_annotations(); - if (result) - right()->compute(result, details, context); - break; - - case O_OR: - assert(left()); - assert(right()); - left()->compute(result, details, context); - if (! result.strip_annotations()) - right()->compute(result, details, context); - break; - - case O_NEQ: - case O_EQ: - case O_LT: - case O_LTE: - case O_GT: - case O_GTE: { - assert(left()); - assert(right()); - value_t temp; - left()->compute(temp, details, context); - right()->compute(result, details, context); - switch (kind) { - case O_NEQ: result = temp != result; break; - case O_EQ: result = temp == result; break; - case O_LT: result = temp < result; break; - case O_LTE: result = temp <= result; break; - case O_GT: result = temp > result; break; - case O_GTE: result = temp >= result; break; - default: assert(false); break; - } - break; - } - - case O_NEG: - assert(left()); - left()->compute(result, details, context); - result.negate(); - break; - - case O_ADD: - case O_SUB: - case O_MUL: - case O_DIV: { - assert(left()); - assert(right()); - value_t temp; - right()->compute(temp, details, context); - left()->compute(result, details, context); - switch (kind) { - case O_ADD: result += temp; break; - case O_SUB: result -= temp; break; - case O_MUL: result *= temp; break; - case O_DIV: result /= temp; break; - default: assert(false); break; - } - break; - } - - case O_PERC: { - assert(left()); - result = "100.0%"; - value_t temp; - left()->compute(temp, details, context); - result *= temp; - break; - } - - case LAST: - default: - assert(false); - break; - } - } - catch (const std::exception& err) { - add_error_context(expr_context(*this)); - throw err; - } -} -#endif - -expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope) -{ - switch (kind) { - case IDENT: - if (ptr_op_t def = scope.lookup(as_ident())) { -#if 1 - return def; -#else - // jww (2008-08-02): Aren't definitions compiled when they go in? - // Would recompiling here really add any benefit? - return def->compile(scope); -#endif - } - return this; - - default: - break; - } - - if (kind < TERMINALS) - return this; - - ptr_op_t lhs(left()->compile(scope)); - ptr_op_t rhs(kind > UNARY_OPERATORS ? right()->compile(scope) : ptr_op_t()); - - if (lhs == left() && (! rhs || rhs == right())) - return this; - - ptr_op_t intermediate(copy(lhs, rhs)); - - if (lhs->is_value() && (! rhs || rhs->is_value())) - return wrap_value(intermediate->calc(scope)); - - return intermediate; -} - -value_t expr_t::op_t::calc(scope_t& scope) -{ - switch (kind) { - case VALUE: - return as_value(); - - case IDENT: -#if 0 - if (ptr_op_t reference = compile(scope)) { - if (reference != this) - return reference->calc(scope); - } -#endif - throw_(calc_error, "Unknown identifier '" << as_ident() << "'"); - - case FUNCTION: { - // 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); - return as_function()(call_args); - } - - case O_CALL: { - call_scope_t call_args(scope); - - if (right()) - call_args.set_args(right()->calc(scope)); - - ptr_op_t func = left(); - string name; - -#if 0 - // The expression must be compiled beforehand in order to resolve this - // into a function. - if (func->kind == IDENT) { - name = func->as_ident(); - ptr_op_t def = func->compile(scope); - if (def == func) - throw_(calc_error, - "Calling unknown function '" << name << "'"); - func = def; - } -#endif - - if (func->kind != FUNCTION) - throw_(calc_error, "Calling non-function"); - - return func->as_function()(call_args); - } - - case O_MATCH: - assert(right()->is_mask()); - return right()->as_mask().match(left()->calc(scope).to_string()); - - case INDEX: { - const call_scope_t& args(downcast<const call_scope_t>(scope)); - - if (as_index() < args.size()) - return args[as_index()]; - else - throw_(calc_error, "Reference to non-existing argument " << as_index()); - break; - } - - case O_NEQ: - return left()->calc(scope) != right()->calc(scope); - case O_EQ: - return left()->calc(scope) == right()->calc(scope); - case O_LT: - return left()->calc(scope) < right()->calc(scope); - case O_LTE: - return left()->calc(scope) <= right()->calc(scope); - case O_GT: - return left()->calc(scope) > right()->calc(scope); - case O_GTE: - return left()->calc(scope) >= right()->calc(scope); - - case O_ADD: - return left()->calc(scope) + right()->calc(scope); - case O_SUB: - return left()->calc(scope) - right()->calc(scope); - case O_MUL: - return left()->calc(scope) * right()->calc(scope); - case O_DIV: - return left()->calc(scope) / right()->calc(scope); - - case O_NEG: - assert(! right()); - return left()->calc(scope).negate(); - - case O_NOT: - assert(! right()); - return ! left()->calc(scope); - - case O_AND: - return ! left()->calc(scope) ? value_t(false) : right()->calc(scope); - - case O_OR: - if (value_t temp = left()->calc(scope)) - return temp; - else - return right()->calc(scope); - - case O_COMMA: { - value_t result(left()->calc(scope)); - - ptr_op_t next = right(); - while (next) { - ptr_op_t value_op; - if (next->kind == O_COMMA /* || next->kind == O_UNION */) { - value_op = next->left(); - next = next->right(); - } else { - value_op = next; - next = NULL; - } - - result.push_back(value_op->calc(scope)); - } - return result; - } - - case LAST: - default: - assert(false); - break; - } - - return NULL_VALUE; -} - -bool expr_t::op_t::print(std::ostream& out, print_context_t& context) const -{ - bool found = false; - - if (context.start_pos && this == context.op_to_find) { - *context.start_pos = static_cast<unsigned long>(out.tellp()) - 1; - found = true; - } - - string symbol; - - switch (kind) { - case VALUE: { - as_value().print(out, context.relaxed); - break; - } - - case IDENT: - out << as_ident(); - break; - - case FUNCTION: - out << "<FUNCTION>"; - break; - - case INDEX: - out << '@' << as_index(); - break; - - case O_NOT: - out << "!"; - if (left() && left()->print(out, context)) - found = true; - break; - case O_NEG: - out << "-"; - if (left() && left()->print(out, context)) - found = true; - break; - - case O_ADD: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " + "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_SUB: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " - "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_MUL: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " * "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_DIV: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " / "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - - case O_NEQ: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " != "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_EQ: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " == "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_LT: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " < "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_LTE: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " <= "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_GT: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " > "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_GTE: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " >= "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - - case O_AND: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " & "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - case O_OR: - out << "("; - if (left() && left()->print(out, context)) - found = true; - out << " | "; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - - case O_COMMA: - if (left() && left()->print(out, context)) - found = true; - out << ", "; - if (right() && right()->print(out, context)) - found = true; - break; - - case O_CALL: - if (left() && left()->print(out, context)) - found = true; - out << "("; - if (right() && right()->print(out, context)) - found = true; - out << ")"; - break; - - case O_MATCH: - out << '/'; - if (left() && left()->print(out, context)) - found = true; - out << "/ =~ "; - if (right() && right()->print(out, context)) - found = true; - break; - - case LAST: - default: - assert(false); - break; - } - - if (! symbol.empty()) { - if (amount_t::current_pool->find(symbol)) - out << '@'; - out << symbol; - } - - if (context.end_pos && this == context.op_to_find) - *context.end_pos = static_cast<unsigned long>(out.tellp()) - 1; - - return found; -} - -void expr_t::op_t::dump(std::ostream& out, const int depth) const -{ - out.setf(std::ios::left); - out.width(10); - out << this; - - for (int i = 0; i < depth; i++) - out << " "; - - switch (kind) { - case VALUE: - out << "VALUE - " << as_value(); - break; - - case IDENT: - out << "IDENT - " << as_ident(); - break; - - case INDEX: - out << "INDEX - " << as_index(); - break; - - case FUNCTION: - out << "FUNCTION"; - break; - - case O_CALL: out << "O_CALL"; break; - case O_MATCH: out << "O_MATCH"; break; - - case O_NOT: out << "O_NOT"; break; - case O_NEG: out << "O_NEG"; break; - - case O_ADD: out << "O_ADD"; break; - case O_SUB: out << "O_SUB"; break; - case O_MUL: out << "O_MUL"; break; - case O_DIV: out << "O_DIV"; break; - - case O_NEQ: out << "O_NEQ"; break; - case O_EQ: out << "O_EQ"; break; - case O_LT: out << "O_LT"; break; - case O_LTE: out << "O_LTE"; break; - case O_GT: out << "O_GT"; break; - case O_GTE: out << "O_GTE"; break; - - case O_AND: out << "O_AND"; break; - case O_OR: out << "O_OR"; break; - - case O_COMMA: out << "O_COMMA"; break; - - case LAST: - default: - assert(false); - break; - } - - out << " (" << refc << ')' << std::endl; - - if (kind > TERMINALS) { - if (left()) { - left()->dump(out, depth + 1); - if (right()) - right()->dump(out, depth + 1); - } else { - assert(! right()); - } - } -} - -void expr_t::op_t::read(const char *& data) -{ -#if 0 - if (! read_bool(data)) - return expr_t::ptr_op_t(); - - expr_t::op_t::kind_t kind; - read_number(data, kind); - - expr_t::ptr_op_t expr = new expr_t::op_t(kind); - - if (kind > expr_t::op_t::TERMINALS) - expr->set_left(read_value_expr(data)); - - switch (expr->kind) { - case expr_t::op_t::INDEX: { - long temp; - read_long(data, temp); - expr->set_index(temp); - break; - } - case expr_t::op_t::VALUE: { - value_t temp; - read_value(data, temp); - expr->set_value(temp); - break; - } - - case expr_t::op_t::MASK: - if (read_bool(data)) - read_mask(data, expr->as_mask_lval()); - break; - - default: - if (kind > expr_t::op_t::TERMINALS) - expr->set_right(read_value_expr(data)); - break; - } - - return expr; -#endif -} - -void expr_t::op_t::write(std::ostream& out) const -{ -#if 0 - if (! expr) { - write_bool(out, false); - return; - } - - write_bool(out, true); - write_number(out, expr->kind); - - if (expr->kind > expr_t::op_t::TERMINALS) - write_value_expr(out, expr->left()); - - switch (expr->kind) { - case expr_t::op_t::INDEX: - write_long(out, expr->as_index()); - break; - case expr_t::op_t::IDENT: - write_long(out, expr->as_ident()); - break; - case expr_t::op_t::VALUE: - write_value(out, expr->as_value()); - break; - - case expr_t::op_t::MASK: - if (expr->as_mask()) { - write_bool(out, true); - write_mask(out, expr->as_mask()); - } else { - write_bool(out, false); - } - break; - - default: - if (expr->kind > expr_t::op_t::TERMINALS) - write_value_expr(out, expr->right()); - break; - } -#endif -} - -#if 0 -class op_predicate : public noncopyable -{ - ptr_op_t op; - - op_predicate(); - -public: - explicit op_predicate(ptr_op_t _op) : op(_op) { - TRACE_CTOR(op_predicate, "ptr_op_t"); - } - ~op_predicate() throw() { - TRACE_DTOR(op_predicate); - } - bool operator()(scope_t& scope) { - return op->calc(scope).to_boolean(); - } -}; - -#endif - -} // namespace ledger |