NEURON
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
Helper class for printing C/C++ code.
void chain_block(std::string const &expression)
end a block and immediately start a new one (i.e. "[indent-1]} [expression] {\n")
void blame()
Blame when on the requested line.
void pop_block()
end of current block scope (i.e. end with "}") and adds one NL character
std::unique_ptr< utils::Blame > blame_printer
CodePrinter(std::ostream &stream, std::unique_ptr< utils::Blame > blame)
CodePrinter(std::unique_ptr< utils::Blame > blame)
void add_indent()
print whitespaces for indentation
void add_multi_line(const std::string &)
void fmt_push_block(Args &&... args)
fmt_push_block(args...) is just shorthand for push_block(fmt::format(args...))
void push_block()
start a block scope without indentation (i.e. "{\n")
void add_text(Args &&... args)
void add_newline(std::size_t n=1)
void add_line(Args &&... args)
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
void fmt_text(Args &&... args)
fmt_text(args...) is just shorthand for add_text(fmt::format(args...))
void fmt_line(Args &&... args)
fmt_line(x, y, z) is just shorthand for add_line(fmt::format(x, y, z))
std::unique_ptr< std::ostream > result
void move(Item *q1, Item *q2, Item *q3)
Definition: list.cpp:200
encapsulates code generation backend implementations
Definition: ast_common.hpp:26
std::ostream & operator<<(std::ostream &stream, const ModToken &mt)
Definition: modtoken.cpp:26
static char suffix[256]
Definition: nocpout.cpp:135
int const size_t const size_t n
Definition: nrngsl.h:10