]> www.ginac.de Git - ginac.git/blob - ginac/container.pl
- created AUTHORS and README files, updated INSTALL
[ginac.git] / ginac / container.pl
1 #!/usr/bin/perl -w
2
3 if ($#ARGV!=0) {
4     die 'usage: container.pl type (type=lst or exprseq)';
5 }
6
7 if ($ARGV[0] eq 'lst') {
8     $type='lst';
9 } elsif ($ARGV[0] eq 'exprseq') {
10     $type='exprseq';
11 } else {
12     die 'only lst and exprseq supported';
13 }
14
15 #$type='lst';
16 #$type='exprseq';
17
18 if ($type eq 'exprseq') {
19
20     # settings for exprseq
21     $CONTAINER="exprseq";
22     $STLHEADER="vector";
23     $reserve=1;
24     $prepend=0;
25     $let_op=0;
26     $open_bracket='(';
27     $close_bracket=')';
28     
29 } elsif ($type eq 'lst') {
30  
31     # settings for lst
32     $CONTAINER="lst";
33     $STLHEADER="list";
34     $reserve=0;
35     $prepend=1;
36     $let_op=1;
37     $open_bracket='[';
38     $close_bracket=']';
39
40 } else {
41     die "invalid type $type";
42 }
43
44 $CONTAINER_UC=uc(${CONTAINER});
45 $STLT="ex".$STLHEADER;
46
47 if ($reserve) {
48     $RESERVE_IMPLEMENTATION="#define RESERVE(s,size) (s).reserve(size)";
49 } else {
50     $RESERVE_IMPLEMENTATION="#define RESERVE(s,size) // no reserve needed for ${STLHEADER}";
51 }
52
53 if ($prepend) {
54     $PREPEND_INTERFACE=<<END_OF_PREPEND_INTERFACE;
55     virtual ${CONTAINER} & prepend(ex const & b);
56 END_OF_PREPEND_INTERFACE
57
58     $PREPEND_IMPLEMENTATION=<<END_OF_PREPEND_IMPLEMENTATION;
59 ${CONTAINER} & ${CONTAINER}::prepend(ex const & b)
60 {
61     ensure_if_modifiable();
62     seq.push_front(b);
63     return *this;
64 }
65 END_OF_PREPEND_IMPLEMENTATION
66 } else {
67     $PREPEND_INTERFACE="    // no prepend possible for ${CONTAINER}";
68     $PREPEND_IMPLEMENTATION="";
69 }
70
71 if ($let_op) {
72     $LET_OP_IMPLEMENTATION=<<END_OF_LET_OP_IMPLEMENTATION
73 ex & ${CONTAINER}::let_op(int const i)
74 {
75     ASSERT(i>=0);
76     ASSERT(i<nops());
77
78     ${STLT}::iterator it=seq.begin();
79     for (int j=0; j<i; j++) {
80         ++it;
81     }
82     return *it;
83 }
84 END_OF_LET_OP_IMPLEMENTATION
85 } else {
86     $LET_OP_IMPLEMENTATION="// ${CONTAINER}::let_op() will be implemented by user elsewhere";
87 }
88
89 $interface=<<END_OF_INTERFACE;
90 /** \@file ${CONTAINER}.h
91  *
92  *  Definition of GiNaC's ${CONTAINER}. 
93  *  This file was generated automatically by container.pl.
94  *  Please do not modify it directly, edit the perl script instead!
95  *  container.pl options: \$CONTAINER=${CONTAINER}
96  *                        \$STLHEADER=${STLHEADER}
97  *                        \$reserve=${reserve}
98  *                        \$prepend=${prepend}
99  *                        \$let_op=${let_op}
100  *                        \$open_bracket=${open_bracket}
101  *                        \$close_bracket=${close_bracket} */
102
103 #ifndef _${CONTAINER_UC}_H_
104 #define _${CONTAINER_UC}_H_
105
106 #include <${STLHEADER}>
107
108 #include <ginac/ginac.h>
109
110 typedef ${STLHEADER}<ex> ${STLT};
111
112 class ${CONTAINER} : public basic
113 {
114
115 public:
116     ${CONTAINER}();
117     ~${CONTAINER}();
118     ${CONTAINER}(${CONTAINER} const & other);
119     ${CONTAINER} const & operator=(${CONTAINER} const & other);
120 protected:
121     void copy(${CONTAINER} const & other);
122     void destroy(bool call_parent);
123
124 public:
125     ${CONTAINER}(${STLT} const & s, bool discardable=0);
126     ${CONTAINER}(${STLT} * vp); // vp will be deleted
127     explicit ${CONTAINER}(ex const & e1);
128     explicit ${CONTAINER}(ex const & e1, ex const & e2);
129     explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3);
130     explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
131              ex const & e4);
132     explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
133              ex const & e4, ex const & e5);
134     explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
135              ex const & e4, ex const & e5, ex const & e6);
136     explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
137              ex const & e4, ex const & e5, ex const & e6,
138              ex const & e7);
139     explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
140              ex const & e4, ex const & e5, ex const & e6,
141              ex const & e7, ex const & e8);
142     explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
143              ex const & e4, ex const & e5, ex const & e6,
144              ex const & e7, ex const & e8, ex const & e9);
145     explicit ${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
146              ex const & e4, ex const & e5, ex const & e6,
147              ex const & e7, ex const & e8, ex const & e9,
148              ex const &e10);
149
150 public:
151     basic * duplicate() const;
152     void printraw(ostream & os) const;
153     void print(ostream & os, unsigned upper_precedence=0) const;
154     void printtree(ostream & os, unsigned indent) const;
155     bool info(unsigned inf) const;
156     int nops() const;
157     ex & let_op(int const i);
158     ex expand(unsigned options=0) const;
159     bool has(ex const & other) const;
160     ex eval(int level=0) const;
161     ex evalf(int level=0) const;
162     ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
163     ex diff(symbol const & s) const;
164     ex subs(lst const & ls, lst const & lr) const;
165 protected:
166     int compare_same_type(basic const & other) const;
167     bool is_equal_same_type(basic const & other) const;
168     unsigned return_type(void) const;
169
170     // new virtual functions which can be overridden by derived classes
171 public:
172     virtual ${CONTAINER} & append(ex const & b);
173 ${PREPEND_INTERFACE}
174 protected:
175     virtual void printseq(ostream & os, char openbracket, char delim,
176                           char closebracket, unsigned this_precedence,
177                           unsigned upper_precedence=0) const;
178     virtual ex this${CONTAINER}(${STLT} const & v) const;
179     virtual ex this${CONTAINER}(${STLT} * vp) const;
180
181 protected:
182     bool is_canonical() const;
183     ${STLT} evalchildren(int level) const;
184     ${STLT} evalfchildren(int level) const;
185     ${STLT} normalchildren(int level) const;
186     ${STLT} diffchildren(symbol const & s) const;
187     ${STLT} * subschildren(lst const & ls, lst const & lr) const;
188
189 protected:
190     ${STLT} seq;
191     static unsigned precedence;
192 };
193
194 // global constants
195
196 extern const ${CONTAINER} some_${CONTAINER};
197 extern type_info const & typeid_${CONTAINER};
198
199 // macros
200
201 #define ex_to_${CONTAINER}(X) (static_cast<${CONTAINER} const &>(*(X).bp))
202
203 #endif // ndef _${CONTAINER_UC}_H_
204
205 END_OF_INTERFACE
206
207 $implementation=<<END_OF_IMPLEMENTATION;
208 /** \@file ${CONTAINER}.cpp
209  *
210  *  Implementation of GiNaC's ${CONTAINER}. 
211  *  This file was generated automatically by container.pl.
212  *  Please do not modify it directly, edit the perl script instead!
213  *  container.pl options: \$CONTAINER=${CONTAINER}
214  *                        \$STLHEADER=${STLHEADER}
215  *                        \$reserve=${reserve}
216  *                        \$prepend=${prepend}
217  *                        \$let_op=${let_op}
218  *                        \$open_bracket=${open_bracket}
219  *                        \$close_bracket=${close_bracket} */
220
221 #include <iostream>
222 #include <stdexcept>
223
224 #include "ginac.h"
225
226 ${RESERVE_IMPLEMENTATION}
227
228 //////////
229 // default constructor, destructor, copy constructor assignment operator and helpers
230 //////////
231
232 // public
233
234 ${CONTAINER}::${CONTAINER}() : basic(TINFO_${CONTAINER_UC})
235 {
236     debugmsg("${CONTAINER} default constructor",LOGLEVEL_CONSTRUCT);
237 }
238
239 ${CONTAINER}::~${CONTAINER}()
240 {
241     debugmsg("${CONTAINER} destructor",LOGLEVEL_DESTRUCT);
242     destroy(0);
243 }
244
245 ${CONTAINER}::${CONTAINER}(${CONTAINER} const & other)
246 {
247     debugmsg("${CONTAINER} copy constructor",LOGLEVEL_CONSTRUCT);
248     copy(other);
249 }
250
251 ${CONTAINER} const & ${CONTAINER}::operator=(${CONTAINER} const & other)
252 {
253     debugmsg("${CONTAINER} operator=",LOGLEVEL_ASSIGNMENT);
254     if (this != &other) {
255         destroy(1);
256         copy(other);
257     }
258     return *this;
259 }
260
261 // protected
262
263 void ${CONTAINER}::copy(${CONTAINER} const & other)
264 {
265     basic::copy(other);
266     seq=other.seq;
267 }
268
269 void ${CONTAINER}::destroy(bool call_parent)
270 {
271     seq.clear();
272     if (call_parent) basic::destroy(call_parent);
273 }
274
275 //////////
276 // other constructors
277 //////////
278
279 // public
280
281 ${CONTAINER}::${CONTAINER}(${STLT} const & s, bool discardable) :  basic(TINFO_${CONTAINER_UC})
282 {
283     debugmsg("${CONTAINER} constructor from ${STLT}",
284              LOGLEVEL_CONSTRUCT);
285     if (discardable) {
286         seq.swap(const_cast<${STLT} &>(s));
287     } else {
288         seq=s;
289     }
290 }
291
292 ${CONTAINER}::${CONTAINER}(${STLT} * vp) : basic(TINFO_${CONTAINER_UC})
293 {
294     debugmsg("${CONTAINER} constructor from ${STLT} *",LOGLEVEL_CONSTRUCT);
295     ASSERT(vp!=0);
296     seq.swap(*vp);
297     delete vp;
298 }
299
300 ${CONTAINER}::${CONTAINER}(ex const & e1) :  basic(TINFO_${CONTAINER_UC})
301 {
302     debugmsg("${CONTAINER} constructor from 1 ex",
303              LOGLEVEL_CONSTRUCT);
304     RESERVE(seq,1);
305     seq.push_back(e1);
306 }
307
308 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2) : basic(TINFO_${CONTAINER_UC})
309 {
310     debugmsg("${CONTAINER} constructor from 2 ex",
311              LOGLEVEL_CONSTRUCT);
312     RESERVE(seq,2);
313     seq.push_back(e1);
314     seq.push_back(e2);
315 }
316
317 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3)
318     : basic(TINFO_${CONTAINER_UC})
319 {
320     debugmsg("${CONTAINER} constructor from 3 ex",
321              LOGLEVEL_CONSTRUCT);
322     RESERVE(seq,3);
323     seq.push_back(e1);
324     seq.push_back(e2);
325     seq.push_back(e3);
326 }
327
328 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
329                      ex const & e4) : basic(TINFO_${CONTAINER_UC})
330 {
331     debugmsg("${CONTAINER} constructor from 4 ex",
332              LOGLEVEL_CONSTRUCT);
333     RESERVE(seq,4);
334     seq.push_back(e1);
335     seq.push_back(e2);
336     seq.push_back(e3);
337     seq.push_back(e4);
338 }
339
340 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
341                      ex const & e4, ex const & e5) : basic(TINFO_${CONTAINER_UC})
342 {
343     debugmsg("${CONTAINER} constructor from 5 ex",
344              LOGLEVEL_CONSTRUCT);
345     RESERVE(seq,5);
346     seq.push_back(e1);
347     seq.push_back(e2);
348     seq.push_back(e3);
349     seq.push_back(e4);
350     seq.push_back(e5);
351 }
352
353 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
354                      ex const & e4, ex const & e5, ex const & e6)
355     : basic(TINFO_${CONTAINER_UC})
356 {
357     debugmsg("${CONTAINER} constructor from 6 ex",
358              LOGLEVEL_CONSTRUCT);
359     RESERVE(seq,6);
360     seq.push_back(e1);
361     seq.push_back(e2);
362     seq.push_back(e3);
363     seq.push_back(e4);
364     seq.push_back(e5);
365     seq.push_back(e6);
366 }
367
368 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
369                      ex const & e4, ex const & e5, ex const & e6,
370                      ex const & e7) : basic(TINFO_${CONTAINER_UC})
371 {
372     debugmsg("${CONTAINER} constructor from 7 ex",
373              LOGLEVEL_CONSTRUCT);
374     RESERVE(seq,7);
375     seq.push_back(e1);
376     seq.push_back(e2);
377     seq.push_back(e3);
378     seq.push_back(e4);
379     seq.push_back(e5);
380     seq.push_back(e6);
381     seq.push_back(e7);
382 }
383
384 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
385                      ex const & e4, ex const & e5, ex const & e6,
386                      ex const & e7, ex const & e8) : basic(TINFO_${CONTAINER_UC})
387 {
388     debugmsg("${CONTAINER} constructor from 8 ex",
389              LOGLEVEL_CONSTRUCT);
390     RESERVE(seq,8);
391     seq.push_back(e1);
392     seq.push_back(e2);
393     seq.push_back(e3);
394     seq.push_back(e4);
395     seq.push_back(e5);
396     seq.push_back(e6);
397     seq.push_back(e7);
398     seq.push_back(e8);
399 }
400
401 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
402                      ex const & e4, ex const & e5, ex const & e6,
403                      ex const & e7, ex const & e8, ex const & e9)
404     : basic(TINFO_${CONTAINER_UC})
405 {
406     debugmsg("${CONTAINER} constructor from 9 ex",
407              LOGLEVEL_CONSTRUCT);
408     RESERVE(seq,9);
409     seq.push_back(e1);
410     seq.push_back(e2);
411     seq.push_back(e3);
412     seq.push_back(e4);
413     seq.push_back(e5);
414     seq.push_back(e6);
415     seq.push_back(e7);
416     seq.push_back(e8);
417     seq.push_back(e9);
418 }
419
420 ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
421                      ex const & e4, ex const & e5, ex const & e6,
422                      ex const & e7, ex const & e8, ex const & e9,
423                      ex const &e10)
424     : basic(TINFO_${CONTAINER_UC})
425 {
426     debugmsg("${CONTAINER} constructor from 10 ex",
427              LOGLEVEL_CONSTRUCT);
428     RESERVE(seq,10);
429     seq.push_back(e1);
430     seq.push_back(e2);
431     seq.push_back(e3);
432     seq.push_back(e4);
433     seq.push_back(e5);
434     seq.push_back(e6);
435     seq.push_back(e7);
436     seq.push_back(e8);
437     seq.push_back(e9);
438     seq.push_back(e10);
439 }
440
441 //////////
442 // functions overriding virtual functions from bases classes
443 //////////
444
445 // public
446
447 basic * ${CONTAINER}::duplicate() const
448 {
449     debugmsg("${CONTAINER} duplicate",LOGLEVEL_DUPLICATE);
450     return new ${CONTAINER}(*this);
451 }
452
453 void ${CONTAINER}::printraw(ostream & os) const
454 {
455     debugmsg("${CONTAINER} printraw",LOGLEVEL_PRINT);
456
457     os << "${CONTAINER}(";
458     for (${STLT}::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
459         (*cit).bp->printraw(os);
460         os << ",";
461     }
462     os << ")";
463 }
464
465 void ${CONTAINER}::print(ostream & os, unsigned upper_precedence) const
466 {
467     debugmsg("${CONTAINER} print",LOGLEVEL_PRINT);
468     // always print brackets around seq, ignore upper_precedence
469     printseq(os,'${open_bracket}',',','${close_bracket}',precedence,precedence+1);
470 }
471
472 void ${CONTAINER}::printtree(ostream & os, unsigned indent) const
473 {
474     debugmsg("${CONTAINER} printtree",LOGLEVEL_PRINT);
475
476     os << string(indent,' ') << "type=" << typeid(*this).name()
477        << ", hash=" << hashvalue << " (0x" << hex << hashvalue << dec << ")"
478        << ", flags=" << flags
479        << ", nops=" << nops() << endl;
480     for (${STLT}::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
481         (*cit).printtree(os,indent+delta_indent);
482     }
483     os << string(indent+delta_indent,' ') << "=====" << endl;
484 }
485
486 // ${CONTAINER}::info() will be implemented by user elsewhere";
487
488 int ${CONTAINER}::nops() const
489 {
490     return seq.size();
491 }
492
493 ${LET_OP_IMPLEMENTATION}
494
495 ex ${CONTAINER}::expand(unsigned options) const
496 {
497     ${STLT} s;
498     RESERVE(s,seq.size());
499     for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
500         s.push_back((*it).expand(options));
501     }
502
503     return this${CONTAINER}(s);
504 }
505
506 // a ${CONTAINER} 'has' an expression if it is this expression itself or a child 'has' it
507
508 bool ${CONTAINER}::has(ex const & other) const
509 {
510     ASSERT(other.bp!=0);
511     if (is_equal(*other.bp)) return true;
512     for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
513         if ((*it).has(other)) return true;
514     }
515     return false;
516 }
517
518 ex ${CONTAINER}::eval(int level) const
519 {
520     if (level==1) {
521         return this->hold();
522     }
523     return this${CONTAINER}(evalchildren(level));
524 }
525
526 ex ${CONTAINER}::evalf(int level) const
527 {
528     return this${CONTAINER}(evalfchildren(level));
529 }
530
531 /** Implementation of ex::normal() for ${CONTAINER}s. It normalizes the arguments
532  *  and replaces the ${CONTAINER} by a temporary symbol.
533  *  \@see ex::normal */
534 ex ${CONTAINER}::normal(lst &sym_lst, lst &repl_lst, int level) const
535 {
536     ex n=this${CONTAINER}(normalchildren(level));
537     return n.bp->basic::normal(sym_lst,repl_lst,level);
538 }
539
540 ex ${CONTAINER}::diff(symbol const & s) const
541 {
542     return this${CONTAINER}(diffchildren(s));
543 }
544
545 ex ${CONTAINER}::subs(lst const & ls, lst const & lr) const
546 {
547     ${STLT} * vp=subschildren(ls,lr);
548     if (vp==0) {
549         return *this;
550     }
551     return this${CONTAINER}(vp);
552 }
553
554 // protected
555
556 int ${CONTAINER}::compare_same_type(basic const & other) const
557 {
558     ASSERT(is_of_type(other,${CONTAINER}));
559     ${CONTAINER} const & o=static_cast<${CONTAINER} const &>
560                                     (const_cast<basic &>(other));
561     int cmpval;
562     ${STLT}::const_iterator it1=seq.begin();
563     ${STLT}::const_iterator it2=o.seq.begin();
564
565     for (; (it1!=seq.end())&&(it2!=o.seq.end()); ++it1, ++it2) {
566         cmpval=(*it1).compare(*it2);
567         if (cmpval!=0) return cmpval;
568     }
569
570     if (it1==seq.end()) {
571         return (it2==o.seq.end() ? 0 : -1);
572     }
573
574     return 1;
575 }
576
577 bool ${CONTAINER}::is_equal_same_type(basic const & other) const
578 {
579     ASSERT(is_of_type(other,${CONTAINER}));
580     ${CONTAINER} const & o=static_cast<${CONTAINER} const &>
581                                     (const_cast<basic &>(other));
582     if (seq.size()!=o.seq.size()) return false;
583
584     ${STLT}::const_iterator it1=seq.begin();
585     ${STLT}::const_iterator it2=o.seq.begin();
586
587     for (; it1!=seq.end(); ++it1, ++it2) {
588         if (!(*it1).is_equal(*it2)) return false;
589     }
590
591     return true;
592 }
593
594 unsigned ${CONTAINER}::return_type(void) const
595 {
596     return return_types::noncommutative_composite;
597 }
598
599 //////////
600 // new virtual functions which can be overridden by derived classes
601 //////////
602
603 // public
604
605 ${CONTAINER} & ${CONTAINER}::append(ex const & b)
606 {
607     ensure_if_modifiable();
608     seq.push_back(b);
609     return *this;
610 }
611
612 ${PREPEND_IMPLEMENTATION}
613
614 // protected
615
616 void ${CONTAINER}::printseq(ostream & os, char openbracket, char delim,
617                          char closebracket, unsigned this_precedence,
618                          unsigned upper_precedence) const
619 {
620     if (this_precedence<=upper_precedence) os << openbracket;
621     if (seq.size()!=0) {
622         ${STLT}::const_iterator it,it_last;
623         it=seq.begin();
624         it_last=seq.end();
625         --it_last;
626         for (; it!=it_last; ++it) {
627             (*it).bp->print(os,this_precedence);
628             os << delim;
629         }
630         (*it).bp->print(os,this_precedence);
631     }
632     if (this_precedence<=upper_precedence) os << closebracket;
633 }
634
635 ex ${CONTAINER}::this${CONTAINER}(${STLT} const & v) const
636 {
637     return ${CONTAINER}(v);
638 }
639
640 ex ${CONTAINER}::this${CONTAINER}(${STLT} * vp) const
641 {
642     return ${CONTAINER}(vp);
643 }
644
645 //////////
646 // non-virtual functions in this class
647 //////////
648
649 // public
650
651 // none
652
653 // protected
654
655 bool ${CONTAINER}::is_canonical() const
656 {
657     if (seq.size()<=1) { return 1; }
658
659     ${STLT}::const_iterator it=seq.begin();
660     ${STLT}::const_iterator it_last=it;
661     for (++it; it!=seq.end(); it_last=it, ++it) {
662         if ((*it_last).compare(*it)>0) {
663             if ((*it_last).compare(*it)>0) {
664                 cout << *it_last << ">" << *it << "\\n";
665                 return 0;
666                 }
667         }
668     }
669     return 1;
670 }
671
672
673 ${STLT} ${CONTAINER}::evalchildren(int level) const
674 {
675     ${STLT} s;
676     RESERVE(s,seq.size());
677
678     if (level==1) {
679         return seq;
680     }
681     if (level == -max_recursion_level) {
682         throw(std::runtime_error("max recursion level reached"));
683     }
684     --level;
685     for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
686         s.push_back((*it).eval(level));
687     }
688     return s;
689 }
690
691 ${STLT} ${CONTAINER}::evalfchildren(int level) const
692 {
693     ${STLT} s;
694     RESERVE(s,seq.size());
695
696     if (level==1) {
697         return seq;
698     }
699     if (level == -max_recursion_level) {
700         throw(std::runtime_error("max recursion level reached"));
701     }
702     --level;
703     for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
704         s.push_back((*it).evalf(level));
705     }
706     return s;
707 }
708
709 ${STLT} ${CONTAINER}::normalchildren(int level) const
710 {
711     ${STLT} s;
712     RESERVE(s,seq.size());
713
714     if (level==1) {
715         return seq;
716     }
717     if (level == -max_recursion_level) {
718         throw(std::runtime_error("max recursion level reached"));
719     }
720     --level;
721     for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
722         s.push_back((*it).normal(level));
723     }
724     return s;
725 }
726
727 ${STLT} ${CONTAINER}::diffchildren(symbol const & y) const
728 {
729     ${STLT} s;
730     RESERVE(s,seq.size());
731     for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
732         s.push_back((*it).diff(y));
733     }
734     return s;
735 }
736
737 /* obsolete subschildren
738 ${STLT} ${CONTAINER}::subschildren(lst const & ls, lst const & lr) const
739 {
740     ${STLT} s;
741     RESERVE(s,seq.size());
742     for (${STLT}::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
743         s.push_back((*it).subs(ls,lr));
744     }
745     return s;
746 }
747 */
748
749 ${STLT} * ${CONTAINER}::subschildren(lst const & ls, lst const & lr) const
750 {
751     // returns a NULL pointer if nothing had to be substituted
752     // returns a pointer to a newly created epvector otherwise
753     // (which has to be deleted somewhere else)
754
755     ${STLT}::const_iterator last=seq.end();
756     ${STLT}::const_iterator cit=seq.begin();
757     while (cit!=last) {
758         ex const & subsed_ex=(*cit).subs(ls,lr);
759         if (!are_ex_trivially_equal(*cit,subsed_ex)) {
760
761             // something changed, copy seq, subs and return it
762             ${STLT} *s=new ${STLT};
763             RESERVE(*s,seq.size());
764
765             // copy parts of seq which are known not to have changed
766             ${STLT}::const_iterator cit2=seq.begin();
767             while (cit2!=cit) {
768                 s->push_back(*cit2);
769                 ++cit2;
770             }
771             // copy first changed element
772             s->push_back(subsed_ex);
773             ++cit2;
774             // copy rest
775             while (cit2!=last) {
776                 s->push_back((*cit2).subs(ls,lr));
777                 ++cit2;
778             }
779             return s;
780         }
781         ++cit;
782     }
783     
784     return 0; // nothing has changed
785 }
786
787 //////////
788 // static member variables
789 //////////
790
791 // protected
792
793 unsigned ${CONTAINER}::precedence=10;
794
795 //////////
796 // global constants
797 //////////
798
799 const ${CONTAINER} some_${CONTAINER};
800 type_info const & typeid_${CONTAINER}=typeid(some_${CONTAINER});
801
802 END_OF_IMPLEMENTATION
803
804 print "Creating interface file ${CONTAINER}.h...";
805 open OUT,">${CONTAINER}.h" or die "cannot open ${CONTAINER}.h";
806 print OUT $interface;
807 close OUT;
808 print "ok.\n";
809
810 print "Creating implementation file ${CONTAINER}.cpp...";
811 open OUT,">${CONTAINER}.cpp" or die "cannot open ${CONTAINER}.cpp";
812 print OUT $implementation;
813 close OUT;
814 print "ok.\n";
815
816 print "done.\n";