]> www.ginac.de Git - ginac.git/blob - ginac/print.h
[BUGFIX] Fix crash in parser.
[ginac.git] / ginac / print.h
1 /** @file print.h
2  *
3  *  Definition of helper classes for expression output. */
4
5 /*
6  *  GiNaC Copyright (C) 1999-2019 Johannes Gutenberg University Mainz, Germany
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22
23 #ifndef GINAC_PRINT_H
24 #define GINAC_PRINT_H
25
26 #include "class_info.h"
27
28 #include <iosfwd>
29 #include <memory>
30 #include <string>
31
32 namespace GiNaC {
33
34 /** This class stores information about a registered print_context class. */
35 class print_context_options {
36 public:
37         print_context_options(const char *n, const char *p, unsigned i)
38          : name(n), parent_name(p), id(i) {}
39
40         const char *get_name() const { return name; }
41         const char *get_parent_name() const { return parent_name; }
42         unsigned get_id() const { return id; }
43
44 private:
45         const char *name;         /**< Class name. */
46         const char *parent_name;  /**< Name of superclass. */
47         unsigned id;              /**< ID number (assigned automatically). */
48 };
49
50 typedef class_info<print_context_options> print_context_class_info;
51
52
53 /** Flags to control the behavior of a print_context. */
54 class print_options {
55 public:
56         enum {
57                 print_index_dimensions = 0x0001 ///< print the dimensions of indices
58         };
59 };
60
61
62 /** Common part of GINAC_DECLARE_PRINT_CONTEXT_BASE and GINAC_DECLARE_PRINT_CONTEXT_DERIVED. */
63 #define GINAC_DECLARE_PRINT_CONTEXT_COMMON(classname)   \
64 public: \
65         friend class function_options; \
66         friend class registered_class_options; \
67         static const GiNaC::print_context_class_info &get_class_info_static(); \
68         classname();
69
70 #define GINAC_DECLARE_PRINT_CONTEXT_BASE(classname) \
71         GINAC_DECLARE_PRINT_CONTEXT_COMMON(classname) \
72         virtual const GiNaC::print_context_class_info &get_class_info() const { return classname::get_class_info_static(); } \
73         virtual const char *class_name() const { return classname::get_class_info_static().options.get_name(); } \
74         virtual classname * duplicate() const { return new classname(*this); } \
75 private:
76
77 /** Macro for inclusion in the declaration of a print_context class.
78  *  It declares some functions that are common to all classes derived
79  *  from 'print_context' as well as all required stuff for the GiNaC
80  *  registry. */
81 #define GINAC_DECLARE_PRINT_CONTEXT(classname, supername) \
82         GINAC_DECLARE_PRINT_CONTEXT_COMMON(classname) \
83         typedef supername inherited; \
84         const GiNaC::print_context_class_info &get_class_info() const override { return classname::get_class_info_static(); } \
85         const char *class_name() const override { return classname::get_class_info_static().options.get_name(); } \
86         classname * duplicate() const override { return new classname(*this); } \
87 private:
88
89 /** Macro for inclusion in the implementation of each print_context class. */
90 #define GINAC_IMPLEMENT_PRINT_CONTEXT(classname, supername) \
91 const GiNaC::print_context_class_info &classname::get_class_info_static() \
92 { \
93         static GiNaC::print_context_class_info reg_info = GiNaC::print_context_class_info(GiNaC::print_context_options(#classname, #supername, GiNaC::next_print_context_id++)); \
94         return reg_info; \
95 }
96
97
98 extern unsigned next_print_context_id;
99
100
101 /** Base class for print_contexts. */
102 class print_context
103 {
104         GINAC_DECLARE_PRINT_CONTEXT_BASE(print_context)
105 public:
106         print_context(std::ostream &, unsigned options = 0);
107         virtual ~print_context() {}
108
109         std::ostream & s; /**< stream to output to */
110         unsigned options; /**< option flags */
111 };
112
113 /** Context for default (ginsh-parsable) output. */
114 class print_dflt : public print_context
115 {
116         GINAC_DECLARE_PRINT_CONTEXT(print_dflt, print_context)
117 public:
118         print_dflt(std::ostream &, unsigned options = 0);
119 };
120
121 /** Context for latex-parsable output. */
122 class print_latex : public print_context
123 {
124         GINAC_DECLARE_PRINT_CONTEXT(print_latex, print_context)
125 public:
126         print_latex(std::ostream &, unsigned options = 0);
127 };
128
129 /** Context for python pretty-print output. */
130 class print_python : public print_context
131 {
132         GINAC_DECLARE_PRINT_CONTEXT(print_python, print_context)
133 public:
134         print_python(std::ostream &, unsigned options = 0);
135 };
136
137 /** Context for python-parsable output. */
138 class print_python_repr : public print_context
139 {
140         GINAC_DECLARE_PRINT_CONTEXT(print_python_repr, print_context)
141 public:
142         print_python_repr(std::ostream &, unsigned options = 0);
143 };
144
145 /** Context for tree-like output for debugging. */
146 class print_tree : public print_context
147 {
148         GINAC_DECLARE_PRINT_CONTEXT(print_tree, print_context)
149 public:
150         print_tree(unsigned d);
151         print_tree(std::ostream &, unsigned options = 0, unsigned d = 4);
152
153         const unsigned delta_indent; /**< size of indentation step */
154 };
155
156 /** Base context for C source output. */
157 class print_csrc : public print_context
158 {
159         GINAC_DECLARE_PRINT_CONTEXT(print_csrc, print_context)
160 public:
161         print_csrc(std::ostream &, unsigned options = 0);
162 };
163
164 /** Context for C source output using float precision. */
165 class print_csrc_float : public print_csrc
166 {
167         GINAC_DECLARE_PRINT_CONTEXT(print_csrc_float, print_csrc)
168 public:
169         print_csrc_float(std::ostream &, unsigned options = 0);
170 };
171
172 /** Context for C source output using double precision. */
173 class print_csrc_double : public print_csrc
174 {
175         GINAC_DECLARE_PRINT_CONTEXT(print_csrc_double, print_csrc)
176 public:
177         print_csrc_double(std::ostream &, unsigned options = 0);
178 };
179
180 /** Context for C source output using CLN numbers. */
181 class print_csrc_cl_N : public print_csrc
182 {
183         GINAC_DECLARE_PRINT_CONTEXT(print_csrc_cl_N, print_csrc)
184 public:
185         print_csrc_cl_N(std::ostream &, unsigned options = 0);
186 };
187
188 /** Check if obj is a T, including base classes. */
189 template <class T>
190 inline bool is_a(const print_context & obj)
191 { return dynamic_cast<const T *>(&obj) != nullptr; }
192
193
194 class basic;
195
196 /** Base class for print_functor handlers */
197 class print_functor_impl {
198 public:
199         virtual ~print_functor_impl() {}
200         virtual print_functor_impl *duplicate() const = 0;
201         virtual void operator()(const basic & obj, const print_context & c, unsigned level) const = 0;
202 };
203
204 /** print_functor handler for pointer-to-functions of class T, context type C */
205 template <class T, class C>
206 class print_ptrfun_handler : public print_functor_impl {
207 public:
208         typedef void (*F)(const T &, const C &, unsigned);
209
210         print_ptrfun_handler(F f_) : f(f_) {}
211         print_ptrfun_handler *duplicate() const override { return new print_ptrfun_handler(*this); }
212
213         void operator()(const basic & obj, const print_context & c, unsigned level) const override
214         {
215                 // Call the supplied function
216                 f(dynamic_cast<const T &>(obj), dynamic_cast<const C &>(c), level);
217         }
218
219 private:
220         F f;
221 };
222
223 /** print_functor handler for member functions of class T, context type C */
224 template <class T, class C>
225 class print_memfun_handler : public print_functor_impl {
226 public:
227         typedef void (T::*F)(const C & c, unsigned level) const;
228
229         print_memfun_handler(F f_) : f(f_) {}
230         print_memfun_handler *duplicate() const override { return new print_memfun_handler(*this); }
231
232         void operator()(const basic & obj, const print_context & c, unsigned level) const override
233         {
234                 // Call the supplied member function
235                 return (dynamic_cast<const T &>(obj).*f)(dynamic_cast<const C &>(c), level);
236         }
237
238 private:
239         F f;
240 };
241
242 /** This class represents a print method for a certain algebraic class and
243  *  print_context type. Its main purpose is to hide the difference between
244  *  member functions and nonmember functions behind one unified operator()
245  *  interface. print_functor has value semantics and acts as a smart pointer
246  *  (with deep copy) to a class derived from print_functor_impl which
247  *  implements the actual function call. */
248 class print_functor {
249 public:
250         print_functor() : impl(nullptr) {}
251         print_functor(const print_functor & other) : impl(other.impl.get() ? other.impl->duplicate() : 0) {}
252         print_functor(std::unique_ptr<print_functor_impl> impl_) : impl(std::move(impl_)) {}
253
254         template <class T, class C>
255         print_functor(void f(const T &, const C &, unsigned)) : impl(new print_ptrfun_handler<T, C>(f)) {}
256
257         template <class T, class C>
258         print_functor(void (T::*f)(const C &, unsigned) const) : impl(new print_memfun_handler<T, C>(f)) {}
259
260         print_functor & operator=(const print_functor & other)
261         {
262                 if (this != &other) {
263                         print_functor_impl *p = other.impl.get();
264                         impl.reset(p ? other.impl->duplicate() : nullptr);
265                 }
266                 return *this;
267         }
268
269         void operator()(const basic & obj, const print_context & c, unsigned level) const
270         {
271                 (*impl)(obj, c, level);
272         }
273
274         bool is_valid() const { return impl.get(); }
275
276 private:
277         std::unique_ptr<print_functor_impl> impl;
278 };
279
280
281 } // namespace GiNaC
282
283 #endif // ndef GINAC_BASIC_H