diff options
author | John Wiegley <johnw@newartisans.com> | 2010-06-13 05:02:14 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2010-06-13 05:02:14 -0400 |
commit | ea1642b3f969463a49e5a671478c92e4ef129665 (patch) | |
tree | 9eba47b8708123b4e3f539dd9d747f1f85d9d2fe /src/scope.h | |
parent | ad3b30a9641b8e09c38ea76e7011b614152d8faf (diff) | |
download | fork-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.h | 333 |
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 |