Spicy
printer.h
1 // Copyright (c) 2020-now by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <cstddef>
6 #include <iostream>
7 #include <memory>
8 #include <string>
9 #include <utility>
10 #include <vector>
11 
12 #include <hilti/ast/forward.h>
13 #include <hilti/ast/id.h>
14 #include <hilti/ast/node.h>
15 #include <hilti/base/util.h>
16 
17 namespace hilti {
18 
19 struct Plugin;
20 
21 namespace printer {
22 
33 void print(std::ostream& out, Node* root, bool compact, bool user_visible);
34 
35 namespace detail {
36 
38 struct State {
39  const Plugin* current_plugin = nullptr;
40 
41  std::vector<ID> scopes = {{""}};
42  std::string pending;
43  int indent = 0;
44  bool wrote_nl = false;
45  bool first_in_block = false;
46  bool last_in_block = false;
47  bool expand_subsequent_type = false;
48  bool compact = false;
49  bool user_visible = true;
50 
51  inline static std::unique_ptr<State> current;
52  inline static uint64_t depth = 0;
53 };
54 } // namespace detail
55 
57 class Stream {
58 public:
59  Stream(std::ostream& s) : _stream(s) {}
60 
61  auto& state() const {
62  assert(detail::State::current.get());
63  return *detail::State::current;
64  }
65 
66  void beginLine() {
67  _flush_pending();
68  _stream << std::string(static_cast<size_t>(state().indent) * 4, ' ');
69  }
70 
71  void endLine() { _stream << '\n'; }
72 
73  void emptyLine() {
74  if ( state().wrote_nl )
75  return;
76 
77  endLine();
78  state().wrote_nl = true;
79  }
80 
81  char newline() const { return '\n'; }
82 
83  bool isExpandSubsequentType() const { return state().expand_subsequent_type; }
84  void setExpandSubsequentType(bool expand) { state().expand_subsequent_type = expand; }
85 
86  bool isCompact() const { return state().compact; }
87  void setCompact(bool compact) { state().compact = compact; }
88 
89  bool isFirstInBlock() const { return state().first_in_block; }
90  bool isLastInBlock() const { return state().last_in_block; }
91  void setPositionInBlock(bool first, bool last) {
92  state().first_in_block = first;
93  state().last_in_block = last;
94  }
95 
96  auto indent() const { return state().indent; }
97  void incrementIndent() { ++state().indent; }
98  void decrementIndent() {
99  --state().indent;
100  state().first_in_block = state().last_in_block = false;
101  }
102 
103  const ID& currentScope() { return state().scopes.back(); }
104  void pushScope(ID id) { state().scopes.push_back(std::move(id)); }
105  void popScope() { state().scopes.pop_back(); }
106 
107  template<typename T>
108  Stream& operator<<(T* t)
109  requires std::is_base_of_v<Node, T>
110  {
111  _flush_pending();
112  _print(t);
113  return *this;
114  }
115 
116  Stream& operator<<(const ID& id);
117 
118  template<typename T>
119  Stream& operator<<(const T& t)
120  requires(! std::is_base_of_v<Node, T>)
121  {
122  state().wrote_nl = false;
123  _flush_pending();
124  _stream << t;
125  return *this;
126  }
127 
128  // Output lists.
129  template<typename T>
130  Stream& operator<<(const std::pair<T, const char*>& p) {
131  bool first = true;
132  for ( const auto& i : p.first ) {
133  _flush_pending();
134 
135  if ( ! first )
136  _stream << p.second;
137 
138  (*this) << i;
139  first = false;
140  }
141 
142  return *this;
143  }
144 
145  template<typename T>
146  Stream& operator<<(std::pair<T*, const char*> p) {
147  bool first = true;
148  for ( auto& i : p.first ) {
149  _flush_pending();
150 
151  if ( ! first )
152  _stream << p.second;
153 
154  (*this) << *i;
155  first = false;
156  }
157 
158  return *this;
159  }
160 
161 private:
162  friend void printer::print(std::ostream& out, Node* root, bool compact, bool user_visible);
163 
164  void _print(Node* root);
165 
166  void _flush_pending() {
167  _stream << state().pending;
168  state().pending.clear();
169  }
170 
171  std::ostream& _stream;
172 };
173 
174 } // namespace printer
175 } // namespace hilti
Definition: id.h:15
Definition: node.h:243
Definition: printer.h:57
void print(const T &t, const hilti::rt::TypeInfo *, bool newline=true)
Definition: hilti.h:23
Definition: plugin.h:47
Definition: printer.h:38