souffle  2.0.2-371-g6315b36
ExplainTree.h
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2017, The Souffle Developers. 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 ExplainTree.h
12  *
13  * Classes for storing a derivation tree
14  *
15  ***********************************************************************/
16 
17 #pragma once
18 
21 #include <algorithm>
22 #include <cassert>
23 #include <cstdint>
24 #include <cstring>
25 #include <memory>
26 #include <sstream>
27 #include <string>
28 #include <utility>
29 #include <vector>
30 
31 namespace souffle {
32 
33 class ScreenBuffer {
34 public:
35  // constructor
36  ScreenBuffer(uint32_t w, uint32_t h) : width(w), height(h), buffer(nullptr) {
37  assert(width > 0 && height > 0 && "wrong dimensions");
38  buffer = new char[width * height];
39  memset(buffer, ' ', width * height);
40  }
41 
42  ~ScreenBuffer() {
43  delete[] buffer;
44  }
45 
46  // write into screen buffer at a specific location
47  void write(uint32_t x, uint32_t y, const std::string& s) {
48  assert(x < width && "wrong x dimension");
49  assert(y < height && "wrong y dimension");
50  assert(x + s.length() <= width && "string too long");
51  for (size_t i = 0; i < s.length(); i++) {
52  buffer[y * width + x + i] = s[i];
53  }
54  }
55 
56  std::string getString() {
57  std::stringstream ss;
58  print(ss);
59  return ss.str();
60  }
61 
62  // print screen buffer
63  void print(std::ostream& os) {
64  if (height > 0 && width > 0) {
65  for (int i = height - 1; i >= 0; i--) {
66  for (size_t j = 0; j < width; j++) {
67  os << buffer[width * i + j];
68  }
69  os << std::endl;
70  }
71  }
72  }
73 
74 private:
75  uint32_t width; // width of the screen buffer
76  uint32_t height; // height of the screen buffer
77  char* buffer; // screen contents
78 };
79 
80 /***
81  * Abstract Class for a Proof Tree Node
82  *
83  */
84 class TreeNode {
85 public:
86  TreeNode(std::string t = "") : txt(std::move(t)) {}
87  virtual ~TreeNode() = default;
88 
89  // get width
90  uint32_t getWidth() const {
91  return width;
92  }
93 
94  // get height
95  uint32_t getHeight() const {
96  return height;
97  }
98 
99  // place the node
100  virtual void place(uint32_t xpos, uint32_t ypos) = 0;
101 
102  // render node in screen buffer
103  virtual void render(ScreenBuffer& s) = 0;
104 
105  size_t getSize() {
106  return size;
107  }
108 
109  void setSize(size_t s) {
110  size = s;
111  }
112 
113  virtual void printJSON(std::ostream& os, int pos) = 0;
114 
115 protected:
116  std::string txt; // text of tree node
117  uint32_t width = 0; // width of node (including sub-trees)
118  uint32_t height = 0; // height of node (including sub-trees)
119  int xpos = 0; // x-position of text
120  int ypos = 0; // y-position of text
121  uint32_t size = 0;
122 };
123 
124 /***
125  * Concrete class
126  */
127 class InnerNode : public TreeNode {
128 public:
129  InnerNode(const std::string& nodeText = "", std::string label = "")
130  : TreeNode(nodeText), label(std::move(label)) {}
131 
132  // add child to node
133  void add_child(Own<TreeNode> child) {
134  children.push_back(std::move(child));
135  }
136 
137  // place node and its sub-trees
138  void place(uint32_t x, uint32_t y) override {
139  // there must exist at least one kid
140  assert(!children.empty() && "no children");
141 
142  // set x/y pos
143  xpos = x;
144  ypos = y;
145 
146  height = 0;
147 
148  // compute size of bounding box
149  for (const Own<TreeNode>& k : children) {
150  k->place(x, y + 2);
151  x += k->getWidth() + 1;
152  width += k->getWidth() + 1;
153  height = std::max(height, k->getHeight());
154  }
155  height += 2;
156 
157  // text of inner node is longer than all its sub-trees
158  if (width < txt.length()) {
159  width = txt.length();
160  }
161  };
162 
163  // render node text and separator line
164  void render(ScreenBuffer& s) override {
165  s.write(xpos + (width - txt.length()) / 2, ypos, txt);
166  for (const Own<TreeNode>& k : children) {
167  k->render(s);
168  }
169  std::string separator(width - label.length(), '-');
170  separator += label;
171  s.write(xpos, ypos + 1, separator);
172  }
173 
174  // print JSON
175  void printJSON(std::ostream& os, int pos) override {
176  std::string tab(pos, '\t');
177  os << tab << R"({ "premises": ")" << stringify(txt) << "\",\n";
178  os << tab << R"( "rule-number": ")" << label << "\",\n";
179  os << tab << " \"children\": [\n";
180  bool first = true;
181  for (const Own<TreeNode>& k : children) {
182  if (first) {
183  first = false;
184  } else {
185  os << ",\n";
186  }
187  k->printJSON(os, pos + 1);
188  }
189  os << tab << "]\n";
190  os << tab << "}";
191  }
192 
193 private:
194  VecOwn<TreeNode> children;
195  std::string label;
196 };
197 
198 /***
199  * Concrete class for leafs
200  */
201 class LeafNode : public TreeNode {
202 public:
203  LeafNode(const std::string& t = "") : TreeNode(t) {
204  setSize(1);
205  }
206 
207  // place leaf node
208  void place(uint32_t x, uint32_t y) override {
209  xpos = x;
210  ypos = y;
211  width = txt.length();
212  height = 1;
213  }
214 
215  // render text of leaf node
216  void render(ScreenBuffer& s) override {
217  s.write(xpos, ypos, txt);
218  }
219 
220  // print JSON
221  void printJSON(std::ostream& os, int pos) override {
222  std::string tab(pos, '\t');
223  os << tab << R"({ "axiom": ")" << stringify(txt) << "\"}";
224  }
225 };
226 
227 } // end of namespace souffle
souffle::TreeNode::setSize
void setSize(size_t s)
Definition: ExplainTree.h:118
souffle::LeafNode::render
void render(ScreenBuffer &s) override
Definition: ExplainTree.h:224
souffle::ScreenBuffer::getString
std::string getString()
Definition: ExplainTree.h:68
souffle::InnerNode::printJSON
void printJSON(std::ostream &os, int pos) override
Definition: ExplainTree.h:183
souffle::TreeNode::getSize
size_t getSize()
Definition: ExplainTree.h:114
souffle::ScreenBuffer::write
void write(uint32_t x, uint32_t y, const std::string &s)
Definition: ExplainTree.h:59
souffle::ScreenBuffer
Definition: ExplainTree.h:39
souffle::TreeNode
Definition: ExplainTree.h:90
souffle::ScreenBuffer::~ScreenBuffer
~ScreenBuffer()
Definition: ExplainTree.h:54
souffle::ScreenBuffer::width
uint32_t width
Definition: ExplainTree.h:87
souffle::Own
std::unique_ptr< A > Own
Definition: ContainerUtil.h:42
souffle::TreeNode::xpos
int xpos
Definition: ExplainTree.h:128
souffle::InnerNode::label
std::string label
Definition: ExplainTree.h:203
souffle::InnerNode
Definition: ExplainTree.h:133
souffle::InnerNode::place
void place(uint32_t x, uint32_t y) override
Definition: ExplainTree.h:146
souffle::TreeNode::size
uint32_t size
Definition: ExplainTree.h:130
souffle::TreeNode::ypos
int ypos
Definition: ExplainTree.h:129
j
var j
Definition: htmlJsChartistMin.h:15
souffle::ScreenBuffer::print
void print(std::ostream &os)
Definition: ExplainTree.h:75
souffle::TreeNode::TreeNode
TreeNode(std::string t="")
Definition: ExplainTree.h:95
souffle::stringify
std::string stringify(const std::string &input)
Stringify a string using escapes for escape, newline, tab, double-quotes and semicolons.
Definition: StringUtil.h:334
i
size_t i
Definition: json11.h:663
ContainerUtil.h
souffle::TreeNode::render
virtual void render(ScreenBuffer &s)=0
souffle::InnerNode::add_child
void add_child(Own< TreeNode > child)
Definition: ExplainTree.h:141
StringUtil.h
souffle::TreeNode::printJSON
virtual void printJSON(std::ostream &os, int pos)=0
souffle::TreeNode::~TreeNode
virtual ~TreeNode()=default
souffle::ScreenBuffer::height
uint32_t height
Definition: ExplainTree.h:88
k
var k
Definition: htmlJsChartistMin.h:15
souffle::InnerNode::children
VecOwn< TreeNode > children
Definition: ExplainTree.h:202
souffle::LeafNode::LeafNode
LeafNode(const std::string &t="")
Definition: ExplainTree.h:211
souffle::TreeNode::getHeight
uint32_t getHeight() const
Definition: ExplainTree.h:104
souffle::TreeNode::height
uint32_t height
Definition: ExplainTree.h:127
souffle::TreeNode::getWidth
uint32_t getWidth() const
Definition: ExplainTree.h:99
std
Definition: Brie.h:3053
souffle::TreeNode::txt
std::string txt
Definition: ExplainTree.h:125
souffle
Definition: AggregateOp.h:25
souffle::LeafNode::place
void place(uint32_t x, uint32_t y) override
Definition: ExplainTree.h:216
souffle::InnerNode::InnerNode
InnerNode(const std::string &nodeText="", std::string label="")
Definition: ExplainTree.h:137
souffle::InnerNode::render
void render(ScreenBuffer &s) override
Definition: ExplainTree.h:172
souffle::ScreenBuffer::ScreenBuffer
ScreenBuffer(uint32_t w, uint32_t h)
Definition: ExplainTree.h:48
souffle::TreeNode::width
uint32_t width
Definition: ExplainTree.h:126
souffle::TreeNode::place
virtual void place(uint32_t xpos, uint32_t ypos)=0
souffle::LeafNode::printJSON
void printJSON(std::ostream &os, int pos) override
Definition: ExplainTree.h:229
souffle::profile::ss
class souffle::profile::Tui ss
Definition: Tui.h:336
souffle::ScreenBuffer::buffer
char * buffer
Definition: ExplainTree.h:89