]> www.ginac.de Git - ginac.git/blob - ginac/structure.pl
- Changes to make it more ANSI-conformant. Stuff detected while trying
[ginac.git] / ginac / structure.pl
1 #!/usr/bin/perl -w
2
3 $input_structure='';
4 $original_input_structure='';
5 while (<>) {
6         $input_structure .= '// '.$_;
7         $original_input_structure .= $_;
8 }
9
10 $original_input_structure =~ tr/ \t\n\r\f/     /;
11 $original_input_structure =~ tr/ //s;
12
13 if ($original_input_structure =~ /^struct (\w+) ?\{ ?(.*)\}\;? ?$/) {
14         $STRUCTURE=$1;
15         $decl=$2;
16 } else {
17         die "illegal struct, must match 'struct name { type var; /*comment*/ ...};': $original_input_structure";
18 }
19
20 # split off a part 'type var[,var...];' with a possible C-comment '/* ... */'
21 while ($decl =~ /^ ?(\w+) ([\w \,]+)\; ?((\/\*.*?\*\/)?)(.*)$/) {
22         $type=$1;
23         $member=$2;
24         $comment=$3;
25         $decl=$5;
26         while ($member =~ /^(\w+) ?\, ?(.*)$/) {
27                 push @TYPES,$type;
28                 push @MEMBERS,$1;
29                 push @COMMENTS,$comment;
30                 if ($comment ne '') {
31                         $comment='/* see above */';
32                 }
33                 $member=$2;
34         }
35         if ($member !~ /^\w+$/) {
36                 die "illegal struct, must match 'struct name { type var; /*comment*/ ...};': $input_structure";
37         }
38         push @TYPES,$type;
39         push @MEMBERS,$member;
40         push @COMMENTS,$comment;
41 }
42
43 if ($decl !~ /^ ?$/) {
44         die "illegal struct, must match 'struct name { type var; /*comment*/ ...};': $input_structure";
45 }
46
47 #$STRUCTURE='teststruct';
48 $STRUCTURE_UC=uc(${STRUCTURE});
49 #@TYPES=('ex','ex','ex');
50 #@MEMBERS=('q10','q20','q21');
51
52 sub generate {
53         my ($template,$conj)=@_;
54         my ($res,$N);
55
56         $res='';
57         for ($N=1; $N<=$#MEMBERS+1; $N++) {
58                 $TYPE=$TYPES[$N-1];
59                 $MEMBER=$MEMBERS[$N-1];
60                 $COMMENT=$COMMENTS[$N-1];
61                 $res .= eval('"' . $template . '"');
62                 $TYPE=''; # to avoid main::TYPE used only once warning
63                 $MEMBER=''; # same as above
64                 $COMMENT=''; # same as above
65                 if ($N!=$#MEMBERS+1) {
66                         $res .= $conj;
67                 }
68         }
69         return $res;
70 }
71
72 $number_of_members=$#MEMBERS+1;
73 $constructor_arglist=generate('ex tmp_${MEMBER}',', ');
74 $member_access_functions=generate('    const ex & ${MEMBER}(void) { return m_${MEMBER}; }',"\n");
75 $op_access_indices_decl=generate('    static unsigned op_${MEMBER};',"\n");
76 $op_access_indices_def=generate('unsigned ${STRUCTURE}::op_${MEMBER}=${N}-1;',"\n");
77 $members=generate('    ex m_${MEMBER}; ${COMMENT}',"\n");
78 $copy_statements=generate('    m_${MEMBER}=other.m_${MEMBER};',"\n");
79 $constructor_statements=generate('m_${MEMBER}(tmp_${MEMBER})',', ');
80 $let_op_statements=generate(
81 '    case ${N}-1:'."\n".
82 '        return m_${MEMBER};'."\n".
83 '        break;',
84 "\n");
85 $temporary_arglist=generate('tmp_${MEMBER}',', ');
86 $expand_statements=generate('    ex tmp_${MEMBER}=m_${MEMBER}.expand(options);',"\n");
87 $has_statements=generate('    if (m_${MEMBER}.has(other)) return true;',"\n");
88 $eval_statements=generate(
89 '    ex tmp_${MEMBER}=m_${MEMBER}.eval(level-1);'."\n".
90 '    all_are_trivially_equal = all_are_trivially_equal &&'."\n".
91 '                              are_ex_trivially_equal(tmp_${MEMBER},m_${MEMBER});',
92 "\n");
93 $evalf_statements=generate(
94 '    ex tmp_${MEMBER}=m_${MEMBER}.evalf(level-1);'."\n".
95 '    all_are_trivially_equal = all_are_trivially_equal &&'."\n".
96 '                              are_ex_trivially_equal(tmp_${MEMBER},m_${MEMBER});',
97 "\n");
98 $normal_statements=generate(
99 '    ex tmp_${MEMBER}=m_${MEMBER}.normal(level-1);'."\n".
100 '    all_are_trivially_equal = all_are_trivially_equal &&'."\n".
101 '                              are_ex_trivially_equal(tmp_${MEMBER},m_${MEMBER});',
102 "\n");
103 $diff_statements=generate('    ex tmp_${MEMBER}=m_${MEMBER}.diff(s);',"\n");
104 $subs_statements=generate(
105 '    ex tmp_${MEMBER}=m_${MEMBER}.subs(ls,lr);'."\n".
106 '    all_are_trivially_equal = all_are_trivially_equal &&'."\n".
107 '                              are_ex_trivially_equal(tmp_${MEMBER},m_${MEMBER});',
108 "\n");
109 $compare_statements=generate(
110 '    cmpval=m_${MEMBER}.compare(o.m_${MEMBER});'."\n".
111 '    if (cmpval!=0) return cmpval;',
112 "\n");
113 $is_equal_statements=generate('    if (!m_${MEMBER}.is_equal(o.m_${MEMBER})) return false;',"\n");
114 $types_ok_statements=generate(
115 '#ifndef SKIP_TYPE_CHECK_FOR_${TYPE}'."\n".
116 '    if (!is_ex_exactly_of_type(m_${MEMBER},${TYPE})) return false;'."\n".
117 '#endif // ndef SKIP_TYPE_CHECK_FOR_${TYPE}',"\n");
118
119 $interface=<<END_OF_INTERFACE;
120 /** \@file ${STRUCTURE}.h
121  *
122  *  Definition of GiNaC's user defined structure ${STRUCTURE}. */
123
124 /*
125  *  This file was generated automatically by structure.pl.
126  *  Please do not modify it directly, edit the perl script instead!
127  *
128  *  GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
129  *
130  *  This program is free software; you can redistribute it and/or modify
131  *  it under the terms of the GNU General Public License as published by
132  *  the Free Software Foundation; either version 2 of the License, or
133  *  (at your option) any later version.
134  *
135  *  This program is distributed in the hope that it will be useful,
136  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
137  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
138  *  GNU General Public License for more details.
139  *
140  *  You should have received a copy of the GNU General Public License
141  *  along with this program; if not, write to the Free Software
142  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
143  */
144
145 // structure.pl input:
146 ${input_structure}
147
148 #ifndef __GINAC_${STRUCTURE_UC}_H__
149 #define __GINAC_${STRUCTURE_UC}_H__
150
151 #include "structure.h"
152
153 #ifndef NO_NAMESPACE_GINAC
154 namespace GiNaC {
155 #endif // ndef NO_NAMESPACE_GINAC
156
157 class ${STRUCTURE} : public structure
158 {
159 // member functions
160
161         // default constructor, destructor, copy constructor assignment operator and helpers
162 public:
163         ${STRUCTURE}();
164         ~${STRUCTURE}();
165         ${STRUCTURE}(${STRUCTURE} const & other);
166         ${STRUCTURE} const & operator=(${STRUCTURE} const & other);
167 protected:
168         void copy(${STRUCTURE} const & other);
169         void destroy(bool call_parent);
170
171         // other constructors
172 public:
173         ${STRUCTURE}(${constructor_arglist});
174
175         // functions overriding virtual functions from bases classes
176 public:
177         basic * duplicate() const;
178         void printraw(ostream & os) const;
179         void print(ostream & os, unsigned upper_precedence=0) const;
180         void printtree(ostream & os, unsigned indent) const;
181         int nops() const;
182         ex & let_op(int i);
183         ex expand(unsigned options=0) const;
184         bool has(const ex & other) const;
185         ex eval(int level=0) const;
186         ex evalf(int level=0) const;
187         ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
188         ex diff(const symbol & s) const;
189         ex subs(const lst & ls, const lst & lr) const;
190 protected:
191         int compare_same_type(const basic & other) const;
192         bool is_equal_same_type(const basic & other) const;
193         unsigned return_type(void) const;
194
195         // new virtual functions which can be overridden by derived classes
196         // none
197
198         // non-virtual functions in this class
199 public:
200 ${member_access_functions}
201         bool types_ok(void) const;
202         
203 // member variables
204 protected:
205 ${members}
206 public:
207 ${op_access_indices_decl}
208 };
209
210 // global constants
211
212 extern const ${STRUCTURE} some_${STRUCTURE};
213 extern const type_info & typeid_${STRUCTURE};
214 extern const unsigned tinfo_${STRUCTURE};
215
216 // macros
217
218 #define ex_to_${STRUCTURE}(X) (static_cast<${STRUCTURE} const &>(*(X).bp))
219
220 #ifndef NO_NAMESPACE_GINAC
221 } // namespace GiNaC
222 #endif // ndef NO_NAMESPACE_GINAC
223
224 #endif // ndef _${STRUCTURE_UC}_H_
225
226 END_OF_INTERFACE
227
228 $implementation=<<END_OF_IMPLEMENTATION;
229 /** \@file ${STRUCTURE}.cpp
230  *
231  *  Implementation of GiNaC's user defined structure ${STRUCTURE}. */
232
233 /*
234  *  This file was generated automatically by STRUCTURE.pl.
235  *  Please do not modify it directly, edit the perl script instead!
236  *
237  *  GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
238  *
239  *  This program is free software; you can redistribute it and/or modify
240  *  it under the terms of the GNU General Public License as published by
241  *  the Free Software Foundation; either version 2 of the License, or
242  *  (at your option) any later version.
243  *
244  *  This program is distributed in the hope that it will be useful,
245  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
246  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
247  *  GNU General Public License for more details.
248  *
249  *  You should have received a copy of the GNU General Public License
250  *  along with this program; if not, write to the Free Software
251  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
252  */
253
254 // structure.pl input:
255 ${input_structure}
256
257 #include <iostream>
258
259 #include "${STRUCTURE}.h"
260
261 #ifndef NO_NAMESPACE_GINAC
262 namespace GiNaC {
263 #endif // ndef NO_NAMESPACE_GINAC
264
265 //////////
266 // default constructor, destructor, copy constructor assignment operator and helpers
267 //////////
268
269 // public
270
271 ${STRUCTURE}::${STRUCTURE}()
272 {
273         debugmsg("${STRUCTURE} default constructor",LOGLEVEL_CONSTRUCT);
274         tinfo_key=tinfo_${STRUCTURE};
275 }
276
277 ${STRUCTURE}::~${STRUCTURE}()
278 {
279         debugmsg("${STRUCTURE} destructor",LOGLEVEL_DESTRUCT);
280         destroy(false);
281 }
282
283 ${STRUCTURE}::${STRUCTURE}(${STRUCTURE} const & other)
284 {
285         debugmsg("${STRUCTURE} copy constructor",LOGLEVEL_CONSTRUCT);
286         copy(other);
287 }
288
289 ${STRUCTURE} const & ${STRUCTURE}::operator=(${STRUCTURE} const & other)
290 {
291         debugmsg("${STRUCTURE} operator=",LOGLEVEL_ASSIGNMENT);
292         if (this != &other) {
293                 destroy(true);
294                 copy(other);
295         }
296         return *this;
297 }
298
299 // protected
300
301 void ${STRUCTURE}::copy(${STRUCTURE} const & other)
302 {
303         structure::copy(other);
304 ${copy_statements}
305 }
306
307 void ${STRUCTURE}::destroy(bool call_parent)
308 {
309         if (call_parent) structure::destroy(call_parent);
310 }
311
312 //////////
313 // other constructors
314 //////////
315
316 // public
317
318 ${STRUCTURE}::${STRUCTURE}(${constructor_arglist}) 
319         : ${constructor_statements}
320 {
321         debugmsg("${STRUCTURE} constructor from children", LOGLEVEL_CONSTRUCT);
322         tinfo_key=tinfo_${STRUCTURE};
323 }
324
325 //////////
326 // functions overriding virtual functions from bases classes
327 //////////
328
329 // public
330
331 basic * ${STRUCTURE}::duplicate() const
332 {
333         debugmsg("${STRUCTURE} duplicate",LOGLEVEL_DUPLICATE);
334         return new ${STRUCTURE}(*this);
335 }
336
337 void ${STRUCTURE}::printraw(ostream & os) const
338 {
339         debugmsg("${STRUCTURE} printraw",LOGLEVEL_PRINT);
340         os << "${STRUCTURE}()";
341 }
342
343 void ${STRUCTURE}::print(ostream & os, unsigned upper_precedence) const
344 {
345         debugmsg("${STRUCTURE} print",LOGLEVEL_PRINT);
346         os << "${STRUCTURE}()";
347 }
348
349 void ${STRUCTURE}::printtree(ostream & os, unsigned indent) const
350 {
351         debugmsg("${STRUCTURE} printtree",LOGLEVEL_PRINT);
352         os << "${STRUCTURE}()";
353 }
354
355 int ${STRUCTURE}::nops() const
356 {
357         return ${number_of_members};
358 }
359
360 ex & ${STRUCTURE}::let_op(int i)
361 {
362         GINAC_ASSERT(i>=0);
363         GINAC_ASSERT(i<nops());
364
365         switch (i) {
366 ${let_op_statements}
367         }
368         errormsg("${STRUCTURE}::let_op(): should not reach this point");
369         return *new ex(fail());
370 }
371
372 ex ${STRUCTURE}::expand(unsigned options) const
373 {
374         bool all_are_trivially_equal=true;
375 ${expand_statements}
376         if (all_are_trivially_equal) {
377                 return *this;
378         }
379         return ${STRUCTURE}(${temporary_arglist});
380 }
381
382 // a ${STRUCTURE} 'has' an expression if it is this expression itself or a child 'has' it
383
384 bool ${STRUCTURE}::has(const ex & other) const
385 {
386         GINAC_ASSERT(other.bp!=0);
387         if (is_equal(*other.bp)) return true;
388 ${has_statements}
389         return false;
390 }
391
392 ex ${STRUCTURE}::eval(int level) const
393 {
394         if (level==1) {
395                 return this->hold();
396         }
397         bool all_are_trivially_equal=true;
398 ${eval_statements}
399         if (all_are_trivially_equal) {
400                 return this->hold();
401         }
402         return ${STRUCTURE}(${temporary_arglist});
403 }
404
405 ex ${STRUCTURE}::evalf(int level) const
406 {
407         if (level==1) {
408                 return *this;
409         }
410         bool all_are_trivially_equal=true;
411 ${evalf_statements}
412         if (all_are_trivially_equal) {
413                 return *this;
414         }
415         return ${STRUCTURE}(${temporary_arglist});
416 }
417
418 /** Implementation of ex::normal() for ${STRUCTURE}s. It normalizes the arguments
419  *  and replaces the ${STRUCTURE} by a temporary symbol.
420  *  \@see ex::normal */
421 ex ${STRUCTURE}::normal(lst &sym_lst, lst &repl_lst, int level) const
422 {
423         if (level==1) {
424                 return basic::normal(sym_lst,repl_lst,level);
425         }
426         bool all_are_trivially_equal=true;
427 ${normal_statements}
428         if (all_are_trivially_equal) {
429                 return basic::normal(sym_lst,repl_lst,level);
430         }
431         ex n=${STRUCTURE}(${temporary_arglist});
432         return n.bp->basic::normal(sym_lst,repl_lst,level);
433 }
434
435 /** ${STRUCTURE}::diff() differentiates the children.
436         there is no need to check for triavially equal, since diff usually
437         does not return itself unevaluated. */
438 ex ${STRUCTURE}::diff(const symbol & s) const
439 {
440 ${diff_statements}
441         return ${STRUCTURE}(${temporary_arglist});
442 }
443
444 ex ${STRUCTURE}::subs(const lst & ls, const lst & lr) const
445 {
446         bool all_are_trivially_equal=true;
447 ${subs_statements}
448         if (all_are_trivially_equal) {
449                 return *this;
450         }
451         return ${STRUCTURE}(${temporary_arglist});
452 }
453
454 // protected
455
456 int ${STRUCTURE}::compare_same_type(const basic & other) const
457 {
458         GINAC_ASSERT(is_of_type(other,${STRUCTURE}));
459         ${STRUCTURE} const & o=static_cast<${STRUCTURE} const &>
460                                                                         (const_cast<basic &>(other));
461         int cmpval;
462 ${compare_statements}
463         return 0;
464 }
465
466 bool ${STRUCTURE}::is_equal_same_type(const basic & other) const
467 {
468         GINAC_ASSERT(is_of_type(other,${STRUCTURE}));
469         ${STRUCTURE} const & o=static_cast<${STRUCTURE} const &>
470                                                                         (const_cast<basic &>(other));
471 ${is_equal_statements}
472         return true;
473 }
474
475 unsigned ${STRUCTURE}::return_type(void) const
476 {
477         return return_types::noncommutative_composite;
478 }
479
480 //////////
481 // new virtual functions which can be overridden by derived classes
482 //////////
483
484 // none
485
486 //////////
487 // non-virtual functions in this class
488 //////////
489
490 // public
491
492 #define SKIP_TYPE_CHECK_FOR_ex
493 // this is a hack since there is no meaningful
494 // is_ex_exactly_of_type(...,ex) macro definition
495
496 bool ${STRUCTURE}::types_ok(void) const
497 {
498 ${types_ok_statements}
499         return true;
500 }
501
502 //////////
503 // static member variables
504 //////////
505
506 ${op_access_indices_def}
507
508 //////////
509 // global constants
510 //////////
511
512 const ${STRUCTURE} some_${STRUCTURE};
513 const type_info & typeid_${STRUCTURE}=typeid(some_${STRUCTURE});
514 const unsigned tinfo_${STRUCTURE}=structure::register_new("${STRUCTURE}");
515
516 #ifndef NO_NAMESPACE_GINAC
517 } // namespace GiNaC
518 #endif // ndef NO_NAMESPACE_GINAC
519
520 END_OF_IMPLEMENTATION
521
522 print "Creating interface file ${STRUCTURE}.h...";
523 open OUT,">${STRUCTURE}.h" or die "cannot open ${STRUCTURE}.h";
524 print OUT $interface;
525 close OUT;
526 print "ok.\n";
527
528 print "Creating implementation file ${STRUCTURE}.cpp...";
529 open OUT,">${STRUCTURE}.cpp" or die "cannot open ${STRUCTURE}.cpp";
530 print OUT $implementation;
531 close OUT;
532 print "ok.\n";
533
534 print "done.\n";