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);
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 
90  bool isFirstInBlock() const { return state().first_in_block; }
91  bool isLastInBlock() const { return state().last_in_block; }
92  void setPositionInBlock(bool first, bool last) {
93  state().first_in_block = first;
94  state().last_in_block = last;
95  }
96 
97  auto indent() const { return state().indent; }
98  void incrementIndent() { ++state().indent; }
99  void decrementIndent() {
100  --state().indent;
101  state().first_in_block = state().last_in_block = false;
102  }
103 
104  const ID& currentScope() { return state().scopes.back(); }
105  void pushScope(ID id) { state().scopes.push_back(std::move(id)); }
106  void popScope() { state().scopes.pop_back(); }
107 
108  template<typename T>
109  Stream& operator<<(T* t)
110  requires std::is_base_of_v<Node, T>
111  {
112  _flush_pending();
113  _print(t);
114  return *this;
115  }
116 
117  Stream& operator<<(const ID& id);
118 
119  template<typename T>
120  Stream& operator<<(const T& t)
121  requires(! std::is_base_of_v<Node, T>)
122  {
123  state().wrote_nl = false;
124  _flush_pending();
125  _stream << t;
126  return *this;
127  }
128 
129  // Output lists.
130  template<typename T>
131  Stream& operator<<(const std::pair<T, const char*>& p) {
132  bool first = true;
133  for ( const auto& i : p.first ) {
134  _flush_pending();
135 
136  if ( ! first )
137  _stream << p.second;
138 
139  (*this) << i;
140  first = false;
141  }
142 
143  return *this;
144  }
145 
146  template<typename T>
147  Stream& operator<<(std::pair<T*, const char*> p) {
148  bool first = true;
149  for ( auto& i : p.first ) {
150  _flush_pending();
151 
152  if ( ! first )
153  _stream << p.second;
154 
155  (*this) << *i;
156  first = false;
157  }
158 
159  return *this;
160  }
161 
162 private:
163  friend void printer::print(std::ostream& out, Node* root, bool compact, bool user_visible);
164 
165  void _print(Node* root);
166 
167  void _flush_pending() {
168  _stream << state().pending;
169  state().pending.clear();
170  }
171 
172  std::ostream& _stream;
173 };
174 
175 } // namespace printer
176 } // namespace hilti
Definition: id.h:15
Definition: node.h:240
Definition: printer.h:57
void print(const T &t, const hilti::rt::TypeInfo *, bool newline=true)
Definition: hilti.h:23
Definition: plugin.h:52
Definition: printer.h:38