User Guide
code_printer.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2023 Blue Brain Project, EPFL.
3  * See the top-level LICENSE file for details.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #pragma once
9 
10 /**
11  * \dir
12  * \brief Code printer implementations
13  *
14  * \file
15  * \brief \copybrief nmodl::printer::CodePrinter
16  */
17 #include <fmt/format.h>
18 
19 #include <fstream>
20 #include <iostream>
21 #include <memory>
22 #include <sstream>
23 #include <string_view>
24 
25 namespace nmodl {
26 /// implementation of various printers
27 namespace printer {
28 
29 /**
30  * @defgroup printer Code Printers
31  * @brief Printers for translating AST to different forms
32  * @{
33  */
34 
35 /**
36  * \class CodePrinter
37  * \brief Helper class for printing C/C++ code
38  *
39  * This class provides common functionality required by code
40  * generation visitor to print C/C++/Cuda code.
41  */
42 class CodePrinter {
43  private:
44  std::ofstream ofs;
45  std::streambuf* sbuf = nullptr;
46  std::unique_ptr<std::ostream> result;
47  size_t current_line = 1;
48  size_t blame_line = 0;
49  size_t indent_level = 0;
50  const size_t NUM_SPACES = 4;
51 
52  public:
53  CodePrinter(size_t blame_line = 0)
54  : result(std::make_unique<std::ostream>(std::cout.rdbuf()))
56 
57  CodePrinter(std::ostream& stream, size_t blame_line = 0)
58  : result(std::make_unique<std::ostream>(stream.rdbuf()))
60 
61  CodePrinter(const std::string& filename, size_t blame_line = 0);
62 
64  ofs.close();
65  }
66 
67  /// print whitespaces for indentation
68  void add_indent();
69 
70  /// start a block scope without indentation (i.e. "{\n")
71  void push_block();
72 
73  /// start a block scope with an expression (i.e. "[indent][expression] {\n")
74  void push_block(const std::string& expression);
75 
76  /// end a block and immediately start a new one (i.e. "[indent-1]} [expression] {\n")
77  void chain_block(std::string const& expression);
78 
79  template <typename... Args>
80  void add_text(Args&&... args) {
81  blame();
82  (operator<<(*result, args), ...);
83  }
84 
85  template <typename... Args>
86  void add_line(Args&&... args) {
87  add_indent();
88  add_text(std::forward<Args>(args)...);
89  add_newline(1);
90  }
91 
92  /// fmt_line(x, y, z) is just shorthand for add_line(fmt::format(x, y, z))
93  template <typename... Args>
94  void fmt_line(Args&&... args) {
95  add_line(fmt::format(std::forward<Args>(args)...));
96  }
97 
98  /// fmt_push_block(args...) is just shorthand for push_block(fmt::format(args...))
99  template <typename... Args>
100  void fmt_push_block(Args&&... args) {
101  push_block(fmt::format(std::forward<Args>(args)...));
102  }
103 
104  /// fmt_text(args...) is just shorthand for add_text(fmt::format(args...))
105  template <typename... Args>
106  void fmt_text(Args&&... args) {
107  add_text(fmt::format(std::forward<Args>(args)...));
108  }
109 
110  void add_multi_line(const std::string&);
111 
112  void add_newline(std::size_t n = 1);
113 
115  indent_level++;
116  }
117 
119  indent_level--;
120  }
121 
122  /// end of current block scope (i.e. end with "}") and adds one NL character
123  void pop_block();
124 
125  /// same as \a pop_block but control the number of NL characters (0 or more) with \a
126  /// num_newlines parameter
127  void pop_block_nl(std::size_t num_newlines = 0);
128 
129  /// end a block with `suffix` before the newline(s) (i.e. [indent]}[suffix]\n*num_newlines)
130  void pop_block(const std::string_view& suffix, std::size_t num_newlines = 1);
131 
133  return NUM_SPACES * indent_level;
134  }
135 
136  private:
137  /// Blame when on the requested line.
138  void blame();
139 };
140 
141 /** @} */ // end of printer
142 
143 } // namespace printer
144 } // namespace nmodl
nmodl::printer::CodePrinter::add_indent
void add_indent()
print whitespaces for indentation
Definition: code_printer.cpp:56
nmodl::printer::CodePrinter::add_multi_line
void add_multi_line(const std::string &)
Definition: code_printer.cpp:60
nmodl::printer::CodePrinter::blame
void blame()
Blame when on the requested line.
Definition: code_printer.cpp:117
nmodl::printer::CodePrinter::add_text
void add_text(Args &&... args)
Definition: code_printer.hpp:80
nmodl::printer::CodePrinter::sbuf
std::streambuf * sbuf
Definition: code_printer.hpp:45
nmodl::printer::CodePrinter::decrease_indent
void decrease_indent()
Definition: code_printer.hpp:118
nmodl::printer::CodePrinter::pop_block_nl
void pop_block_nl(std::size_t num_newlines=0)
same as pop_block but control the number of NL characters (0 or more) with num_newlines parameter
Definition: code_printer.cpp:104
nmodl
encapsulates code generation backend implementations
Definition: ast_common.hpp:26
nmodl::printer::CodePrinter::NUM_SPACES
const size_t NUM_SPACES
Definition: code_printer.hpp:50
nmodl::printer::CodePrinter::~CodePrinter
~CodePrinter()
Definition: code_printer.hpp:63
nmodl::printer::CodePrinter::fmt_text
void fmt_text(Args &&... args)
fmt_text(args...) is just shorthand for add_text(fmt::format(args...))
Definition: code_printer.hpp:106
nmodl::printer::CodePrinter::CodePrinter
CodePrinter(size_t blame_line=0)
Definition: code_printer.hpp:53
nmodl::printer::CodePrinter::result
std::unique_ptr< std::ostream > result
Definition: code_printer.hpp:46
nmodl::printer::CodePrinter::add_line
void add_line(Args &&... args)
Definition: code_printer.hpp:86
nmodl::printer::CodePrinter::chain_block
void chain_block(std::string const &expression)
end a block and immediately start a new one (i.e. "[indent-1]} [expression] {\n")
Definition: code_printer.cpp:48
nmodl::printer::CodePrinter::increase_indent
void increase_indent()
Definition: code_printer.hpp:114
nmodl::printer::CodePrinter::CodePrinter
CodePrinter(std::ostream &stream, size_t blame_line=0)
Definition: code_printer.hpp:57
nmodl::printer::CodePrinter::indent_level
size_t indent_level
Definition: code_printer.hpp:49
nmodl::printer::CodePrinter::pop_block
void pop_block()
end of current block scope (i.e. end with "}") and adds one NL character
Definition: code_printer.cpp:100
nmodl::operator<<
std::ostream & operator<<(std::ostream &stream, const ModToken &mt)
Definition: modtoken.cpp:26
nmodl::printer::CodePrinter::fmt_push_block
void fmt_push_block(Args &&... args)
fmt_push_block(args...) is just shorthand for push_block(fmt::format(args...))
Definition: code_printer.hpp:100
nmodl::printer::CodePrinter::blame_line
size_t blame_line
Definition: code_printer.hpp:48
nmodl::printer::CodePrinter::indent_spaces
int indent_spaces()
Definition: code_printer.hpp:132
nmodl::printer::CodePrinter::current_line
size_t current_line
Definition: code_printer.hpp:47
nmodl::printer::CodePrinter::fmt_line
void fmt_line(Args &&... args)
fmt_line(x, y, z) is just shorthand for add_line(fmt::format(x, y, z))
Definition: code_printer.hpp:94
nmodl::printer::CodePrinter::push_block
void push_block()
start a block scope without indentation (i.e. "{\n")
Definition: code_printer.cpp:35
nmodl::printer::CodePrinter::add_newline
void add_newline(std::size_t n=1)
Definition: code_printer.cpp:93
nmodl::printer::CodePrinter
Helper class for printing C/C++ code.
Definition: code_printer.hpp:42
nmodl::printer::CodePrinter::ofs
std::ofstream ofs
Definition: code_printer.hpp:44