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