summaryrefslogtreecommitdiff
path: root/src/scope.h
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2010-06-13 05:02:14 -0400
committerJohn Wiegley <johnw@newartisans.com>2010-06-13 05:02:14 -0400
commitea1642b3f969463a49e5a671478c92e4ef129665 (patch)
tree9eba47b8708123b4e3f539dd9d747f1f85d9d2fe /src/scope.h
parentad3b30a9641b8e09c38ea76e7011b614152d8faf (diff)
downloadfork-ledger-ea1642b3f969463a49e5a671478c92e4ef129665.tar.gz
fork-ledger-ea1642b3f969463a49e5a671478c92e4ef129665.tar.bz2
fork-ledger-ea1642b3f969463a49e5a671478c92e4ef129665.zip
Completely reworked argument passing in expressions
Diffstat (limited to 'src/scope.h')
-rw-r--r--src/scope.h333
1 files changed, 267 insertions, 66 deletions
diff --git a/src/scope.h b/src/scope.h
index 1b10d7a6..f9bea6b6 100644
--- a/src/scope.h
+++ b/src/scope.h
@@ -117,6 +117,9 @@ public:
virtual value_t::type_t type_context() const {
return value_t::VOID;
}
+ virtual bool type_required() const {
+ return false;
+ }
#if defined(HAVE_BOOST_SERIALIZATION)
private:
@@ -172,6 +175,76 @@ private:
#endif // HAVE_BOOST_SERIALIZATION
};
+class bind_scope_t : public child_scope_t
+{
+ bind_scope_t();
+
+public:
+ scope_t& grandchild;
+
+ explicit bind_scope_t(scope_t& _parent,
+ scope_t& _grandchild)
+ : child_scope_t(_parent), grandchild(_grandchild) {
+ TRACE_CTOR(bind_scope_t, "scope_t&, scope_t&");
+ }
+ virtual ~bind_scope_t() {
+ TRACE_DTOR(bind_scope_t);
+ }
+
+ virtual void define(const symbol_t::kind_t kind, const string& name,
+ expr_t::ptr_op_t def) {
+ parent->define(kind, name, def);
+ grandchild.define(kind, name, def);
+ }
+
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name) {
+ if (expr_t::ptr_op_t def = grandchild.lookup(kind, name))
+ return def;
+ return child_scope_t::lookup(kind, name);
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & boost::serialization::base_object<child_scope_t>(*this);
+ ar & grandchild;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+template <typename T>
+T * search_scope(scope_t * ptr)
+{
+ if (T * sought = dynamic_cast<T *>(ptr))
+ return sought;
+
+ if (bind_scope_t * scope = dynamic_cast<bind_scope_t *>(ptr)) {
+ if (T * sought = search_scope<T>(&scope->grandchild))
+ return sought;
+ return search_scope<T>(scope->parent);
+ }
+ else if (child_scope_t * scope = dynamic_cast<child_scope_t *>(ptr)) {
+ return search_scope<T>(scope->parent);
+ }
+ return NULL;
+}
+
+template <typename T>
+inline T& find_scope(child_scope_t& scope, bool skip_this = true)
+{
+ if (T * sought = search_scope<T>(skip_this ? scope.parent : &scope))
+ return *sought;
+
+ throw_(std::runtime_error, _("Could not find scope"));
+ return reinterpret_cast<T&>(scope); // never executed
+}
+
class symbol_scope_t : public child_scope_t
{
typedef std::map<symbol_t, expr_t::ptr_op_t> symbol_map;
@@ -212,12 +285,15 @@ private:
class context_scope_t : public child_scope_t
{
value_t::type_t value_type_context;
+ bool required;
public:
explicit context_scope_t(scope_t& _parent,
- value_t::type_t _type_context = value_t::VOID)
- : child_scope_t(_parent), value_type_context(_type_context) {
- TRACE_CTOR(context_scope_t, "scope_t&, value_t::type_t");
+ value_t::type_t _type_context = value_t::VOID,
+ const bool _required = true)
+ : child_scope_t(_parent), value_type_context(_type_context),
+ required(_required) {
+ TRACE_CTOR(context_scope_t, "scope_t&, value_t::type_t, bool");
}
virtual ~context_scope_t() {
TRACE_DTOR(context_scope_t);
@@ -226,17 +302,26 @@ public:
virtual value_t::type_t type_context() const {
return value_type_context;
}
+ virtual bool type_required() const {
+ return required;
+ }
};
class call_scope_t : public context_scope_t
{
- value_t args;
+ value_t args;
+ mutable void * ptr;
+
+ value_t& resolve(const std::size_t index,
+ value_t::type_t context = value_t::VOID,
+ const bool required = false);
public:
explicit call_scope_t(scope_t& _parent,
- value_t::type_t _type_context = value_t::VOID)
- : context_scope_t(_parent, _type_context) {
- TRACE_CTOR(call_scope_t, "scope_t&, value_t::type_t");
+ value_t::type_t _type_context = value_t::VOID,
+ const bool _required = true)
+ : context_scope_t(_parent, _type_context, _required), ptr(NULL) {
+ TRACE_CTOR(call_scope_t, "scope_t&, value_t::type_t, bool");
}
virtual ~call_scope_t() {
TRACE_DTOR(call_scope_t);
@@ -246,15 +331,36 @@ public:
args = _args;
}
value_t& value() {
+ // Make sure that all of the arguments have been resolved.
+ for (std::size_t index = 0; index < args.size(); index++)
+ resolve(index);
return args;
}
value_t& operator[](const std::size_t index) {
- return args[index];
+ return resolve(index);
}
+#if 0
const value_t& operator[](const std::size_t index) const {
return args[index];
}
+#endif
+
+ bool has(std::size_t index) {
+ return index < args.size() && ! (*this)[index].is_null();
+ }
+ template <typename T>
+ bool has(std::size_t index);
+ template <typename T>
+ T get(std::size_t index, bool convert = true);
+
+ template <typename T>
+ T& context() {
+ if (ptr == NULL)
+ ptr = &find_scope<T>(*this);
+ assert(ptr != NULL);
+ return *static_cast<T *>(ptr);
+ }
void push_front(const value_t& val) {
args.push_front(val);
@@ -309,74 +415,169 @@ private:
#endif // HAVE_BOOST_SERIALIZATION
};
-class bind_scope_t : public child_scope_t
-{
- bind_scope_t();
-
-public:
- scope_t& grandchild;
-
- explicit bind_scope_t(scope_t& _parent,
- scope_t& _grandchild)
- : child_scope_t(_parent), grandchild(_grandchild) {
- TRACE_CTOR(bind_scope_t, "scope_t&, scope_t&");
+template <>
+inline bool call_scope_t::has<bool>(std::size_t index) {
+ if (index < args.size()) {
+ resolve(index, value_t::BOOLEAN, false);
+ return ! args[index].is_null();
}
- virtual ~bind_scope_t() {
- TRACE_DTOR(bind_scope_t);
+ return false;
+}
+template <>
+inline bool call_scope_t::has<int>(std::size_t index) {
+ if (index < args.size()) {
+ resolve(index, value_t::INTEGER, false);
+ return ! args[index].is_null();
}
-
- virtual void define(const symbol_t::kind_t kind, const string& name,
- expr_t::ptr_op_t def) {
- parent->define(kind, name, def);
- grandchild.define(kind, name, def);
+ return false;
+}
+template <>
+inline bool call_scope_t::has<long>(std::size_t index) {
+ if (index < args.size()) {
+ resolve(index, value_t::INTEGER, false);
+ return ! args[index].is_null();
}
-
- virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
- const string& name) {
- if (expr_t::ptr_op_t def = grandchild.lookup(kind, name))
- return def;
- return child_scope_t::lookup(kind, name);
+ return false;
+}
+template <>
+inline bool call_scope_t::has<amount_t>(std::size_t index) {
+ if (index < args.size()) {
+ resolve(index, value_t::AMOUNT, false);
+ return ! args[index].is_null();
}
-
-#if defined(HAVE_BOOST_SERIALIZATION)
-private:
- /** Serialization. */
-
- friend class boost::serialization::access;
-
- template<class Archive>
- void serialize(Archive& ar, const unsigned int /* version */) {
- ar & boost::serialization::base_object<child_scope_t>(*this);
- ar & grandchild;
+ return false;
+}
+template <>
+inline bool call_scope_t::has<balance_t>(std::size_t index) {
+ if (index < args.size()) {
+ resolve(index, value_t::BALANCE, false);
+ return ! args[index].is_null();
}
-#endif // HAVE_BOOST_SERIALIZATION
-};
-
-template <typename T>
-T * search_scope(scope_t * ptr)
-{
- if (T * sought = dynamic_cast<T *>(ptr))
- return sought;
-
- if (bind_scope_t * scope = dynamic_cast<bind_scope_t *>(ptr)) {
- if (T * sought = search_scope<T>(&scope->grandchild))
- return sought;
- return search_scope<T>(scope->parent);
+ return false;
+}
+template <>
+inline bool call_scope_t::has<string>(std::size_t index) {
+ if (index < args.size()) {
+ resolve(index, value_t::STRING, false);
+ return ! args[index].is_null();
}
- else if (child_scope_t * scope = dynamic_cast<child_scope_t *>(ptr)) {
- return search_scope<T>(scope->parent);
+ return false;
+}
+template <>
+inline bool call_scope_t::has<date_t>(std::size_t index) {
+ if (index < args.size()) {
+ resolve(index, value_t::DATE, false);
+ return ! args[index].is_null();
}
- return NULL;
+ return false;
+}
+template <>
+inline bool call_scope_t::has<datetime_t>(std::size_t index) {
+ if (index < args.size()) {
+ resolve(index, value_t::DATETIME, false);
+ return ! args[index].is_null();
+ }
+ return false;
+}
+template <>
+inline bool call_scope_t::has<scope_t *>(std::size_t index) {
+ if (index < args.size()) {
+ resolve(index, value_t::SCOPE, false);
+ return ! args[index].is_null();
+ }
+ return false;
+}
+template <>
+inline bool call_scope_t::has<expr_t::ptr_op_t>(std::size_t index) {
+ if (index < args.size()) {
+ resolve(index, value_t::ANY, false);
+ return ! args[index].is_null();
+ }
+ return false;
}
-template <typename T>
-inline T& find_scope(child_scope_t& scope, bool skip_this = true)
-{
- if (T * sought = search_scope<T>(skip_this ? scope.parent : &scope))
- return *sought;
+template <>
+inline bool call_scope_t::get<bool>(std::size_t index, bool convert) {
+ if (convert)
+ return resolve(index, value_t::BOOLEAN, false).to_boolean();
+ else
+ return resolve(index, value_t::BOOLEAN).as_boolean();
+}
+template <>
+inline int call_scope_t::get<int>(std::size_t index, bool) {
+ return resolve(index, value_t::INTEGER, false).to_int();
+}
+template <>
+inline long call_scope_t::get<long>(std::size_t index, bool convert) {
+ if (convert)
+ return resolve(index, value_t::INTEGER, false).to_long();
+ else
+ return resolve(index, value_t::INTEGER).as_long();
+}
+template <>
+inline amount_t call_scope_t::get<amount_t>(std::size_t index, bool convert) {
+ if (convert)
+ return resolve(index, value_t::AMOUNT, false).to_amount();
+ else
+ return resolve(index, value_t::AMOUNT).as_amount();
+}
+template <>
+inline balance_t call_scope_t::get<balance_t>(std::size_t index, bool convert) {
+ if (convert)
+ return resolve(index, value_t::BALANCE, false).to_balance();
+ else
+ return resolve(index, value_t::BALANCE).as_balance();
+}
+template <>
+inline string call_scope_t::get<string>(std::size_t index, bool convert) {
+ if (convert)
+ return resolve(index, value_t::STRING, false).to_string();
+ else
+ return resolve(index, value_t::STRING).as_string();
+}
+template <>
+inline mask_t call_scope_t::get<mask_t>(std::size_t index, bool convert) {
+ if (convert)
+ return resolve(index, value_t::MASK, false).to_mask();
+ else
+ return resolve(index, value_t::MASK).as_mask();
+}
+template <>
+inline date_t call_scope_t::get<date_t>(std::size_t index, bool convert) {
+ if (convert)
+ return resolve(index, value_t::DATE, false).to_date();
+ else
+ return resolve(index, value_t::DATE).as_date();
+}
+template <>
+inline datetime_t call_scope_t::get<datetime_t>(std::size_t index, bool convert) {
+ if (convert)
+ return resolve(index, value_t::DATETIME, false).to_datetime();
+ else
+ return resolve(index, value_t::DATETIME).as_datetime();
+}
- throw_(std::runtime_error, _("Could not find scope"));
- return reinterpret_cast<T&>(scope); // never executed
+#if 0
+template <>
+inline value_t::sequence_t&
+call_scope_t::get<value_t::sequence_t&>(std::size_t index, bool) {
+ return resolve(index, value_t::SEQUENCE).as_sequence_lval();
+}
+template <>
+inline const value_t::sequence_t&
+call_scope_t::get<const value_t::sequence_t&>(std::size_t index, bool) {
+ return resolve(index, value_t::SEQUENCE).as_sequence();
+}
+#endif
+
+template <>
+inline scope_t * call_scope_t::get<scope_t *>(std::size_t index, bool) {
+ return resolve(index, value_t::SCOPE).as_scope();
+}
+template <>
+inline expr_t::ptr_op_t
+call_scope_t::get<expr_t::ptr_op_t>(std::size_t index, bool) {
+ return resolve(index, value_t::ANY).as_any<expr_t::ptr_op_t>();
}
class value_scope_t : public scope_t