souffle  2.0.2-371-g6315b36
WriteStream.h
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2013, 2014, 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 WriteStream.h
12  *
13  ***********************************************************************/
14 
15 #pragma once
16 
17 #include "souffle/RamTypes.h"
18 #include "souffle/RecordTable.h"
19 #include "souffle/SymbolTable.h"
22 #include "souffle/utility/json11.h"
23 #include <cassert>
24 #include <cstddef>
25 #include <map>
26 #include <memory>
27 #include <ostream>
28 #include <string>
29 
30 namespace souffle {
31 
32 using json11::Json;
33 
34 class WriteStream : public SerialisationStream<true> {
35 public:
36  WriteStream(const std::map<std::string, std::string>& rwOperation, const SymbolTable& symbolTable,
37  const RecordTable& recordTable)
39  summary(rwOperation.at("IO") == "stdoutprintsize") {}
40 
41  template <typename T>
42  void writeAll(const T& relation) {
43  if (summary) {
44  return writeSize(relation.size());
45  }
46  auto lease = symbolTable.acquireLock();
47  (void)lease; // silence "unused variable" warning
48  if (arity == 0) {
49  if (relation.begin() != relation.end()) {
50  writeNullary();
51  }
52  return;
53  }
54  for (const auto& current : relation) {
55  writeNext(current);
56  }
57  }
58 
59  template <typename T>
60  void writeSize(const T& relation) {
61  writeSize(relation.size());
62  }
63 
64 protected:
65  const bool summary;
66 
67  virtual void writeNullary() = 0;
68  virtual void writeNextTuple(const RamDomain* tuple) = 0;
69  virtual void writeSize(std::size_t) {
70  fatal("attempting to print size of a write operation");
71  }
72 
73  template <typename Tuple>
74  void writeNext(const Tuple tuple) {
75  using tcb::make_span;
77  }
78 
79  void outputRecord(std::ostream& destination, const RamDomain value, const std::string& name) {
80  auto&& recordInfo = types["records"][name];
81 
82  // Check if record type information are present
83  assert(!recordInfo.is_null() && "Missing record type information");
84 
85  // Check for nil
86  if (value == 0) {
87  destination << "nil";
88  return;
89  }
90 
91  auto&& recordTypes = recordInfo["types"];
92  const size_t recordArity = recordInfo["arity"].long_value();
93 
94  const RamDomain* tuplePtr = recordTable.unpack(value, recordArity);
95 
96  destination << "[";
97 
98  // print record's elements
99  for (size_t i = 0; i < recordArity; ++i) {
100  if (i > 0) {
101  destination << ", ";
102  }
103 
104  const std::string& recordType = recordTypes[i].string_value();
105  const RamDomain recordValue = tuplePtr[i];
106 
107  switch (recordType[0]) {
108  case 'i': destination << recordValue; break;
109  case 'f': destination << ramBitCast<RamFloat>(recordValue); break;
110  case 'u': destination << ramBitCast<RamUnsigned>(recordValue); break;
111  case 's': destination << symbolTable.unsafeResolve(recordValue); break;
112  case 'r': outputRecord(destination, recordValue, recordType); break;
113  case '+': outputADT(destination, recordValue, recordType); break;
114  default: fatal("Unsupported type attribute: `%c`", recordType[0]);
115  }
116  }
117  destination << "]";
118  }
119 
120  void outputADT(std::ostream& destination, const RamDomain value, const std::string& name) {
121  auto&& adtInfo = types["ADTs"][name];
122 
123  assert(!adtInfo.is_null() && "Missing adt type information");
124 
125  const size_t numBranches = adtInfo["arity"].long_value();
126  assert(numBranches > 0);
127 
128  // adt is encoded in one of three possible ways:
129  // [branchID, [branch_args]] when |branch_args| != 1
130  // [branchID, arg] when a branch takes a single argument.
131  // branchID when ADT is an enumeration.
132  bool isEnum = adtInfo["enum"].bool_value();
133 
134  RamDomain branchId = value;
135  const RamDomain* branchArgs = nullptr;
136  json11::Json branchInfo;
137  json11::Json::array branchTypes;
138 
139  if (!isEnum) {
140  const RamDomain* tuplePtr = recordTable.unpack(value, 2);
141 
142  branchId = tuplePtr[0];
143  branchInfo = adtInfo["branches"][branchId];
144  branchTypes = branchInfo["types"].array_items();
145 
146  // Prepare branch's arguments for output.
147  branchArgs = [&]() -> const RamDomain* {
148  if (branchTypes.size() > 1) {
149  return recordTable.unpack(tuplePtr[1], branchTypes.size());
150  } else {
151  return &tuplePtr[1];
152  }
153  }();
154  } else {
155  branchInfo = adtInfo["branches"][branchId];
156  branchTypes = branchInfo["types"].array_items();
157  }
158 
159  destination << "$" << branchInfo["name"].string_value();
160 
161  if (branchTypes.size() > 0) {
162  destination << "(";
163  }
164 
165  // Print arguments
166  for (size_t i = 0; i < branchTypes.size(); ++i) {
167  if (i > 0) {
168  destination << ", ";
169  }
170 
171  auto argType = branchTypes[i].string_value();
172  switch (argType[0]) {
173  case 'i': destination << branchArgs[i]; break;
174  case 'f': destination << ramBitCast<RamFloat>(branchArgs[i]); break;
175  case 'u': destination << ramBitCast<RamUnsigned>(branchArgs[i]); break;
176  case 's': destination << symbolTable.unsafeResolve(branchArgs[i]); break;
177  case 'r': outputRecord(destination, branchArgs[i], argType); break;
178  case '+': outputADT(destination, branchArgs[i], argType); break;
179  default: fatal("Unsupported type attribute: `%c`", argType[0]);
180  }
181  }
182 
183  if (branchTypes.size() > 0) {
184  destination << ")";
185  }
186  }
187 };
188 
189 class WriteStreamFactory {
190 public:
191  virtual Own<WriteStream> getWriter(const std::map<std::string, std::string>& rwOperation,
192  const SymbolTable& symbolTable, const RecordTable& recordTable) = 0;
193 
194  virtual const std::string& getName() const = 0;
195  virtual ~WriteStreamFactory() = default;
196 };
197 
198 template <>
199 inline void WriteStream::writeNext(const RamDomain* tuple) {
201 }
202 
203 } /* namespace souffle */
souffle::WriteStreamFactory::getWriter
virtual Own< WriteStream > getWriter(const std::map< std::string, std::string > &rwOperation, const SymbolTable &symbolTable, const RecordTable &recordTable)=0
souffle::SerialisationStream< true >::recordTable
RO< RecordTable > & recordTable
Definition: SerialisationStream.h:72
souffle::RamDomain
int32_t RamDomain
Definition: RamTypes.h:56
souffle::SerialisationStream
Definition: SerialisationStream.h:43
SymbolTable.h
SerialisationStream.h
relation
Relation & relation
Definition: Reader.h:130
souffle::WriteStream::outputADT
void outputADT(std::ostream &destination, const RamDomain value, const std::string &name)
Definition: WriteStream.h:124
MiscUtil.h
json11.h
souffle::WriteStream::WriteStream
WriteStream(const std::map< std::string, std::string > &rwOperation, const SymbolTable &symbolTable, const RecordTable &recordTable)
Definition: WriteStream.h:40
souffle::WriteStream::summary
const bool summary
Definition: WriteStream.h:69
souffle::WriteStreamFactory::getName
virtual const std::string & getName() const =0
souffle::WriteStreamFactory::~WriteStreamFactory
virtual ~WriteStreamFactory()=default
souffle::SerialisationStream< true >::symbolTable
RO< SymbolTable > & symbolTable
Definition: SerialisationStream.h:71
souffle::WriteStream::writeNext
void writeNext(const Tuple tuple)
Definition: WriteStream.h:78
souffle::SerialisationStream< true >::types
Json types
Definition: SerialisationStream.h:73
json11::Json::array_items
const array & array_items() const
Definition: json11.h:554
souffle::WriteStream::outputRecord
void outputRecord(std::ostream &destination, const RamDomain value, const std::string &name)
Definition: WriteStream.h:83
i
size_t i
Definition: json11.h:663
souffle::WriteStream::writeNullary
virtual void writeNullary()=0
json11::Json::array
std::vector< Json > array
Definition: json11.h:93
souffle::Tuple
std::array< A, N > Tuple
Definition: RamTypes.h:36
json11::Json::string_value
const std::string & string_value() const
Definition: json11.h:551
json11::Json
Definition: json11.h:87
RecordTable.h
RamTypes.h
souffle::fatal
void fatal(const char *format, const Args &... args)
Definition: MiscUtil.h:198
TCB_SPAN_NAMESPACE_NAME::make_span
constexpr span< ElementType, Extent > make_span(span< ElementType, Extent > s) noexcept
Definition: span.h:543
souffle
Definition: AggregateOp.h:25
souffle::SerialisationStream< true >::arity
size_t arity
Definition: SerialisationStream.h:76
TCB_SPAN_NAMESPACE_NAME::detail::data
constexpr auto data(C &c) -> decltype(c.data())
Definition: span.h:210
souffle::WriteStream::writeSize
void writeSize(const T &relation)
Definition: WriteStream.h:64
souffle::tuple
Defines a tuple for the OO interface such that relations with varying columns can be accessed.
Definition: SouffleInterface.h:443
souffle::WriteStream::writeNextTuple
virtual void writeNextTuple(const RamDomain *tuple)=0
souffle::WriteStream::writeAll
void writeAll(const T &relation)
Definition: WriteStream.h:46