From 5cddc57932997e1f34e640ffd53d858b32b21108 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 17 Dec 2012 23:17:32 +0100 Subject: [PATCH] WIP extend query with a warpper for indexing and ordering ...to extract the syntetic ordering from DefsRegistry and make that a responsibility of the (internal) syntactic representation of the query. doesn't pass the compiler yet --- src/common/query.hpp | 99 ++++++++++++++++++++++++-- src/common/query/defs-manager-impl.hpp | 7 +- src/common/query/defs-registry.hpp | 49 ++++++++----- src/lib/query-util.cpp | 12 ++++ src/lib/query-util.hpp | 4 +- 5 files changed, 144 insertions(+), 27 deletions(-) diff --git a/src/common/query.hpp b/src/common/query.hpp index 0794bd4a0..46ef4ff01 100644 --- a/src/common/query.hpp +++ b/src/common/query.hpp @@ -35,6 +35,7 @@ #include "lib/util.hpp" #include +#include #include #include #include @@ -55,7 +56,9 @@ namespace lumiera { class Goal; class Resolution; - class QueryResolver; + class QueryResolver; + class QueryKey; + /** Allow for taking ownership of a result set */ typedef std::tr1::shared_ptr PReso; @@ -253,10 +256,10 @@ namespace lumiera { rebuild() const; string - extractID (Symbol predicate) const - { - return this->rebuild().extractID (predicate); - } + extractID (Symbol predicate) const; + + operator QueryKey() const; + /* results retrieval */ @@ -298,6 +301,55 @@ namespace lumiera { + /** + * Wrapper for indexing and ordering. + * Defines a synthetic totally ordered index value. + * Implicitly convertible to and from Query instances. + */ + class QueryKey + : boost::totally_ordered< QueryKey> + { + Goal::QueryID id_; + lib::QueryText def_; + + public: + QueryKey (Goal::QueryID id, lib::QueryText def) + : id_(id) + , def_(q) + { } + + // default copyable + + template + operator Query() const + { + return Query::build().withConditions(def_); + } + + uint + degree() const + { + return def_.degree(); + } + + + friend bool + operator< (QueryKey const& q1, QueryKey const& q2) + { + return q1.degree() < q2.degree(); + } + + friend size_t + hash_value (QueryKey const& q) + { + return hash_value (q.def_); /////////////////TODO include the QueryID into the generated hash? + } + }; + + + + + /** * Helper for establishing, * reworking and remolding queries. @@ -360,19 +412,54 @@ namespace lumiera { return *this; } + Builder& + withConditions (string additionalQueryPredicates) + { + lib::query::appendTerms(this->predicateForm_, additionalQueryPredicates); + return *this; + } + }; template - typename Query::Builder + inline typename Query::Builder Query::rebuild() const { return Builder(this->id_, this->def_); } + /** convenience shortcut to extract a desired name-ID. + * @todo used extensively for the mock implementation of query resolution. + * For real resolution queries, such a function is quite nonsensical. + * To be revisited and (likely) to be removed on the long run + * @see Query::Builder#extractID + */ + template + inline string + Query::extractID (Symbol predicate) const + { + return this->rebuild().extractID (predicate); + } + + + /** automatic conversion from Query to QueryKey for indexing and ordering. + * By defining a parameter of type QueryKey, any provided Query will be + * automatically transformed into an generic representation usable for + * ordered storage in sets, maps and for generation of metrics. + */ + template + Query::operator QueryKey() const + { + return QueryKey (this->id_, this->def_); + } + + + + } // namespace lumiera #endif diff --git a/src/common/query/defs-manager-impl.hpp b/src/common/query/defs-manager-impl.hpp index ae277adf4..005fc8774 100644 --- a/src/common/query/defs-manager-impl.hpp +++ b/src/common/query/defs-manager-impl.hpp @@ -31,7 +31,7 @@ ** For the standard use-case within the session / Proc-Layer, this is performed for the ** core MObject types, alongside with the definition of the generic config-query-resolver. ** - ** @see config-resolver.cpp definition of the explicit specialisiations for the session + ** @see config-resolver.cpp definition of the explicit specialisations for the session ** @see proc::ConfigResolver ** */ @@ -139,11 +139,10 @@ namespace query { return res; else res = create (capabilities); // not yet known as default, create new - - UNIMPLEMENTED("String representation of queries, here just for diagnostics"); + if (!res) throw lumiera::error::Config (_Fmt("The following Query could not be resolved: %s.") - % "TODO"//capabilities.asKey()////////////////////////////////////////////////////////////////////////////////////////////TODO + % capabilities.rebuild().asKey() , LUMIERA_ERROR_CAPABILITY_QUERY ); else return res; diff --git a/src/common/query/defs-registry.hpp b/src/common/query/defs-registry.hpp index bc6dce4b1..28f9af8a0 100644 --- a/src/common/query/defs-registry.hpp +++ b/src/common/query/defs-registry.hpp @@ -23,11 +23,19 @@ /** @file defs-registry.hpp ** A piece of implementation code factored out into a separate header (include). - ** Only used in defs-manager.cpp and for the unit tests. We can't place it into - ** a separate compilation unit, because defs-manager.cpp defines some explicit + ** Only used through defs-manager-impl.hpp and for the unit tests. We can't place it + ** into a separate compilation unit, because config-resolver.cpp defines some explicit ** template instantiation, which cause the different Slots of the DefsrRegistry#table_ ** to be filled with data and defaults for the specific Types. ** + ** Basically, this piece of code defines a specialised index / storage table to hold + ** Queries-for-default objects. This allows to remember what actually was used as + ** "default" solution for some query and to oder possible default solutions. + ** @remarks as of 2012, we're still using a fake implementation of the resolution, + ** no real resolution engine. While the basic idea of this "defaults registry" + ** is likely to stay, the actual order relation and maybe even the components + ** to be stored in this registry might be subject to change. + ** ** @see mobject::session::DefsManager ** @see DefsRegistryImpl_test ** @@ -44,13 +52,13 @@ #include "lib/util.hpp" #include "lib/util-foreach.hpp" #include "lib/sync-classlock.hpp" +#include "lib/format-string.hpp" #include "lib/query-util.hpp" #include "common/query.hpp" #include #include #include -#include #include #include @@ -70,8 +78,10 @@ namespace query { namespace impl { namespace { + using util::_Fmt; + uint maxSlots (0); ///< number of different registered Types - format dumpRecord ("%2i| %64s --> %s\n"); + _Fmt dumpRecord ("%2i| %64s --> %s\n"); } @@ -95,7 +105,7 @@ namespace query { Query query; weak_ptr objRef; - Record (const Query& q, const P& obj) + Record (Query const& q, P const& obj) : degree (lib::query::countPred ("TODO")),//q)),////////////////////////////////////////////////////////////////////////////////////////////TODO query (q), objRef (obj) @@ -106,13 +116,13 @@ namespace query { struct Search ///< Functor searching for a specific object { - Search (const P& obj) + Search (P const& obj) : obj_(obj) { } - const P& obj_; + P const& obj_; bool - operator() (const Record& rec) + operator() (Record const& rec) { P storedObj (rec.objRef.lock()); return storedObj && (storedObj == obj_); @@ -131,7 +141,7 @@ namespace query { } }; - operator string () const { return str (dumpRecord % degree % query % dumpObj()); } + operator string () const { return dumpRecord % degree % query % dumpObj(); } string dumpObj () const { P o (objRef.lock()); return o? string(*o):"dead"; } }; @@ -141,7 +151,8 @@ namespace query { * separate tree (set) of registry entries */ template - struct Slot : public TableEntry + struct Slot + : public TableEntry { typedef typename Record::OrderRelation Ordering; typedef std::set, Ordering> Registry; @@ -195,7 +206,8 @@ namespace query { * @todo as of 3/2008 the real query implementation is missing, and the * exact behaviour has to be defined. */ - class DefsRegistry : private boost::noncopyable + class DefsRegistry + : boost::noncopyable { Table table_; @@ -223,7 +235,8 @@ namespace query { operator++ (); // init to first element (or to null if empty) } - P findNext () throw() + P + findNext () ///< EX_FREE { while (!next) { @@ -256,7 +269,8 @@ namespace query { * @note none of the queries will be evaluated (we're just counting predicates) */ template - Iter candidates (const Query& query) + Iter + candidates (Query const& query) { P dummy; Record entry (query, dummy); @@ -282,7 +296,8 @@ namespace query { * case, also the param obj shared-ptr is rebound! */ template - bool put (P& obj, const Query& query) + bool + put (P& obj, Query const& query) { Record entry (query, obj); typedef typename Slot::Registry Registry; @@ -311,7 +326,8 @@ namespace query { * @return false if the object wasn't registered at all. */ template - bool forget (const P& obj) + bool + forget (P const& obj) { typedef typename Slot::Registry Registry; typedef typename Record::Search SearchFunc; @@ -325,7 +341,8 @@ namespace query { * @note to use it, your objects need an operator string() */ template - string dump() + string + dump () { string res; util::for_each ( Slot::access(table_) diff --git a/src/lib/query-util.cpp b/src/lib/query-util.cpp index 7a29f3c39..bd5899425 100644 --- a/src/lib/query-util.cpp +++ b/src/lib/query-util.cpp @@ -138,6 +138,18 @@ namespace lib { return cnt; } + + /** @note preliminary implementation without any syntax checks + * @return a conjunction of the predicates + */ + string + appendTerms (string const& pred1, string const& pred2) + { + string res(pred1); + return res + ", " + pred2; + } + + } // namespace query } // namespace lib diff --git a/src/lib/query-util.hpp b/src/lib/query-util.hpp index 81e6deae4..f83bfd3a1 100644 --- a/src/lib/query-util.hpp +++ b/src/lib/query-util.hpp @@ -58,10 +58,12 @@ namespace lib { uint countPred (const string&); - const string extractID (Symbol, const string& termString); + const string extractID (Symbol, string const& termString); const string removeTerm (Symbol, string& termString); + string appendTerms (string const& pred1, string const& pred2); + template const string