Lumiera  0.pre.03
»edit your freedom«
query.hpp
Go to the documentation of this file.
1 /*
2  QUERY.hpp - interface for generic queries
3 
4  Copyright (C) Lumiera.org
5  2008, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
74 #ifndef LUMIERA_QUERY_H
75 #define LUMIERA_QUERY_H
76 
77 
78 #include "lib/typed-counter.hpp"
79 #include "lib/iter-adapter.hpp"
80 #include "lib/query-text.hpp"
81 #include "lib/query-util.hpp"
82 #include "lib/hash-value.h"
83 #include "lib/nocopy.hpp"
84 #include "lib/symbol.hpp"
85 #include "lib/util.hpp"
86 
87 #include <boost/lexical_cast.hpp>
88 #include <boost/operators.hpp>
89 #include <memory>
90 #include <typeinfo>
91 #include <cctype>
92 #include <string>
93 
94 
95 namespace lumiera {
96 
97  using lib::IxID;
98  using lib::Symbol;
99  using lib::Literal;
100  using util::isnil;
101  using util::unConst;
102  using boost::lexical_cast;
103  using std::string;
104 
105 
106  /* ==== common definitions for rule based queries ==== */
107 
108  class Goal;
109  class Resolution;
110  class QueryResolver;
111  class QueryKey;
112 
113 
116 
117 
118 
125  class Goal
127  {
128  public:
129  virtual ~Goal();
130 
131  enum Kind
132  { EMPTY = 0
133  , GENERIC = 1
134  , DISCOVERY
135  , PLACEMENT
136  };
137 
138  struct QueryID
139  {
140  Kind kind;
141  IxID type;
142 
143  explicit
144  QueryID(Kind k =EMPTY, IxID t=1)
145  : kind(k)
146  , type(t)
147  { }
148  };
149 
150  QueryID const&
151  getQID() const
152  {
153  return id_;
154  }
155 
156 
163  class Result
164  {
165  void* cur_;
166 
167  protected:
168  void point_at(void* p) { cur_ = p; }
169 
170  template<typename RES>
171  RES&
172  access()
173  {
174  REQUIRE (cur_);
175  return *reinterpret_cast<RES*> (cur_);
176  }
177 
178  public:
179  explicit operator bool() const { return isValid(); }
180  bool isValid() const { return bool(cur_); }
181 
182  Result() : cur_(0) { }
183  };
184 
185 
186 
187  protected:
188  QueryID id_;
189 
190  Goal (QueryID qid)
191  : id_(qid)
192  { }
193 
194  };
195 
196 
197  inline bool
198  operator< (Goal::QueryID const& id1, Goal::QueryID const& id2)
199  {
200  return id1.kind < id2.kind
201  ||(id1.kind == id2.kind && id1.type < id2.type);
202  }
203 
204  inline bool
205  operator== (Goal::QueryID const& id1, Goal::QueryID const& id2)
206  {
207  return id1.kind == id2.kind
208  && id1.type == id2.type;
209  }
210 
211  inline bool
212  operator!= (Goal::QueryID const& id1, Goal::QueryID const& id2)
213  {
214  return not (id1 == id2);
215  }
216 
217 
218 
219  namespace {
223 
224  template<typename RES>
225  inline IxID
226  getResultTypeID()
227  {
228  return ResultType::ID<RES>::get();
229  }
230 
232  inline size_t
233  taggedHash (size_t hash, Goal::QueryID typeID)
234  {
235  lib::hash::combine (hash, typeID.kind);
236  lib::hash::combine (hash, typeID.type);
237  return hash;
238  }
239  }
240 
241 
242 
243 
278  template<class RES>
279  class Query
280  : public Goal
281  {
284 
285  protected:
286  static QueryID
287  defineQueryTypeID (Kind queryType = Goal::GENERIC)
288  {
289  QueryID id(queryType, getResultTypeID<RES>());
290  return id;
291  }
292 
303  virtual lib::QueryText
305  {
306  WARN (query, "internal query not outfitted with a suitable query definition");
307  return string("bottom");
308  }
309 
314  {
315  if (isnil(this->def_))
316  def_ = this->buildSyntacticRepresentation();
317  return def_;
318  }
319 
320 
321  class Builder;
322 
323  Query (QueryID typeID, lib::QueryText const& genericQuerySpec)
324  : Goal (typeID)
325  , def_(genericQuerySpec)
326  { }
327 
328  Query (QueryID typeID, string querySpec)
329  : Goal (defineQueryTypeID(typeID.kind))
330  , def_(querySpec)
331  {
332  REQUIRE (this->getQID().type == typeID.type);
333  }
334 
335  friend class Builder;
336 
337 
338  public:
339  Query()
340  : Goal (defineQueryTypeID(Goal::EMPTY))
341  { }
342 
343  explicit
344  Query (string querySpec)
345  : Goal (defineQueryTypeID(Goal::GENERIC))
346  , def_(querySpec)
347  { }
348 
349  operator QueryKey() const;
350 
351  static Builder build (Kind queryType = Goal::GENERIC);
352  Builder rebuild() const;
353 
354  string extractID (Symbol predicate) const;
355  bool usesPredicate (Symbol predicate) const;
356 
357 
358 
359  /* results retrieval */
360  class Cursor
361  : public Goal::Result
362  {
363  public:
364  typedef RES value_type;
365  typedef RES& reference;
366  typedef RES* pointer;
367 
368  RES& operator* () { return access<RES>(); }
369  RES* operator->() { return & access<RES>(); }
370 
371  void point_at(RES* r){ Goal::Result::point_at(r);}
372  void point_at(RES& r){ Goal::Result::point_at(&r);}
373  };
374 
375 
377 
378  iterator operator() (QueryResolver const& resolver) const;
379  iterator resolveBy (QueryResolver const& resolver) const;
380 
381 
382  friend size_t
383  hash_value (Query const& q)
384  {
385  return taggedHash (hash_value(q.getQueryDefinition()), q.id_);
386  }
387  };
388 
389 
390 
391 
397  class QueryKey
398  : boost::totally_ordered<QueryKey>
399  {
400  Goal::QueryID id_;
401  lib::QueryText def_;
402 
403  public:
405  : id_(id)
406  , def_(q)
407  {
408  ENSURE (!isnil(def_));
409  }
410 
413  : id_()
414  , def_("false")
415  { }
416 
417  // default copyable
418 
419  template<class RES>
420  operator Query<RES>() const
421  {
422  REQUIRE (getResultTypeID<RES>() == id_.type);
423  return Query<RES>::build(id_.kind).fromText(def_);
424  }
425 
426  string
427  display() const
428  {
429  return "kind=" + lexical_cast<string>(id_.kind)
430  +",type=" + lexical_cast<string>(id_.type)
431  +",def=" + string(def_);
432  }
433 
434  string
435  getQueryString() const
436  {
437  return string(def_);
438  }
439 
440 
441  uint
442  degree() const
443  {
444  return def_.degree_of_constriction();
445  }
446 
447  bool
448  empty() const
449  {
450  return Goal::EMPTY == id_.kind;
451  }
452 
453 
454  friend bool
455  operator< (QueryKey const& q1, QueryKey const& q2)
456  {
457  uint d1 = q1.degree();
458  uint d2 = q2.degree();
459  return d1 < d2
460  ||(d1 == d2 && ( q1.def_ < q2.def_
461  ||(q1.def_ == q2.def_ && q1.id_ < q2.id_)));
462  }
463 
464  friend bool
465  operator== (QueryKey const& q1, QueryKey const& q2)
466  {
467  return q1.def_ == q2.def_;
468  }
469 
470  friend size_t
471  hash_value (QueryKey const& q)
472  {
473  return taggedHash (hash_value(q.def_), q.id_);
474  }
475  };
476 
477 
478 
479 
480 
485  template<class RES>
486  class Query<RES>::Builder
487  {
488  QueryID typeID_;
489  string predicateForm_;
490 
491  Builder (QueryID kind, string baseDef ="")
492  : typeID_(kind)
493  , predicateForm_(baseDef)
494  { }
495 
496  friend class Query<RES>;
497 
498 
499  public:
502  operator Query<RES>()
503  {
504  return Query<RES>(typeID_, predicateForm_);
505  }
506 
507 
511  string
512  asKey() const
513  {
514  return "type("
515  + lexical_cast<string> (getResultTypeID<RES>())
516  + "), "+predicateForm_;
517  }
518 
519 
525  string
526  extractID (Symbol predicate) const
527  {
528  return lib::query::extractID (predicate, this->predicateForm_);
529  }
530 
531 
536  Builder&
537  removeTerm (Symbol termPredicate)
538  {
539  lib::query::removeTerm(termPredicate, this->predicateForm_);
540  return *this;
541  }
542 
543  Builder&
544  withConditions (string additionalQueryPredicates)
545  {
546  this->predicateForm_ =
547  lib::query::appendTerms(this->predicateForm_, additionalQueryPredicates);
548  return *this;
549  }
550 
551  Builder&
552  prependConditions (string additionalQueryPredicates)
553  {
554  this->predicateForm_ =
555  lib::query::appendTerms(additionalQueryPredicates, this->predicateForm_);
556  return *this;
557  }
558 
559  Builder&
560  fromText (string queryPredicates)
561  {
562  this->predicateForm_ = queryPredicates;
563  return *this;
564  }
565 
566  };
567 
568 
569 
570 
571  template<class RES>
572  inline typename Query<RES>::Builder
573  Query<RES>::build (Kind queryType)
574  {
575  return Builder(defineQueryTypeID (queryType));
576  }
577 
578 
579  template<class RES>
580  inline typename Query<RES>::Builder
581  Query<RES>::rebuild() const
582  {
583  return Builder(this->id_, getQueryDefinition());
584  }
585 
586 
593  template<class RES>
594  inline string
595  Query<RES>::extractID (Symbol predicate) const
596  {
597  return this->rebuild().extractID (predicate);
598  }
599 
600 
601  template<class RES>
602  inline bool
603  Query<RES>::usesPredicate (Symbol predicate) const
604  {
605  return lib::query::hasTerm(predicate, getQueryDefinition());
606  }
607 
608 
614  template<class RES>
615  inline
617  {
618  return QueryKey (this->id_, getQueryDefinition());
619  }
620 
621 
622 
623 
624 
625 } // namespace lumiera
626 #endif
Query ABC: unspecific goal for resolution or retrieval.
Definition: query.hpp:125
Utilities to support working with predicate queries.
Creating series of type-based contexts.
std::shared_ptr< Resolution > PReso
Allow to take and transfer ownership of a result set.
Interface: a facility for resolving (some kind of) queries A concrete subclass has the ability to cre...
virtual lib::QueryText buildSyntacticRepresentation() const
Extension point to generate a generic query definition on demand.
Definition: query.hpp:304
Helper template(s) for creating Lumiera Forward Iterators.
lib::QueryText getQueryDefinition() const
access the complete syntactical representation of this query.
Definition: query.hpp:313
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:85
void combine(size_t &combinedHash, size_t additionalHash)
meld the additional hash value into the given base hash value.
Definition: hash-value.h:71
Builder & removeTerm(Symbol termPredicate)
remove the first term from this query definition, which matches the given predicate symbol ...
Definition: query.hpp:537
A generic syntactical representation for all kinds of queries.
lib::TypedContext< Goal::Result > ResultType
Context used for generating type-IDs to denote the specific result types of issued queries...
Definition: query.hpp:222
size_t taggedHash(size_t hash, Goal::QueryID typeID)
includes the QueryID type distinction into the given hash value
Definition: query.hpp:233
string extractID(Symbol predicate) const
extract an ID term defined as (single) parameter for the given predicate.
Definition: query.hpp:526
Token or Atom with distinct identity.
Definition: symbol.hpp:126
lib::QueryText def_
generic syntactical definition
Definition: query.hpp:283
Mix-Ins to allow or prohibit various degrees of copying and cloning.
virtual ~Goal()
this is a marker baseclass
Marker types to indicate a literal string and a Symbol.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Wrapper for indexing and ordering.
Definition: query.hpp:397
Result()
create an NIL result
Definition: query.hpp:182
Types marked with this mix-in may be created by copy-construction (or move construction), but may be not reassigned thereafter.
Definition: nocopy.hpp:91
Hash value types and utilities.
string asKey() const
Definition: query.hpp:512
Lumiera public interface.
Definition: advice.cpp:113
QueryKey()
the empty or bottom query key
Definition: query.hpp:412
Provide type-IDs for a specific context.
uint degree_of_constriction() const
synthetic total order to classify query definitions.
Definition: query-text.hpp:110
Adapter for building an implementation of the »Lumiera Forward Iterator« concept. ...
Generic interface to express a query for specifically typed result elements exposing some capabilitie...
Definition: query.hpp:279
Helper for establishing, reworking and remolding queries.
Definition: query.hpp:486
Syntactical query representation.
Definition: query-text.hpp:70
string extractID(Symbol predicate) const
convenience shortcut to extract a desired name-ID.
Definition: query.hpp:595
Single Solution, possibly part of a result set.
Definition: query.hpp:163