1 // -*- Mode : c++ -*-
2 //
3 // SUMMARY :
4 // USAGE :
5 // ORG :
6 // AUTHOR : Frederic Hecht
7 // E-MAIL : hecht@ann.jussieu.fr
8 //
9
10 /*
11
12 This file is part of Freefem++
13
14 Freefem++ is free software; you can redistribute it and/or modify
15 it under the terms of the GNU Lesser General Public License as published by
16 the Free Software Foundation; either version 2.1 of the License, or
17 (at your option) any later version.
18
19 Freefem++ is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU Lesser General Public License for more details.
23
24 You should have received a copy of the GNU Lesser General Public License
25 along with Freefem++; if not, write to the Free Software
26 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 */
28 //#pragma dont_inline on
29 //#pragma inline_depth(1)
30
31 // TODO: remove this block as soon as autoconf is removed from FreeFem++
32 #ifndef CMAKE
33 #include <config.h>
34 #endif
35
36 #include <complex>
37 #include "AFunction.hpp"
38 #include <cstdarg>
39 #include <cstring>
40 #include "error.hpp"
41 #include "lex.hpp"
42
43 #include "RNM.hpp"
44
45 #include "Operator.hpp"
46 // for exec routine
47 #include "rgraph.hpp"
48 #include "InitFunct.hpp"
49
50 vector<pair<const E_Routine*,int> > *debugstack=0;
51
52
53 class vectorOfInst : public E_F0mps { public:
54 int n;
55 Expression * v;
vectorOfInst(int k)56 vectorOfInst(int k): n(k),v(new Expression[k]) {ffassert(v);
57 for(int i=0;i<n;++i) v[i]=0; }
~vectorOfInst()58 ~vectorOfInst(){ delete [] v;}
empty() const59 bool empty() const {return n;}
60
operator ()(Stack s) const61 AnyType operator()(Stack s) const {
62 for (int i=0;i<n;++i)
63 {
64 ffassert(v[i]);
65 (*(v[i]))(s);
66 }
67 return Nothing;
68 }
eval(Stack s,int j=-1) const69 void eval(Stack s,int j=-1) const {
70 if(j>=0) j = n-j;
71 else j =0;
72 if(verbosity>999) cout << " eval vectorOfInst " << j << " " << n << endl;
73 for (int i=j;i<n;++i)
74 {
75 ffassert(v[i]);
76 (*(v[i]))(s);
77 }
78 }
79
80 private:
81 vectorOfInst(const vectorOfInst &);
82 void operator=(const vectorOfInst &);
83 };
84
85 double VersionNumber();
86
Find(const ArrayOfaType & at) const87 OneOperator::pair_find OneOperator::Find(const ArrayOfaType & at)const
88 {
89 const OneOperator *w=0,*oo;
90 int nn=0,p=-10000;
91 for (int ncast=0;ncast<=n;ncast++) // loop on the number of cast
92 {
93 p=-10000;
94 for (oo=this;oo;oo=oo->next)
95 if (oo->pref>=p && oo->WithCast(at,ncast))
96 {
97 if(p<oo->pref) {nn=0;p=oo->pref;}
98 nn++;
99 w=oo;}
100 if (nn) return make_pair(w,nn);
101 }
102 for (oo=this;oo;oo=oo->next)
103 if (oo->WithCast(at))
104 {nn++;
105 w=oo;}
106 return make_pair(w,nn);
107 }
108
FindWithOutCast(const ArrayOfaType & at) const109 OneOperator::pair_find OneOperator::FindWithOutCast(const ArrayOfaType & at)const
110 {
111 const OneOperator *w=0,*oo;
112 int n=0;
113 for (oo=this;oo;oo=oo->next)
114 if (oo->WithOutCast(at))
115 {n++;
116 w=oo;}
117 return make_pair(w,n);
118 }
119
120 // <<FindSameR>>
FindSameR(const ArrayOfaType & at)121 OneOperator* OneOperator::FindSameR(const ArrayOfaType & at)
122 {
123 if (this==tnull) return 0;
124 OneOperator *oo,*r;
125 int n=0;
126 for (oo=this;oo;oo=oo->next)
127 {
128 if (at==*oo) n++,r=oo;
129 else if (oo->WithOutCast(at)) n++,r=oo;
130 }
131 return n==1 ? r : 0;
132 }
133
Show(ostream & f) const134 void OneOperator::Show(ostream &f) const
135 {
136 const OneOperator *oo;
137 for (oo=this;oo;oo=oo->next)
138 f << "\t (" << *oo << ")\n";
139 }
140
Show(const ArrayOfaType & at,ostream & f) const141 void OneOperator::Show(const ArrayOfaType & at,ostream &f) const
142 {
143 const OneOperator *oo;
144 int n=0,np=0;
145 for (oo=this;oo;oo=oo->next)
146 if (oo->WithOutCast(at)) {n++;f << "\t (" << *oo << ")\n";}
147 if(n==0)
148 for (oo=this;oo;oo=oo->next)
149 if (oo->WithCast(at)) {
150 n++;
151 if (oo->pref) np++;
152 if (oo->pref)
153 f << " c(" << oo->pref << ") \t (" << *oo << ")\n" ;
154 else f << " \t c(" << *oo << ")\n";
155 }
156 if (n==0)
157 {
158 f << " List of choices "<< endl;
159 Show(f);
160 }
161 else if (np != 1)
162 f << " We have ambiguity " << n << endl;
163 }
164
Find(const char * op,const ArrayOfaType & at) const165 const OneOperator * Polymorphic::Find(const char *op, const ArrayOfaType &at) const
166 {
167 const_iterator i=m.find(op);
168 int nf=0;
169 if (i!=m.end())
170 {
171 OneOperator::pair_find r=i->second->Find(at);
172 if (r.second==1) return r.first;
173 nf=max(nf,r.second);
174 }
175 if(nf) { cerr << "\n Warning ambiguity Polymorphic Find "<< nf << endl;
176 Show(op,at,cerr); }
177 return 0;
178 }
FindWithOutCast(const char * op,const ArrayOfaType & at) const179 const OneOperator * Polymorphic::FindWithOutCast(const char *op, const ArrayOfaType &at) const
180 {
181 int nf=0;
182 const_iterator i=m.find(op);
183 if (i!=m.end())
184 {
185 OneOperator::pair_find r=i->second->FindWithOutCast(at);
186 if (r.second==1) return r.first;
187 nf=max(nf,r.second);
188 }
189 if(nf) { cerr << "\n Warning ambiguity Polymorphic FindWithOutCast "<<op<< " "<< nf << endl; Show(op,at,cerr);}
190 return 0;
191 }
192
193
Show(const char * op,const ArrayOfaType & at,ostream & f) const194 void Polymorphic::Show(const char *op,const ArrayOfaType & at,ostream &f) const
195 {
196 const_iterator i=m.find(op);
197 if (i==m.end()) f << " unknow " << op << " operator " << endl;
198 else i->second->Show(at,f);
199 }
200
201 // <<C_F0_constructor_pop_char_basicAC_F0_impl>> cf [[file:AFunction.hpp::C_F0_constructor_pop_char_basicAC_F0_decl]]
C_F0(const Polymorphic * poly,const char * op,const basicAC_F0 & p)202 C_F0::C_F0(const Polymorphic * poly,const char *op,const basicAC_F0 & p)
203 {
204 ArrayOfaType at(p);
205 if (poly) { // a Polymorphic => polymorphisme
206 const OneOperator * ff=poly->Find(op,at);
207 if (ff) {
208 if( verbosity>9999) {cout << endl;
209 poly->Show(op,at,cout);
210 cout << op << ": (in " << at << ") => " << " " << *ff<< "\n\n";}
211
212 // [[file:AFunction.hpp::OneOperator_code2]]
213 *this= ff->code2(p);
214 }
215 else
216 { if(mpirank==0)
217 {
218 cerr << " error operator " << op << " " << at << endl;
219 poly->Show(op,at,cerr);
220 poly->Find(op,at);
221 }
222 CompileError();
223 }
224 }
225 else {
226 // no polymorphisme
227 if(mpirank==0){
228 cerr << " const Polymorphic * poly,const char *op,const basicAC_F0 & p) " << endl;
229 cerr << op << " " << at << endl;
230
231 }
232 CompileError();
233 }
234 }
235
236 // operator without parameter
C_F0(const Polymorphic * pop,const char * op)237 C_F0::C_F0(const Polymorphic * pop,const char *op)
238 {
239 basicAC_F0 p;
240 p=0;
241 *this= C_F0(pop,op,p);
242 }
243 // operator unaire
C_F0(const Polymorphic * pop,const char * op,const C_F0 & aa)244 C_F0::C_F0(const Polymorphic * pop,const char *op,const C_F0 & aa)
245 {
246 basicAC_F0 p;
247 C_F0 a(aa);
248 p=a;
249 *this= C_F0(pop,op,p);
250 }
251
252 // <<C_F0_constructor_binary_operator>> operator binaire
C_F0(const Polymorphic * pop,const char * op,const C_F0 & a,const C_F0 & b)253 C_F0::C_F0(const Polymorphic * pop,const char *op,const C_F0 & a,const C_F0 & b)
254 {
255 C_F0 tab[2]={a,b};
256 basicAC_F0 p;
257 p=make_pair<int,C_F0*>(2,tab);
258
259 // [[file:AFunction.hpp::C_F0_constructor_pop_char_basicAC_F0_decl]]
260 *this=C_F0(pop,op,p);
261 }
262
263 // operator trinaire
C_F0(const Polymorphic * pop,const char * op,const C_F0 & a,const C_F0 & b,const C_F0 & c)264 C_F0::C_F0(const Polymorphic * pop,const char *op,const C_F0 & a,const C_F0 & b,const C_F0 & c)
265 {
266 C_F0 tab[3]={a,b,c};
267 basicAC_F0 p;
268 p=make_pair<int,C_F0*>(3,tab);
269 *this= C_F0(pop,op,p);
270 }
271
272
~OneOperator()273 OneOperator::~OneOperator(){
274 OneOperator * d=next;
275 next=0;
276 if(! CodeAlloc::cleanning) // hash FH (pour les fuite de m�moire)
277 while(d)
278 {
279 OneOperator * dd=d->next;
280 d->next=0;
281 delete d;
282 d=dd;
283 }
284 }
285
OneOperator(aType rr)286 OneOperator::OneOperator(aType rr)
287 : ArrayOfaType(),r(rr),next(0),pref(0) {throwassert(r);}
OneOperator(aType rr,aType a)288 OneOperator::OneOperator(aType rr,aType a)
289 : ArrayOfaType(a,false),r(rr),next(0),pref(0) {throwassert(rr && a );}
OneOperator(aType rr,aType a,aType b)290 OneOperator::OneOperator(aType rr,aType a,aType b)
291 : ArrayOfaType(a,b,false),r(rr),next(0),pref(0) {
292 throwassert(rr && a && b);}
OneOperator(aType rr,aType a,aType b,aType c)293 OneOperator::OneOperator(aType rr,aType a,aType b,aType c)
294 : ArrayOfaType(a,b,c,false),r(rr),next(0),pref(0)
295 {throwassert(rr && a && b && c);}
OneOperator(aType rr,aType a,aType b,aType c,aType d)296 OneOperator::OneOperator(aType rr,aType a,aType b,aType c,aType d)
297 : ArrayOfaType(a,b,c,d,false),r(rr),next(0),pref(0)
298 {throwassert(rr && a && b && c);}
299
OneOperator(aType rr,aType a,aType b,aType c,aType d,aType e)300 OneOperator::OneOperator(aType rr,aType a,aType b,aType c,aType d,aType e)
301 : ArrayOfaType(a,b,c,d,e,false),r(rr),next(0),pref(0)
302 {throwassert(rr && a && b && c && d);} // Added by Fabian Dortu (5 parameters)
OneOperator(aType rr,aType a,aType b,aType c,aType d,aType e,aType f)303 OneOperator::OneOperator(aType rr,aType a,aType b,aType c,aType d,aType e,aType f)
304 : ArrayOfaType(a,b,c,d,e,f,false),r(rr),next(0),pref(0)
305 {throwassert(rr && a && b && c && d && e && f);} // Added by Fabian Dortu (6 parameters)
OneOperator(aType rr,aType a,aType b,aType c,aType d,aType e,aType f,aType g)306 OneOperator::OneOperator(aType rr,aType a,aType b,aType c,aType d,aType e,aType f, aType g)
307 : ArrayOfaType(a,b,c,d,e,f,g,false),r(rr),next(0),pref(0)
308 {throwassert(rr && a && b && c && d && e && f && g);} // Added by Fabian Dortu (7 parameters)
OneOperator(aType rr,aType a,aType b,aType c,aType d,aType e,aType f,aType g,aType h)309 OneOperator::OneOperator(aType rr,aType a,aType b,aType c,aType d,aType e,aType f, aType g, aType h)
310 : ArrayOfaType(a,b,c,d,e,f,g,h,false),r(rr),next(0),pref(0)
311 {throwassert(rr && a && b && c && d && e && f && g && h);} // Added by Fabian Dortu (8 parameters)
OneOperator(aType rr,aType a,aType b,aType c,aType d,aType e,aType f,aType g,aType h,aType i)312 OneOperator::OneOperator(aType rr,aType a,aType b,aType c,aType d,aType e,aType f, aType g, aType h, aType i)
313 : ArrayOfaType(a,b,c,d,e,f,g,h,i,false),r(rr),next(0),pref(0)
314 {throwassert(rr && a && b && c && d && e && f && g && h && i);} // Added by Fabian Dortu (9 parameters)
OneOperator(aType rr,aType a,aType b,aType c,aType d,aType e,aType f,aType g,aType h,aType i,aType j)315 OneOperator::OneOperator(aType rr,aType a,aType b,aType c,aType d,aType e,aType f, aType g, aType h, aType i, aType j)
316 : ArrayOfaType(a,b,c,d,e,f,g,h,i,j,false),r(rr),next(0),pref(0)
317 {throwassert(rr && a && b && c && d && e && f && g && h && i && j);} // Added by Fabian Dortu (10 parameters)
318
319
320
OneOperator(aType rr,const ArrayOfaType & ta)321 OneOperator::OneOperator(aType rr,const ArrayOfaType &ta)
322 : ArrayOfaType(ta),r(rr),next(0),pref(0)
323 {throwassert(rr);}
OneOperator(aType rr,bool ellipse)324 OneOperator::OneOperator(aType rr,bool ellipse)
325 : ArrayOfaType(ellipse),r(rr),next(0),pref(0)
326 {throwassert(rr );}
OneOperator(aType rr,const ListOfId * l)327 OneOperator::OneOperator(aType rr,const ListOfId *l)
328 : ArrayOfaType(l),r(rr),next(0),pref(0)
329 {throwassert(rr );}
330
Addp(const char * op,Value pp,...) const331 void Polymorphic::Addp (const char *op, Value pp, ...) const {
332 pair<iterator,bool> p = m.insert(pair<const Key, Value>(op, pp));
333 Value f = p.first->second;
334 if (!p.second) // not insert => old
335 *f += *pp;
336 va_list ap;
337 va_start(ap, pp);
338 for (pp = va_arg(ap, OneOperator*); pp; pp = va_arg(ap, OneOperator*))
339 *f += *pp;
340 va_end(ap);
341 }
342
Add(const char * op,Value * pp) const343 void Polymorphic::Add(const char * op,Value *pp) const
344 {
345 if (*pp)
346 {
347 pair<iterator,bool> p=m.insert(pair<const Key,Value>(op,*pp));
348 Value f= p.first->second;
349 if (!p.second) // not insert => old
350 *f += **pp;
351 pp++;
352 for(;*pp;pp++)
353 *f += **pp;
354 }
355
356 }
357
358
359 // <<FindType>>
FindType(const char * name)360 int FindType(const char * name)
361 {
362 C_F0 r;
363
364 ListOfTOfId::const_iterator i=tables_of_identifier.begin();
365 for(;i!=tables_of_identifier.end();++i)
366 {
367 TableOfIdentifier * ti=*i;
368 r = ti->Find(name);
369 if (r.NotNull()) return r.TYPEOFID();
370 }
371 return 0;
372 }
373
374 /// <<Find>> uses [[file:global.cpp::tables_of_identifier]]
375
Find(const char * name)376 C_F0 Find(const char * name)
377 {
378 C_F0 r;
379 ListOfTOfId::const_iterator i=tables_of_identifier.begin();
380 for(;i!=tables_of_identifier.end();++i)
381 {
382 TableOfIdentifier * ti=*i;
383 r = ti->Find(name);
384 if (r.NotNull()) return r;
385 }
386 if(mpirank==0)
387 cerr << " The Identifier " << name << " does not exist " << endl;
388 CompileError();
389 return r;
390 }
391
newdestroy()392 vectorOfInst* TableOfIdentifier::newdestroy()
393 {
394 int k=0;
395 for (pKV * i=listofvar;i;i=i->second.next)
396 {
397 if (i->second.del && i->second.first->ExistDestroy() )
398 assert(i->second.first);
399 if (i->second.del && i->second.first->ExistDestroy() ) k++;
400 }
401 ffassert(nIdWithDelete==k);
402 // new code
403 vectorOfInst * l= new vectorOfInst(k);
404 int j=0;
405 for (pKV * i=listofvar;i;i=i->second.next)
406 if (i->second.del && i->second.first->ExistDestroy())
407 l->v[j++]=i->second.first->Destroy(i->second) ;
408 ffassert(j==k);
409 return l;
410 }
destroy()411 C_F0 TableOfIdentifier::destroy() {return C_F0(newdestroy());}
clear()412 void TableOfIdentifier::clear()
413 {
414 for (iterator i=m.begin();i!=m.end();++i)
415 {
416 // delete i->first;
417 }
418 m.clear();
419 }
420
Destroy(const C_F0 & e) const421 Expression basicForEachType::Destroy(const C_F0 & e) const
422 {
423 return destroy ? NewExpression(destroy,e) : (Expression) e;
424 }
425
~basicForEachType()426 basicForEachType::~basicForEachType()
427 {
428 if(casting) delete casting;
429 ti.clear();
430 }
431
basicForEachType(const type_info & k,const size_t s,const E_F1_funcT_Type * p,basicForEachType * rr,Function1 iv,Function1 id,Function1 dreturn)432 basicForEachType::basicForEachType(const type_info & k,
433 const size_t s,
434 const E_F1_funcT_Type * p,
435 basicForEachType *rr,
436 Function1 iv,Function1 id, Function1 dreturn)
437 : ktype(&k),//ktypefunc(0),
438 size(s),
439 un_ptr_type(rr?rr:this),
440 casting(0), // no casting to
441 un_ptr(p),
442 InitExp(iv),
443 DoOnReturn(dreturn),
444 //funct_type(0),
445 destroy(id) {}
SetArgs(const ListOfId * lid) const446 void basicForEachType::SetArgs(const ListOfId *lid) const
447 { SHOWVERB(cout << "SetArgs::\n ") ;ffassert(lid==0 || lid->size()==0);}
448
449
450
TableOfIdentifier()451 TableOfIdentifier::TableOfIdentifier() : listofvar(0),nIdWithDelete(0) {}
~TableOfIdentifier()452 TableOfIdentifier:: ~TableOfIdentifier() {}
453
454
Block(Block * f)455 Block::Block(Block * f):fatherblock(f),top(f?f->top:BeginOffset*sizeof(void*)),topmax(top)
456 {
457 itabl=tables_of_identifier.insert(tables_of_identifier.begin(),&table);
458 }
~Block()459 Block::~Block(){}
460
snewclose(Block * & c)461 vectorOfInst * Block::snewclose(Block *& c) {
462 Block * a=c;
463 tables_of_identifier.erase(a->itabl);
464 c=a->fatherblock;
465 if (a->fatherblock) {a->fatherblock->topmax=a->topmax;
466 a->fatherblock->top=a->top;}
467
468 vectorOfInst * r;
469 r = a->table.newdestroy();
470 delete a;
471 return r;}
472
close(Block * & c,C_F0 ins)473 CC_F0 Block::close(Block *& c,C_F0 ins)
474 {
475 CListOfInst inst;
476 CC_F0 cins; cins=ins;
477 inst = cins;
478 inst.setclose(Block::snewclose(c));
479 CC_F0 rr;
480 rr=inst;
481 return rr;
482 }
483
close(Block * & c,CListOfInst inst)484 CC_F0 Block::close(Block *& c,CListOfInst inst) {
485
486 inst.setclose(Block::snewclose(c));
487 CC_F0 rr;
488 rr=inst;
489 return rr;
490 }
491
open(Block * & cb)492 Block * Block::open(Block *& cb)
493 {
494 Block * ncb = new Block(cb);
495 if(verbosity>99) cout << " Block::open " << ncb << " " << cb << endl;
496
497 return cb = ncb;
498 }
499
500
New(Key k,const Type_Expr & v,bool del)501 const Type_Expr & TableOfIdentifier::New(Key k,const Type_Expr & v,bool del)
502 {
503 if( this != &Global) {
504 if ( Global.m.find(k) != Global.m.end() )
505 {
506 if(mpirank==0 && (verbosity>0))
507 cerr << "\n *** Warning The identifier " << k << " hide a Global identifier \n";
508
509 }
510 }
511 pair<iterator,bool> p=m.insert(pKV(k,Value(v,listofvar,del)));
512 listofvar = &*m.find(k);
513 if (!p.second)
514 {
515 if(mpirank==0) {
516 cerr << " The identifier " << k << " exists \n";
517 cerr << " \t the existing type is " << *p.first->second.first << endl;
518 cerr << " \t the new type is " << *v.first << endl;
519 }
520 CompileError();
521 }
522 if(del && v.first->ExistDestroy() )
523 {
524 nIdWithDelete++;
525 if(verbosity>9999) cout << "\n \t add ExistDestroy" << endl;
526
527 }
528 return v;
529 }
Add(Key k,Key op,OneOperator * p0,OneOperator * p1,OneOperator * p2,OneOperator * p3,OneOperator * p4,OneOperator * p5,OneOperator * p6)530 void TableOfIdentifier::Add(Key k,Key op,OneOperator *p0,OneOperator *p1,
531 OneOperator *p2,OneOperator *p3,OneOperator *p4,OneOperator *p5,OneOperator *p6)
532 {
533 iterator i= m.find(k);
534 if (i==m.end()) // new
535 {
536 Value poly0=Value(atype<Polymorphic*>(),new Polymorphic(),listofvar);
537 i=m.insert(pair<const Key,Value>(k,poly0)).first;
538 listofvar= &*i;
539 }
540 const Polymorphic * p= dynamic_cast<const Polymorphic *>(i->second.second);
541 if ( !p) {
542 if(mpirank==0)
543 cerr << k << " is not a Polymorphic id " << endl;
544 CompileError();
545 }
546 p->Add(op,p0,p1,p2,p3,p4,p5,p6);
547 }
548
ArrayOfaType(const ListOfId * l)549 ArrayOfaType::ArrayOfaType(const ListOfId * l)
550 : n(l->size()),t(new aType[n]),ellipse(false)
551 {
552 for (int i=0;i<n;i++)
553 {
554 t[i]=(*l)[i].r;
555 if ( ! t[i])
556 {
557 if(mpirank==0)
558 cerr << " Argument " << i << " '"<< (*l)[i].id << "' without type\n";
559 CompileError("DCL routine: Argument without type ");
560 }
561 }
562 }
563
WithOutCast(const ArrayOfaType & a) const564 bool ArrayOfaType::WithOutCast( const ArrayOfaType & a) const
565 {
566 if ( ( !ellipse && (a.n != n)) || (ellipse && n > a.n) ) return false;
567 for (int i=0;i<n;i++)
568 if (! a.t[i]->SametypeRight(t[i]))
569 return false;
570 return true;
571 }
572
573
WithCast(const ArrayOfaType & a,int nbcast) const574 bool ArrayOfaType::WithCast( const ArrayOfaType & a,int nbcast) const
575 {
576 if ( ( !ellipse && (a.n != n)) || (ellipse && n > a.n) ) return false;
577 for (int i=0;i<n;i++)
578 if ( a.t[i]->SametypeRight(t[i])) ;
579 else if (! t[i]->CastingFrom(a.t[i])) return false;
580 else if ( --nbcast <0) return false;
581 return true;
582 }
583
AddCast(CastFunc f1,CastFunc f2,CastFunc f3,CastFunc f4,CastFunc f5,CastFunc f6,CastFunc f7,CastFunc f8)584 void basicForEachType::AddCast(CastFunc f1,CastFunc f2,CastFunc f3,CastFunc f4,
585 CastFunc f5,CastFunc f6,CastFunc f7,CastFunc f8)
586 {
587 CastFunc ff[]={f1,f2,f3,f4,f5,f6,f7,f8,0};
588 for (int i=0;ff[i];i++)
589 {
590 ffassert(this == *ff[i] );
591 if (casting->FindSameR(*ff[i]))
592 {
593 if(mpirank==0)
594 {
595 cerr << " The casting to " << *ff[i] << " exists " << endl;
596 cerr << " List of cast " << endl;
597 casting->Show(cerr);
598 }
599 CompileError();
600 }
601 if (casting) *casting += *ff[i];
602 else casting = ff[i];
603 }
604 }
605
operator <<(ostream & f,const OneOperator & a)606 ostream & operator<<(ostream & f,const OneOperator & a)
607 {
608 f << "\t " << * (a.r) << " : " <<(const ArrayOfaType &) a;
609 return f;
610 }
611
operator <<(ostream & f,const Polymorphic & a)612 ostream & operator<<(ostream & f,const Polymorphic & a)
613 {
614 Polymorphic::const_iterator i;
615 if(&a==E_F0::tnull) return f << "Null " << endl;
616 for (i=a.m.begin();i!=a.m.end();i++)
617 {
618 f << " operator" << i->first << " : " << endl;
619 i->second->Show(f);
620 }
621 return f;
622 }
operator <<(ostream & f,const ArrayOfaType & a)623 ostream & operator<<(ostream & f,const ArrayOfaType & a)
624 {
625 for (int i=0;i<a.n;i++)
626 f << (i ? ", " : " ") << *a.t[i];
627 if (a.ellipse ) f << "... ";
628 else f << " ";
629 return f;}
operator <<(ostream & f,const TableOfIdentifier & t)630 ostream & operator<<(ostream & f,const TableOfIdentifier & t )
631 {
632 TableOfIdentifier::const_iterator i;
633 for(i=t.m.begin();i!=t.m.end();i++)
634 {
635 TableOfIdentifier::Value v=i->second;
636 f << i->first << ": " << *v.first << " <- " ;
637 const Polymorphic * p=dynamic_cast<const Polymorphic *>(v.second);
638 if(p) f << "Polymorphic " << *p << endl;
639 else f << " Simple @" << v.second << endl;
640 }
641 return f;
642 }
643
NewExpression(Function1 f,Expression a)644 Expression NewExpression(Function1 f,Expression a)
645 {
646 ffassert(f);
647 return new E_F0_Func1(f,a);
648 }
NewExpression(Function2 f,Expression a,Expression b)649 Expression NewExpression(Function2 f,Expression a,Expression b)
650 {
651 ffassert(f);
652 return new E_F0_Func2(f,a,b);
653
654 }
655
656 // <<ShowType>>
ShowType(ostream & f)657 void ShowType(ostream & f)
658 {
659
660 map<const string,basicForEachType *>::const_iterator i;
661 for(i=map_type.begin();i!=map_type.end();i++)
662 {
663 f << " --"<< i->first <<" = " ;
664 i->second->Show(f) ;
665 f << endl;
666 }
667
668 }
669
Show(ostream & f) const670 void basicForEachType::Show(ostream & f) const {
671 f << " " <<* this << endl;
672 if (casting) casting->Show(f) ;
673 if (ti.m.size())
674 {
675 TableOfIdentifier::const_iterator mc=ti.m.begin();
676 TableOfIdentifier::const_iterator end=ti.m.end();
677 for (;mc != end;mc++)
678 {
679 f << " " << mc->first << ", type :" << *mc->second.first << endl;
680 const Polymorphic * op =dynamic_cast<const Polymorphic *>(mc->second.second) ;
681 if ( op ) f << *op << endl;
682 }
683 }
684 }
685
686
687
688
689
E_Routine(const Routine * routine,const basicAC_F0 & args)690 E_Routine::E_Routine(const Routine * routine,const basicAC_F0 & args)
691 : code(routine->ins),
692 rt(routine->tret),
693 nbparam(args.size()),
694 param(new Expression[nbparam]),
695 name(routine->name)
696 {
697 assert(routine->ins);
698 for (int i=0;i<args.size();i++) // bug pb copie des string dec 2007 FH ???????????????
699 {
700 if(verbosity>10000) cout << "E_Routine " << *routine->param[i].r << " <- " << *args[i].left() << endl;
701 param[i]=routine->param[i].r->CastTo(args[i]);
702 }
703 };
704
~E_Routine()705 E_Routine::~E_Routine() {
706 if(verbosity>10000) cout << "~E_Routine()"<< endl;
707 delete [] param;}
operator ()(Stack s) const708 AnyType E_Routine::operator()(Stack s) const {
709 debugstack->push_back(pair<const E_Routine*,int>(this,TheCurrentLine));
710 const int lgsave=BeginOffset*sizeof(void*);
711 char save[lgsave];
712 AnyType ret=Nothing;
713 memcpy(save,s,lgsave); // save
714 AnyType *listparam;
715 Add2StackOfPtr2FreeA(s,listparam=new AnyType[nbparam]);
716
717 // to day the memory gestion of the local variable are static,
718 for (int i=0;i<nbparam;i++)
719 listparam[i]= (*param[i])(s); // set of the parameter
720 Stack_Ptr<AnyType>(s,ParamPtrOffset) = listparam;
721 WhereStackOfPtr2Free(s)=new StackOfPtr2Free(s);// FH mars 2006
722
723 try {
724 ret=(*code)(s);
725 }
726 catch( E_exception & e) {
727 if (e.type() == E_exception::e_return)
728 ret = e.r;
729 else
730 ErrorExec("E_exception: break or contine not in loop ",1);
731 }
732 catch(...) { // clean and rethrow the exception
733 WhereStackOfPtr2Free(s)->clean(); // FH mars 2005
734 memcpy(s,save,lgsave); // restore
735 TheCurrentLine=debugstack->back().second;
736 debugstack->pop_back();
737
738 throw ;
739 }
740
741 // (*clean)(s); // the clean is done in CleanE_Routine delete .
742 // delete [] listparam; after return
743 memcpy(s,save,lgsave); // restore
744 TheCurrentLine=debugstack->back().second;
745 debugstack->pop_back();
746
747 // il faudrait que les variable locale soit detruire apres le return
748 // cf routine clean, pour le cas ou l'on retourne un tableau local.
749 // plus safe ????? FH. (fait 2008)
750 // mais pb si a = f()+g() OK les pointeurs des instruction sont detruit
751 // en fin d'instruction programme de l'appelant FH 2007
752 // ... ou alors changer le return ???? qui doit copie le resultat.. (voir)
753 return ret;
754 }
755 extern Block *currentblock;// def in lg.ypp
Add(const C_F0 & ins)756 void ListOfInst::Add(const C_F0 & ins) {
757 if( (!ins.Empty()) ) {
758 if( verbosity > 9999 )
759 cout << " Add " << n << " " << TheCurrentLine << endl;
760 if (n%nx==0){
761 Expression * l = new Expression [n+nx];
762 int * ln = new int [n+nx];
763 int * lsd = new int [n+nx];
764 for (int i=0;i<n;i++) {
765 l[i]=list[i];
766 ln[i]=linenumber[i];
767 lsd[i]=lsldel[i];
768 }
769 delete [] list;
770 delete [] linenumber;
771 delete [] lsldel;
772 list =l;
773 linenumber=ln;
774 lsldel=lsd;
775 }
776 throwassert(list);
777 linenumber[n]= TheCurrentLine;
778 lsldel[n]=currentblock->nIdWithDelete();
779 list[n++] = ins;
780 }
781 }
782
783 /// <<ListOfInst::operator()>> Iteratively calls each item in the local array #list of type #Expression
784
operator ()(Stack s) const785 AnyType ListOfInst::operator()(Stack s) const {
786 AnyType r;
787 int i;
788 double s0=CPUtime(),s1=s0,ss0=s0;
789 StackOfPtr2Free * sptr = WhereStackOfPtr2Free(s);
790 try { // modif FH oct 2006
791 for (i=0;i<n;i++)
792 {
793 TheCurrentLine=linenumber[i] ;
794 r=(*list[i])(s);
795 sptr->clean(); // modif FH mars 2006 clean Ptr
796 s1=CPUtime();
797 if (showCPU)
798 cout << " CPU: "<< i <<" " << linenumber[i] << ": " << s1-s0 << "s" << " " << s1-ss0 << "s" << " / " << " " <<lsldel[i] << " " << mpirank << endl;
799 s0=CPUtime();
800 }
801 if(atclose && atclose->n) {
802 if(verbosity>99999 ) cout << " ListOfInst::atclose() " << n << " " << atclose->n << " // " << lsldel[n-1] << endl;
803 atclose->eval(s,atclose->n);}// Add for sep 2016 FH
804 }
805 catch( E_exception & e)
806 {
807 if(verbosity>999) cout << " catch E_exception " << i << " " << lsldel[i] << endl;
808 if(atclose) {atclose->eval(s,lsldel[i]);}// Add sep 2016 FH for clean init varaible
809 if (e.type() != E_exception::e_return)
810 sptr->clean(); // pour ne pas detruire la valeur retourne ... FH jan 2007
811 throw; // rethow
812 }
813 catch(...)
814 {
815 if(verbosity>999) cout << " catch .... " << i << " " << lsldel[i] << endl;
816 if(atclose) {atclose->eval(s,lsldel[i]);}
817 sptr->clean();
818 throw;
819 }
820 return r;}
821
ShowDebugStack()822 void ShowDebugStack()
823 {
824 if (mpisize)
825 cerr << " current line = " << TheCurrentLine
826 << " mpirank " << mpirank << " / " << mpisize <<endl;
827 else
828 cerr << " current line = " << TheCurrentLine << endl;
829 if(debugstack)
830 for (int i=0; i<debugstack->size(); ++i)
831 {
832
833 cerr << " call " << debugstack->at(i).first->name<< " at line "
834 <<debugstack->at(i).second << endl;
835 }
836 }
837
838
Optimize(deque<pair<Expression,int>> & l,MapOfE_F0 & m,size_t & n)839 int E_F0::Optimize(deque<pair<Expression,int> > &l,MapOfE_F0 & m, size_t & n)
840 {
841 int rr = find(m);
842 if (rr) return rr;
843 if( (verbosity / 10)% 10 == 1)
844 cout << "\n new expression : " << n << " mi=" << MeshIndependent()<< " " << typeid(*this).name()
845 << " :" << *this << endl;
846 return insert(this,l,m,n);
847 }
848
849
850 class E_F0para :public E_F0 { public:
851 const int i;
operator ()(Stack s) const852 AnyType operator()(Stack s) const {
853 return Stack_Ptr<AnyType>(s,ParamPtrOffset)[i];
854 }
E_F0para(int ii)855 E_F0para(int ii) : i(ii){}
856 };
857
Routine(aType tf,aType tr,const char * iden,ListOfId * l,Block * & cb)858 Routine::Routine(aType tf,aType tr,const char * iden, ListOfId *l,Block * & cb)
859 : OneOperator(tr,l),offset(cb->OffSet(sizeof(void*))),
860 tfunc(tf),tret(tr),name(iden),param(*l),
861 currentblock(new Block(cb)),ins(0)//,clean(0)
862 {
863 delete l; // add FH 24032005 (trap )
864 cb = currentblock;
865 for (size_t i=0;i<param.size();i++)
866 {
867 currentblock->NewID(param[i].r,param[i].id,C_F0(new E_F0para(i),// modif FH 2007
868 param[i].r),
869 !param[i].ref);
870 }
871 }
Set(CListOfInst instrs)872 Block * Routine::Set(CListOfInst instrs)
873 {
874 instrs.setclose(Block::snewclose(currentblock));
875 ins=instrs;
876 return currentblock;}
877
878
code(const basicAC_F0 & args) const879 E_F0 * Routine::code(const basicAC_F0 & args) const
880 {
881
882 return new E_Routine(this,args);
883 }
884
SetNameParam(int n,name_and_type * l,Expression * e) const885 void basicAC_F0::SetNameParam(int n,name_and_type *l , Expression * e) const
886 {
887 int k=0;
888 if ( !n && !named_parameter) return;
889
890 for (int i=0;i<n;i++)
891 {
892 C_F0 ce=find(l[i].name) ;
893 if (ce.LeftValue()==0)
894 e[i]=0;
895 else {
896 if(!map_type[l[i].type->name()] )
897 {
898 if(mpirank==0)
899 {
900 cerr << " missing ff type: '" <<l[i].type->name() << "' "<< map_type.size() << "\n";
901 cerr << "i= " << i << "\n";
902 }
903 InternalError(" missing type ");
904 assert(map_type[l[i].type->name()]);
905 }
906 e[i]= map_type[l[i].type->name()]->CastTo(ce);
907 k++;
908 }
909 }
910
911 if (!named_parameter) return;
912
913 if ((size_t) k!= named_parameter->size())
914 {
915 cout << " Sorry some name parameter are not used! found" << k << " == " << named_parameter->size() <<endl;
916 for(const_iterator ii=named_parameter->begin(); ii != named_parameter->end();ii++)
917 {
918 for (int i=0;i<n;i++)
919 if (!strcmp(l[i].name,ii->first))
920 goto L1;
921 cout << "\t the parameter is '" << ii->first << "' is unused " << endl;
922 L1:;
923 }
924 if ( n && mpirank==0) {
925 cerr << " The named parameter can be " << endl;
926 for (int i=0;i<n;i++)
927 cerr << "\t" << l[i].name << " = <" << l[i].type->name() << ">\n";
928 }
929 CompileError("Unused named parameter");
930 }
931 }
932
933
934 // change FH to bluid .dll
935
lgerror(const char * s)936 void lgerror (const char* s)
937 {
938 if(mpirank==0)
939 {
940 cerr << endl;
941 cerr <<" Error line number " << zzzfff->lineno() << ", in file " << zzzfff->filename()
942 <<", before token " <<zzzfff->YYText() << endl
943 << s << endl;
944 }
945 throw(ErrorCompile(s,zzzfff->lineno(),zzzfff->YYText() ));
946 }
947
948
949
ForAll(Block * cb,ListOfId * id,C_F0 m)950 C_F0 ForAll(Block *cb,ListOfId * id,C_F0 m)
951 {
952
953 //Block::open(cb); // new block
954 // decl variable
955 if(verbosity>1000)
956 cout << "InitAutoLoop ::: " << id->size()<< " type=" << *(m.left()) << endl;
957
958 ffassert(id->size()<4);
959 aType t=m.left() ;
960 ffassert(id->size()<=0 || t->typev);
961 ffassert(id->size()<=1 || t->typei);
962 ffassert(id->size()<=2 || t->typej);
963 // missing this king of code atype<T>->SetTypeLoop(atype<string**>(),atype<K*>()) maybe !!!! FH.
964 ffassert(id->size()<4);
965 // find the size do data
966 aType tt[4];
967 int k=0;
968 if(t->typei) tt[k++]=t->typei;
969 if(t->typej) tt[k++]=t->typej;
970 if(t->typev) tt[k++]=t->typev;
971
972 for(int i=0;i<k;++i)
973 {
974 if(verbosity>1000)
975 cout << " aType = " << i << " left " << *tt[i] << " right="<< *tt[i]->right() <<endl;
976 }
977 AC_F0 args;
978 args=0; // reset
979 args+=m;
980 for(int j=0,i=id->size(); j<id->size() ; ++j)
981 {
982 --i;
983 C_F0 ci=cb->NewVar<LocalVariable>((*id)[i].id,tt[i]);
984 C_F0 cv=Find((*id)[i].id);
985 args+=cv;
986 const LocalVariable *lv = dynamic_cast<LocalVariable*>((E_F0*) cv);
987 if(verbosity>1000)
988 cout << " new id " << tt[i] << " "<< (*id)[i].id << " " << " E="
989 << (Expression) args[j] << " "
990 << (Expression) ci << " " <<args.size()-1 << " ov: " << (lv ? lv->offset: -1) << " " << *cv.left() << endl;
991 }
992 Expression loop= new PolymorphicLoop(m,args);
993 if(verbosity>1000)
994 cout << "a type: " << *atype<PolymorphicLoop*>() << " " << loop << endl;
995
996 return C_F0(loop,atype<PolymorphicLoop*>());
997 }
998
ForAll(C_F0 cloop,C_F0 inst)999 C_F0 ForAll(C_F0 cloop,C_F0 inst)
1000 {
1001 if(verbosity>1000)
1002 cout << " type cloop " << *cloop.left() << " " << cloop.LeftValue() << " " << endl;
1003 const PolymorphicLoop *loop= dynamic_cast<const PolymorphicLoop *>(cloop.LeftValue());
1004 ffassert(loop);
1005 AC_F0 args;
1006 args=0;
1007 args+=loop->t;
1008 args+=cloop;
1009 C_F0 instt(inst,atype<NothingType>());
1010 args+=instt;
1011 return C_F0(TheOperators,"{}",args);
1012 }
1013
InitLoop()1014 void InitLoop()
1015 {
1016 Dcl_Type<PolymorphicLoop*>(0);
1017
1018 }
1019