summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/annotate.cc62
-rw-r--r--src/annotate.h46
-rw-r--r--src/expr.h3
-rw-r--r--src/predicate.cc40
-rw-r--r--test/unit/t_expr.cc2
-rw-r--r--tools/Makefile.am41
6 files changed, 98 insertions, 96 deletions
diff --git a/src/annotate.cc b/src/annotate.cc
index 1e243beb..b1db6bd5 100644
--- a/src/annotate.cc
+++ b/src/annotate.cc
@@ -33,6 +33,7 @@
#include "amount.h"
#include "commodity.h"
+#include "expr.h"
#include "annotate.h"
#include "pool.h"
@@ -47,6 +48,9 @@ bool annotation_t::operator<(const annotation_t& rhs) const
if (! tag && rhs.tag) return true;
if (tag && ! rhs.tag) return false;
+ if (! value_expr && rhs.value_expr) return true;
+ if (value_expr && ! rhs.value_expr) return false;
+
if (price) {
if (price->commodity().symbol() < rhs.price->commodity().symbol())
return true;
@@ -63,6 +67,10 @@ bool annotation_t::operator<(const annotation_t& rhs) const
if (*tag < *rhs.tag) return true;
if (*tag > *rhs.tag) return false;
}
+ if (value_expr) {
+ if (value_expr->text() < rhs.value_expr->text()) return true;
+ if (value_expr->text() > rhs.value_expr->text()) return false;
+ }
return false;
}
@@ -112,17 +120,41 @@ void annotation_t::parse(std::istream& in)
date = parse_date(buf);
}
else if (c == '(') {
- if (tag)
- throw_(amount_error, _("Commodity specifies more than one tag"));
-
in.get(c);
- READ_INTO(in, buf, 255, c, c != ')');
- if (c == ')')
- in.get(c);
- else
- throw_(amount_error, _("Commodity tag lacks closing parenthesis"));
+ c = static_cast<char>(in.peek());
+ if (c == '(') {
+ if (value_expr)
+ throw_(amount_error,
+ _("Commodity specifies more than one valuation expresion"));
- tag = buf;
+ in.get(c);
+ READ_INTO(in, buf, 255, c, c != ')');
+ if (c == ')') {
+ in.get(c);
+ c = static_cast<char>(in.peek());
+ if (c == ')')
+ in.get(c);
+ else
+ throw_(amount_error,
+ _("Commodity valuation expression lacks closing parentheses"));
+ } else {
+ throw_(amount_error,
+ _("Commodity valuation expression lacks closing parentheses"));
+ }
+
+ value_expr = expr_t(buf);
+ } else {
+ if (tag)
+ throw_(amount_error, _("Commodity specifies more than one tag"));
+
+ READ_INTO(in, buf, 255, c, c != ')');
+ if (c == ')')
+ in.get(c);
+ else
+ throw_(amount_error, _("Commodity tag lacks closing parenthesis"));
+
+ tag = buf;
+ }
}
else {
in.clear();
@@ -156,6 +188,10 @@ void annotation_t::print(std::ostream& out, bool keep_base,
if (tag &&
(! no_computed_annotations || ! has_flags(ANNOTATION_TAG_CALCULATED)))
out << " (" << *tag << ')';
+
+ if (value_expr && (! no_computed_annotations ||
+ ! has_flags(ANNOTATION_VALUE_EXPR_CALCULATED)))
+ out << " ((" << *value_expr << "))";
}
bool keep_details_t::keep_all(const commodity_t& comm) const
@@ -220,12 +256,14 @@ annotated_commodity_t::strip_annotations(const keep_details_t& what_to_keep)
if ((keep_price && details.price) ||
(keep_date && details.date) ||
- (keep_tag && details.tag))
+ (keep_tag && details.tag) ||
+ details.value_expr)
{
new_comm = pool().find_or_create
(referent(), annotation_t(keep_price ? details.price : none,
keep_date ? details.date : none,
- keep_tag ? details.tag : none));
+ keep_tag ? details.tag : none,
+ details.value_expr));
// Transfer over any relevant annotation flags, as they still apply.
if (new_comm->annotated) {
@@ -238,6 +276,8 @@ annotated_commodity_t::strip_annotations(const keep_details_t& what_to_keep)
new_details.add_flags(details.flags() & ANNOTATION_DATE_CALCULATED);
if (keep_tag)
new_details.add_flags(details.flags() & ANNOTATION_TAG_CALCULATED);
+ if (details.value_expr)
+ new_details.add_flags(details.flags() & ANNOTATION_VALUE_EXPR_CALCULATED);
}
return *new_comm;
diff --git a/src/annotate.h b/src/annotate.h
index 29294e88..eb87a1b2 100644
--- a/src/annotate.h
+++ b/src/annotate.h
@@ -46,29 +46,38 @@
#ifndef _ANNOTATE_H
#define _ANNOTATE_H
+#include "expr.h"
+
namespace ledger {
struct annotation_t : public supports_flags<>,
public equality_comparable<annotation_t>
{
-#define ANNOTATION_PRICE_CALCULATED 0x01
-#define ANNOTATION_PRICE_FIXATED 0x02
-#define ANNOTATION_DATE_CALCULATED 0x04
-#define ANNOTATION_TAG_CALCULATED 0x08
+#define ANNOTATION_PRICE_CALCULATED 0x01
+#define ANNOTATION_PRICE_FIXATED 0x02
+#define ANNOTATION_DATE_CALCULATED 0x04
+#define ANNOTATION_TAG_CALCULATED 0x08
+#define ANNOTATION_VALUE_EXPR_CALCULATED 0x10
optional<amount_t> price;
optional<date_t> date;
optional<string> tag;
-
- explicit annotation_t(const optional<amount_t>& _price = none,
- const optional<date_t>& _date = none,
- const optional<string>& _tag = none)
- : supports_flags<>(), price(_price), date(_date), tag(_tag) {
- TRACE_CTOR(annotation_t, "const optional<amount_t>& + date_t + string");
+ optional<expr_t> value_expr;
+
+ explicit annotation_t(const optional<amount_t>& _price = none,
+ const optional<date_t>& _date = none,
+ const optional<string>& _tag = none,
+ const optional<expr_t>& _value_expr = none)
+ : supports_flags<>(), price(_price), date(_date), tag(_tag),
+ value_expr(_value_expr) {
+ TRACE_CTOR(annotation_t,
+ "const optional<amount_t>& + date_t + string + expr_t");
}
annotation_t(const annotation_t& other)
: supports_flags<>(other.flags()),
- price(other.price), date(other.date), tag(other.tag) {
+ price(other.price), date(other.date), tag(other.tag),
+ value_expr(other.value_expr)
+ {
TRACE_CTOR(annotation_t, "copy");
}
~annotation_t() {
@@ -76,14 +85,15 @@ struct annotation_t : public supports_flags<>,
}
operator bool() const {
- return price || date || tag;
+ return price || date || tag || value_expr;
}
bool operator<(const annotation_t& rhs) const;
bool operator==(const annotation_t& rhs) const {
- return (price == rhs.price &&
- date == rhs.date &&
- tag == rhs.tag);
+ return (price == rhs.price &&
+ date == rhs.date &&
+ tag == rhs.tag &&
+ value_expr == rhs.value_expr);
}
void parse(std::istream& in);
@@ -133,6 +143,12 @@ inline void to_xml(std::ostream& out, const annotation_t& details)
push_xml y(out, "tag");
out << y.guard(*details.tag);
}
+
+ if (details.value_expr)
+ {
+ push_xml y(out, "value-expr");
+ out << y.guard(details.value_expr->text());
+ }
}
struct keep_details_t
diff --git a/src/expr.h b/src/expr.h
index e082efa5..ab3487fe 100644
--- a/src/expr.h
+++ b/src/expr.h
@@ -58,6 +58,9 @@ public:
typedef intrusive_ptr<op_t> ptr_op_t;
typedef intrusive_ptr<const op_t> const_ptr_op_t;
+ friend void intrusive_ptr_add_ref(const op_t * op);
+ friend void intrusive_ptr_release(const op_t * op);
+
enum check_expr_kind_t {
EXPR_GENERAL,
EXPR_ASSERTION,
diff --git a/src/predicate.cc b/src/predicate.cc
deleted file mode 100644
index 58d6c752..00000000
--- a/src/predicate.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2003-2012, 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 <system.hh>
-
-#include "predicate.h"
-#include "query.h"
-#include "op.h"
-
-namespace ledger {
-
-} // namespace ledger
diff --git a/test/unit/t_expr.cc b/test/unit/t_expr.cc
index f882f3a1..c10ee029 100644
--- a/test/unit/t_expr.cc
+++ b/test/unit/t_expr.cc
@@ -1,5 +1,5 @@
#define BOOST_TEST_DYN_LINK
-#define BOOST_TEST_MODULE expr
+//#define BOOST_TEST_MODULE expr
#include <boost/test/unit_test.hpp>
#include <system.hh>
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 671db294..a598966a 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -8,7 +8,6 @@ DISTCLEANFILES = .timestamp
lib_LTLIBRARIES = \
libledger_report.la \
libledger_data.la \
- libledger_expr.la \
libledger_math.la \
libledger_util.la
@@ -28,6 +27,14 @@ libledger_util_la_CPPFLAGS = $(lib_cppflags)
libledger_util_la_LDFLAGS = -release $(LIBVERSION)
libledger_math_la_SOURCES = \
+ src/format.cc \
+ src/query.cc \
+ src/scope.cc \
+ src/expr.cc \
+ src/op.cc \
+ src/parser.cc \
+ src/token.cc \
+ src/value.cc \
src/balance.cc \
src/quotes.cc \
src/history.cc \
@@ -39,22 +46,8 @@ libledger_math_la_SOURCES = \
libledger_math_la_CPPFLAGS = $(lib_cppflags)
libledger_math_la_LDFLAGS = -release $(LIBVERSION)
-libledger_expr_la_SOURCES = \
- src/option.cc \
- src/format.cc \
- src/query.cc \
- src/predicate.cc \
- src/scope.cc \
- src/expr.cc \
- src/op.cc \
- src/parser.cc \
- src/token.cc \
- src/value.cc
-
-libledger_expr_la_CPPFLAGS = $(lib_cppflags)
-libledger_expr_la_LDFLAGS = -release $(LIBVERSION)
-
libledger_data_la_SOURCES = \
+ src/option.cc \
src/lookup.cc \
src/compare.cc \
src/iterators.cc \
@@ -204,7 +197,6 @@ DISTCLEANFILES += ledger.elc timeclock.elc
all_sources = $(libledger_util_la_SOURCES) \
$(libledger_math_la_SOURCES) \
- $(libledger_expr_la_SOURCES) \
$(libledger_data_la_SOURCES) \
$(libledger_report_la_SOURCES) \
$(libledger_python_la_SOURCES) \
@@ -259,8 +251,7 @@ TESTS = RegressTests BaselineTests ManualTests ConfirmTests \
if HAVE_BOOST_TEST
TESTS += \
UtilTests \
- MathTests \
- ExprTests
+ MathTests
# DataTests \
# ReportTests
endif
@@ -285,6 +276,7 @@ UtilTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
UtilTests_LDADD = libledger_util.la $(TESTLIBS)
MathTests_SOURCES = \
+ test/unit/t_expr.cc \
test/unit/t_commodity.cc \
test/unit/t_amount.cc \
test/unit/t_balance.cc
@@ -292,16 +284,10 @@ MathTests_SOURCES = \
MathTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
MathTests_LDADD = libledger_math.la $(UtilTests_LDADD)
-ExprTests_SOURCES = \
- test/unit/t_expr.cc
-
-ExprTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
-ExprTests_LDADD = libledger_expr.la $(MathTests_LDADD)
-
DataTests_SOURCES =
DataTests_CPPFLAGS = -I$(srcdir)/test $(lib_cppflags)
-DataTests_LDADD = libledger_data.la $(ExprTests_LDADD)
+DataTests_LDADD = libledger_data.la $(MathTests_LDADD)
ReportTests_SOURCES =
@@ -311,7 +297,6 @@ ReportTests_LDADD = libledger_report.la $(DataTests_LDADD)
all_tests_sources = \
$(UtilTests_SOURCES) \
$(MathTests_SOURCES) \
- $(ExprTests_SOURCES) \
$(DataTests_SOURCES) \
$(ReportTests_SOURCES)
@@ -421,8 +406,6 @@ unittests: check
2>&1 | grep -v '^GuardMalloc:'
@sh $(FULLCHECK) $(top_builddir)/MathTests$(EXEEXT) --verify \
2>&1 | grep -v '^GuardMalloc:'
- @sh $(FULLCHECK) $(top_builddir)/ExprTests$(EXEEXT) --verify \
- 2>&1 | grep -v '^GuardMalloc:'
# @sh $(FULLCHECK) $(top_builddir)/DataTests$(EXEEXT) --verify \
# 2>&1 | grep -v '^GuardMalloc:'
# @sh $(FULLCHECK) $(top_builddir)/ReportTests$(EXEEXT) --verify \