Spicy
printer.h
1 // Copyright (c) 2020-2021 by the Zeek Project. See LICENSE for details.
2 
3 #pragma once
4 
5 #include <iostream>
6 #include <string>
7 #include <utility>
8 #include <vector>
9 
10 #include <hilti/base/util.h>
11 #include <hilti/compiler/detail/visitors.h>
12 
13 namespace hilti::printer {
14 
15 class Stream {
16 public:
17  Stream(std::ostream& s, bool _compact) : _stream(s), _compact(_compact), _nl(_compact ? ' ' : '\n') {}
18 
19  void beginLine() { _stream << std::string(_indent * 4, ' '); }
20  void endLine() { _stream << (_compact ? ' ' : '\n'); }
21  void emptyLine() {
22  if ( _wrote_nl )
23  return;
24 
25  _stream << (_compact ? ' ' : '\n');
26  _wrote_nl = true;
27  }
28 
29  char newline() const { return _nl; }
30 
31  const ID& currentScope() const { return _scopes.back(); }
32  void pushScope(ID id) { _scopes.push_back(std::move(id)); }
33  void popScope() { _scopes.pop_back(); }
34 
35  bool isCompact() { return _compact; }
36  bool setCompact(bool new_compact) {
37  auto old = _compact;
38  _compact = new_compact;
39  return old;
40  }
41 
42  bool isExpandSubsequentType() const { return _expand_subsequent_type; }
43  void setExpandSubsequentType(bool expand) { _expand_subsequent_type = expand; }
44 
45  bool isFirstInBlock() const { return _first_in_block; }
46  bool isLastInBlock() const { return _last_in_block; }
47  void setPositionInBlock(bool first, bool last) {
48  _first_in_block = first;
49  _last_in_block = last;
50  }
51 
52  auto indent() const { return _indent; }
53  void incrementIndent() { ++_indent; }
54  void decrementIndent() {
55  --_indent;
56  _first_in_block = _last_in_block = false;
57  }
58 
59  template<typename T, IF_DERIVED_FROM(T, trait::isNode)>
60  Stream& operator<<(const T& t) {
61  if constexpr ( std::is_base_of<trait::isType, T>::value ) {
62  if ( auto id = Type(t).typeID() )
63  _stream << *id;
64  }
65  else
66  hilti::detail::printAST(t, *this);
67 
68  return *this;
69  }
70 
71  template<typename T, IF_NOT_DERIVED_FROM(T, trait::isNode)>
72  Stream& operator<<(const T& t) {
73  _wrote_nl = false;
74  _stream << t;
75  _expand_subsequent_type = false;
76  return *this;
77  }
78 
79  // Output lists.
80  template<typename T>
81  Stream& operator<<(std::pair<T, const char*> p) {
82  bool first = true;
83  for ( auto& i : p.first ) {
84  if ( ! first )
85  _stream << p.second;
86 
87  (*this) << i;
88  first = false;
89  }
90 
91  return *this;
92  }
93 
94 private:
95  std::ostream& _stream;
96  bool _compact;
97  char _nl;
98  int _indent = 0;
99  bool _wrote_nl = false;
100  bool _first_in_block = false;
101  bool _last_in_block = false;
102  bool _expand_subsequent_type = false;
103  std::vector<ID> _scopes = {""};
104 };
105 
106 } // namespace hilti::printer
Definition: visitors.h:23
Definition: printer.h:15
Definition: id.h:18