diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2015-08-24 09:51:15 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2015-08-24 14:52:43 +0200 |
commit | 68f96f9213e849d0d7c4cedf3edeaec99743ee27 (patch) | |
tree | 271913d74c906971cac555319f5e14d0c66e0c16 /build/variable.ixx | |
parent | 0d5234f4aefd3cc5b5948cc1b9dd009e50046f5e (diff) |
New variable architecture
Diffstat (limited to 'build/variable.ixx')
-rw-r--r-- | build/variable.ixx | 403 |
1 files changed, 345 insertions, 58 deletions
diff --git a/build/variable.ixx b/build/variable.ixx index b97815e..16ea7c0 100644 --- a/build/variable.ixx +++ b/build/variable.ixx @@ -4,108 +4,395 @@ namespace build { - // value_proxy + // value // - inline bool value_proxy:: - empty () const {return as<const list_value&> ().empty ();} + template <typename T> + inline void + assign (value& v, const variable& var) + { + auto t (&value_traits<T>::value_type); + + if (v.type != t) + assign (v, t, var); + } + + template <typename T> + inline typename value_traits<T>::type + as (value& v) + { + return value_traits<T>::as (v); + } + + template <typename T> + inline typename value_traits<T>::const_type + as (const value& v) + { + return value_traits<T>::as (v); + } + + template <typename T> + inline bool + assign (name& n) + { + return value_traits<T>::assign (n); + } + + template <typename T> + inline typename value_traits<T>::type + as (name& n) + { + return value_traits<T>::as (n); + } - inline const value_proxy& value_proxy:: - operator= (value_ptr v) const + template <typename T> + inline typename value_traits<T>::const_type + as (const name& n) { - *p = std::move (v); + return value_traits<T>::as (n); + } + + template <typename T> + inline value& value:: + operator= (T v) + { + value_traits<T>::assign (*this, std::move (v)); + return *this; + } + + template <typename T> + inline value& value:: + operator+= (T v) + { + value_traits<T>::append (*this, std::move (v)); return *this; } - inline const value_proxy& value_proxy:: - operator= (const value_proxy& v) const + inline void value:: + assign (names v, const variable& var) + { + data_ = std::move (v); + state_ = (type != nullptr && type->assign != nullptr + ? type->assign (data_, var) + : !data_.empty ()) + ? state_type::filled + : state_type::empty; + } + + // bool value + // + inline bool_value<name> value_traits<bool>:: + as (value& v) + { + assert (v.type == bool_type); + return bool_value<name> (v.data_.front ()); + } + + inline bool_value<const name> value_traits<bool>:: + as (const value& v) { - if (this != &v) + assert (v.type == bool_type); + return bool_value<const name> (v.data_.front ()); + } + + inline void value_traits<bool>:: + assign (value& v, bool x) + { + if (v.null ()) { - if (v) - *p = v.as<const value&> ().clone (); - else - p->reset (); + if (v.type == nullptr) + v.type = bool_type; + v.data_.emplace_back (name ()); + v.state_ = value::state_type::empty; } - return *this; + as (v) = x; + v.state_ = value::state_type::filled; } - inline const value_proxy& value_proxy:: - operator= (list_value v) const + inline void value_traits<bool>:: + append (value& v, bool x) { - if (*p == nullptr) - p->reset (new list_value (std::move (v))); + if (v.null ()) + assign (v, x); else - //@@ Assuming it is a list_value. - // - as<list_value&> () = std::move (v); + as (v) += x; // Cannot be empty. + } - return *this; + // string value + // + inline std::string& value_traits<std::string>:: + as (value& v) + { + assert (v.type == string_type); + return v.data_.front ().value; } - inline const value_proxy& value_proxy:: - operator= (std::string v) const + inline const std::string& value_traits<std::string>:: + as (const value& v) { - // In most cases this is used to initialize a new variable, so - // don't bother trying to optimize for the case where p is not - // NULL. - // - p->reset (new list_value (std::move (v))); + assert (v.type == string_type); + return v.data_.front ().value; + } + + inline void value_traits<std::string>:: + assign (value& v, std::string x) + { + if (v.null ()) + { + if (v.type == nullptr) + v.type = string_type; + v.data_.emplace_back (name ()); + v.state_ = value::state_type::empty; + } + + v.state_ = (as (v) = std::move (x)).empty () + ? value::state_type::empty + : value::state_type::filled; + } + + inline void value_traits<std::string>:: + append (value& v, std::string x) + { + if (v.null ()) + assign (v, std::move (x)); + else + v.state_ = (as (v) += std::move (x)).empty () + ? value::state_type::empty + : value::state_type::filled; + } + + // dir_path value + // + inline dir_path& value_traits<dir_path>:: + as (value& v) + { + assert (v.type == dir_path_type); + return v.data_.front ().dir; + } + + inline const dir_path& value_traits<dir_path>:: + as (const value& v) + { + assert (v.type == dir_path_type); + return v.data_.front ().dir; + } + + inline void value_traits<dir_path>:: + assign (value& v, dir_path x) + { + if (v.null ()) + { + if (v.type == nullptr) + v.type = dir_path_type; + v.data_.emplace_back (name ()); + v.state_ = value::state_type::empty; + } + + v.state_ = (as (v) = std::move (x)).empty () + ? value::state_type::empty + : value::state_type::filled; + } + + inline void value_traits<dir_path>:: + append (value& v, dir_path x) + { + if (v.null ()) + assign (v, std::move (x)); + else + v.state_ = (as (v) /= std::move (x)).empty () + ? value::state_type::empty + : value::state_type::filled; + } + + // name value + // + inline name& value_traits<name>:: + as (value& v) + { + assert (v.type == name_type); + return v.data_.front (); + } + + inline const name& value_traits<name>:: + as (const value& v) + { + assert (v.type == name_type); + return v.data_.front (); + } + + inline void value_traits<name>:: + assign (value& v, name x) + { + if (v.null ()) + { + if (v.type == nullptr) + v.type = name_type; + v.data_.emplace_back (name ()); + v.state_ = value::state_type::empty; + } + + v.state_ = (as (v) = std::move (x)).empty () + ? value::state_type::empty + : value::state_type::filled; + } + + // vector<T> value + // + template <typename T, typename D> + inline vector_value<T, D>& vector_value<T, D>:: + assign (std::vector<T> v) + { + d->clear (); + d->insert (d->end (), + std::make_move_iterator (v.begin ()), + std::make_move_iterator (v.end ())); return *this; } - inline const value_proxy& value_proxy:: - operator= (dir_path v) const + template <typename T, typename D> + template <typename D1> + inline vector_value<T, D>& vector_value<T, D>:: + assign (const vector_value<T, D1>& v) { - p->reset (new list_value (std::move (v))); + d->clear (); + d->insert (d->end (), v.begin (), v.end ()); return *this; } - inline const value_proxy& value_proxy:: - operator= (std::nullptr_t) const + template <typename T, typename D> + template <typename D1> + inline vector_value<T, D>& vector_value<T, D>:: + append (const vector_value<T, D1>& v) { - p->reset (); + d->insert (d->end (), v.begin (), v.end ()); return *this; } - inline const value_proxy& value_proxy:: - operator+= (const value_proxy& v) const + template <typename T> + inline vector_value<T, names> value_traits<std::vector<T>>:: + as (value& v) + { + assert (v.type == &value_traits<std::vector<T>>::value_type); + return vector_value<T, names> (v.data_); + } + + template <typename T> + inline vector_value<T, const names> value_traits<std::vector<T>>:: + as (const value& v) { - if (v && this != &v) + assert (v.type == &value_traits<std::vector<T>>::value_type); + return vector_value<T, const names> (v.data_); + } + + template <typename T> + template <typename V> + inline void value_traits<std::vector<T>>:: + assign (value& v, V x) + { + if (v.null ()) { - if (*p == nullptr) - *this = v; - else - //@@ Assuming it is a list_value. - // - *this += v.as<const list_value&> (); + if (v.type == nullptr) + v.type = &value_traits<std::vector<T>>::value_type; + v.state_ = value::state_type::empty; } - return *this; + v.state_ = (as (v).assign (std::move (x))).empty () + ? value::state_type::empty + : value::state_type::filled; } - inline const value_proxy& value_proxy:: - operator+= (const list_value& v) const + template <typename T> + template <typename V> + inline void value_traits<std::vector<T>>:: + append (value& v, V x) { - if (*p == nullptr) - *this = v; + if (v.null ()) + assign (v, std::move (x)); else + v.state_ = (as (v).append (std::move (x))).empty () + ? value::state_type::empty + : value::state_type::filled; + } + + // map<K, V> value + // + template <typename K, typename V> + inline map_value<K, V, names> value_traits<std::map<K, V>>:: + as (value& v) + { + assert ((v.type == &value_traits<std::map<K, V>>::value_type)); + return map_value<K, V, names> (v.data_); + } + + template <typename K, typename V> + inline map_value<K, V, const names> value_traits<std::map<K, V>>:: + as (const value& v) + { + assert ((v.type == &value_traits<std::map<K, V>>::value_type)); + return map_value<K, V, const names> (v.data_); + } + + template <typename K, typename V> + template <typename M> + inline void value_traits<std::map<K, V>>:: + assign (value& v, M x) + { + if (v.null ()) { - list_value& lv (as<list_value&> ()); - lv.insert (lv.end (), v.begin (), v.end ()); + if (v.type == nullptr) + v.type = &value_traits<std::map<K, V>>::value_type; + v.state_ = value::state_type::empty; } - return *this; + v.state_ = (as (v).assign (std::move (x))).empty () + ? value::state_type::empty + : value::state_type::filled; } - inline const value_proxy& value_proxy:: - operator+= (std::string v) const + template <typename K, typename V> + template <typename M> + inline void value_traits<std::map<K, V>>:: + append (value& v, M x) { - if (*p == nullptr) - *this = v; + if (v.null ()) + assign (v, std::move (x)); else - as<list_value&> ().emplace_back (std::move (v)); + v.state_ = (as (v).append (std::move (x))).empty () + ? value::state_type::empty + : value::state_type::filled; + } - return *this; + // variable_map::iterator_adapter + // + template <typename I> + inline typename I::reference variable_map::iterator_adapter<I>:: + operator* () const + { + auto& r (I::operator* ()); + const variable& var (r.first); + auto& val (r.second); + + // First access after being assigned a type? + // + if (var.type != nullptr && val.type != var.type) + build::assign (const_cast<value&> (val), var.type, var); + + return r; + } + + template <typename I> + inline typename I::pointer variable_map::iterator_adapter<I>:: + operator-> () const + { + auto p (I::operator-> ()); + const variable& var (p->first); + auto& val (p->second); + + // First access after being assigned a type? + // + if (var.type != nullptr && val.type != var.type) + build::assign (const_cast<value&> (val), var.type, var); + + return p; } } |