souffle  2.0.2-371-g6315b36
SouffleInterface.h
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file SouffleInterface.h
12  *
13  * Main include file for generated C++ classes of Souffle
14  *
15  ***********************************************************************/
16 
17 #pragma once
18 
19 #include "souffle/RamTypes.h"
20 #include "souffle/RecordTable.h"
21 #include "souffle/SymbolTable.h"
23 #include <algorithm>
24 #include <cassert>
25 #include <cstddef>
26 #include <cstdint>
27 #include <initializer_list>
28 #include <iostream>
29 #include <map>
30 #include <memory>
31 #include <string>
32 #include <tuple>
33 #include <utility>
34 #include <vector>
35 
36 namespace souffle {
37 
38 class tuple;
39 
40 /**
41  * Object-oriented wrapper class for Souffle's templatized relations.
42  */
43 class Relation {
44 public:
45  using arity_type = uint32_t;
46 
47 protected:
48  /**
49  * Abstract iterator class.
50  *
51  * When tuples are inserted into a relation, they will be stored contiguously.
52  * Intially, the iterator_base of a relation will point to the first tuple inserted.
53  * iterator_base can be moved to point to the next tuple until the end.
54  * The tuple iterator_base is pointing to can be accessed.
55  * However, users can not use this to access tuples since iterator class is protected.
56  * Instead, they should use the public class - iterator which interacts with iterator_base.
57  */
58  class iterator_base {
59  protected:
60  /**
61  * Required for identifying type of iterator
62  * (NB: LLVM has no typeinfo).
63  *
64  * TODO (Honghyw) : Provide a clear documentation of what id is used for.
65  */
66  uint32_t id;
67 
68  public:
69  /**
70  * Get the ID of the iterator_base object.
71  *
72  * @return ID of the iterator_base object (unit32_t)
73  */
74  virtual uint32_t getId() const {
75  return id;
76  }
77 
78  /**
79  * Constructor.
80  *
81  * Create an instance of iterator_base and set its ID to be arg_id.
82  *
83  * @param arg_id ID of an iterator object (unit32_t)
84  */
85  iterator_base(uint32_t arg_id) : id(arg_id) {}
86 
87  /**
88  * Destructor.
89  */
90  virtual ~iterator_base() = default;
91 
92  /**
93  * Overload the "++" operator.
94  *
95  * Increment the iterator_base so that the iterator_base will now point to the next tuple.
96  * The definition of this overloading has to be defined by the child class of iterator_base.
97  */
98  virtual void operator++() = 0;
99 
100  /**
101  * Overload the "*" operator.
102  *
103  * Return the tuple that is pointed to by the iterator_base.
104  * The definition of this overloading has to be defined by the child class of iterator_base.
105  *
106  * @return tuple Reference to a tuple object
107  */
108  virtual tuple& operator*() = 0;
109 
110  /**
111  * Overload the "==" operator.
112  *
113  * @param o Reference to an object of the iterator_base class
114  * @return A boolean value, if the ID of o is the same as the ID of the current object and equal(o)
115  * returns true. Otherwise return false
116  */
117  bool operator==(const iterator_base& o) const {
118  return this->getId() == o.getId() && equal(o);
119  }
120 
121  /**
122  * Clone the iterator_base.
123  * The definition of clone has to be defined by the child class of iterator_base.
124  *
125  * @return An iterator_base pointer
126  */
127  virtual iterator_base* clone() const = 0;
128 
129  protected:
130  /**
131  * Check if the passed-in object of o is the the same as the current iterator_base.
132  *
133  * TODO (Honghyw) : Provide a clear documentation of what equal function does.
134  *
135  * @param o Reference to an object of the iterator_base class
136  * @return A boolean value. If two iterator_base are the same return true. Otherwise return false
137  */
138  virtual bool equal(const iterator_base& o) const = 0;
139  };
140 
141 public:
142  /**
143  * Destructor.
144  */
145  virtual ~Relation() = default;
146 
147  /**
148  * Wrapper class for abstract iterator.
149  *
150  * Users must use iterator class to access the tuples stored in a relation.
151  */
152  class iterator {
153  protected:
154  /*
155  * iterator_base class pointer.
156  *
157  */
158  std::unique_ptr<iterator_base> iter = nullptr;
159 
160  public:
161  /**
162  * Constructor.
163  */
164  iterator() = default;
165 
166  /**
167  * Move constructor.
168  *
169  * The new iterator now has ownerhsip of the iterator base.
170  *
171  * @param arg lvalue reference to an iterator object
172  */
173  iterator(iterator&& arg) = default;
174 
175  /**
176  * Constructor.
177  *
178  * Initialise this iterator with a given iterator base
179  *
180  * The new iterator has ownership of the iterator base.
181  *
182  * @param arg An iterator_base class pointer
183  */
184  iterator(std::unique_ptr<iterator_base> it) : iter(std::move(it)) {}
185 
186  /**
187  * Destructor.
188  *
189  * The iterator_base instance iter is pointing is destructed.
190  */
191  ~iterator() = default;
192 
193  /**
194  * Constructor.
195  *
196  * Initialise the iter to be the clone of arg.
197  *
198  * @param o Reference to an iterator object
199  */
200  iterator(const iterator& o) : iter(o.iter->clone()) {}
201 
202  /**
203  * Overload the "=" operator.
204  *
205  * The original iterator_base instance is destructed.
206  */
207  iterator& operator=(const iterator& o) {
208  iter.reset(o.iter->clone());
209  return *this;
210  }
211 
213  iter.swap(o.iter);
214  return *this;
215  }
216 
217  /**
218  * Overload the "++" operator.
219  *
220  * Increment the iterator_base object that iter is pointing to so that iterator_base object points to
221  * next tuple.
222  *
223  * @return Reference to the iterator object which points to the next tuple in a relation
224  */
225  iterator& operator++() {
226  ++(*iter);
227  return *this;
228  }
229 
230  /**
231  * Overload the "++" operator.
232  *
233  * Copies the iterator, increments itself, and returns the (pre-increment) copy.
234  * WARNING: Expensive due to copy! Included for API compatibility.
235  *
236  * @return Pre-increment copy of `this`.
237  */
238  iterator operator++(int) {
239  auto cpy = *this;
240  ++(*this);
241  return cpy;
242  }
243 
244  /**
245  * Overload the "*" operator.
246  *
247  * This will return the tuple that the iterator is pointing to.
248  *
249  * @return Reference to a tuple object
250  */
251 
252  tuple& operator*() const {
253  return *(*iter);
254  }
255 
256  /**
257  * Overload the "==" operator.
258  *
259  * Check if either the iter of o and the iter of current object are the same or the corresponding
260  * iterator_base objects are the same.
261  *
262  * @param o Reference to a iterator object
263  * @return Boolean. True, if either of them is true. False, otherwise
264  */
265  bool operator==(const iterator& o) const {
266  return (iter == o.iter) || (*iter == *o.iter);
267  }
268 
269  /**
270  * Overload the "!=" operator.
271  *
272  * Check if the iterator object o is not the same as the current object.
273  *
274  * @param o Reference to a iterator object
275  * @return Boolean. True, if they are not the same. False, otherwise
276  */
277  bool operator!=(const iterator& o) const {
278  return !(*this == o);
279  }
280  };
281 
282  /**
283  * Insert a new tuple into the relation.
284  * The definition of insert function has to be defined by the child class of relation class.
285  *
286  * @param t Reference to a tuple class object
287  */
288  virtual void insert(const tuple& t) = 0;
289 
290  /**
291  * Check whether a tuple exists in a relation.
292  * The definition of contains has to be defined by the child class of relation class.
293  *
294  * @param t Reference to a tuple object
295  * @return Boolean. True, if the tuple exists. False, otherwise
296  */
297  virtual bool contains(const tuple& t) const = 0;
298 
299  /**
300  * Return an iterator pointing to the first tuple of the relation.
301  * This iterator is used to access the tuples of the relation.
302  *
303  * @return Iterator
304  */
305  virtual iterator begin() const = 0;
306 
307  /**
308  * Return an iterator pointing to next to the last tuple of the relation.
309  *
310  * @return Iterator
311  */
312  virtual iterator end() const = 0;
313 
314  /**
315  * Get the number of tuples in a relation.
316  *
317  * @return The number of tuples in a relation (std::size_t)
318  */
319  virtual std::size_t size() const = 0;
320 
321  /**
322  * Get the name of a relation.
323  *
324  * @return The name of a relation (std::string)
325  */
326  virtual std::string getName() const = 0;
327 
328  /**
329  * Get the attribute type of a relation at the column specified by the parameter.
330  * The attribute type is in the form "<primitive type>:<type name>".
331  * <primitive type> can be s, f, u, or i standing for symbol, float, unsigned, and integer respectively,
332  * which are the primitive types in Souffle.
333  * <type name> is the name given by the user in the Souffle program
334  *
335  * @param The index of the column starting starting from 0 (size_t)
336  * @return The constant string of the attribute type
337  */
338  virtual const char* getAttrType(size_t) const = 0;
339 
340  /**
341  * Get the attribute name of a relation at the column specified by the parameter.
342  * The attribute name is the name given to the type by the user in the .decl statement. For example, for
343  * ".decl edge (node1:Node, node2:Node)", the attribute names are node1 and node2.
344  *
345  * @param The index of the column starting starting from 0 (size_t)
346  * @return The constant string of the attribute name
347  */
348  virtual const char* getAttrName(size_t) const = 0;
349 
350  /**
351  * Return the arity of a relation.
352  * For example for a tuple (1 2) the arity is 2 and for a tuple (1 2 3) the arity is 3.
353  *
354  * @return Arity of a relation (`arity_type`)
355  */
356  virtual arity_type getArity() const = 0;
357 
358  /**
359  * Return the number of auxiliary attributes. Auxiliary attributes
360  * are used for provenance and and other alternative evaluation
361  * strategies. They are stored as the last attributes of a tuple.
362  *
363  * @return Number of auxiliary attributes of a relation (`arity_type`)
364  */
365  virtual arity_type getAuxiliaryArity() const = 0;
366 
367  /**
368  * Return the number of non-auxiliary attributes.
369  * Auxiliary attributes are used for provenance and and other alternative
370  * evaluation strategies.
371  * They are stored as the last attributes of a tuple.
372  *
373  * @return Number of non-auxiliary attributes of a relation (`arity_type`)
374  */
375  arity_type getPrimaryArity() const {
376  assert(getAuxiliaryArity() <= getArity());
377  return getArity() - getAuxiliaryArity();
378  }
379 
380  /**
381  * Get the symbol table of a relation.
382  * The symbols in a tuple to be stored into a relation are stored and assigned with a number in a table
383  * called symbol table. For example, to insert ("John","Student") to a relation, "John" and "Student" are
384  * stored in symbol table and they are assigned with number say 0 and 1. After this, instead of inserting
385  * ("John","Student"), (0, 1) is inserted. When accessing this tuple, 0 and 1 will be looked up in the
386  * table and replaced by "John" and "Student". This is done so to save memory space if same symbols are
387  * inserted many times. Symbol table has many rows where each row contains a symbol and its corresponding
388  * assigned number.
389  *
390  * @return Reference to a symbolTable object
391  */
392  virtual SymbolTable& getSymbolTable() const = 0;
393 
394  /**
395  * Get the signature of a relation.
396  * The signature is in the form <<primitive type 1>:<type name 1>,<primitive type 2>:<type name 2>...> for
397  * all the attributes in a relation. For example, <s:Node,s:Node>. The primitive type and type name are
398  * explained in getAttrType.
399  *
400  * @return String of the signature of a relation
401  */
402  std::string getSignature() {
403  if (getArity() == 0) {
404  return "<>";
405  }
406 
407  std::string signature = "<" + std::string(getAttrType(0));
408  for (arity_type i = 1; i < getArity(); i++) {
409  signature += "," + std::string(getAttrType(i));
410  }
411  signature += ">";
412  return signature;
413  }
414 
415  /**
416  * Delete all the tuples in relation.
417  *
418  * When purge() is called, it sets the head and tail of the table (table is a
419  * singly-linked list structure) to nullptr, and for every elements
420  * in the table, set the next element pointer points to the current element itself.
421  */
422  virtual void purge() = 0;
423 };
424 
425 /**
426  * Defines a tuple for the OO interface such that
427  * relations with varying columns can be accessed.
428  *
429  * Tuples are stored in relations.
430  * In Souffle, one row of data to be stored into a relation is represented as a tuple.
431  * For example if we have a relation called dog with attributes name, colour and age which are string, string
432  * and interger type respectively. One row of data a relation to be stored can be (mydog, black, 3). However,
433  * this is not directly stored as a tuple. There will be a symbol table storing the actual content and
434  * associate them with numbers (For example, |1|mydog| |2|black| |3|3|). And when this row of data is stored
435  * as a tuple, (1, 2, 3) will be stored.
436  */
437 class tuple {
438  /**
439  * The relation to which the tuple belongs.
440  */
441  const Relation& relation;
442 
443  /**
444  * Dynamic array used to store the elements in a tuple.
445  */
446  std::vector<RamDomain> array;
447 
448  /**
449  * pos shows what the current position of a tuple is.
450  * Initially, pos is 0 meaning we are at the head of the tuple.
451  * If we have an empty tuple and try to insert things, pos lets us know where to insert the element. After
452  * the element is inserted, pos will be incremented by 1. If we have a tuple with content, pos lets us
453  * know where to read the element. After we have read one element, pos will be incremented by 1. pos also
454  * helps to make sure we access an insert a tuple within the bound by making sure pos never exceeds the
455  * arity of the relation.
456  */
457  size_t pos;
458 
459 public:
460  /**
461  * Constructor.
462  *
463  * Tuples are constructed here by passing a relation, then may be subsequently inserted into that same
464  * passed relation. The passed relation pointer will be stored within the tuple instance, while the arity
465  * of the relation will be used to initialize the vector holding the elements of the tuple. Where such an
466  * element is of integer type, it will be stored directly within the vector. Otherwise, if the element is
467  * of a string type, the index of that string within the associated symbol table will be stored instead.
468  * The tuple also stores the index of some "current" element, referred to as its position. The constructor
469  * initially sets this position to the first (zeroth) element of the tuple, while subsequent methods of
470  * this class use that position for element access and modification.
471  *
472  * @param r Relation pointer pointing to a relation
473  */
474  tuple(const Relation* r) : relation(*r), array(r->getArity()), pos(0), data(array.data()) {}
475 
476  /**
477  * Constructor.
478  *
479  * Tuples are constructed here by passing a tuple.
480  * The relation to which the passed tuple belongs to will be stored.
481  * The array of the passed tuple, which stores the elements will be stroed.
482  * The pos will be set to be the same as the pos of passed tuple.
483  * belongs to.
484  *
485  * @param Reference to a tuple object.
486  */
487  tuple(const tuple& t) : relation(t.relation), array(t.array), pos(t.pos), data(array.data()) {}
488 
489  /**
490  * Allows printing using WriteStream.
491  */
492  const RamDomain* data = nullptr;
493 
494  /**
495  * Get the reference to the relation to which the tuple belongs.
496  *
497  * @return Reference to a relation.
498  */
499  const Relation& getRelation() const {
500  return relation;
501  }
502 
503  /**
504  * Return the number of elements in the tuple.
505  *
506  * @return the number of elements in the tuple (size_t).
507  */
508  Relation::arity_type size() const {
509  assert(array.size() <= std::numeric_limits<Relation::arity_type>::max());
510  return Relation::arity_type(array.size());
511  }
512 
513  /**
514  * Overload the operator [].
515  *
516  * Direct access to tuple elements via index and
517  * return the element in idx position of a tuple.
518  *
519  * TODO (Honghyw) : This interface should be hidden and
520  * only be used by friendly classes such as
521  * iterators; users should not use this interface.
522  *
523  * @param idx This is the idx of element in a tuple (size_t).
524  */
525  RamDomain& operator[](size_t idx) {
526  return array[idx];
527  }
528 
529  /**
530  * Overload the operator [].
531  *
532  * Direct access to tuple elements via index and
533  * Return the element in idx position of a tuple. The returned element can not be changed.
534  *
535  * TODO (Honghyw) : This interface should be hidden and
536  * only be used by friendly classes such as
537  * iterators; users should not use this interface.
538  *
539  * @param idx This is the idx of element in a tuple (size_t).
540  */
541  const RamDomain& operator[](size_t idx) const {
542  return array[idx];
543  }
544 
545  /**
546  * Reset the index giving the "current element" of the tuple to zero.
547  */
548  void rewind() {
549  pos = 0;
550  }
551 
552  /**
553  * Set the "current element" of the tuple to the given string, then increment the index giving the current
554  * element.
555  *
556  * @param str Symbol to be added (std::string)
557  * @return Reference to the tuple
558  */
559  tuple& operator<<(const std::string& str) {
560  assert(pos < size() && "exceeded tuple's size");
561  assert(*relation.getAttrType(pos) == 's' && "wrong element type");
563  return *this;
564  }
565 
566  /**
567  * Set the "current element" of the tuple to the given int, then increment the index giving the current
568  * element.
569  *
570  * @param integer Integer to be added
571  * @return Reference to the tuple
572  */
573  tuple& operator<<(RamSigned integer) {
574  assert(pos < size() && "exceeded tuple's size");
575  assert((*relation.getAttrType(pos) == 'i' || *relation.getAttrType(pos) == 'r') &&
576  "wrong element type");
577  array[pos++] = integer;
578  return *this;
579  }
580 
581  /**
582  * Set the "current element" of the tuple to the given uint, then increment the index giving the current
583  * element.
584  *
585  * @param uint Unsigned number to be added
586  * @return Reference to the tuple
587  */
588  tuple& operator<<(RamUnsigned uint) {
589  assert(pos < size() && "exceeded tuple's size");
590  assert((*relation.getAttrType(pos) == 'u') && "wrong element type");
591  array[pos++] = ramBitCast(uint);
592  return *this;
593  }
594 
595  /**
596  * Set the "current element" of the tuple to the given float, then increment the index giving the current
597  * element.
598  *
599  * @param float float to be added
600  * @return Reference to the tuple
601  */
602  tuple& operator<<(RamFloat ramFloat) {
603  assert(pos < size() && "exceeded tuple's size");
604  assert((*relation.getAttrType(pos) == 'f') && "wrong element type");
605  array[pos++] = ramBitCast(ramFloat);
606  return *this;
607  }
608 
609  /**
610  * Get the "current element" of the tuple as a string, then increment the index giving the current
611  * element.
612  *
613  * @param str Symbol to be loaded from the tuple(std::string)
614  * @return Reference to the tuple
615  */
616  tuple& operator>>(std::string& str) {
617  assert(pos < size() && "exceeded tuple's size");
618  assert(*relation.getAttrType(pos) == 's' && "wrong element type");
620  return *this;
621  }
622 
623  /**
624  * Get the "current element" of the tuple as a int, then increment the index giving the current
625  * element.
626  *
627  * @param integer Integer to be loaded from the tuple
628  * @return Reference to the tuple
629  */
630  tuple& operator>>(RamSigned& integer) {
631  assert(pos < size() && "exceeded tuple's size");
632  assert((*relation.getAttrType(pos) == 'i' || *relation.getAttrType(pos) == 'r') &&
633  "wrong element type");
634  integer = ramBitCast<RamSigned>(array[pos++]);
635  return *this;
636  }
637 
638  /**
639  * Get the "current element" of the tuple as a unsigned, then increment the index giving the current
640  * element.
641  *
642  * @param uint Unsigned number to be loaded from the tuple
643  * @return Reference to the tuple
644  */
645  tuple& operator>>(RamUnsigned& uint) {
646  assert(pos < size() && "exceeded tuple's size");
647  assert((*relation.getAttrType(pos) == 'u') && "wrong element type");
648  uint = ramBitCast<RamUnsigned>(array[pos++]);
649  return *this;
650  }
651 
652  /**
653  * Get the "current element" of the tuple as a float, then increment the index giving the current
654  * element.
655  *
656  * @param ramFloat Float to be loaded from the tuple
657  * @return Reference to the tuple
658  */
659  tuple& operator>>(RamFloat& ramFloat) {
660  assert(pos < size() && "exceeded tuple's size");
661  assert((*relation.getAttrType(pos) == 'f') && "wrong element type");
662  ramFloat = ramBitCast<RamFloat>(array[pos++]);
663  return *this;
664  }
665 
666  /**
667  * Iterator for direct access to tuple's data.
668  *
669  * @see Relation::iteraor::begin()
670  */
671  decltype(array)::iterator begin() {
672  return array.begin();
673  }
674 
675  /**
676  * Construct using initialisation list.
677  */
678  tuple(const Relation* relation, std::initializer_list<RamDomain> tupleList)
679  : relation(*relation), array(tupleList), pos(tupleList.size()), data(array.data()) {
680  assert(tupleList.size() == relation->getArity() && "tuple arity does not match relation arity");
681  }
682 };
683 
684 /**
685  * Abstract base class for generated Datalog programs.
686  */
687 class SouffleProgram {
688 private:
689  /**
690  * Define a relation map for external access, when getRelation(name) is called,
691  * the relation with the given name will be returned from this map,
692  * relationMap stores all the relations in a map with its name
693  * as the key and relation as the value.
694  */
695  std::map<std::string, Relation*> relationMap;
696 
697  /**
698  * inputRelations stores all the input relation in a vector.
699  */
700  std::vector<Relation*> inputRelations;
701 
702  /**
703  * outputRelations stores all the output relation in a vector.
704  */
705  std::vector<Relation*> outputRelations;
706 
707  /**
708  * internalRelation stores all the relation in a vector that are neither an input or an output.
709  */
710  std::vector<Relation*> internalRelations;
711 
712  /**
713  * allRelations store all the relation in a vector.
714  */
715  std::vector<Relation*> allRelations;
716  /**
717  * The number of threads used by OpenMP
718  */
719  std::size_t numThreads = 1;
720 
721 protected:
722  /**
723  * Add the relation to relationMap (with its name) and allRelations,
724  * depends on the properties of the relation, if the relation is an input relation, it will be added to
725  * inputRelations, else if the relation is an output relation, it will be added to outputRelations,
726  * otherwise will add to internalRelations. (a relation could be both input and output at the same time.)
727  *
728  * @param name the name of the relation (std::string)
729  * @param rel a reference to the relation
730  * @param isInput a bool argument, true if the relation is a input relation, else false (bool)
731  * @param isOnput a bool argument, true if the relation is a ouput relation, else false (bool)
732  */
733  void addRelation(const std::string& name, Relation& rel, bool isInput, bool isOutput) {
734  relationMap[name] = &rel;
735  allRelations.push_back(&rel);
736  if (isInput) {
737  inputRelations.push_back(&rel);
738  }
739  if (isOutput) {
740  outputRelations.push_back(&rel);
741  }
742  if (!isInput && !isOutput) {
743  internalRelations.push_back(&rel);
744  }
745  }
746 
747  [[deprecated("pass `rel` by reference; `rel` may not be null"), maybe_unused]] void addRelation(
748  const std::string& name, Relation* rel, bool isInput, bool isOutput) {
749  assert(rel && "`rel` may not be null");
750  addRelation(name, *rel, isInput, isOutput);
751  }
752 
753 public:
754  /**
755  * Destructor.
756  *
757  * Destructor of SouffleProgram.
758  */
759  virtual ~SouffleProgram() = default;
760 
761  /**
762  * Execute the souffle program, without any loads or stores.
763  */
764  virtual void run() {}
765 
766  /**
767  * Execute program, loading inputs and storing outputs as required.
768  * File IO types can use the given directories to find their input file.
769  *
770  * @param inputDirectory If non-empty, specifies the input directory
771  * @param outputDirectory If non-empty, specifies the output directory
772  */
773  virtual void runAll(std::string inputDirectory = "", std::string outputDirectory = "") = 0;
774 
775  /**
776  * Read all input relations.
777  *
778  * File IO types can use the given directory to find their input file.
779  * @param inputDirectory If non-empty, specifies the input directory
780  */
781  virtual void loadAll(std::string inputDirectory = "") = 0;
782 
783  /**
784  * Store all output relations.
785  *
786  * File IO types can use the given directory to find their input file.
787  * @param outputDirectory If non-empty, specifies the output directory
788  */
789  virtual void printAll(std::string outputDirectory = "") = 0;
790 
791  /**
792  * Output all the input relations in stdout, without generating any files. (for debug purposes).
793  */
794  virtual void dumpInputs() = 0;
795 
796  /**
797  * Output all the output relations in stdout, without generating any files. (for debug purposes).
798  */
799  virtual void dumpOutputs() = 0;
800 
801  /**
802  * Set the number of threads to be used
803  */
804  void setNumThreads(std::size_t numThreadsValue) {
805  this->numThreads = numThreadsValue;
806  }
807 
808  /**
809  * Get the number of threads to be used
810  */
811  std::size_t getNumThreads() {
812  return numThreads;
813  }
814 
815  /**
816  * Get Relation by its name from relationMap, if relation not found, return a nullptr.
817  *
818  * @param name The name of the target relation (const std::string)
819  * @return The pointer of the target relation, or null pointer if the relation not found (Relation*)
820  */
821  Relation* getRelation(const std::string& name) const {
822  auto it = relationMap.find(name);
823  if (it != relationMap.end()) {
824  return (*it).second;
825  } else {
826  return nullptr;
827  }
828  };
829 
830  /**
831  * Return the size of the target relation from relationMap.
832  *
833  * @param name The name of the target relation (const std::string)
834  * @return The size of the target relation (std::size_t)
835  */
836  std::size_t getRelationSize(const std::string& name) const {
837  return getRelation(name)->size();
838  }
839 
840  /**
841  * Return the name of the target relation from relationMap.
842  *
843  * @param name The name of the target relation (const std::string)
844  * @return The name of the target relation (std::string)
845  */
846  std::string getRelationName(const std::string& name) const {
847  return getRelation(name)->getName();
848  }
849 
850  /**
851  * Getter of outputRelations, which this vector structure contains all output relations.
852  *
853  * @return outputRelations (std::vector)
854  * @see outputRelations
855  */
856  std::vector<Relation*> getOutputRelations() const {
857  return outputRelations;
858  }
859 
860  /**
861  * Getter of inputRelations, which this vector structure contains all input relations.
862  *
863  * @return intputRelations (std::vector)
864  * @see inputRelations
865  */
866  std::vector<Relation*> getInputRelations() const {
867  return inputRelations;
868  }
869 
870  /**
871  * Getter of internalRelations, which this vector structure contains all relations
872  * that are neither an input relation or an output relation.
873  *
874  * @return internalRelations (std::vector)
875  * @see internalRelations
876  */
877  std::vector<Relation*> getInternalRelations() const {
878  return internalRelations;
879  }
880 
881  /**
882  * Getter of allRelations, which this vector structure contains all relations.
883  *
884  * @return allRelations (std::vector)
885  * @see allRelations
886  */
887  std::vector<Relation*> getAllRelations() const {
888  return allRelations;
889  }
890 
891  /**
892  * Execute a subroutine
893  * @param name Name of a subroutine (std:string)
894  * @param arg Arguments of the subroutine (std::vector<RamDomain>&)
895  * @param ret Return values of the subroutine (std::vector<RamDomain>&)
896  */
897  virtual void executeSubroutine(std::string /* name */, const std::vector<RamDomain>& /* args */,
898  std::vector<RamDomain>& /* ret */) {
899  fatal("unknown subroutine");
900  }
901 
902  /**
903  * Get the symbol table of the program.
904  */
905  virtual SymbolTable& getSymbolTable() = 0;
906 
907  /**
908  * Get the record table of the program.
909  */
910  virtual RecordTable& getRecordTable() = 0;
911 
912  /**
913  * Remove all the tuples from the outputRelations, calling the purge method of each.
914  *
915  * @see Relation::purge()
916  */
917  void purgeOutputRelations() {
919  relation->purge();
920  }
921  }
922 
923  /**
924  * Remove all the tuples from the inputRelations, calling the purge method of each.
925  *
926  * @see Relation::purge()
927  */
928  void purgeInputRelations() {
929  for (Relation* relation : inputRelations) {
930  relation->purge();
931  }
932  }
933 
934  /**
935  * Remove all the tuples from the internalRelations, calling the purge method of each.
936  *
937  * @see Relation::purge()
938  */
939  void purgeInternalRelations() {
941  relation->purge();
942  }
943  }
944 
945  /**
946  * Helper function for the wrapper function Relation::insert() and Relation::contains().
947  */
948  template <typename Tuple, size_t N>
949  struct tuple_insert {
950  static void add(const Tuple& t, souffle::tuple& t1) {
952  t1 << std::get<N - 1>(t);
953  }
954  };
955 
956  /**
957  * Helper function for the wrapper function Relation::insert() and Relation::contains() for the
958  * first element of the tuple.
959  */
960  template <typename Tuple>
961  struct tuple_insert<Tuple, 1> {
962  static void add(const Tuple& t, souffle::tuple& t1) {
963  t1 << std::get<0>(t);
964  }
965  };
966 
967  /**
968  * Insert function with std::tuple as input (wrapper)
969  *
970  * @param t The insert tuple (std::tuple)
971  * @param relation The relation that perform insert operation (Relation*)
972  * @see Relation::insert()
973  */
974  template <typename... Args>
975  void insert(const std::tuple<Args...>& t, Relation* relation) {
976  tuple t1(relation);
977  tuple_insert<decltype(t), sizeof...(Args)>::add(t, t1);
978  relation->insert(t1);
979  }
980 
981  /**
982  * Contains function with std::tuple as input (wrapper)
983  *
984  * @param t The existence searching tuple (std::tuple)
985  * @param relation The relation that perform contains operation (Relation*)
986  * @return A boolean value, return true if the tuple found, otherwise return false
987  * @see Relation::contains()
988  */
989  template <typename... Args>
990  bool contains(const std::tuple<Args...>& t, Relation* relation) {
991  tuple t1(relation);
992  tuple_insert<decltype(t), sizeof...(Args)>::add(t, t1);
993  return relation->contains(t1);
994  }
995 };
996 
997 /**
998  * Abstract program factory class.
999  */
1000 class ProgramFactory {
1001 protected:
1002  /**
1003  * Singly linked-list to store all program factories
1004  * Note that STL data-structures are not possible due
1005  * to "static initialization order fiasco (problem)".
1006  * (The problem of the order static objects get initialized, causing effect
1007  * such as program access static variables before they initialized.)
1008  * The static container needs to be a primitive type such as pointer
1009  * set to NULL.
1010  * Link to next factory.
1011  */
1012  ProgramFactory* link = nullptr;
1013 
1014  /**
1015  * The name of factory.
1016  */
1017  std::string name;
1019 protected:
1020  /**
1021  * Constructor.
1022  *
1023  * Constructor adds factory to static singly-linked list
1024  * for registration.
1025  */
1026  ProgramFactory(std::string name) : name(std::move(name)) {
1027  registerFactory(this);
1028  }
1029 
1030 private:
1031  /**
1032  * Helper method for creating a factory map, which map key is the name of the program factory, map value
1033  * is the pointer of the ProgramFactory.
1034  *
1035  * TODO (NubKel) : Improve documentation of use and interaction between inline and static, here and for
1036  * the whole class.
1037  *
1038  * @return The factory registration map (std::map)
1039  */
1040  static inline std::map<std::string, ProgramFactory*>& getFactoryRegistry() {
1041  static std::map<std::string, ProgramFactory*> factoryReg;
1042  return factoryReg;
1043  }
1044 
1045 protected:
1046  /**
1047  * Create and insert a factory into the factoryReg map.
1048  *
1049  * @param factory Pointer of the program factory (ProgramFactory*)
1050  */
1051  static inline void registerFactory(ProgramFactory* factory) {
1052  auto& entry = getFactoryRegistry()[factory->name];
1053  assert(!entry && "double-linked/defined souffle analyis");
1054  entry = factory;
1055  }
1056 
1057  /**
1058  * Find a factory by its name, return the fatory if found, return nullptr if the
1059  * factory not found.
1060  *
1061  * @param factoryName The factory name (const std::string)
1062  * @return The pointer of the target program factory, or null pointer if the program factory not found
1063  * (ProgramFactory*)
1064  */
1065  static inline ProgramFactory* find(const std::string& factoryName) {
1066  const auto& reg = getFactoryRegistry();
1067  auto pos = reg.find(factoryName);
1068  return (pos == reg.end()) ? nullptr : pos->second;
1069  }
1070 
1071  /**
1072  * Create new instance (abstract).
1073  */
1074  virtual SouffleProgram* newInstance() = 0;
1075 
1076 public:
1077  /**
1078  * Destructor.
1079  *
1080  * Destructor of ProgramFactory.
1081  */
1082  virtual ~ProgramFactory() = default;
1083 
1084  /**
1085  * Create an instance by finding the name of the program factory, return nullptr if the instance not
1086  * found.
1087  *
1088  * @param name Instance name (const std::string)
1089  * @return The new instance(SouffleProgram*), or null pointer if the instance not found
1090  */
1091  static SouffleProgram* newInstance(const std::string& name) {
1092  ProgramFactory* factory = find(name);
1093  if (factory != nullptr) {
1094  return factory->newInstance();
1095  } else {
1096  return nullptr;
1097  }
1098  }
1099 };
1100 } // namespace souffle
souffle::ProgramFactory::link
ProgramFactory * link
Singly linked-list to store all program factories Note that STL data-structures are not possible due ...
Definition: SouffleInterface.h:1018
souffle::SouffleProgram::contains
bool contains(const std::tuple< Args... > &t, Relation *relation)
Contains function with std::tuple as input (wrapper)
Definition: SouffleInterface.h:996
souffle::RamUnsigned
uint32_t RamUnsigned
Definition: RamTypes.h:58
souffle::SouffleProgram::~SouffleProgram
virtual ~SouffleProgram()=default
Destructor.
souffle::Relation::iterator
Wrapper class for abstract iterator.
Definition: SouffleInterface.h:158
souffle::SouffleProgram::purgeOutputRelations
void purgeOutputRelations()
Remove all the tuples from the outputRelations, calling the purge method of each.
Definition: SouffleInterface.h:923
souffle::Relation::iterator_base::~iterator_base
virtual ~iterator_base()=default
Destructor.
souffle::Relation::iterator_base::clone
virtual iterator_base * clone() const =0
Clone the iterator_base.
souffle::SouffleProgram::getInternalRelations
std::vector< Relation * > getInternalRelations() const
Getter of internalRelations, which this vector structure contains all relations that are neither an i...
Definition: SouffleInterface.h:883
souffle::ProgramFactory::newInstance
virtual SouffleProgram * newInstance()=0
Create new instance (abstract).
souffle::Relation::getAttrType
virtual const char * getAttrType(size_t) const =0
Get the attribute type of a relation at the column specified by the parameter.
souffle::tuple::tuple
tuple(const Relation *r)
Constructor.
Definition: SouffleInterface.h:480
souffle::SouffleProgram::runAll
virtual void runAll(std::string inputDirectory="", std::string outputDirectory="")=0
Execute program, loading inputs and storing outputs as required.
souffle::SymbolTable::resolve
const std::string & resolve(const RamDomain index) const
Find a symbol in the table by its index, note that this gives an error if the index is out of bounds.
Definition: SymbolTable.h:154
souffle::ProgramFactory::name
std::string name
The name of factory.
Definition: SouffleInterface.h:1023
souffle::RamDomain
int32_t RamDomain
Definition: RamTypes.h:56
souffle::Relation::iterator::operator++
iterator & operator++()
Overload the "++" operator.
Definition: SouffleInterface.h:231
souffle::ProgramFactory::find
static ProgramFactory * find(const std::string &factoryName)
Find a factory by its name, return the fatory if found, return nullptr if the factory not found.
Definition: SouffleInterface.h:1071
souffle::tuple::operator<<
tuple & operator<<(const std::string &str)
Set the "current element" of the tuple to the given string, then increment the index giving the curre...
Definition: SouffleInterface.h:565
souffle::id
A functor representing the identity function for a generic type T.
Definition: StreamUtil.h:136
souffle::ProgramFactory::registerFactory
static void registerFactory(ProgramFactory *factory)
Create and insert a factory into the factoryReg map.
Definition: SouffleInterface.h:1057
SymbolTable.h
souffle::tuple::relation
const Relation & relation
The relation to which the tuple belongs.
Definition: SouffleInterface.h:447
souffle::Relation::iterator::operator!=
bool operator!=(const iterator &o) const
Overload the "!=" operator.
Definition: SouffleInterface.h:283
souffle::RecordTable
Definition: RecordTable.h:114
souffle::Relation::iterator::iterator
iterator()=default
Constructor.
souffle::SouffleProgram::setNumThreads
void setNumThreads(std::size_t numThreadsValue)
Set the number of threads to be used.
Definition: SouffleInterface.h:810
relation
Relation & relation
Definition: Reader.h:130
souffle::RamFloat
float RamFloat
Definition: RamTypes.h:60
MiscUtil.h
souffle::SouffleProgram::outputRelations
std::vector< Relation * > outputRelations
outputRelations stores all the output relation in a vector.
Definition: SouffleInterface.h:711
souffle::Relation::insert
virtual void insert(const tuple &t)=0
Insert a new tuple into the relation.
souffle::Relation::iterator_base::equal
virtual bool equal(const iterator_base &o) const =0
Check if the passed-in object of o is the the same as the current iterator_base.
souffle::SouffleProgram::getRelationSize
std::size_t getRelationSize(const std::string &name) const
Return the size of the target relation from relationMap.
Definition: SouffleInterface.h:842
souffle::tuple::pos
size_t pos
pos shows what the current position of a tuple is.
Definition: SouffleInterface.h:463
souffle::Relation::contains
virtual bool contains(const tuple &t) const =0
Check whether a tuple exists in a relation.
souffle::Relation::iterator_base
Abstract iterator class.
Definition: SouffleInterface.h:64
souffle::ProgramFactory::~ProgramFactory
virtual ~ProgramFactory()=default
Destructor.
str
const std::string & str
Definition: json11.h:662
souffle::Relation::iterator::operator*
tuple & operator*() const
Overload the "*" operator.
Definition: SouffleInterface.h:258
array
souffle::SymbolTable::lookup
RamDomain lookup(const std::string &symbol)
Find the index of a symbol in the table, inserting a new symbol if it does not exist there already.
Definition: SymbolTable.h:124
souffle::Relation
Object-oriented wrapper class for Souffle's templatized relations.
Definition: SouffleInterface.h:49
souffle::SouffleProgram::printAll
virtual void printAll(std::string outputDirectory="")=0
Store all output relations.
souffle::clone
auto clone(const std::vector< A * > &xs)
Definition: ContainerUtil.h:172
souffle::SouffleProgram
Abstract base class for generated Datalog programs.
Definition: SouffleInterface.h:693
souffle::tuple::getRelation
const Relation & getRelation() const
Get the reference to the relation to which the tuple belongs.
Definition: SouffleInterface.h:505
i
size_t i
Definition: json11.h:663
souffle::SouffleProgram::run
virtual void run()
Execute the souffle program, without any loads or stores.
Definition: SouffleInterface.h:770
souffle::SouffleProgram::allRelations
std::vector< Relation * > allRelations
allRelations store all the relation in a vector.
Definition: SouffleInterface.h:721
souffle::SouffleProgram::getRecordTable
virtual RecordTable & getRecordTable()=0
Get the record table of the program.
souffle::ProgramFactory::getFactoryRegistry
static std::map< std::string, ProgramFactory * > & getFactoryRegistry()
Helper method for creating a factory map, which map key is the name of the program factory,...
Definition: SouffleInterface.h:1046
souffle::tuple::data
const RamDomain * data
Allows printing using WriteStream.
Definition: SouffleInterface.h:498
souffle::Relation::iterator_base::operator*
virtual tuple & operator*()=0
Overload the "*" operator.
o
var o
Definition: htmlJsChartistMin.h:15
souffle::Relation::getPrimaryArity
arity_type getPrimaryArity() const
Return the number of non-auxiliary attributes.
Definition: SouffleInterface.h:381
souffle::SouffleProgram::internalRelations
std::vector< Relation * > internalRelations
internalRelation stores all the relation in a vector that are neither an input or an output.
Definition: SouffleInterface.h:716
souffle::SymbolTable
Definition: SymbolTable.h:48
souffle::SouffleProgram::getOutputRelations
std::vector< Relation * > getOutputRelations() const
Getter of outputRelations, which this vector structure contains all output relations.
Definition: SouffleInterface.h:862
souffle::SouffleProgram::dumpOutputs
virtual void dumpOutputs()=0
Output all the output relations in stdout, without generating any files.
souffle::SouffleProgram::getRelationName
std::string getRelationName(const std::string &name) const
Return the name of the target relation from relationMap.
Definition: SouffleInterface.h:852
souffle::SouffleProgram::numThreads
std::size_t numThreads
The number of threads used by OpenMP.
Definition: SouffleInterface.h:725
TCB_SPAN_NAMESPACE_NAME::get
constexpr auto get(span< E, S > s) -> decltype(s[N])
Definition: span.h:599
souffle::SouffleProgram::getInputRelations
std::vector< Relation * > getInputRelations() const
Getter of inputRelations, which this vector structure contains all input relations.
Definition: SouffleInterface.h:872
souffle::Relation::iterator_base::operator==
bool operator==(const iterator_base &o) const
Overload the "==" operator.
Definition: SouffleInterface.h:123
souffle::Relation::iterator::~iterator
~iterator()=default
Destructor.
souffle::SouffleProgram::tuple_insert::add
static void add(const Tuple &t, souffle::tuple &t1)
Definition: SouffleInterface.h:956
souffle::SouffleProgram::addRelation
void addRelation(const std::string &name, Relation &rel, bool isInput, bool isOutput)
Add the relation to relationMap (with its name) and allRelations, depends on the properties of the re...
Definition: SouffleInterface.h:739
souffle::Tuple
std::array< A, N > Tuple
Definition: RamTypes.h:36
souffle::Relation::iterator_base::operator++
virtual void operator++()=0
Overload the "++" operator.
souffle::SouffleProgram::getAllRelations
std::vector< Relation * > getAllRelations() const
Getter of allRelations, which this vector structure contains all relations.
Definition: SouffleInterface.h:893
RecordTable.h
souffle::Relation::iterator::operator=
iterator & operator=(const iterator &o)
Overload the "=" operator.
Definition: SouffleInterface.h:213
souffle::Relation::end
virtual iterator end() const =0
Return an iterator pointing to next to the last tuple of the relation.
souffle::Relation::~Relation
virtual ~Relation()=default
Destructor.
souffle::SouffleProgram::insert
void insert(const std::tuple< Args... > &t, Relation *relation)
Insert function with std::tuple as input (wrapper)
Definition: SouffleInterface.h:981
souffle::Relation::getSignature
std::string getSignature()
Get the signature of a relation.
Definition: SouffleInterface.h:408
souffle::SouffleProgram::dumpInputs
virtual void dumpInputs()=0
Output all the input relations in stdout, without generating any files.
souffle::Relation::getName
virtual std::string getName() const =0
Get the name of a relation.
souffle::Relation::begin
virtual iterator begin() const =0
Return an iterator pointing to the first tuple of the relation.
souffle::SouffleProgram::relationMap
std::map< std::string, Relation * > relationMap
Define a relation map for external access, when getRelation(name) is called, the relation with the gi...
Definition: SouffleInterface.h:701
souffle::tuple::size
Relation::arity_type size() const
Return the number of elements in the tuple.
Definition: SouffleInterface.h:514
souffle::Relation::getAuxiliaryArity
virtual arity_type getAuxiliaryArity() const =0
Return the number of auxiliary attributes.
souffle::Relation::size
virtual std::size_t size() const =0
Get the number of tuples in a relation.
souffle::Relation::purge
virtual void purge()=0
Delete all the tuples in relation.
souffle::SouffleProgram::executeSubroutine
virtual void executeSubroutine(std::string, const std::vector< RamDomain > &, std::vector< RamDomain > &)
Execute a subroutine.
Definition: SouffleInterface.h:903
souffle::Relation::iterator_base::iterator_base
iterator_base(uint32_t arg_id)
Constructor.
Definition: SouffleInterface.h:91
souffle::tuple::operator[]
RamDomain & operator[](size_t idx)
Overload the operator [].
Definition: SouffleInterface.h:531
souffle::SouffleProgram::getRelation
Relation * getRelation(const std::string &name) const
Get Relation by its name from relationMap, if relation not found, return a nullptr.
Definition: SouffleInterface.h:827
souffle::ProgramFactory
Abstract program factory class.
Definition: SouffleInterface.h:1006
souffle::SouffleProgram::inputRelations
std::vector< Relation * > inputRelations
inputRelations stores all the input relation in a vector.
Definition: SouffleInterface.h:706
std
Definition: Brie.h:3053
souffle::Relation::iterator::iter
std::unique_ptr< iterator_base > iter
Definition: SouffleInterface.h:164
souffle::Relation::getArity
virtual arity_type getArity() const =0
Return the arity of a relation.
RamTypes.h
souffle::tuple::operator>>
tuple & operator>>(std::string &str)
Get the "current element" of the tuple as a string, then increment the index giving the current eleme...
Definition: SouffleInterface.h:622
souffle::fatal
void fatal(const char *format, const Args &... args)
Definition: MiscUtil.h:198
souffle::SouffleProgram::loadAll
virtual void loadAll(std::string inputDirectory="")=0
Read all input relations.
souffle
Definition: AggregateOp.h:25
souffle::ramBitCast
To ramBitCast(From source)
In C++20 there will be a new way to cast between types by reinterpreting bits (std::bit_cast),...
Definition: RamTypes.h:87
souffle::tuple::rewind
void rewind()
Reset the index giving the "current element" of the tuple to zero.
Definition: SouffleInterface.h:554
souffle::RamSigned
RamDomain RamSigned
Definition: RamTypes.h:57
souffle::SouffleProgram::purgeInputRelations
void purgeInputRelations()
Remove all the tuples from the inputRelations, calling the purge method of each.
Definition: SouffleInterface.h:934
souffle::Relation::arity_type
uint32_t arity_type
Definition: SouffleInterface.h:51
souffle::tuple::array
std::vector< RamDomain > array
Dynamic array used to store the elements in a tuple.
Definition: SouffleInterface.h:452
souffle::Relation::iterator::operator==
bool operator==(const iterator &o) const
Overload the "==" operator.
Definition: SouffleInterface.h:271
souffle::Relation::iterator_base::id
uint32_t id
Required for identifying type of iterator (NB: LLVM has no typeinfo).
Definition: SouffleInterface.h:72
rel
void rel(size_t limit, bool showLimit=true)
Definition: Tui.h:1086
souffle::Relation::getAttrName
virtual const char * getAttrName(size_t) const =0
Get the attribute name of a relation at the column specified by the parameter.
souffle::tuple
Defines a tuple for the OO interface such that relations with varying columns can be accessed.
Definition: SouffleInterface.h:443
souffle::SouffleProgram::tuple_insert
Helper function for the wrapper function Relation::insert() and Relation::contains().
Definition: SouffleInterface.h:955
souffle::tuple::begin
decltype(array) ::iterator begin()
Iterator for direct access to tuple's data.
Definition: SouffleInterface.h:677
souffle::Relation::iterator_base::getId
virtual uint32_t getId() const
Get the ID of the iterator_base object.
Definition: SouffleInterface.h:80
souffle::Relation::getSymbolTable
virtual SymbolTable & getSymbolTable() const =0
Get the symbol table of a relation.
souffle::SouffleProgram::purgeInternalRelations
void purgeInternalRelations()
Remove all the tuples from the internalRelations, calling the purge method of each.
Definition: SouffleInterface.h:945
souffle::SouffleProgram::getNumThreads
std::size_t getNumThreads()
Get the number of threads to be used.
Definition: SouffleInterface.h:817
souffle::SouffleProgram::getSymbolTable
virtual SymbolTable & getSymbolTable()=0
Get the symbol table of the program.
souffle::ProgramFactory::ProgramFactory
ProgramFactory(std::string name)
Constructor.
Definition: SouffleInterface.h:1032