summaryrefslogtreecommitdiff
path: root/op.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2008-08-05 13:17:04 -0400
committerJohn Wiegley <johnw@newartisans.com>2008-08-05 18:05:49 -0400
commitf6f4a46cf5b14f9a2170cd6475958efbf320caec (patch)
tree05bc1defcdebc201de3dd10477483d906a842821 /op.cc
parentb7970b29855563e4c67f85af8b31233eda80c22a (diff)
downloadfork-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.cc1130
1 files changed, 0 insertions, 1130 deletions
diff --git a/op.cc b/op.cc
deleted file mode 100644
index b412c47f..00000000
--- a/op.cc
+++ /dev/null
@@ -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