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)
5  2008, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
14 
65 #ifndef LUMIERA_QUERY_H
66 #define LUMIERA_QUERY_H
67 
68 
69 #include "lib/hash-combine.hpp"
70 #include "lib/typed-counter.hpp"
71 #include "lib/iter-adapter.hpp"
72 #include "lib/query-text.hpp"
73 #include "lib/query-util.hpp"
74 #include "lib/nocopy.hpp"
75 #include "lib/symbol.hpp"
76 #include "lib/util.hpp"
77 
78 #include <boost/lexical_cast.hpp>
79 #include <boost/operators.hpp>
80 #include <memory>
81 #include <typeinfo>
82 #include <cctype>
83 #include <string>
84 
85 
86 namespace lumiera {
87 
88  using lib::IxID;
89  using lib::Symbol;
90  using lib::Literal;
91  using util::isnil;
92  using util::unConst;
93  using boost::lexical_cast;
94  using std::string;
95 
96 
97  /* ==== common definitions for rule based queries ==== */
98 
99  class Goal;
100  class Resolution;
101  class QueryResolver;
102  class QueryKey;
103 
104 
107 
108 
109 
116  class Goal
118  {
119  public:
120  virtual ~Goal();
121 
122  enum Kind
123  { EMPTY = 0
124  , GENERIC = 1
125  , DISCOVERY
126  , PLACEMENT
127  };
128 
129  struct QueryID
130  {
131  Kind kind;
132  IxID type;
133 
134  explicit
135  QueryID(Kind k =EMPTY, IxID t=1)
136  : kind(k)
137  , type(t)
138  { }
139  };
140 
141  QueryID const&
142  getQID() const
143  {
144  return id_;
145  }
146 
147 
154  class Result
155  {
156  void* cur_;
157 
158  protected:
159  void point_at(void* p) { cur_ = p; }
160 
161  template<typename RES>
162  RES&
163  access()
164  {
165  REQUIRE (cur_);
166  return *reinterpret_cast<RES*> (cur_);
167  }
168 
169  public:
170  explicit operator bool() const { return isValid(); }
171  bool isValid() const { return bool(cur_); }
172 
173  Result() : cur_(0) { }
174  };
175 
176 
177 
178  protected:
179  QueryID id_;
180 
181  Goal (QueryID qid)
182  : id_(qid)
183  { }
184 
185  };
186 
187 
188  inline bool
189  operator< (Goal::QueryID const& id1, Goal::QueryID const& id2)
190  {
191  return id1.kind < id2.kind
192  ||(id1.kind == id2.kind && id1.type < id2.type);
193  }
194 
195  inline bool
196  operator== (Goal::QueryID const& id1, Goal::QueryID const& id2)
197  {
198  return id1.kind == id2.kind
199  && id1.type == id2.type;
200  }
201 
202  inline bool
203  operator!= (Goal::QueryID const& id1, Goal::QueryID const& id2)
204  {
205  return not (id1 == id2);
206  }
207 
208 
209 
210  namespace {
214 
215  template<typename RES>
216  inline IxID
217  getResultTypeID()
218  {
219  return ResultType::ID<RES>::get();
220  }
221 
223  inline size_t
224  taggedHash (size_t hash, Goal::QueryID typeID)
225  {
226  lib::hash::combine (hash, typeID.kind);
227  lib::hash::combine (hash, typeID.type);
228  return hash;
229  }
230  }
231 
232 
233 
234 
269  template<class RES>
270  class Query
271  : public Goal
272  {
275 
276  protected:
277  static QueryID
278  defineQueryTypeID (Kind queryType = Goal::GENERIC)
279  {
280  QueryID id(queryType, getResultTypeID<RES>());
281  return id;
282  }
283 
294  virtual lib::QueryText
296  {
297  WARN (query, "internal query not outfitted with a suitable query definition");
298  return string("bottom");
299  }
300 
305  {
306  if (isnil(this->def_))
307  def_ = this->buildSyntacticRepresentation();
308  return def_;
309  }
310 
311 
312  class Builder;
313 
314  Query (QueryID typeID, lib::QueryText const& genericQuerySpec)
315  : Goal (typeID)
316  , def_(genericQuerySpec)
317  { }
318 
319  Query (QueryID typeID, string querySpec)
320  : Goal (defineQueryTypeID(typeID.kind))
321  , def_(querySpec)
322  {
323  REQUIRE (this->getQID().type == typeID.type);
324  }
325 
326  friend class Builder;
327 
328 
329  public:
330  Query()
331  : Goal (defineQueryTypeID(Goal::EMPTY))
332  { }
333 
334  explicit
335  Query (string querySpec)
336  : Goal (defineQueryTypeID(Goal::GENERIC))
337  , def_(querySpec)
338  { }
339 
340  operator QueryKey() const;
341 
342  static Builder build (Kind queryType = Goal::GENERIC);
343  Builder rebuild() const;
344 
345  string extractID (Symbol predicate) const;
346  bool usesPredicate (Symbol predicate) const;
347 
348 
349 
350  /* results retrieval */
351  class Cursor
352  : public Goal::Result
353  {
354  public:
355  typedef RES value_type;
356  typedef RES& reference;
357  typedef RES* pointer;
358 
359  RES& operator* () { return access<RES>(); }
360  RES* operator->() { return & access<RES>(); }
361 
362  void point_at(RES* r){ Goal::Result::point_at(r);}
363  void point_at(RES& r){ Goal::Result::point_at(&r);}
364  };
365 
366 
368 
369  iterator operator() (QueryResolver const& resolver) const;
370  iterator resolveBy (QueryResolver const& resolver) const;
371 
372 
373  friend size_t
374  hash_value (Query const& q)
375  {
376  return taggedHash (hash_value(q.getQueryDefinition()), q.id_);
377  }
378  };
379 
380 
381 
382 
388  class QueryKey
389  : boost::totally_ordered<QueryKey>
390  {
391  Goal::QueryID id_;
392  lib::QueryText def_;
393 
394  public:
396  : id_(id)
397  , def_(q)
398  {
399  ENSURE (!isnil(def_));
400  }
401 
404  : id_()
405  , def_("false")
406  { }
407 
408  // default copyable
409 
410  template<class RES>
411  operator Query<RES>() const
412  {
413  REQUIRE (getResultTypeID<RES>() == id_.type);
414  return Query<RES>::build(id_.kind).fromText(def_);
415  }
416 
417  string
418  display() const
419  {
420  return "kind=" + lexical_cast<string>(id_.kind)
421  +",type=" + lexical_cast<string>(id_.type)
422  +",def=" + string(def_);
423  }
424 
425  string
426  getQueryString() const
427  {
428  return string(def_);
429  }
430 
431 
432  uint
433  degree() const
434  {
435  return def_.degree_of_constriction();
436  }
437 
438  bool
439  empty() const
440  {
441  return Goal::EMPTY == id_.kind;
442  }
443 
444 
445  friend bool
446  operator< (QueryKey const& q1, QueryKey const& q2)
447  {
448  uint d1 = q1.degree();
449  uint d2 = q2.degree();
450  return d1 < d2
451  ||(d1 == d2 && ( q1.def_ < q2.def_
452  ||(q1.def_ == q2.def_ && q1.id_ < q2.id_)));
453  }
454 
455  friend bool
456  operator== (QueryKey const& q1, QueryKey const& q2)
457  {
458  return q1.def_ == q2.def_;
459  }
460 
461  friend size_t
462  hash_value (QueryKey const& q)
463  {
464  return taggedHash (hash_value(q.def_), q.id_);
465  }
466  };
467 
468 
469 
470 
471 
476  template<class RES>
477  class Query<RES>::Builder
478  {
479  QueryID typeID_;
480  string predicateForm_;
481 
482  Builder (QueryID kind, string baseDef ="")
483  : typeID_(kind)
484  , predicateForm_(baseDef)
485  { }
486 
487  friend class Query<RES>;
488 
489 
490  public:
493  operator Query<RES>()
494  {
495  return Query<RES>(typeID_, predicateForm_);
496  }
497 
498 
502  string
503  asKey() const
504  {
505  return "type("
506  + lexical_cast<string> (getResultTypeID<RES>())
507  + "), "+predicateForm_;
508  }
509 
510 
516  string
517  extractID (Symbol predicate) const
518  {
519  return lib::query::extractID (predicate, this->predicateForm_);
520  }
521 
522 
527  Builder&
528  removeTerm (Symbol termPredicate)
529  {
530  lib::query::removeTerm(termPredicate, this->predicateForm_);
531  return *this;
532  }
533 
534  Builder&
535  withConditions (string additionalQueryPredicates)
536  {
537  this->predicateForm_ =
538  lib::query::appendTerms(this->predicateForm_, additionalQueryPredicates);
539  return *this;
540  }
541 
542  Builder&
543  prependConditions (string additionalQueryPredicates)
544  {
545  this->predicateForm_ =
546  lib::query::appendTerms(additionalQueryPredicates, this->predicateForm_);
547  return *this;
548  }
549 
550  Builder&
551  fromText (string queryPredicates)
552  {
553  this->predicateForm_ = queryPredicates;
554  return *this;
555  }
556 
557  };
558 
559 
560 
561 
562  template<class RES>
563  inline typename Query<RES>::Builder
564  Query<RES>::build (Kind queryType)
565  {
566  return Builder(defineQueryTypeID (queryType));
567  }
568 
569 
570  template<class RES>
571  inline typename Query<RES>::Builder
572  Query<RES>::rebuild() const
573  {
574  return Builder(this->id_, getQueryDefinition());
575  }
576 
577 
584  template<class RES>
585  inline string
586  Query<RES>::extractID (Symbol predicate) const
587  {
588  return this->rebuild().extractID (predicate);
589  }
590 
591 
592  template<class RES>
593  inline bool
594  Query<RES>::usesPredicate (Symbol predicate) const
595  {
596  return lib::query::hasTerm(predicate, getQueryDefinition());
597  }
598 
599 
605  template<class RES>
606  inline
608  {
609  return QueryKey (this->id_, getQueryDefinition());
610  }
611 
612 
613 
614 
615 
616 } // namespace lumiera
617 #endif
Query ABC: unspecific goal for resolution or retrieval.
Definition: query.hpp:116
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:295
Helper template(s) for creating Lumiera Forward Iterators.
lib::QueryText getQueryDefinition() const
access the complete syntactical representation of this query.
Definition: query.hpp:304
inline string literal This is a marker type to indicate that
Definition: symbol.hpp:76
void combine(size_t &combinedHash, size_t additionalHash)
meld the additional hash value into the given base hash value.
Builder & removeTerm(Symbol termPredicate)
remove the first term from this query definition, which matches the given predicate symbol ...
Definition: query.hpp:528
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:213
size_t taggedHash(size_t hash, Goal::QueryID typeID)
includes the QueryID type distinction into the given hash value
Definition: query.hpp:224
string extractID(Symbol predicate) const
extract an ID term defined as (single) parameter for the given predicate.
Definition: query.hpp:517
Token or Atom with distinct identity.
Definition: symbol.hpp:117
lib::QueryText def_
generic syntactical definition
Definition: query.hpp:274
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:388
Result()
create an NIL result
Definition: query.hpp:173
Types marked with this mix-in may be duplicated by copy-construction, yet may not be moved or transfe...
Definition: nocopy.hpp:95
string asKey() const
Definition: query.hpp:503
Lumiera public interface.
Definition: advice.cpp:104
QueryKey()
the empty or bottom query key
Definition: query.hpp:403
Provide type-IDs for a specific context.
uint degree_of_constriction() const
synthetic total order to classify query definitions.
Definition: query-text.hpp:101
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:270
Helper for establishing, reworking and remolding queries.
Definition: query.hpp:477
Syntactical query representation.
Definition: query-text.hpp:61
string extractID(Symbol predicate) const
convenience shortcut to extract a desired name-ID.
Definition: query.hpp:586
Single Solution, possibly part of a result set.
Definition: query.hpp:154