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