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