1 /***************************************************************************
2                           prognodeexpr.cpp  -  GDL's AST is made of DNodes
3                              -------------------
4     begin                : July 22 2002
5     copyright            : (C) 2002 by Marc Schellens
6     email                : m_schellens@users.sf.net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "includefirst.hpp"
19 
20 #include <memory>
21 #include <cassert>
22 
23 #include <antlr/ASTFactory.hpp>
24 
25 #include "dinterpreter.hpp"
26 #include "prognodeexpr.hpp"
27 #include "basegdl.hpp"
28 #include "arrayindexlistt.hpp"
29 #include "envt.hpp"
30 #include "gdlexception.hpp"
31 #include "nullgdl.hpp"
32 #include "basic_fun.hpp"
33 #include "basic_fun_jmg.hpp"
34 
35 #include "initsysvar.hpp"
36 
37 using namespace std;
38 
39 
BinaryExpr(const RefDNode & refNode)40 BinaryExpr::BinaryExpr( const RefDNode& refNode): DefaultNode( refNode)
41 {
42   op1 = GetFirstChild();
43   op2 = GetFirstChild()->GetNextSibling();
44   setType( GDLTokenTypes::EXPR);
45 }
46 
BinaryExprNC(const RefDNode & refNode)47 BinaryExprNC::BinaryExprNC( const RefDNode& refNode): BinaryExpr( refNode)
48 {
49   op1NC = NonCopyNode( op1->getType());
50   op2NC = NonCopyNode( op2->getType());
51 }
52 
ProgNode()53 ProgNode::ProgNode(): // for NULLProgNode
54   ttype( antlr::Token::NULL_TREE_LOOKAHEAD),
55   text( "NULLProgNode"),
56 	keepRight( false),
57 	keepDown( false),
58 	breakTarget( NULL),
59   down( NULL),
60   right( NULL),
61   cData( NULL),
62   var( NULL),
63   libFun( NULL),
64   libPro( NULL),
65   lineNumber( 0),
66   labelStart( 0),
67   labelEnd( 0)
68 {}
69 
EvalNC()70 BaseGDL* ProgNode::EvalNC()
71 {
72   throw GDLException( this,
73 		      "Internal error. ProgNode::EvalNC() called.",true,false);
74 }
EvalNCNull()75 BaseGDL* ProgNode::EvalNCNull()
76 {
77   return this->EvalNC();
78 }
79 
LEval()80 BaseGDL** ProgNode::LEval()
81 {
82   throw GDLException( this,
83 		      "Internal error. ProgNode::LEval() called.",true,false);
84 }
EvalRefCheck(BaseGDL * & rEval)85 BaseGDL** ProgNode::EvalRefCheck( BaseGDL*& rEval) // default like Eval()
86 {
87   rEval = this->Eval();
88   return NULL;
89 }
90 
Run()91 RetCode   ProgNode::Run()
92 {
93   throw GDLException( this,
94 		      "Internal error. ProgNode::Run() called.",true,false);
95   return RC_OK; // silence compiler
96 }
97 
SetRightDown(const ProgNodeP r,const ProgNodeP d)98 void ProgNode::SetRightDown( const ProgNodeP r, const ProgNodeP d)
99 {
100   right = r;
101   down  = d;
102 }
103 
Eval()104 BaseGDL* ProgNode::Eval()
105 {
106   throw GDLException( this,
107 		      "Internal error. ProgNode::Eval() called.",true,false);
108 //   return ProgNode::interpreter->expr( this);
109 }
110 
111 
112 
113 // converts inferior type to superior type
114 // for not (yet) overloaded operators
AdjustTypes(Guard<BaseGDL> & a,Guard<BaseGDL> & b)115 void ProgNode::AdjustTypes(Guard<BaseGDL>& a, Guard<BaseGDL>& b)
116 {
117   DType aTy=a->Type();
118   DType bTy=b->Type();
119   if( aTy == bTy) return;
120 
121   // Will be checked by Convert2() function
122 //   if( DTypeOrder[aTy] > 100 || DTypeOrder[bTy] > 100) // GDL_STRUCT, GDL_PTR, OBJ
123 //     {
124 //       //exception
125 //       throw GDLException( "Expressions of this type cannot be converted.");
126 //     }
127 
128   // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
129     DType cxTy = PromoteComplexOperand( aTy, bTy);
130     if( cxTy != GDL_UNDEF)
131     {
132       a.reset( a.release()->Convert2( cxTy));
133       b.reset( b.release()->Convert2( cxTy));
134       return;
135     }
136 
137   // Change > to >= JMG
138   if( DTypeOrder[aTy] >= DTypeOrder[bTy])
139     {
140       // convert b to a
141       b.reset( b.release()->Convert2( aTy));
142     }
143   else
144     {
145       // convert a to b
146       a.reset( a.release()->Convert2( bTy));
147     }
148 }
149 // converts inferior type to superior type
150 // handles overloaded operators
AdjustTypesObj(Guard<BaseGDL> & a,Guard<BaseGDL> & b)151 void ProgNode::AdjustTypesObj(Guard<BaseGDL>& a, Guard<BaseGDL>& b)
152 {
153   DType aTy=a->Type();
154   DType bTy=b->Type();
155   if( aTy == bTy) return;
156 
157   // Will be checked by Convert2() function
158 //   if( DTypeOrder[aTy] > 100 || DTypeOrder[bTy] > 100) // GDL_STRUCT, GDL_PTR, OBJ
159 //     {
160 //       //exception
161 //       throw GDLException( "Expressions of this type cannot be converted.");
162 //     }
163 
164   // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
165     DType cxTy = PromoteComplexOperand( aTy, bTy);
166     if( cxTy != GDL_UNDEF)
167     {
168       a.reset( a.release()->Convert2( cxTy));
169       b.reset( b.release()->Convert2( cxTy));
170       return;
171     }
172 
173   // Change > to >= JMG
174   if( DTypeOrder[aTy] >= DTypeOrder[bTy])
175     {
176       // convert b to a
177       if( aTy == GDL_OBJ) // only check for aTy is ok because GDL_OBJ has highest order
178 	return; // for operator overloading, do not convert other type then
179       b.reset( b.release()->Convert2( aTy));
180     }
181   else
182     {
183       // convert a to b
184       if( bTy == GDL_OBJ) // only check for bTy is ok because GDL_OBJ has highest order
185 	return; // for operator overloading, do not convert other type then
186       a.reset( a.release()->Convert2( bTy));
187     }
188 }
189 
190 // for not (yet) overloaded operators
AdjustTypesNC(Guard<BaseGDL> & g1,BaseGDL * & e1,Guard<BaseGDL> & g2,BaseGDL * & e2)191 void BinaryExprNC::AdjustTypesNC(Guard<BaseGDL>& g1, BaseGDL*& e1,
192 				 Guard<BaseGDL>& g2, BaseGDL*& e2)
193 {
194   if( op1NC)
195     {
196       e1 = op1->EvalNC();
197     }
198   else
199     {
200       e1 = op1->Eval();
201       g1.reset( e1);
202     }
203   if( op2NC)
204     {
205       e2 = op2->EvalNC();
206     }
207   else
208     {
209       e2 = op2->Eval();
210       g2.reset( e2);
211     }
212 
213   DType aTy=e1->Type();
214   DType bTy=e2->Type();
215   if( aTy == bTy) return;
216 
217   // Will be checked by Convert2() function
218 //   if( DTypeOrder[aTy] > 100 || DTypeOrder[bTy] > 100) // GDL_STRUCT, GDL_PTR, OBJ
219 //     {
220 //       throw GDLException( "Expressions of this type cannot be converted.");
221 //     }
222     DType cxTy = PromoteComplexOperand( aTy, bTy);
223     if( cxTy != GDL_UNDEF)
224     {
225 	  e2 = e2->Convert2( cxTy, BaseGDL::COPY);
226 	  g2.reset( e2); // delete former e2
227 	  e1 = e1->Convert2( cxTy, BaseGDL::COPY);
228 	  g1.reset( e1); // delete former e1
229 	  return;
230     }
231 
232   // Change > to >= JMG
233   if( DTypeOrder[aTy] >= DTypeOrder[bTy])
234     {
235 //       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
236 //       if( (aTy == GDL_COMPLEX && bTy == GDL_DOUBLE))
237 // 	{
238 // 	  e2 = e2->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
239 // 	  g2.reset( e2); // delete former e2
240 // 	  e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
241 // 	  g1.reset( e1); // delete former e1
242 // 	  return;
243 // 	}
244 
245       // convert e2 to e1
246       e2 = e2->Convert2( aTy, BaseGDL::COPY);
247       g2.reset( e2); // delete former e2
248     }
249   else
250     {
251 //       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
252 //       if( (bTy == GDL_COMPLEX && aTy == GDL_DOUBLE))
253 // 	{
254 // 	  e2 = e2->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
255 // 	  g2.reset( e2); // delete former e2
256 // 	  e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
257 // 	  g1.reset( e1); // delete former e1
258 // 	  return;
259 // 	}
260 
261       // convert e1 to e2
262       e1 = e1->Convert2( bTy, BaseGDL::COPY);
263       g1.reset( e1); // delete former e1
264     }
265 }
266 
267 // handles overloaded operators
SetupGuards(Guard<BaseGDL> & g1,BaseGDL * & e1,Guard<BaseGDL> & g2,BaseGDL * & e2)268 void BinaryExprNC::SetupGuards(Guard<BaseGDL>& g1, BaseGDL*& e1,
269 				 Guard<BaseGDL>& g2, BaseGDL*& e2)
270 {
271   if( op1NC)
272     {
273       e1 = op1->EvalNC();
274     }
275   else
276     {
277       e1 = op1->Eval();
278       g1.Init( e1);
279     }
280   if( op2NC)
281     {
282       e2 = op2->EvalNC();
283     }
284   else
285     {
286       e2 = op2->Eval();
287       g2.Init( e2);
288     }
289 }
290 
291 
292 // only called from EqOp and NeOp
293 // also handles overloaded operators
AdjustTypesNCNull(Guard<BaseGDL> & g1,BaseGDL * & e1,Guard<BaseGDL> & g2,BaseGDL * & e2)294 void BinaryExprNC::AdjustTypesNCNull(Guard<BaseGDL>& g1, BaseGDL*& e1,
295 				 Guard<BaseGDL>& g2, BaseGDL*& e2)
296 {
297   if( op1NC)
298     {
299       e1 = op1->EvalNCNull();
300     }
301   else
302     {
303       e1 = op1->Eval();
304       g1.Init( e1);
305     }
306   if( op2NC)
307     {
308       e2 = op2->EvalNCNull();
309     }
310   else
311     {
312       e2 = op2->Eval();
313       g2.Init( e2);
314     }
315 
316   // if at least one is !NULL make sure this is e1
317   if( e1 == NullGDL::GetSingleInstance())
318     return;
319   if( e2 == NullGDL::GetSingleInstance())
320   {
321     // e1 is not !NULL (but might be NULL)
322 //     BaseGDL* tmp = e1;
323 //     e1 = e2;
324 //     e2 = tmp;
325     e2 = e1;
326     e1 = NullGDL::GetSingleInstance();
327     return;
328   }
329 
330   if( e1 == NULL)
331   {
332     // provoke error
333     e1 = op1->EvalNC();
334     assert( false); // code should never reach here
335   }
336   else if(  e2 == NULL)
337   {
338     // provoke error
339     e2 = op2->EvalNC();
340     assert( false); // code should never reach here
341   }
342 
343   DType aTy=e1->Type();
344   DType bTy=e2->Type();
345   if( aTy == bTy) return;
346 
347   // Will be checked by Convert2() function
348 //   if( DTypeOrder[aTy] > 100 || DTypeOrder[bTy] > 100) // GDL_STRUCT, GDL_PTR, OBJ
349 //     {
350 //       throw GDLException( "Expressions of this type cannot be converted.");
351 //     }
352 
353   // Change > to >= JMG
354     DType cxTy = PromoteComplexOperand( aTy, bTy);
355     if( cxTy != GDL_UNDEF)
356     {
357 	  e2 = e2->Convert2( cxTy, BaseGDL::COPY);
358 	  g2.Reset( e2); // delete former e2
359 	  e1 = e1->Convert2( cxTy, BaseGDL::COPY);
360 	  g1.Reset( e1); // delete former e1
361 	  return;
362     }
363 
364     if( DTypeOrder[aTy] >= DTypeOrder[bTy])
365     {
366 //       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
367 //       if( (aTy == GDL_COMPLEX && bTy == GDL_DOUBLE))
368 // 	{
369 // 	  e2 = e2->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
370 // 	  g2.Reset( e2); // delete former e2
371 // 	  e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
372 // 	  g1.Reset( e1); // delete former e1
373 // 	  return;
374 // 	}
375 
376       // no conversion because of operator overloads
377       if( aTy == GDL_OBJ) // only check for aTy is ok because GDL_OBJ has highest order
378 	return;
379 
380       // convert e2 to e1
381       e2 = e2->Convert2( aTy, BaseGDL::COPY);
382       g2.Reset( e2); // delete former e2
383     }
384   else
385     {
386 //       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
387 //       if( (bTy == GDL_COMPLEX && aTy == GDL_DOUBLE))
388 // 	{
389 // 	  e2 = e2->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
390 // 	  g2.Reset( e2); // delete former e2
391 // 	  e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
392 // 	  g1.Reset( e1); // delete former e1
393 // 	  return;
394 // 	}
395 
396       // no conversion because of operator overloads
397       if( bTy == GDL_OBJ) // only check for bTy is ok because GDL_OBJ has highest order
398 	return;
399 
400       // convert e1 to e2
401       e1 = e1->Convert2( bTy, BaseGDL::COPY);
402       g1.Reset( e1); // delete former e1
403     }
404 }
405 
Eval()406 BaseGDL* VARNode::Eval()
407 {
408     BaseGDL* vData = this->EvalNC();
409 	if( vData == NULL)
410         {
411             throw GDLException( this, "Variable is undefined: "+this->getText(),true,false);
412         }
413 	return vData->Dup();
414 }
Eval()415 BaseGDL* VARPTRNode::Eval()
416 {
417     BaseGDL* vData = this->EvalNC();
418 	if( vData == NULL)
419         {
420             throw GDLException( this, "Common block variable is undefined.",true,false);
421         }
422 	return vData->Dup();
423 }
Eval()424 BaseGDL* SYSVARNode::Eval()
425 {
426   return this->EvalNC()->Dup();
427 }
428 
EvalNC()429 BaseGDL* VARNode::EvalNC()
430 {
431 	EnvStackT& callStack=interpreter->CallStack();
432 	BaseGDL* res=static_cast<EnvUDT*> ( callStack.back() )->GetKW ( this->varIx );
433 	if ( res == NULL )
434 		throw GDLException ( this, "Variable is undefined: "+
435 		                     callStack.back()->GetString ( this->varIx ),true,false );
436 	return res;
437 }
EvalNCNull()438 BaseGDL* VARNode::EvalNCNull()
439 {
440 	EnvStackT& callStack=interpreter->CallStack();
441 	BaseGDL* res=static_cast<EnvUDT*> ( callStack.back() )->GetKW ( this->varIx );
442 // 	if ( res == NULL )
443 // 	  res = NullGDL::GetSingleInstance();
444 	return res;
445 }
446 
EvalNC()447 BaseGDL* VARPTRNode::EvalNC()
448 {
449       BaseGDL* res=this->var->Data();
450       if( res == NULL)
451 	{
452 	  EnvStackT& callStack=interpreter->CallStack();
453 	  throw GDLException( this, "Variable is undefined: "+
454 			      callStack.back()->GetString( res),true,false);
455 	}
456       return res;
457 }
EvalNCNull()458 BaseGDL* VARPTRNode::EvalNCNull()
459 {
460       BaseGDL* res=this->var->Data();
461 //       if( res == NULL)
462 // 	  res = NullGDL::GetSingleInstance();
463       return res;
464 }
465 
EvalNC()466 BaseGDL* CONSTANTNode::EvalNC()
467 {
468   return this->cData;
469 }
Eval()470 BaseGDL* CONSTANTNode::Eval()
471 {
472   return this->cData->Dup();
473 }
474 
EvalNC()475 BaseGDL* SYSVARNode::EvalNC()
476 {
477   //GD: explore also obsoleteSysVarList (costs nothing)
478   if( this->var == NULL)
479     {
480       this->var=FindInVarList(sysVarList,this->getText());
481       if( this->var == NULL)	{
482         this->var=FindInVarList(obsoleteSysVarList,this->getText());
483         if( this->var == NULL) throw GDLException( this, "Not a legal system variable: !"+this->getText(),true,false);
484       }
485     }
486 
487   // we have these two variables which need to be updated before returning
488   if( SysVar::STime() == this->var->Data()) SysVar::UpdateSTime();
489 //  if( SysVar::D() == this->var->Data()) SysVar::UpdateD();
490 
491   // system variables are always defined
492   return this->var->Data();
493 }
494 
EvalRefCheck(BaseGDL * & rEval)495 BaseGDL** SYSVARNode::EvalRefCheck( BaseGDL*& rEval)
496 {
497   return this->LEval();
498 }
499 
LEval()500 BaseGDL** SYSVARNode::LEval()
501 {
502   const ProgNodeP& sysVar = this;
503   //match(antlr::RefAST(_t),SYSVAR);
504   if( sysVar->var == NULL)
505   {
506     sysVar->var=FindInVarList(sysVarList,sysVar->getText());
507     if( sysVar->var == NULL) {
508       sysVar->var = FindInVarList(obsoleteSysVarList, sysVar->getText());
509       if (sysVar->var == NULL) {
510          throw GDLException( sysVar, "Not a legal system variable: !"+sysVar->getText(),true,false);
511       }
512     }
513 
514     // note: this works, because system variables are never
515     //       passed by reference
516     SizeT rdOnlySize = sysVarRdOnlyList.size();
517     for( SizeT i=0; i<rdOnlySize; ++i)
518       if( sysVarRdOnlyList[ i] == sysVar->var)
519 	throw GDLException( this,
520 	"Attempt to write to a readonly variable: !"+
521 	sysVar->getText(),true,false);
522   }
523 //   interpreter->SetRetTree( sysVar->getNextSibling());
524   // system variables are always defined
525   return &sysVar->var->Data();
526 }
527 
528 
Eval()529 BaseGDL* DEREFNode::Eval()
530 {
531   Guard<BaseGDL> e1_guard;
532   BaseGDL* e1;
533   ProgNodeP evalExpr = this->getFirstChild();
534   if( NonCopyNode( evalExpr->getType()))
535     {
536       e1 = evalExpr->EvalNC();
537     }
538   else
539     {
540       BaseGDL** ref = evalExpr->EvalRefCheck(e1);
541       if( ref == NULL)
542 	  // here a guard is ok here as we return a copy
543 	  e1_guard.Init( e1);
544       else
545 	  e1 = *ref;
546     }
547 
548   if( e1 == NULL || e1->Type() != GDL_PTR)
549   throw GDLException( evalExpr, "Pointer type required"
550 		      " in this context: "+interpreter->Name(e1),true,false);
551 
552   DPtrGDL* ptr=static_cast<DPtrGDL*>(e1);
553 
554   DPtr sc;
555   if( !ptr->StrictScalar(sc))
556     throw GDLException( this, "Expression must be a scalar in this context: "+
557 				interpreter->Name(e1),true,false);
558   if( sc == 0)
559     throw GDLException( this, "Unable to dereference NULL pointer: "+
560 				interpreter->Name(e1),true,false);
561 
562   BaseGDL** res;
563   try{
564     res = &interpreter->GetHeap(sc);
565   }
566   catch( DInterpreter::HeapException)
567   {
568     throw GDLException( this, "Invalid pointer: "+interpreter->Name(e1),true,false);
569   }
570 
571   if( *res == NULL)
572 	  throw GDLException( this, "Variable is undefined: "+
573 				      interpreter->Name(res),true,false);
574   return (*res)->Dup();
575 }
576 
EvalNC()577 BaseGDL* DEREFNode::EvalNC()
578 {
579   BaseGDL* e1;
580   ProgNodeP evalExpr = this->getFirstChild();
581   if( NonCopyNode( evalExpr->getType()))
582     {
583       e1 = evalExpr->EvalNC();
584     }
585   else
586     {
587       BaseGDL** ref = evalExpr->EvalRefCheck(e1);
588       if( ref == NULL)
589       {
590 	  // use new env if set (during parameter parsing)
591 	  EnvBaseT* actEnv = DInterpreter::CallStackBack()->GetNewEnv();
592 	  if( actEnv == NULL) actEnv = DInterpreter::CallStackBack();
593 	  assert( actEnv != NULL);
594 	  // this is crucial, a guard does not work here as a temporary
595 	  // ptr will be cleaned up at return from this function
596 	  actEnv->DeleteAtExit( e1);
597       }
598       else
599 	  e1 = *ref;
600     }
601 
602   if( e1 == NULL || e1->Type() != GDL_PTR)
603     throw GDLException( this, "Pointer type required"
604 			" in this context: "+interpreter->Name(e1),true,false);
605   DPtrGDL* ptr=static_cast<DPtrGDL*>(e1);
606   DPtr sc;
607   if( !ptr->Scalar(sc))
608     throw GDLException( this, "Expression must be a "
609 			"scalar in this context: "+interpreter->Name(e1),true,false);
610   if( sc == 0)
611     throw GDLException( this, "Unable to dereference"
612 			" NULL pointer: "+interpreter->Name(e1),true,false);
613 
614   try{
615     return interpreter->GetHeap(sc);
616   }
617   catch( GDLInterpreter::HeapException)
618     {
619       throw GDLException( this, "Invalid pointer: "+interpreter->Name(e1),true,false);
620     }
621 }
622 
EvalRefCheck(BaseGDL * & rEval)623 BaseGDL** DEREFNode::EvalRefCheck( BaseGDL*& rEval)
624 {
625   return this->LEval();
626 }
627 
LEval()628 BaseGDL** DEREFNode::LEval()
629 {
630   BaseGDL* e1;
631   ProgNodeP evalExpr = this->getFirstChild();
632   if( NonCopyNode( evalExpr->getType()))
633     {
634       e1 = evalExpr->EvalNC();
635     }
636   else
637     {
638       BaseGDL** ref = evalExpr->EvalRefCheck(e1);
639       if( ref == NULL)
640       {
641 	  // use new env if set (during parameter parsing)
642 	  EnvBaseT* actEnv = DInterpreter::CallStackBack()->GetNewEnv();
643 	  if( actEnv == NULL) actEnv = DInterpreter::CallStackBack();
644 	  assert( actEnv != NULL);
645 	  // this is crucial, a guard does not work here as a temporary
646 	  // ptr will be cleaned up at return from this function
647 	  actEnv->DeleteAtExit( e1);
648       }
649       else
650 	  e1 = *ref;
651     }
652 
653   if( e1 == NULL || e1->Type() != GDL_PTR)
654     throw GDLException( evalExpr, "Pointer type required in this context: "+
655 				    interpreter->Name(e1),true,false);
656 
657   DPtrGDL* ptr=static_cast<DPtrGDL*>(e1);
658 
659   DPtr sc;
660   if( !ptr->StrictScalar(sc))
661   throw GDLException( this, "Expression must be a scalar in this context: "+
662 			      interpreter->Name(e1),true,false);
663   if( sc == 0)
664   throw GDLException( this, "Unable to dereference NULL pointer: "+
665 			      interpreter->Name(e1),true,false);
666 
667   BaseGDL** res;
668   try{
669     res = &interpreter->GetHeap(sc);
670   }
671   catch( DInterpreter::HeapException)
672   {
673     throw GDLException( this, "Invalid pointer: "+interpreter->Name(e1),true,false);
674   }
675 
676   return res;
677 }
678 
679 
680 
681 
682 
683 // trinary operator
EvalRefCheck(BaseGDL * & rEval)684 BaseGDL** QUESTIONNode::EvalRefCheck( BaseGDL*& rEval)
685 {
686   ProgNodeP branch = this->GetThisBranch();
687   return branch->EvalRefCheck( rEval);
688 }
689 
LEval()690 BaseGDL** QUESTIONNode::LEval()
691 {
692   ProgNodeP branch = this->GetThisBranch();
693   return branch->LEval();
694 }
695 
Eval()696 BaseGDL* QUESTIONNode::Eval()
697 {
698   ProgNodeP branch = this->GetThisBranch();
699   return branch->Eval();
700 
701 //   Guard<BaseGDL> e1_guard;
702 //   BaseGDL* e1;
703 //   if( NonCopyNode( op1->getType()))
704 //   {
705 // 	e1 = op1->EvalNC();
706 //   }
707 //   else
708 //   {
709 // // 	e1 = op1->Eval();
710 // //      e1_guard.Init(e1);
711 // 	BaseGDL** ref = op1->EvalRefCheck(e1);
712 // 	if( ref == NULL)
713 // 	  e1_guard.Init(e1);
714 // 	else
715 // 	  e1 = *ref;
716 //   }
717 // //  Guard<BaseGDL> e1( op1->Eval());
718 //   if( e1->True())
719 //     {
720 //       return op2->Eval(); // right->down
721 //     }
722 //   return op3->Eval(); // right->right
723 }
724 
GetThisBranch()725 ProgNodeP QUESTIONNode::GetThisBranch()
726 {
727     Guard<BaseGDL> e1_guard;
728     BaseGDL* e1;
729     if( NonCopyNode( op1->getType()))
730     {
731         e1 = op1->EvalNC();
732     }
733     else
734     {
735 // 	e1 = op1->Eval();
736 //      e1_guard.Init(e1);
737 	BaseGDL** ref = op1->EvalRefCheck(e1);
738 	if( ref == NULL)
739 	  e1_guard.Init(e1);
740 	else
741 	  e1 = *ref;
742     }
743 //  Guard<BaseGDL> e1( op1->Eval());
744     if( e1->True())
745     {
746         return op2;
747     }
748     return op3;
749 }
750 
751 // unary operators
Eval()752 BaseGDL* UMINUSNode::Eval()
753 {
754   BaseGDL* e1 = down->Eval();
755   return e1->UMinus(); // might delete e1 (GDL_STRING)
756 }
Eval()757 BaseGDL* NOT_OPNode::Eval()
758 {
759   BaseGDL* e1 = down->Eval();
760   return e1->NotOp();
761 }
Eval()762 BaseGDL* LOG_NEGNode::Eval()
763 {
764   Guard<BaseGDL> e1( down->Eval());
765   return e1->LogNeg();
766 }
767 
768 // binary operators
Eval()769 BaseGDL* AND_OPNode::Eval()
770 { BaseGDL* res;
771   Guard<BaseGDL> e1( op1->Eval());
772   Guard<BaseGDL> e2( op2->Eval());
773   AdjustTypes(e1,e2);
774   if( e1->StrictScalar())
775     {
776     res= e2->AndOpS(e1.get()); // scalar+scalar or array+scalar
777     e2.release();
778     }
779   else
780     if( e2->StrictScalar())
781       {
782       res= e1->AndOpInvS(e2.get()); // array+scalar
783       e1.release();
784       }
785     else
786       if( e1->N_Elements() <= e2->N_Elements())
787 	{
788 	res = e1->AndOpInv(e2.get()); // smaller_array + larger_array or same size
789 	e1.release();
790 	}
791       else
792 	{
793 	res = e2->AndOp(e1.get()); // smaller + larger
794 	e2.release();
795 	}
796   return res;
797 }
Eval()798 BaseGDL* OR_OPNode::Eval()
799 { BaseGDL* res;
800  Guard<BaseGDL> e1( op1->Eval());
801  Guard<BaseGDL> e2( op2->Eval());
802  AdjustTypes(e1,e2);
803  if( e1->StrictScalar())
804    {
805      res= e2->OrOpS(e1.get()); // scalar+scalar or array+scalar
806      e2.release();
807    }
808  else
809    if( e2->StrictScalar())
810      {
811        res= e1->OrOpInvS(e2.get()); // array+scalar
812        e1.release();
813      }
814    else
815      if( e1->N_Elements() <= e2->N_Elements())
816        {
817 	 res= e1->OrOpInv(e2.get()); // smaller_array + larger_array or same size
818 	 e1.release();
819        }
820      else
821        {
822 	 res= e2->OrOp(e1.get()); // smaller + larger
823 	 e2.release();
824        }
825  return res;
826 }
Eval()827 BaseGDL* XOR_OPNode::Eval()
828 { BaseGDL* res;
829   Guard<BaseGDL> e1( op1->Eval());
830   Guard<BaseGDL> e2( op2->Eval());
831   AdjustTypes(e1,e2);
832   if( e1->N_Elements() <= e2->N_Elements())
833     {
834     res= e1->XorOp(e2.get()); // smaller_array + larger_array or same size
835 	 e1.release();
836     }
837   else
838     {
839     res= e2->XorOp(e1.get()); // smaller + larger
840 	 e2.release();
841     }
842   return res;
843 }
Eval()844 BaseGDL* LOG_ANDNode::Eval()
845 { BaseGDL* res;
846   Guard<BaseGDL> e1( op1->Eval());
847   if( !e1->LogTrue()) return new DByteGDL( 0);
848   Guard<BaseGDL> e2( op2->Eval());
849   if( !e2->LogTrue()) return new DByteGDL( 0);
850   return new DByteGDL( 1);
851 }
Eval()852 BaseGDL* LOG_ORNode::Eval()
853 { BaseGDL* res;
854   Guard<BaseGDL> e1( op1->Eval());
855   if( e1->LogTrue()) return new DByteGDL( 1);
856   Guard<BaseGDL> e2( op2->Eval());
857   if( e2->LogTrue()) return new DByteGDL( 1);
858   return new DByteGDL( 0);
859 }
860 
Eval()861 BaseGDL* EQ_OPNode::Eval()
862 {
863   Guard<BaseGDL> e1( op1->Eval());
864   Guard<BaseGDL> e2( op2->Eval());
865   AdjustTypesObj(e1,e2);
866   if( e2->Type() == GDL_OBJ)
867   {
868     if( e1->Type() != GDL_OBJ)
869     {
870       // order is critical: overload might just be defined for one of the object types
871       // use e2 only if e1 is no object
872       BaseGDL* res=e2->EqOp(e1.get());
873       if( e1.Get() == NullGDL::GetSingleInstance())
874 	e1.Release();
875       return res;
876     }
877   }
878   BaseGDL* res=e1->EqOp(e2.get());
879   if( e1.Get() == NullGDL::GetSingleInstance())
880     e1.Release();
881   if( e2.Get() == NullGDL::GetSingleInstance())
882     e2.Release();
883   return res;
884 }
Eval()885 BaseGDL* NE_OPNode::Eval()
886 {
887   Guard<BaseGDL> e1( op1->Eval());
888   Guard<BaseGDL> e2( op2->Eval());
889   AdjustTypesObj(e1,e2);
890   if( e2->Type() == GDL_OBJ)
891   {
892     if( e1->Type() != GDL_OBJ)
893     {
894       // order is critical: overload might just be defined for one of the object types
895       // use e2 only if e1 is no object
896       BaseGDL* res=e2->NeOp(e1.get());
897       if( e1.Get() == NullGDL::GetSingleInstance())
898 	e1.Release();
899       return res;
900     }
901   }
902   BaseGDL* res=e1->NeOp(e2.get());
903   if( e1.Get() == NullGDL::GetSingleInstance())
904     e1.Release();
905   if( e2.Get() == NullGDL::GetSingleInstance())
906     e2.Release();
907   return res;
908 }
Eval()909 BaseGDL* LE_OPNode::Eval()
910 { BaseGDL* res;
911   Guard<BaseGDL> e1( op1->Eval());
912   Guard<BaseGDL> e2( op2->Eval());
913   AdjustTypes(e1,e2);
914   res=e1->LeOp(e2.get());
915   return res;
916 }
Eval()917 BaseGDL* LT_OPNode::Eval()
918 { BaseGDL* res;
919   Guard<BaseGDL> e1( op1->Eval());
920   Guard<BaseGDL> e2( op2->Eval());
921   AdjustTypes(e1,e2);
922   res=e1->LtOp(e2.get());
923   return res;
924 }
Eval()925 BaseGDL* GE_OPNode::Eval()
926 { BaseGDL* res;
927   Guard<BaseGDL> e1( op1->Eval());
928   Guard<BaseGDL> e2( op2->Eval());
929   AdjustTypes(e1,e2);
930   res=e1->GeOp(e2.get());
931   return res;
932 }
Eval()933 BaseGDL* GT_OPNode::Eval()
934 { BaseGDL* res;
935   Guard<BaseGDL> e1( op1->Eval());
936   Guard<BaseGDL> e2( op2->Eval());
937   AdjustTypes(e1,e2);
938   res=e1->GtOp(e2.get());
939   return res;
940 }
Eval()941 BaseGDL* PLUSNode::Eval()
942 {
943   BaseGDL* res;
944   Guard<BaseGDL> e1 ( op1->Eval() );
945   Guard<BaseGDL> e2 ( op2->Eval() );
946 
947   DType aTy=e1->Type();
948   DType bTy=e2->Type();
949   if( aTy == bTy)
950   {
951     if( aTy == GDL_OBJ) // we MUST do this here (correct guard handling)
952       return e1->Add( e2.get());; // operator overloading
953 
954   }
955       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
956   else
957   {
958     DType cxTy = PromoteComplexOperand( aTy, bTy);
959     if( cxTy != GDL_UNDEF)
960     {
961       e1.reset( e1.release()->Convert2( cxTy));
962       e2.reset( e2.release()->Convert2( cxTy));
963     }
964   // Change > to >= JMG
965   else if( DTypeOrder[aTy] >= DTypeOrder[bTy])
966     {
967       // convert b to a
968       if( aTy == GDL_OBJ) // only check for aTy is ok because GDL_OBJ has highest order
969 	return e1->Add( e2.get());; // for operator overloading, do not convert other type then
970       e2.reset( e2.release()->Convert2( aTy));
971     }
972   else
973     {
974       // convert a to b
975       if( bTy == GDL_OBJ) // only check for bTy is ok because GDL_OBJ has highest order
976 	return e2->AddInv( e1.get());; // for operator overloading, do not convert other type then
977       e1.reset( e1.release()->Convert2( bTy));
978     }
979   }
980 
981   if ( e1->StrictScalar() )
982   {
983     res= e2->AddInvS ( e1.get() ); // scalar+scalar or array+scalar
984     e2.release();
985   }
986   else
987   if ( e2->StrictScalar() )
988   {
989 	  res= e1->AddS ( e2.get() ); // array+scalar
990 	  e1.release();
991   }
992   else
993   if ( e1->N_Elements() <= e2->N_Elements() )
994   {
995 	  res= e1->Add ( e2.get() ); // smaller_array + larger_array or same size
996 	  e1.release();
997   }
998   else
999   {
1000 	  res= e2->AddInv ( e1.get() ); // smaller + larger
1001 	  e2.release();
1002   }
1003   return res;
1004 }
1005 
Eval()1006 BaseGDL* MINUSNode::Eval()
1007 {
1008   BaseGDL* res;
1009   Guard<BaseGDL> e1( op1->Eval());
1010   Guard<BaseGDL> e2( op2->Eval());
1011 //  AdjustTypes(e1,e2);
1012 
1013   DType aTy=e1->Type();
1014   DType bTy=e2->Type();
1015   if( aTy == bTy)
1016   {
1017     if( aTy == GDL_OBJ) // we MUST do this here (correct guard handling)
1018       return e1->Sub( e2.get());; // operator overloading
1019 
1020   }
1021       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
1022   else
1023   {
1024     DType cxTy = PromoteComplexOperand( aTy, bTy);
1025     if( cxTy != GDL_UNDEF)
1026     {
1027       e1.reset( e1.release()->Convert2( cxTy));
1028       e2.reset( e2.release()->Convert2( cxTy));
1029     }
1030   // Change > to >= JMG
1031   else if( DTypeOrder[aTy] >= DTypeOrder[bTy])
1032     {
1033       // convert b to a
1034       if( aTy == GDL_OBJ) // only check for aTy is ok because GDL_OBJ has highest order
1035 	return e1->Sub( e2.get());; // for operator overloading, do not convert other type then
1036       e2.reset( e2.release()->Convert2( aTy));
1037     }
1038   else
1039     {
1040       // convert a to b
1041       if( bTy == GDL_OBJ) // only check for bTy is ok because GDL_OBJ has highest order
1042 	return e2->SubInv( e1.get());; // for operator overloading, do not convert other type then
1043       e1.reset( e1.release()->Convert2( bTy));
1044     }
1045   }
1046  if( e1->StrictScalar())
1047    {
1048      res= e2->SubInvS(e1.get()); // scalar+scalar or array+scalar
1049      e2.release();
1050    }
1051  else
1052    if( e2->StrictScalar())
1053      {
1054        res= e1->SubS(e2.get()); // array+scalar
1055        e1.release();
1056      }
1057    else
1058      if( e1->N_Elements() <= e2->N_Elements())
1059        {
1060 	 res= e1->Sub(e2.get()); // smaller_array + larger_array or same size
1061 	 e1.release();
1062        }
1063      else
1064        {
1065 	 res= e2->SubInv(e1.get()); // smaller + larger
1066 	 e2.release();
1067        }
1068 
1069  return res;
1070 }
Eval()1071 BaseGDL* LTMARKNode::Eval()
1072 { BaseGDL* res;
1073  Guard<BaseGDL> e1( op1->Eval());
1074  Guard<BaseGDL> e2( op2->Eval());
1075  AdjustTypes(e1,e2);
1076  if( e1->StrictScalar())
1077    {
1078      res= e2->LtMarkS(e1.get()); // scalar+scalar or array+scalar
1079      e2.release();
1080    }
1081  else
1082    if( e2->StrictScalar())
1083      {
1084        res= e1->LtMarkS(e2.get()); // array+scalar
1085        e1.release();
1086      }
1087    else
1088      if( e1->N_Elements() <= e2->N_Elements())
1089        {
1090 	 res= e1->LtMark(e2.get()); // smaller_array + larger_array or same size
1091 	 e1.release();
1092        }
1093      else
1094        {
1095 	 res= e2->LtMark(e1.get()); // smaller + larger
1096 	 e2.release();
1097        }
1098  return res;
1099 }
Eval()1100 BaseGDL* GTMARKNode::Eval()
1101 { BaseGDL* res;
1102  Guard<BaseGDL> e1( op1->Eval());
1103  Guard<BaseGDL> e2( op2->Eval());
1104  AdjustTypes(e1,e2);
1105  if( e1->StrictScalar())
1106    {
1107      res= e2->GtMarkS(e1.get()); // scalar+scalar or array+scalar
1108      e2.release();
1109    }
1110  else
1111    if( e2->StrictScalar())
1112      {
1113        res= e1->GtMarkS(e2.get()); // array+scalar
1114        e1.release();
1115      }
1116    else
1117      if( e1->N_Elements() <= e2->N_Elements())
1118        {
1119 	 res= e1->GtMark(e2.get()); // smaller_array + larger_array or same size
1120 	 e1.release();
1121        }
1122      else
1123        {
1124 	 res= e2->GtMark(e1.get()); // smaller + larger
1125 	 e2.release();
1126        }
1127  return res;
1128 }
Eval()1129 BaseGDL* ASTERIXNode::Eval()
1130 {
1131 	BaseGDL* res;
1132 	Guard<BaseGDL> e1 ( op1->Eval() );
1133 	Guard<BaseGDL> e2 ( op2->Eval() );
1134 	AdjustTypes ( e1,e2 );
1135 	if ( e1->StrictScalar() )
1136 	{
1137 		res= e2->MultS ( e1.get() ); // scalar+scalar or array+scalar
1138 		e2.release();
1139 	}
1140 	else if ( e2->StrictScalar() )
1141 	{
1142 		res= e1->MultS ( e2.get() ); // array+scalar
1143 		e1.release();
1144 	}
1145 	else
1146 		if ( e1->N_Elements() <= e2->N_Elements() )
1147 		{
1148 			res= e1->Mult ( e2.get() ); // smaller_array + larger_array or same size
1149 			e1.release();
1150 		}
1151 		else
1152 		{
1153 			res= e2->Mult ( e1.get() ); // smaller + larger
1154 			e2.release();
1155 		}
1156 	return res;
1157 }
1158 
Eval()1159 BaseGDL* MATRIX_OP1Node::Eval()
1160 { BaseGDL* res;
1161   Guard<BaseGDL> e1( op1->Eval());
1162   Guard<BaseGDL> e2( op2->Eval());
1163   DType aTy=e1->Type();
1164   DType bTy=e2->Type();
1165 
1166 //   DType maxTy=(DTypeOrder[aTy] >= DTypeOrder[bTy])? aTy: bTy;
1167 //   DType cTy=maxTy;
1168 //   if( maxTy == GDL_BYTE || maxTy == GDL_INT)
1169 //     cTy=GDL_LONG;
1170 //   else if( maxTy == GDL_UINT)
1171 //     cTy=GDL_ULONG;
1172 
1173   DType cTy = PromoteMatrixOperands( aTy, bTy);
1174 
1175   if( aTy != cTy)
1176     e1.reset( e1.release()->Convert2( cTy));
1177 
1178   AdjustTypes(e1,e2);
1179   res=e1->MatrixOp(e2.get());
1180   return res;
1181 }
Eval()1182 BaseGDL* MATRIX_OP2Node::Eval()
1183 { BaseGDL* res;
1184   Guard<BaseGDL> e1( op1->Eval());
1185   Guard<BaseGDL> e2( op2->Eval());
1186   DType aTy=e1->Type();
1187   DType bTy=e2->Type();
1188 
1189 //   DType maxTy=(DTypeOrder[aTy] >= DTypeOrder[bTy])? aTy: bTy;
1190 //   DType cTy=maxTy;
1191 //   if( maxTy == GDL_BYTE || maxTy == GDL_INT)
1192 //     cTy=GDL_LONG;
1193 //   else if( maxTy == GDL_UINT)
1194 //     cTy=GDL_ULONG;
1195 
1196   DType cTy = PromoteMatrixOperands( aTy, bTy);
1197 
1198   if( aTy != cTy)
1199     e1.reset( e1.release()->Convert2( cTy));
1200 
1201   AdjustTypes(e1,e2);
1202   res=e2->MatrixOp(e1.get());
1203   return res;
1204 }
Eval()1205 BaseGDL* SLASHNode::Eval()
1206 { BaseGDL* res;
1207  Guard<BaseGDL> e1( op1->Eval());
1208  Guard<BaseGDL> e2( op2->Eval());
1209  AdjustTypes(e1,e2);
1210  if( e1->StrictScalar())
1211    {
1212      res= e2->DivInvS(e1.get()); // scalar+scalar or array+scalar
1213      e2.release();
1214    }
1215  else
1216    if( e2->StrictScalar())
1217      {
1218        res= e1->DivS(e2.get()); // array+scalar
1219        e1.release();
1220      }
1221    else
1222      if( e1->N_Elements() <= e2->N_Elements())
1223        {
1224 	 res= e1->Div(e2.get()); // smaller_array + larger_array or same size
1225 	 e1.release();
1226        }
1227      else
1228        {
1229 	 res= e2->DivInv(e1.get()); // smaller + larger
1230 	 e2.release();
1231        }
1232 
1233  return res;
1234 }
Eval()1235 BaseGDL* MOD_OPNode::Eval()
1236 { BaseGDL* res;
1237  Guard<BaseGDL> e1( op1->Eval());
1238  Guard<BaseGDL> e2( op2->Eval());
1239  AdjustTypes(e1,e2);
1240  if( e1->StrictScalar())
1241    {
1242      res= e2->ModInvS(e1.get()); // scalar+scalar or array+scalar
1243      e2.release();
1244    }
1245  else
1246    if( e2->StrictScalar())
1247      {
1248        res= e1->ModS(e2.get()); // array+scalar
1249        e1.release();
1250      }
1251    else
1252      if( e1->N_Elements() <= e2->N_Elements())
1253        {
1254 	 res= e1->Mod(e2.get()); // smaller_array + larger_array or same size
1255 	 e1.release();
1256        }
1257      else
1258        {
1259 	 res= e2->ModInv(e1.get()); // smaller + larger
1260 	 e2.release();
1261        }
1262  return res;
1263 }
1264 
1265 
Eval()1266 BaseGDL* POWNode::Eval()
1267 { BaseGDL* res;
1268   Guard<BaseGDL> e1( op1->Eval());
1269   Guard<BaseGDL> e2( op2->Eval());
1270   // special handling for aTy == complex && bTy != complex
1271   DType aTy=e1->Type();
1272   DType bTy=e2->Type();
1273  if( aTy == GDL_STRING)
1274    {
1275      e1.reset( e1->Convert2( GDL_FLOAT, BaseGDL::COPY));
1276      aTy = GDL_FLOAT;
1277    }
1278  if( bTy == GDL_STRING)
1279    {
1280      e2.reset( e2->Convert2( GDL_FLOAT, BaseGDL::COPY));
1281      bTy = GDL_FLOAT;
1282    }
1283   if( ComplexType( aTy))
1284     {
1285       if( IntType( bTy))
1286 	{
1287 	  e2.reset( e2.release()->Convert2( GDL_LONG));
1288 	  res = e1->Pow( e2.get());
1289 	  if( res == e1.get())
1290 	    e1.release();
1291 	  return res;
1292 	}
1293       if( aTy == GDL_COMPLEX)
1294 	{
1295 	  if( bTy == GDL_DOUBLE)
1296 	    {
1297 	      e1.reset( e1.release()->Convert2( GDL_COMPLEXDBL));
1298 	      aTy = GDL_COMPLEXDBL;
1299 	    }
1300 	  else if( bTy == GDL_FLOAT)
1301 	    {
1302 	      res = e1->Pow( e2.get());
1303 	      if( res == e1.get())
1304 		e1.release();
1305 	      return res;
1306 	    }
1307 	}
1308       if( aTy == GDL_COMPLEXDBL)
1309 	{
1310 	  if( bTy == GDL_FLOAT)
1311 	    {
1312 	      e2.reset( e2.release()->Convert2( GDL_DOUBLE));
1313 	      bTy = GDL_DOUBLE;
1314 	    }
1315 	  if( bTy == GDL_DOUBLE)
1316 	    {
1317 	      res = e1->Pow( e2.get());
1318 	      if( res == e1.get())
1319 		e1.release();
1320 	      return res;
1321 	    }
1322 	}
1323     }
1324 
1325   if( IntType( bTy) && FloatType( aTy))
1326     {
1327       e2.reset( e2.release()->Convert2( GDL_LONG));
1328 
1329       res = e1->PowInt( e2.get());
1330       if( res == e1.get())
1331 	e1.release();
1332 
1333       return res;
1334     }
1335 
1336   DType convertBackT;
1337 
1338   // convert back
1339   if( IntType( bTy) && (DTypeOrder[ bTy] > DTypeOrder[ aTy]))
1340 //   if( IntType( bTy) && (DTypeOrder[ bTy] > DTypeOrder[ aTy]))
1341     convertBackT = aTy;
1342   else
1343     convertBackT = GDL_UNDEF;
1344 
1345   //  first operand determines type JMG
1346   //  AdjustTypes(e2,e1); // order crucial here (for converting back)
1347   AdjustTypes(e1,e2); // order crucial here (for converting back)
1348 
1349   if( e1->StrictScalar())
1350     {
1351       res= e2->PowInvS(e1.get()); // scalar+scalar or array+scalar
1352       e2.release();
1353     }
1354   else
1355     if( e2->StrictScalar())
1356       {
1357       res= e1->PowS(e2.get()); // array+scalar
1358       e1.release();
1359       }
1360     else
1361       if( e1->N_Elements() <= e2->N_Elements())
1362 	{
1363 	res= e1->Pow(e2.get()); // smaller_array + larger_array or same size
1364 	e1.release();
1365 	}
1366       else
1367 	{
1368 	  res= e2->PowInv(e1.get()); // smaller + larger
1369 	  e2.release();
1370 	}
1371   if( convertBackT != GDL_UNDEF)
1372     {
1373       res = res->Convert2( convertBackT, BaseGDL::CONVERT);
1374     }
1375  endPOW:
1376   return res;
1377 }
1378 // BaseGDL* DECNode::Eval()
1379 // { BaseGDL* res;
1380 //   return new DECNode( refNode);
1381 // }
1382 // BaseGDL* INCNode::Eval()
1383 // { BaseGDL* res;
1384 //   return new INCNode( refNode);
1385 // }
1386 // BaseGDL* POSTDECNode::Eval()
1387 // { BaseGDL* res;
1388 //   return new POSTDECNode( refNode);
1389 // }
1390 // BaseGDL* POSTINCNode::Eval()
1391 // { BaseGDL* res;
1392 //   return new POSTINCNode( refNode);
1393 // }
1394 
1395 // ***********************
1396 // **** nonCopy nodes ****
1397 // ***********************
Eval()1398 BaseGDL* AND_OPNCNode::Eval()
1399 { BaseGDL* res;
1400  Guard<BaseGDL> g1;
1401  Guard<BaseGDL> g2;
1402  BaseGDL *e1, *e2; AdjustTypesNC( g1, e1, g2, e2);
1403 
1404  if( e1->StrictScalar())
1405    {
1406      if( g2.get() == NULL) return e2->AndOpSNew( e1);  else  g2.release();
1407      res= e2->AndOpS(e1); // scalar+scalar or array+scalar
1408 
1409    }
1410  else
1411    if( e2->StrictScalar())
1412      {
1413        if( g1.get() == NULL) return e1->AndOpInvSNew( e2); else g1.release();
1414        res= e1->AndOpInvS(e2); // array+scalar
1415 
1416      }
1417    else
1418      if( e1->N_Elements() == e2->N_Elements())
1419        {
1420 	 if( g1.get() != NULL)
1421 	   {
1422 	     g1.release();
1423 	     return e1->AndOpInv(e2);
1424 	   }
1425 	 if( g2.get() != NULL)
1426 	   {
1427 	     g2.release();
1428 	     res = e2->AndOp(e1);
1429 	     res->SetDim( e1->Dim());
1430 	     return res;
1431 	   }
1432 	 else
1433 	   {
1434 	     return e1->AndOpInvNew(e2);
1435 	   }
1436        }
1437      else if( e1->N_Elements() < e2->N_Elements())
1438        {
1439 	 if( g1.get() == NULL) return e1->AndOpInvNew( e2); else g1.release();
1440 	 res = e1->AndOpInv(e2); // smaller_array + larger_array or same size
1441 
1442        }
1443      else
1444        {
1445 	 if( g2.get() == NULL) return e2->AndOpNew( e1); else g2.release();
1446 	 res = e2->AndOp(e1); // smaller + larger
1447 
1448        }
1449 
1450  return res;
1451 }
Eval()1452 BaseGDL* OR_OPNCNode::Eval()
1453 { BaseGDL* res;
1454  Guard<BaseGDL> g1;
1455  Guard<BaseGDL> g2;
1456  BaseGDL *e1, *e2; AdjustTypesNC( g1, e1, g2, e2);
1457 
1458  if( e1->StrictScalar())
1459    {
1460      if( g2.get() == NULL) return e2->OrOpSNew( e1); else g2.release();
1461      res= e2->OrOpS(e1); // scalar+scalar or array+scalar
1462 
1463    }
1464  else
1465    if( e2->StrictScalar())
1466      {
1467        if( g1.get() == NULL) return e1->OrOpInvSNew( e2); else g1.release();
1468        res= e1->OrOpInvS(e2); // array+scalar
1469 
1470      }
1471    else
1472  if( e1->N_Elements() == e2->N_Elements())
1473    {
1474      if( g1.get() != NULL)
1475        {
1476 	 g1.release();
1477 	 return e1->OrOpInv(e2);
1478        }
1479      if( g2.get() != NULL)
1480        {
1481 	 g2.release();
1482 	 res = e2->OrOp(e1);
1483 	 res->SetDim( e1->Dim());
1484 	 return res;
1485        }
1486      else
1487        {
1488 	 return e1->OrOpInvNew(e2);
1489        }
1490    }
1491 else if( e1->N_Elements() < e2->N_Elements())
1492        {
1493 	 if( g1.get() == NULL) return e1->OrOpInvNew( e2); else g1.release();
1494 	 res= e1->OrOpInv(e2); // smaller_array + larger_array or same size
1495 
1496        }
1497      else
1498        {
1499 	 if( g2.get() == NULL) return e2->OrOpNew( e1); else g2.release();
1500 	 res= e2->OrOp(e1); // smaller + larger
1501 
1502        }
1503  return res;
1504 }
Eval()1505 BaseGDL* XOR_OPNCNode::Eval()
1506 { BaseGDL* res;
1507   Guard<BaseGDL> g1;
1508   Guard<BaseGDL> g2;
1509   BaseGDL *e1, *e2; AdjustTypesNC( g1, e1, g2, e2);
1510 
1511   if( e1->StrictScalar())
1512     {
1513       if( g2.get() == NULL) return e2->XorOpSNew( e1); else g2.release();
1514       res= e2->XorOpS(e1); // scalar+scalar or array+scalar
1515 
1516     }
1517   else if( e2->StrictScalar())
1518       {
1519 	if( g1.get() == NULL) return e1->XorOpSNew( e2); else g1.release();
1520 	res= e1->XorOpS(e2); // array+scalar
1521 
1522       }
1523     else if( e1->N_Elements() == e2->N_Elements())
1524       {
1525 	if( g1.get() != NULL)
1526 	  {
1527 	    g1.release();
1528 	    return e1->XorOp(e2);
1529 	  }
1530 	if( g2.get() != NULL)
1531 	  {
1532 	    g2.release();
1533 	    res = e2->XorOp(e1);
1534 	    res->SetDim( e1->Dim());
1535 	    return res;
1536 	  }
1537 	else
1538 	  {
1539 	    return e1->XorOpNew(e2);
1540 	  }
1541       }
1542     else if( e1->N_Elements() < e2->N_Elements())
1543       {
1544 	if( g1.get() == NULL) return e1->XorOpNew( e2); else g1.release();
1545 	res= e1->XorOp(e2); // smaller_array + larger_array or same size
1546 
1547       }
1548     else
1549       {
1550 	if( g2.get() == NULL) return e2->XorOpNew( e1); else g2.release();
1551 	res= e2->XorOp(e1); // smaller + larger
1552 
1553       }
1554   return res;
1555 }
Eval()1556 BaseGDL* LOG_ANDNCNode::Eval()
1557 { BaseGDL* res;
1558  Guard<BaseGDL> g1;
1559  Guard<BaseGDL> g2;
1560  BaseGDL *e1, *e2;
1561  if( op1NC)
1562    {
1563      e1 = op1->EvalNC();
1564    }
1565  else
1566    {
1567      e1 = op1->Eval();
1568      g1.reset( e1);
1569    }
1570  if( !e1->LogTrue()) return new DByteGDL( 0);
1571 
1572  if( op2NC)
1573    {
1574      e2 = op2->EvalNC();
1575    }
1576  else
1577    {
1578      e2 = op2->Eval();
1579      g2.reset( e2);
1580    }
1581  if( !e2->LogTrue()) return new DByteGDL( 0);
1582  return new DByteGDL( 1);
1583 }
Eval()1584 BaseGDL* LOG_ORNCNode::Eval()
1585 { BaseGDL* res;
1586  Guard<BaseGDL> g1;
1587  Guard<BaseGDL> g2;
1588  BaseGDL *e1, *e2;
1589  if( op1NC)
1590    {
1591      e1 = op1->EvalNC();
1592    }
1593  else
1594    {
1595      e1 = op1->Eval();
1596      g1.reset( e1);
1597    }
1598  if( e1->LogTrue()) return new DByteGDL( 1);
1599  if( op2NC)
1600    {
1601      e2 = op2->EvalNC();
1602    }
1603  else
1604    {
1605      e2 = op2->Eval();
1606      g2.reset( e2);
1607    }
1608  if( e2->LogTrue()) return new DByteGDL( 1);
1609  return new DByteGDL( 0);
1610 }
1611 
1612 
Eval()1613 BaseGDL* EQ_OPNCNode::Eval()
1614 { BaseGDL* res;
1615   Guard<BaseGDL> g1;
1616   Guard<BaseGDL> g2;
1617   BaseGDL *e1, *e2;
1618   AdjustTypesNCNull( g1, e1, g2, e2);
1619   if( e2 != NULL && e2->Type() == GDL_OBJ)
1620   {
1621     if( e1->Type() != GDL_OBJ)
1622     {
1623       // order is critical: overload might just be defined for one of the object types
1624       // use e2 only if e1 is no object
1625       BaseGDL* res=e2->EqOp(e1);
1626       return res;
1627     }
1628   }
1629   res=e1->EqOp(e2);
1630   return res;
1631 }
Eval()1632 BaseGDL* NE_OPNCNode::Eval()
1633 { BaseGDL* res;
1634   Guard<BaseGDL> g1;
1635   Guard<BaseGDL> g2;
1636   BaseGDL *e1, *e2;
1637   AdjustTypesNCNull( g1, e1, g2, e2);
1638   if( e2 != NULL && e2->Type() == GDL_OBJ)
1639   {
1640     if( e1->Type() != GDL_OBJ)
1641     {
1642       // order is critical: overload might just be defined for one of the object types
1643       // use e2 only if e1 is no object
1644       BaseGDL* res=e2->NeOp(e1);
1645       return res;
1646     }
1647   }
1648   res=e1->NeOp(e2);
1649   return res;
1650 }
Eval()1651 BaseGDL* LE_OPNCNode::Eval()
1652 { BaseGDL* res;
1653   Guard<BaseGDL> g1;
1654   Guard<BaseGDL> g2;
1655   BaseGDL *e1, *e2;
1656   AdjustTypesNC( g1, e1, g2, e2);
1657   res=e1->LeOp(e2);
1658   return res;
1659 }
Eval()1660 BaseGDL* LT_OPNCNode::Eval()
1661 { BaseGDL* res;
1662   Guard<BaseGDL> g1;
1663   Guard<BaseGDL> g2;
1664   BaseGDL *e1, *e2;
1665   AdjustTypesNC( g1, e1, g2, e2);
1666   res=e1->LtOp(e2);
1667   return res;
1668 }
Eval()1669 BaseGDL* GE_OPNCNode::Eval()
1670 { BaseGDL* res;
1671   Guard<BaseGDL> g1;
1672   Guard<BaseGDL> g2;
1673   BaseGDL *e1, *e2;
1674   AdjustTypesNC( g1, e1, g2, e2);
1675   res=e1->GeOp(e2);
1676   return res;
1677 }
Eval()1678 BaseGDL* GT_OPNCNode::Eval()
1679 { BaseGDL* res;
1680   Guard<BaseGDL> g1;
1681   Guard<BaseGDL> g2;
1682   BaseGDL *e1, *e2;
1683   AdjustTypesNC( g1, e1, g2, e2);
1684   res=e1->GtOp(e2);
1685   return res;
1686 }
Eval()1687 BaseGDL* PLUSNC12Node::Eval()
1688 {
1689   BaseGDL *e1 = op1->EvalNC();
1690   BaseGDL *e2 = op2->EvalNC();
1691   DType aTy=e1->Type();
1692   DType bTy=e2->Type();
1693   if( aTy == bTy)
1694   {
1695     // as all Add...New() functions are implemented for GDL_OBJ, we can save the if(...) here
1696     // (as there are no guards up to here)
1697     //     if( aTy == GDL_OBJ) // this saves us to implement all Add...New() functions
1698     //       return e1->Add( e2);
1699 
1700     if ( e1->StrictScalar() )
1701     {
1702       return e2->AddInvSNew( e1 ); // scalar+scalar or array+scalar
1703     }
1704     else if ( e2->StrictScalar() )
1705     {
1706       return e1->AddSNew( e2); // array+scalar
1707     }
1708     else if ( e1->N_Elements() <= e2->N_Elements() )
1709     {
1710       return e1->AddNew ( e2 );
1711     }
1712     else // e1->N_Elements() > e2->N_Elements() )
1713     {
1714       return e2->AddInvNew( e1); // smaller + larger
1715     }
1716   }
1717   Guard<BaseGDL> g1;
1718   Guard<BaseGDL> g2;
1719   DType cxTy = PromoteComplexOperand( aTy, bTy);
1720   if( cxTy != GDL_UNDEF)
1721   {
1722 	  e2 = e2->Convert2( cxTy, BaseGDL::COPY);
1723 	  g2.reset( e2);
1724 	  e1 = e1->Convert2( cxTy, BaseGDL::COPY);
1725 	  g1.reset( e1);
1726      }
1727   else if( DTypeOrder[aTy] >= DTypeOrder[bTy])
1728     {
1729       if( aTy == GDL_OBJ)
1730 	return e1->Add( e2);
1731 
1732 //       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
1733 //       if(aTy == GDL_COMPLEX && bTy == GDL_DOUBLE)
1734 //       {
1735 // 	  e2 = e2->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
1736 // 	  g2.reset( e2);
1737 // 	  e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
1738 // 	  g1.reset( e1);
1739 //       }
1740 //       else
1741       {
1742 	// convert e2 to e1
1743 	e2 = e2->Convert2( aTy, BaseGDL::COPY);
1744 	g2.reset( e2);
1745       }
1746     }
1747   else
1748     {
1749       if( bTy == GDL_OBJ)
1750 	return e2->AddInv( e1);
1751 
1752       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
1753 //       if( (bTy == GDL_COMPLEX && aTy == GDL_DOUBLE))
1754 // 	{
1755 // 	  e2 = e2->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
1756 // 	  g2.reset( e2);
1757 // 	  e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
1758 // 	  g1.reset( e1);
1759 // 	}
1760 //       else
1761 	{// convert e1 to e2
1762 	    e1 = e1->Convert2( bTy, BaseGDL::COPY);
1763 	    g1.reset( e1);
1764 	}
1765     }
1766 
1767   // 'classic handling from here
1768   BaseGDL* res;
1769   if ( e1->StrictScalar() )
1770   {
1771 	  if ( g2.get() == NULL )
1772 	  {
1773 		  res= e2->AddInvSNew( e1 ); // scalar+scalar or array+scalar
1774 	  }
1775 	  else
1776 	  {
1777 		  g2.release();
1778 		  res= e2->AddInvS( e1 ); // scalar+scalar or array+scalar
1779 	  }
1780   }
1781   else if ( e2->StrictScalar() )
1782   {
1783 	  if ( g1.get() == NULL )
1784 		  res= e1->AddSNew( e2); // array+scalar
1785 	  else
1786 	  {
1787 		  g1.release();
1788 		  res= e1->AddS( e2); // array+scalar
1789 	  }
1790   }
1791   else if ( e1->N_Elements() == e2->N_Elements() )
1792   {
1793 	  if ( g1.get() != NULL )
1794 	  {
1795 		  g1.release();
1796 		  return e1->Add ( e2 );
1797 	  }
1798 	  if ( g2.get() != NULL )
1799 	  {
1800 		  g2.release();
1801 		  res = e2->AddInv ( e1 );
1802 		  res->SetDim ( e1->Dim() );
1803 		  return res;
1804 	  }
1805 	  else
1806 	  {
1807 		  return e1->AddNew ( e2 );
1808 	  }
1809   }
1810   else if ( e1->N_Elements() < e2->N_Elements() )
1811   {
1812 	  if ( g1.get() == NULL )
1813 		  res= e1->AddNew ( e2 ); // smaller_array + larger_array or same size
1814 	    else
1815 	    {
1816 		  g1.release();
1817 		  res= e1->Add ( e2 ); // smaller_array + larger_array or same size
1818 	  }
1819   }
1820   else // e1->N_Elements() > e2->N_Elements() )
1821   {
1822 	  if ( g2.get() == NULL )
1823 		  res= e2->AddInvNew( e1); // smaller + larger
1824 	  else
1825 	  {
1826 		  g2.release();
1827 		  res= e2->AddInv( e1); // smaller + larger
1828 	  }
1829   }
1830   return res;
1831 }
Eval()1832 BaseGDL* PLUSNCNode::Eval()
1833 {
1834   BaseGDL* res;
1835   Guard<BaseGDL> g1;
1836   Guard<BaseGDL> g2;
1837   BaseGDL *e1, *e2;
1838   SetupGuards( g1, e1, g2, e2 );
1839 
1840   DType aTy=e1->Type();
1841   DType bTy=e2->Type();
1842   if( aTy == bTy)
1843   {
1844     if( aTy == GDL_OBJ) // we MUST do this here (correct guard handling)
1845       return e1->Add( e2);
1846 
1847     // otherwise continue below
1848   }
1849   else // aTy != bTy
1850   {
1851     DType cxTy = PromoteComplexOperand( aTy, bTy);
1852     if( cxTy != GDL_UNDEF)
1853     {
1854 	  e2 = e2->Convert2( cxTy, BaseGDL::COPY);
1855 	  g2.Reset( e2); // delete former e2
1856 	  e1 = e1->Convert2( cxTy, BaseGDL::COPY);
1857 	  g1.Reset( e1); // delete former e1
1858     }
1859     // Change > to >= JMG
1860     else if( DTypeOrder[aTy] >= DTypeOrder[bTy])
1861     {
1862 //       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
1863 //       if( (aTy == GDL_COMPLEX && bTy == GDL_DOUBLE))
1864 // 	{
1865 // 	  e2 = e2->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
1866 // 	  g2.Reset( e2); // delete former e2
1867 // 	  e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
1868 // 	  g1.Reset( e1); // delete former e1
1869 // 	}
1870 //       else
1871       if( aTy == GDL_OBJ) // only check for aTy is ok because GDL_OBJ has highest order
1872 	return e1->Add(e2); // for operator overloading, do not convert other type then
1873       else
1874       {
1875 	// convert e2 to e1
1876 	e2 = e2->Convert2( aTy, BaseGDL::COPY);
1877 	g2.Reset( e2); // delete former e2
1878       }
1879     }
1880     else
1881     {
1882 //       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
1883 //       if( (bTy == GDL_COMPLEX && aTy == GDL_DOUBLE))
1884 // 	{
1885 // 	  e2 = e2->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
1886 // 	  g2.Reset( e2); // delete former e2
1887 // 	  e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
1888 // 	  g1.Reset( e1); // delete former e1
1889 // 	}
1890 //       else
1891       if( bTy == GDL_OBJ) // only check for bTy is ok because GDL_OBJ has highest order
1892 	return e2->AddInv( e1); // for operator overloading, do not convert other type then
1893       else
1894       {
1895 	// convert e1 to e2
1896 	e1 = e1->Convert2( bTy, BaseGDL::COPY);
1897 	g1.Reset( e1); // delete former e1
1898       }
1899     }
1900   } // aTy != bTy
1901 
1902   if ( e1->StrictScalar() )
1903   {
1904     if ( g2.IsNull() )
1905     {
1906 	    res= e2->AddInvSNew( e1 ); // scalar+scalar or array+scalar
1907     }
1908     else
1909     {
1910 	    g2.Release();
1911 	    res= e2->AddInvS( e1 ); // scalar+scalar or array+scalar
1912     }
1913   }
1914   else if ( e2->StrictScalar() )
1915   {
1916     if ( g1.IsNull() )
1917 	    res= e1->AddSNew( e2); // array+scalar
1918     else
1919     {
1920 	    g1.Release();
1921 	    res= e1->AddS( e2); // array+scalar
1922     }
1923   }
1924   else if ( e1->N_Elements() == e2->N_Elements() )
1925   {
1926     if ( !g1.IsNull() )
1927     {
1928 	    g1.Release();
1929 	    return e1->Add ( e2 );
1930     }
1931     if ( !g2.IsNull() )
1932     {
1933 	    g2.Release();
1934 	    res = e2->AddInv ( e1 );
1935 	    res->SetDim ( e1->Dim() );
1936 	    return res;
1937     }
1938     else
1939     {
1940 	    return e1->AddNew ( e2 );
1941     }
1942   }
1943   else if ( e1->N_Elements() < e2->N_Elements() )
1944   {
1945     if ( g1.IsNull() )
1946 	    res= e1->AddNew ( e2 ); // smaller_array + larger_array or same size
1947       else
1948       {
1949 	    g1.Release();
1950 	    res= e1->Add ( e2 ); // smaller_array + larger_array or same size
1951     }
1952   }
1953   else // e1->N_Elements() > e2->N_Elements() )
1954   {
1955     if ( g2.IsNull() )
1956 	    res= e2->AddInvNew( e1); // smaller + larger
1957     else
1958     {
1959 	    g2.Release();
1960 	    res= e2->AddInv( e1); // smaller + larger
1961     }
1962   }
1963   return res;
1964 }
1965 
1966 
Eval()1967 BaseGDL* MINUSNC12Node::Eval()
1968 {
1969   BaseGDL *e1 = op1->EvalNC();
1970   BaseGDL *e2 = op2->EvalNC();
1971   DType aTy=e1->Type();
1972   DType bTy=e2->Type();
1973   if( aTy == bTy)
1974   {
1975     // as all Sub...New() functions are implemented for GDL_OBJ, we can save the if(...) here
1976     // (as there are no guards up to here)
1977     //     if( aTy == GDL_OBJ) // this saves us to implement all Add...New() functions
1978     //       return e1->Add( e2);
1979 
1980     if ( e1->StrictScalar() )
1981     {
1982       return e2->SubInvSNew( e1 ); // scalar+scalar or array+scalar
1983     }
1984     else if ( e2->StrictScalar() )
1985     {
1986       return e1->SubSNew( e2); // array+scalar
1987     }
1988     else if ( e1->N_Elements() <= e2->N_Elements() )
1989     {
1990       return e1->SubNew ( e2 );
1991     }
1992     else // e1->N_Elements() > e2->N_Elements() )
1993     {
1994       return e2->SubInvNew( e1); // smaller + larger
1995     }
1996   }
1997 
1998   Guard<BaseGDL> g1;
1999   Guard<BaseGDL> g2;
2000 
2001   DType cxTy = PromoteComplexOperand( aTy, bTy);
2002   if( cxTy != GDL_UNDEF)
2003     {
2004 	  e2 = e2->Convert2( cxTy, BaseGDL::COPY);
2005 	  g2.reset( e2);
2006 	  e1 = e1->Convert2( cxTy, BaseGDL::COPY);
2007 	  g1.reset( e1);
2008     }
2009   else if( DTypeOrder[aTy] >= DTypeOrder[bTy])
2010     {
2011       if( aTy == GDL_OBJ)
2012 	return e1->Sub( e2);
2013 
2014 //       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
2015 //       if( aTy == GDL_COMPLEX && bTy == GDL_DOUBLE)
2016 //       {
2017 // 	  e2 = e2->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2018 // 	  g2.reset( e2);
2019 // 	  e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2020 // 	  g1.reset( e1);
2021 //       }
2022 //       else
2023       {
2024 	// convert e2 to e1
2025 	e2 = e2->Convert2( aTy, BaseGDL::COPY);
2026 	g2.reset( e2);
2027       }
2028     }
2029   else
2030     {
2031       if( bTy == GDL_OBJ)
2032 	return e2->SubInv( e1);
2033 
2034 //       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
2035 //       if( (bTy == GDL_COMPLEX && aTy == GDL_DOUBLE))
2036 // 	{
2037 // 	  e2 = e2->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2038 // 	  g2.reset( e2);
2039 // 	  e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2040 // 	  g1.reset( e1);
2041 // 	}
2042 //       else
2043 	{// convert e1 to e2
2044 	    e1 = e1->Convert2( bTy, BaseGDL::COPY);
2045 	    g1.reset( e1);
2046 	}
2047     }
2048 
2049   // 'classic handling from here
2050   BaseGDL* res;
2051   if( e1->StrictScalar())
2052     {
2053       if( g2.get() == NULL) return e2->SubInvSNew( e1); else g2.release();
2054       res= e2->SubInvS(e1); // scalar+scalar or array+scalar
2055 
2056     }
2057   else
2058     if( e2->StrictScalar())
2059       {
2060 	if( g1.get() == NULL) return e1->SubSNew( e2); else g1.release();
2061 	res= e1->SubS(e2); // array+scalar
2062 
2063       }
2064     else if( e1->N_Elements() == e2->N_Elements())
2065     {
2066       if( g1.get() != NULL)
2067 	{
2068 	  g1.release();
2069 	  return e1->Sub(e2);
2070 	}
2071       if( g2.get() != NULL)
2072 	{
2073 	  g2.release();
2074 	  res = e2->SubInv(e1);
2075 	  res->SetDim( e1->Dim());
2076 	  return res;
2077 	}
2078       else
2079 	{
2080 	return e1->SubNew(e2);
2081 	}
2082     }
2083   else if( e1->N_Elements() < e2->N_Elements())
2084 	{
2085 	  if( g1.get() == NULL) return e1->SubNew( e2); else g1.release();
2086 	  res= e1->Sub(e2); // smaller_array + larger_array or same size
2087 
2088 	}
2089       else
2090 	{
2091 	  if( g2.get() == NULL) return e2->SubInvNew( e1); else g2.release();
2092 	  res= e2->SubInv(e1); // smaller + larger
2093 
2094 	}
2095   return res;
2096 }
Eval()2097 BaseGDL* MINUSNCNode::Eval()
2098 {
2099  BaseGDL* res;
2100  Guard<BaseGDL> g1;
2101  Guard<BaseGDL> g2;
2102  BaseGDL *e1, *e2;
2103 //  AdjustTypesNC( g1, e1, g2, e2);
2104 
2105   SetupGuards( g1, e1, g2, e2 );
2106 
2107   DType aTy=e1->Type();
2108   DType bTy=e2->Type();
2109   if( aTy == bTy)
2110   {
2111     if( aTy == GDL_OBJ) // we MUST do this here (correct guard handling)
2112       return e1->Sub( e2);
2113 
2114     // otherwise continue below
2115   }
2116   else // aTy != bTy
2117   {
2118     DType cxTy = PromoteComplexOperand( aTy, bTy);
2119     if( cxTy != GDL_UNDEF)
2120     {
2121 	  e2 = e2->Convert2( cxTy, BaseGDL::COPY);
2122 	  g2.Reset( e2); // delete former e2
2123 	  e1 = e1->Convert2( cxTy, BaseGDL::COPY);
2124 	  g1.Reset( e1); // delete former e1
2125 
2126     }    // Change > to >= JMG
2127     else if( DTypeOrder[aTy] >= DTypeOrder[bTy])
2128     {
2129 //       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
2130 //       if( (aTy == GDL_COMPLEX && bTy == GDL_DOUBLE))
2131 // 	{
2132 // 	  e2 = e2->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2133 // 	  g2.Reset( e2); // delete former e2
2134 // 	  e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2135 // 	  g1.Reset( e1); // delete former e1
2136 // 	}
2137 //       else
2138       if( aTy == GDL_OBJ) // only check for aTy is ok because GDL_OBJ has highest order
2139 	return e1->Sub(e2); // for operator overloading, do not convert other type then
2140       else
2141       {
2142 	// convert e2 to e1
2143 	e2 = e2->Convert2( aTy, BaseGDL::COPY);
2144 	g2.Reset( e2); // delete former e2
2145       }
2146     }
2147     else
2148     {
2149 //       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
2150 //       if( (bTy == GDL_COMPLEX && aTy == GDL_DOUBLE))
2151 // 	{
2152 // 	  e2 = e2->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2153 // 	  g2.Reset( e2); // delete former e2
2154 // 	  e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2155 // 	  g1.Reset( e1); // delete former e1
2156 // 	}
2157 //       else
2158       if( bTy == GDL_OBJ) // only check for bTy is ok because GDL_OBJ has highest order
2159 	return e2->SubInv( e1); // for operator overloading, do not convert other type then
2160       else
2161       {
2162 	// convert e1 to e2
2163 	e1 = e1->Convert2( bTy, BaseGDL::COPY);
2164 	g1.Reset( e1); // delete former e1
2165       }
2166     }
2167   } // aTy != bTy
2168 
2169  if( e1->StrictScalar())
2170    {
2171      if( g2.Get() == NULL) return e2->SubInvSNew( e1); else g2.Release();
2172      res= e2->SubInvS(e1); // scalar+scalar or array+scalar
2173 
2174    }
2175  else
2176    if( e2->StrictScalar())
2177      {
2178        if( g1.Get() == NULL) return e1->SubSNew( e2); else g1.Release();
2179        res= e1->SubS(e2); // array+scalar
2180 
2181      }
2182    else if( e1->N_Elements() == e2->N_Elements())
2183    {
2184      if( g1.Get() != NULL)
2185        {
2186 	 g1.Release();
2187 	 return e1->Sub(e2);
2188        }
2189      if( g2.Get() != NULL)
2190        {
2191 	 g2.Release();
2192 	 res = e2->SubInv(e1);
2193 	 res->SetDim( e1->Dim());
2194 	 return res;
2195        }
2196      else
2197        {
2198        return e1->SubNew(e2);
2199        }
2200    }
2201 else if( e1->N_Elements() < e2->N_Elements())
2202        {
2203 	 if( g1.Get() == NULL) return e1->SubNew( e2); else g1.Release();
2204 	 res= e1->Sub(e2); // smaller_array + larger_array or same size
2205 
2206        }
2207      else
2208        {
2209 	 if( g2.Get() == NULL) return e2->SubInvNew( e1); else g2.Release();
2210 	 res= e2->SubInv(e1); // smaller + larger
2211 
2212        }
2213  return res;
2214 }
Eval()2215 BaseGDL* LTMARKNCNode::Eval()
2216 { BaseGDL* res;
2217  Guard<BaseGDL> g1;
2218  Guard<BaseGDL> g2;
2219  BaseGDL *e1, *e2; AdjustTypesNC( g1, e1, g2, e2);
2220 
2221  if( e1->StrictScalar())
2222    {
2223      if( g2.get() == NULL) return e2->LtMarkSNew( e1); else g2.release();
2224      res= e2->LtMarkS(e1); // scalar+scalar or array+scalar
2225 
2226    }
2227  else
2228    if( e2->StrictScalar())
2229      {
2230        if( g1.get() == NULL) return e1->LtMarkSNew( e2); else g1.release();
2231        res= e1->LtMarkS(e2); // array+scalar
2232 
2233      }
2234    else if( e1->N_Elements() == e2->N_Elements())
2235    {
2236      if( g1.get() != NULL)
2237        {
2238 	 g1.release();
2239 	 return e1->LtMark(e2);
2240        }
2241      if( g2.get() != NULL)
2242        {
2243 	 g2.release();
2244 	 res = e2->LtMark(e1);
2245 	 res->SetDim( e1->Dim());
2246 	 return res;
2247        }
2248      else
2249        {
2250        return e1->LtMarkNew(e2);
2251        }
2252    }
2253    else if( e1->N_Elements() < e2->N_Elements())
2254        {
2255 	 if( g1.get() == NULL) return e1->LtMarkNew( e2); else g1.release();
2256 	 res= e1->LtMark(e2); // smaller_array + larger_array or same size
2257 
2258        }
2259      else
2260        {
2261 	 if( g2.get() == NULL) return e2->LtMarkNew( e1); else g2.release();
2262 	 res= e2->LtMark(e1); // smaller + larger
2263 
2264        }
2265  return res;
2266 }
Eval()2267 BaseGDL* GTMARKNCNode::Eval()
2268 { BaseGDL* res;
2269  Guard<BaseGDL> g1;
2270  Guard<BaseGDL> g2;
2271  BaseGDL *e1, *e2; AdjustTypesNC( g1, e1, g2, e2);
2272 
2273  if( e1->StrictScalar())
2274    {
2275      if( g2.get() == NULL) return e2->GtMarkSNew( e1); else g2.release();
2276      res= e2->GtMarkS(e1); // scalar+scalar or array+scalar
2277 
2278    }
2279  else
2280    if( e2->StrictScalar())
2281      {
2282        if( g1.get() == NULL) return e1->GtMarkSNew( e2); else g1.release();
2283        res= e1->GtMarkS(e2); // array+scalar
2284 
2285      }
2286    else if( e1->N_Elements() == e2->N_Elements())
2287    {
2288      if( g1.get() != NULL)
2289        {
2290 	 g1.release();
2291 	 return e1->GtMark(e2);
2292        }
2293      if( g2.get() != NULL)
2294        {
2295 	 g2.release();
2296 	 res = e2->GtMark(e1);
2297 	 res->SetDim( e1->Dim());
2298 	 return res;
2299        }
2300      else
2301        {
2302        return e1->GtMarkNew(e2);
2303        }
2304    }
2305 else if( e1->N_Elements() < e2->N_Elements())
2306        {
2307 	 if( g1.get() == NULL) return e1->GtMarkNew( e2); else g1.release();
2308 	 res= e1->GtMark(e2); // smaller_array + larger_array or same size
2309 
2310        }
2311      else
2312        {
2313 	 if( g2.get() == NULL) return e2->GtMarkNew( e1); else g2.release();
2314 	 res= e2->GtMark(e1); // smaller + larger
2315 
2316        }
2317  return res;
2318 }
2319 
Eval()2320 BaseGDL* ASTERIXNC12Node::Eval()
2321 {
2322   BaseGDL *e1 = op1->EvalNC();
2323   BaseGDL *e2 = op2->EvalNC();
2324   DType aTy=e1->Type();
2325   DType bTy=e2->Type();
2326   if( aTy == bTy)
2327   {
2328     if ( e1->StrictScalar() )
2329     {
2330       return e2->MultSNew( e1 ); // scalar+scalar or array+scalar
2331     }
2332     else if ( e2->StrictScalar() )
2333     {
2334       return e1->MultSNew( e2); // array+scalar
2335     }
2336     else if ( e1->N_Elements() <= e2->N_Elements() )
2337     {
2338       return e1->MultNew ( e2 );
2339     }
2340     else // e1->N_Elements() > e2->N_Elements() )
2341     {
2342       return e2->MultNew( e1); // smaller + larger
2343     }
2344   }
2345 
2346   Guard<BaseGDL> g1;
2347   Guard<BaseGDL> g2;
2348 
2349   DType cxTy = PromoteComplexOperand( aTy, bTy);
2350   if( cxTy != GDL_UNDEF)
2351   {
2352       e2 = e2->Convert2( cxTy, BaseGDL::COPY);
2353       g2.reset( e2);
2354       e1 = e1->Convert2( cxTy, BaseGDL::COPY);
2355       g1.reset( e1);
2356   }
2357   else if( DTypeOrder[aTy] >= DTypeOrder[bTy])
2358     {
2359 //       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
2360 //       if( aTy == GDL_COMPLEX && bTy == GDL_DOUBLE)
2361 //       {
2362 // 	  e2 = e2->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2363 // 	  g2.reset( e2);
2364 // 	  e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2365 // 	  g1.reset( e1);
2366 //       }
2367 //       else
2368       {
2369 	// convert e2 to e1
2370 	e2 = e2->Convert2( aTy, BaseGDL::COPY);
2371 	g2.reset( e2);
2372       }
2373     }
2374   else
2375     {
2376 //       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
2377 //       if( (bTy == GDL_COMPLEX && aTy == GDL_DOUBLE))
2378 // 	{
2379 // 	  e2 = e2->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2380 // 	  g2.reset( e2);
2381 // 	  e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2382 // 	  g1.reset( e1);
2383 // 	}
2384 //       else
2385 	{// convert e1 to e2
2386 	    e1 = e1->Convert2( bTy, BaseGDL::COPY);
2387 	    g1.reset( e1);
2388 	}
2389     }
2390 
2391   // 'classic handling from here
2392   BaseGDL* res;
2393   if ( e1->StrictScalar() )
2394   {
2395 	  if ( g2.get() == NULL )
2396 	  {
2397 		  res= e2->MultSNew( e1); // scalar+scalar or array+scalar
2398 	  }
2399 	  else
2400 	  {
2401 		  g2.release();
2402 		  res= e2->MultS( e1); // scalar+scalar or array+scalar
2403 	  }
2404   }
2405   else	if ( e2->StrictScalar() )
2406   {
2407 	  if ( g1.get() == NULL )
2408 	  {
2409 // 			return e1->New( e2);
2410 		  res= e1->MultSNew( e2); // array+scalar
2411 	  }
2412 	  else
2413 	  {
2414 		  g1.release();
2415 		  res= e1->MultS( e2); // array+scalar
2416 	  }
2417   }
2418   else if ( e1->N_Elements() == e2->N_Elements() )
2419   {
2420 	  if ( g1.get() != NULL )
2421 	  {
2422 		  g1.release();
2423 		  return e1->Mult( e2);
2424 	  }
2425 	  else if ( g2.get() != NULL )
2426 	  {
2427 		  g2.release();
2428 		  res = e2->Mult( e1);
2429 		  res->SetDim( e1->Dim());
2430 		  return res;
2431 	  }
2432 	  else
2433 	  {
2434 		  return e1->MultNew( e2);
2435 // 			return e1->Dup()->Mult ( e2 );
2436 	  }
2437   }
2438   else if ( e1->N_Elements() < e2->N_Elements() )
2439   {
2440 	  if ( g1.get() == NULL )
2441 	  {
2442 		  // 		 return e1->New( e2);
2443 		  res= e1->MultNew( e2); // smaller_array + larger_array or same size
2444 	    }
2445 	  else
2446 	  {
2447 		  g1.release();
2448 		  res= e1->Mult( e2); // smaller_array + larger_array or same size
2449 	  }
2450   }
2451   else
2452   {
2453 	  if ( g2.get() == NULL )
2454 	  {
2455 		  res = e2->MultNew( e1); // smaller + larger
2456 	  }
2457 	    else
2458 	  {
2459 		  g2.release();
2460 		  res= e2->Mult( e1); // smaller + larger
2461 	  }
2462   }
2463   return res;
2464 }
Eval()2465 BaseGDL* ASTERIXNCNode::Eval()
2466 {
2467 	BaseGDL* res;
2468 	Guard<BaseGDL> g1;
2469 	Guard<BaseGDL> g2;
2470 	BaseGDL *e1, *e2; AdjustTypesNC ( g1, e1, g2, e2 );
2471 
2472 	if ( e1->StrictScalar() )
2473 	{
2474 		if ( g2.get() == NULL )
2475 		{
2476 			res= e2->MultSNew( e1); // scalar+scalar or array+scalar
2477 		}
2478 		else
2479 		{
2480 			g2.release();
2481 			res= e2->MultS( e1); // scalar+scalar or array+scalar
2482 		}
2483 	}
2484 	else	if ( e2->StrictScalar() )
2485 	{
2486 		if ( g1.get() == NULL )
2487 		{
2488 // 			return e1->New( e2);
2489 			res= e1->MultSNew( e2); // array+scalar
2490 		}
2491 		else
2492 		{
2493 			g1.release();
2494 			res= e1->MultS( e2); // array+scalar
2495 		}
2496 	}
2497 	else if ( e1->N_Elements() == e2->N_Elements() )
2498 	{
2499 		if ( g1.get() != NULL )
2500 		{
2501 			g1.release();
2502 			return e1->Mult( e2);
2503 		}
2504 		else if ( g2.get() != NULL )
2505 		{
2506 			g2.release();
2507 			res = e2->Mult( e1);
2508 			res->SetDim( e1->Dim());
2509 			return res;
2510 		}
2511 		else
2512 		{
2513 			return e1->MultNew( e2);
2514 // 			return e1->Dup()->Mult ( e2 );
2515 		}
2516 	}
2517 	else if ( e1->N_Elements() < e2->N_Elements() )
2518 	{
2519 		if ( g1.get() == NULL )
2520 		{
2521 			// 		 return e1->New( e2);
2522 			res= e1->MultNew( e2); // smaller_array + larger_array or same size
2523 		 }
2524 		else
2525 		{
2526 			g1.release();
2527 			res= e1->Mult( e2); // smaller_array + larger_array or same size
2528 		}
2529 	}
2530 	else
2531 	{
2532 		if ( g2.get() == NULL )
2533 		{
2534 			res = e2->MultNew( e1); // smaller + larger
2535 		}
2536 		 else
2537 		{
2538 			g2.release();
2539 			res= e2->Mult( e1); // smaller + larger
2540 		}
2541 	}
2542 	return res;
2543 }
2544 
Eval()2545 BaseGDL* MATRIX_OP1NCNode::Eval()
2546 { BaseGDL* res;
2547  Guard<BaseGDL> g1;
2548  Guard<BaseGDL> g2;
2549  BaseGDL *e1, *e2;
2550  if( op1NC)
2551    {
2552      e1 = op1->EvalNC();
2553    }
2554  else
2555    {
2556      e1 = op1->Eval();
2557      g1.reset( e1);
2558    }
2559  if( op2NC)
2560    {
2561      e2 = op2->EvalNC();
2562    }
2563  else
2564    {
2565      e2 = op2->Eval();
2566      g2.reset( e2);
2567    }
2568  DType aTy=e1->Type();
2569  DType bTy=e2->Type();
2570 //  DType maxTy=(DTypeOrder[aTy] >= DTypeOrder[bTy])? aTy: bTy;
2571 //  if( maxTy > 100)
2572 //    {
2573 //      throw GDLException( "Expressions of this type cannot be converted.");
2574 //    }
2575 //  DType cTy=maxTy;
2576 //  if( maxTy == GDL_BYTE || maxTy == GDL_INT)
2577 //    cTy=GDL_LONG;
2578 //  else if( maxTy == GDL_UINT)
2579 //    cTy=GDL_ULONG;
2580  DType cTy = PromoteMatrixOperands( aTy, bTy);
2581 
2582  if( aTy != cTy)
2583    {
2584      e1 = e1->Convert2( cTy, BaseGDL::COPY);
2585      g1.reset( e1);
2586    }
2587  if( bTy != cTy)
2588    {
2589      e2 = e2->Convert2( cTy, BaseGDL::COPY);
2590      g2.reset( e2);
2591    }
2592 
2593  res=e1->MatrixOp(e2);
2594  return res;
2595 }
Eval()2596 BaseGDL* MATRIX_OP2NCNode::Eval()
2597 {
2598  BaseGDL* res;
2599  Guard<BaseGDL> g1;
2600  Guard<BaseGDL> g2;
2601  BaseGDL *e1, *e2;
2602  if( op1NC)
2603    {
2604      e1 = op1->EvalNC();
2605    }
2606  else
2607    {
2608      e1 = op1->Eval();
2609      g1.reset( e1);
2610    }
2611  if( op2NC)
2612    {
2613      e2 = op2->EvalNC();
2614    }
2615  else
2616    {
2617      e2 = op2->Eval();
2618      g2.reset( e2);
2619    }
2620  DType aTy=e1->Type();
2621  DType bTy=e2->Type();
2622 //  DType maxTy=(DTypeOrder[aTy] >= DTypeOrder[bTy])? aTy: bTy;
2623 //  if( maxTy > 100)
2624 //    {
2625 //      throw GDLException( "Expressions of this type cannot be converted.");
2626 //    }
2627 //  DType cTy=maxTy;
2628 //  if( maxTy == GDL_BYTE || maxTy == GDL_INT)
2629 //    cTy=GDL_LONG;
2630 //  else if( maxTy == GDL_UINT)
2631 //    cTy=GDL_ULONG;
2632 
2633  DType cTy = PromoteMatrixOperands( aTy, bTy);
2634 
2635  if( aTy != cTy)
2636    {
2637      e1 = e1->Convert2( cTy, BaseGDL::COPY);
2638      g1.reset( e1);
2639    }
2640  if( bTy != cTy)
2641    {
2642      e2 = e2->Convert2( cTy, BaseGDL::COPY);
2643      g2.reset( e2);
2644    }
2645 
2646  res=e2->MatrixOp(e1);
2647  return res;
2648 }
2649 
Eval()2650 BaseGDL* SLASHNC12Node::Eval()
2651 {
2652   BaseGDL *e1 = op1->EvalNC();
2653   BaseGDL *e2 = op2->EvalNC();
2654   DType aTy=e1->Type();
2655   DType bTy=e2->Type();
2656   if( aTy == bTy)
2657   {
2658     if ( e1->StrictScalar() )
2659     {
2660       return e2->DivInvSNew( e1 ); // scalar+scalar or array+scalar
2661     }
2662     else if ( e2->StrictScalar() )
2663     {
2664       return e1->DivSNew( e2); // array+scalar
2665     }
2666     else if ( e1->N_Elements() <= e2->N_Elements() )
2667     {
2668       return e1->DivNew ( e2 );
2669     }
2670     else // e1->N_Elements() > e2->N_Elements() )
2671     {
2672       return e2->DivInvNew( e1); // smaller + larger
2673     }
2674   }
2675   Guard<BaseGDL> g1;
2676   Guard<BaseGDL> g2;
2677 
2678   DType cxTy = PromoteComplexOperand( aTy, bTy);
2679   if( cxTy != GDL_UNDEF)
2680   {
2681 	e2 = e2->Convert2( cxTy, BaseGDL::COPY);
2682 	g2.reset( e2);
2683 	e1 = e1->Convert2( cxTy, BaseGDL::COPY);
2684 	g1.reset( e1);
2685   }
2686   else if( DTypeOrder[aTy] >= DTypeOrder[bTy])
2687     {
2688 //       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
2689 //       if( aTy == GDL_COMPLEX && bTy == GDL_DOUBLE)
2690 //       {
2691 // 	  e2 = e2->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2692 // 	  g2.reset( e2);
2693 // 	  e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2694 // 	  g1.reset( e1);
2695 //       }
2696 //       else
2697       {
2698 	// convert e2 to e1
2699 	e2 = e2->Convert2( aTy, BaseGDL::COPY);
2700 	g2.reset( e2);
2701       }
2702     }
2703   else
2704     {
2705 //       // GDL_COMPLEX op GDL_DOUBLE = GDL_COMPLEXDBL
2706 //       if( (bTy == GDL_COMPLEX && aTy == GDL_DOUBLE))
2707 // 	{
2708 // 	  e2 = e2->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2709 // 	  g2.reset( e2);
2710 // 	  e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2711 // 	  g1.reset( e1);
2712 // 	}
2713 //       else
2714 	{// convert e1 to e2
2715 	    e1 = e1->Convert2( bTy, BaseGDL::COPY);
2716 	    g1.reset( e1);
2717 	}
2718     }
2719 
2720  // 'classic handling from here
2721  BaseGDL* res;
2722  if( e1->StrictScalar())
2723    {
2724      if( g2.get() == NULL) return e2->DivInvSNew( e1); else g2.release();
2725      res= e2->DivInvS(e1); // scalar+scalar or array+scalar
2726 
2727    }
2728  else
2729    if( e2->StrictScalar())
2730      {
2731        if( g1.get() == NULL) return e1->DivSNew( e2); else g1.release();
2732        res= e1->DivS(e2); // array+scalar
2733 
2734      }
2735    else if( e1->N_Elements() == e2->N_Elements())
2736    {
2737      if( g1.get() != NULL)
2738        {
2739 	 g1.release();
2740 	 return e1->Div(e2);
2741        }
2742      if( g2.get() != NULL)
2743        {
2744 	 g2.release();
2745 	 res = e2->DivInv(e1);
2746 	 res->SetDim( e1->Dim());
2747 	 return res;
2748        }
2749      else
2750        {
2751        return e1->DivNew(e2);
2752        }
2753    }
2754 else if( e1->N_Elements() < e2->N_Elements())
2755        {
2756 	 if( g1.get() == NULL) return e1->DivNew( e2); else g1.release();
2757 	 res= e1->Div(e2); // smaller_array + larger_array or same size
2758 
2759        }
2760      else
2761        {
2762 	 if( g2.get() == NULL) return e2->DivInvNew( e1); else g2.release();
2763 	 res= e2->DivInv(e1); // smaller + larger
2764 
2765        }
2766 
2767  return res;
2768 }
Eval()2769 BaseGDL* SLASHNCNode::Eval()
2770 { BaseGDL* res;
2771  Guard<BaseGDL> g1;
2772  Guard<BaseGDL> g2;
2773  BaseGDL *e1, *e2; AdjustTypesNC( g1, e1, g2, e2);
2774 
2775  if( e1->StrictScalar())
2776    {
2777      if( g2.get() == NULL) return e2->DivInvSNew( e1); else g2.release();
2778      res= e2->DivInvS(e1); // scalar+scalar or array+scalar
2779 
2780    }
2781  else
2782    if( e2->StrictScalar())
2783      {
2784        if( g1.get() == NULL) return e1->DivSNew( e2); else g1.release();
2785        res= e1->DivS(e2); // array+scalar
2786 
2787      }
2788    else if( e1->N_Elements() == e2->N_Elements())
2789    {
2790      if( g1.get() != NULL)
2791        {
2792 	 g1.release();
2793 	 return e1->Div(e2);
2794        }
2795      if( g2.get() != NULL)
2796        {
2797 	 g2.release();
2798 	 res = e2->DivInv(e1);
2799 	 res->SetDim( e1->Dim());
2800 	 return res;
2801        }
2802      else
2803        {
2804        return e1->DivNew(e2);
2805        }
2806    }
2807 else if( e1->N_Elements() < e2->N_Elements())
2808        {
2809 	 if( g1.get() == NULL) return e1->DivNew( e2); else g1.release();
2810 	 res= e1->Div(e2); // smaller_array + larger_array or same size
2811 
2812        }
2813      else
2814        {
2815 	 if( g2.get() == NULL) return e2->DivInvNew( e1); else g2.release();
2816 	 res= e2->DivInv(e1); // smaller + larger
2817 
2818        }
2819 
2820  return res;
2821 }
Eval()2822 BaseGDL* MOD_OPNCNode::Eval()
2823 { BaseGDL* res;
2824  Guard<BaseGDL> g1;
2825  Guard<BaseGDL> g2;
2826  BaseGDL *e1, *e2; AdjustTypesNC( g1, e1, g2, e2);
2827 
2828  if( e1->StrictScalar())
2829    {
2830      if( g2.get() == NULL) return e2->ModInvSNew( e1); else g2.release();
2831      res= e2->ModInvS(e1); // scalar+scalar or array+scalar
2832 
2833    }
2834  else if( e2->StrictScalar())
2835      {
2836        if( g1.get() == NULL) return e1->ModSNew( e2); else g1.release();
2837        res= e1->ModS(e2); // array+scalar
2838 
2839      }
2840    else if( e1->N_Elements() == e2->N_Elements())
2841    {
2842      if( g1.get() != NULL)
2843        {
2844 	 g1.release();
2845 	 return e1->Mod(e2);
2846        }
2847      if( g2.get() != NULL)
2848        {
2849 	 g2.release();
2850 	 res = e2->ModInv(e1);
2851 	 res->SetDim( e1->Dim());
2852 	 return res;
2853        }
2854      else
2855        {
2856        return e1->ModNew(e2);
2857        }
2858    }
2859 else if( e1->N_Elements() < e2->N_Elements())
2860        {
2861 	 if( g1.get() == NULL) return e1->ModNew( e2); else g1.release();
2862 	 res= e1->Mod(e2); // smaller_array + larger_array or same size
2863 
2864        }
2865      else
2866        {
2867 	 if( g2.get() == NULL) return e2->ModInvNew( e1); else g2.release();
2868 	 res= e2->ModInv(e1); // smaller + larger
2869 
2870        }
2871  return res;
2872 }
2873 
2874 
Eval()2875 BaseGDL* POWNCNode::Eval()
2876 {
2877   BaseGDL* res;
2878   Guard<BaseGDL> g1;
2879   Guard<BaseGDL> g2;
2880   BaseGDL *e1, *e2;
2881   if( op1NC)
2882     {
2883       e1 = op1->EvalNC();
2884     }
2885   else
2886     {
2887       e1 = op1->Eval();
2888       g1.reset( e1);
2889     }
2890   if( op2NC)
2891     {
2892       e2 = op2->EvalNC();
2893     }
2894   else
2895     {
2896       e2 = op2->Eval();
2897       g2.reset( e2);
2898     }
2899 
2900   DType aTy=e1->Type();
2901   DType bTy=e2->Type();
2902 
2903   if( aTy == GDL_STRING)
2904     {
2905       e1 = e1->Convert2( GDL_FLOAT, BaseGDL::COPY);
2906       g1.reset( e1); // deletes old e1
2907       aTy = GDL_FLOAT;
2908     }
2909   if( bTy == GDL_STRING)
2910     {
2911       e2 = e2->Convert2( GDL_FLOAT, BaseGDL::COPY);
2912       g2.reset( e2); // deletes old e2
2913       bTy = GDL_FLOAT;
2914     }
2915 
2916   if( ComplexType(aTy))
2917     {
2918       if( IntType( bTy))
2919 	{
2920 	  if( bTy != GDL_LONG)
2921 	    {
2922 	      e2 = e2->Convert2( GDL_LONG, BaseGDL::COPY);
2923 	      g2.reset( e2);
2924 	    }
2925 	  if( g1.get() == NULL)
2926 	    {
2927 	      return e1->PowNew( e2);
2928 	    }
2929 	  else
2930 	    {
2931 	      res = g1->Pow( e2);
2932 	      if( res == g1.get())
2933 		g1.release();
2934 	      return res;
2935 	    }
2936 	}
2937       if( aTy == GDL_COMPLEX)
2938 	{
2939 	  if( bTy == GDL_DOUBLE)
2940 	    {
2941 	      e1 = e1->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY);
2942 	      g1.reset( e1);
2943 	      aTy = GDL_COMPLEXDBL;
2944 	    }
2945 	  else if( bTy == GDL_FLOAT)
2946 	    {
2947 	      if( g1.get() == NULL)
2948 		{
2949 		  return e1->PowNew( e2);
2950 		}
2951 	      else
2952 		{
2953 		  res = g1->Pow( e2);
2954 		  if( res == g1.get())
2955 		    g1.release();
2956 		  return res;
2957 		}
2958 	    }
2959 	}
2960       if( aTy == GDL_COMPLEXDBL)
2961 	{
2962 	  if( bTy == GDL_FLOAT)
2963 	    {
2964 	      e2 = e2->Convert2( GDL_DOUBLE, BaseGDL::COPY);
2965 	      g2.reset( e2);
2966 	      bTy = GDL_DOUBLE;
2967 	    }
2968 	  if( bTy == GDL_DOUBLE)
2969 	    {
2970 	      if( g1.get() == NULL)
2971 		{
2972 		  return e1->PowNew( e2);
2973 		}
2974 	      else
2975 		{
2976 		  res = g1->Pow( e2);
2977 		  if( res == g1.get())
2978 		    g1.release();
2979 		  return res;
2980 		}
2981 	    }
2982 	}
2983     }
2984 
2985   if( IntType( bTy) && FloatType( aTy))
2986     {
2987       if( bTy != GDL_LONG)
2988 	{
2989 	  e2 = e2->Convert2( GDL_LONG, BaseGDL::COPY);
2990 	  g2.reset( e2);
2991 	}
2992       if( g1.get() == NULL)
2993 	res = e1->PowIntNew( e2);
2994       else
2995 	{
2996 	  res = g1->PowInt( e2);
2997 	  if( res == g1.get())
2998 		g1.release();
2999 	}
3000       return res;
3001     }
3002 
3003   DType convertBackT;
3004 
3005   bool aTyGEbTy = DTypeOrder[aTy] >= DTypeOrder[bTy];
3006   // convert back
3007   if( IntType( bTy) && !aTyGEbTy)
3008     convertBackT = aTy;
3009   else
3010     convertBackT = GDL_UNDEF;
3011 
3012   if( aTy != bTy)
3013     {
3014       if( aTyGEbTy) // crucial: '>' -> '>='
3015 	{
3016 	  if( DTypeOrder[aTy] > 100)
3017 	    {
3018 	      throw GDLException( "Expressions of this type cannot be converted.");
3019 	    }
3020 
3021 	  // convert e2 to e1
3022 	  e2 = e2->Convert2( aTy, BaseGDL::COPY);
3023 	  g2.reset( e2); // delete former e2
3024 	}
3025       else // bTy > aTy (order)
3026 	{
3027 	  if( DTypeOrder[bTy] > 100)
3028 	    {
3029 	      throw GDLException( "Expressions of this type cannot be converted.");
3030 	    }
3031 
3032 	  // convert e1 to e2
3033 	  e1 = e1->Convert2( bTy, BaseGDL::COPY);
3034 	  g1.reset( e1); // delete former e1
3035 	}
3036     }
3037 
3038   // AdjustTypes(e2,e1); // order crucial here (for converting back)
3039   if( e1->StrictScalar())
3040     {
3041 	if( g2.get() == NULL)
3042 		res = e2->PowInvSNew( e1);
3043 	else
3044 	{
3045 		g2.release();
3046 		res = e2->PowInvS(e1); // scalar+scalar or array+scalar
3047 	}
3048     }
3049   else if( e2->StrictScalar())
3050     {
3051       if( g1.get() == NULL)
3052 	{
3053 	  res = e1->PowSNew( e2);
3054 // 	  res = e1->PowS(e2); // array+scalar
3055 	}
3056       else
3057 	{
3058 	  g1.release();
3059 	  res= e1->PowS(e2); // array+scalar
3060 	}
3061     }
3062   else if( e1->N_Elements() == e2->N_Elements())
3063     {
3064       if( g1.get() != NULL)
3065 	{
3066 	  g1.release();
3067 	  res = e1->Pow(e2);
3068 	}
3069       else if( g2.get() != NULL)
3070 	{
3071 	  g2.release();
3072 	  res = e2->PowInv(e1);
3073 	  res->SetDim( e1->Dim());
3074 	}
3075       else
3076 	{
3077 	res = e1->PowNew( e2);
3078 // 	  res = e1->Pow(e2);
3079 	}
3080     }
3081   else if( e1->N_Elements() < e2->N_Elements())
3082       {
3083 	if( g1.get() == NULL)
3084 	  {
3085 	    res = e1->PowNew( e2);
3086 // 	    res= e1->Pow(e2); // smaller_array + larger_array or same size
3087 	  }
3088 	else
3089 	  {
3090 	    g1.release();
3091 	    res= e1->Pow(e2); // smaller_array + larger_array or same size
3092 	  }
3093       }
3094     else
3095       {
3096 	if( g2.get() == NULL)
3097 		res = e2->PowInvNew( e1);
3098 	else
3099 	{
3100 		g2.release();
3101 		res= e2->PowInv(e1); // smaller + larger
3102 	}
3103       }
3104   if( convertBackT != GDL_UNDEF)
3105     {
3106       res = res->Convert2( convertBackT, BaseGDL::CONVERT);
3107     }
3108   return res;
3109 }
3110 
LEval()3111 BaseGDL** FCALL_LIB_N_ELEMENTSNode::LEval()
3112 {
3113     // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack
3114     StackGuard<EnvStackT> guard(ProgNode::interpreter->CallStack());
3115     throw GDLException(this,"Internal error: N_ELEMENTS called as left expr.");
3116 }
3117 
Eval()3118 BaseGDL* FCALL_LIB_N_ELEMENTSNode::Eval()
3119 {
3120     if( this->getFirstChild()->getNextSibling() != 0)
3121               throw GDLException(this,"Keyword parameters not allowed in call.");
3122     try
3123     {
3124         BaseGDL* param=NULL;
3125         bool isReference =
3126             static_cast<ParameterNode*>(this->getFirstChild())->ParameterDirect( param);
3127         Guard<BaseGDL> guard;
3128         if( !isReference)
3129             guard.Reset( param);
3130 
3131         if( param == NULL)
3132             return new DLongGDL( 0);
3133 
3134         if( param->IsAssoc())
3135             return new DLongGDL( 1);
3136 		if(param->Type() == GDL_OBJ and param->Scalar())
3137 		{
3138 			DObj ID = (*static_cast<DObjGDL*>( param))[0];
3139 
3140 			DStructGDL* s = NULL;
3141 			Guard<BaseGDL> guard(s);
3142 		   try {
3143 				  s= BaseGDL::interpreter->GetObjHeap( ID);
3144 				}
3145 				catch( GDLInterpreter::HeapException& hEx)
3146 				{
3147 				  throw GDLException(this, "Object ID <"+i2s(ID)+"> not found.");
3148 				}
3149         	if( s->Desc()->IsParent("LIST"))
3150 			  return new DLongGDL( lib::LIST_count(s));
3151 			else
3152 			if( s->Desc()->IsParent("HASH"))
3153 			  return new DLongGDL( lib::HASH_count(s));
3154 		}
3155 	if (param->N_Elements() > 2147483647UL)
3156 	  return new DLong64GDL( param->N_Elements());
3157 	else
3158 	  return new DLongGDL( param->N_Elements());
3159     }
3160     catch( GDLException& e)
3161     {
3162         // an error occured -> parameter is undefined
3163         return new DLongGDL( 0);
3164     }
3165 }
3166 
LEval()3167 BaseGDL** FCALL_LIB_RETNEWNode::LEval()
3168 {
3169     throw GDLException(this,"Internal error: FCALL_LIB_RETNEW as left expr.");
3170 }
3171 
Eval()3172 BaseGDL* FCALL_LIB_RETNEWNode::Eval()
3173 {
3174 // 	match(antlr::RefAST(_t),FCALL_LIB_RETNEW);
3175     EnvT* newEnv=new EnvT( this, this->libFun);
3176 
3177     ProgNode::interpreter->parameter_def_nocheck(this->getFirstChild(), newEnv);
3178 
3179     Guard<EnvT> guardEnv( newEnv);
3180 
3181     BaseGDL* res = this->libFunFun(newEnv);
3182     //*** MUST always return a defined expression
3183     assert( res != NULL);
3184     return res;
3185 }
3186 
LEval()3187 BaseGDL** FCALL_LIB_DIRECTNode::LEval()
3188 {
3189     throw GDLException(this,"Internal error: FCALL_LIB_DIRECTNode as left expr.");
3190 }
3191 
Eval()3192 BaseGDL* FCALL_LIB_DIRECTNode::Eval()
3193 {
3194     BaseGDL* param;
3195     bool isReference =
3196         static_cast<ParameterNode*>(this->getFirstChild())->ParameterDirect( param);
3197     Guard<BaseGDL> guard;
3198     if( !isReference)
3199         guard.Init( param);
3200     // check already here to keep functions leaner
3201     if( param == NULL)
3202     {
3203         assert( isReference);
3204         // unfortunately we cannot retrieve the variable's name here without some effort
3205         throw GDLException(this,
3206                            this->libFun->ObjectName()+": Variable is undefined.",
3207                            false,false);
3208     }
3209     try {
3210         BaseGDL* res = this->libFunDirectFun(param, isReference);
3211 // 	static_cast<DLibFunDirect*>(this->libFun)->FunDirect()(param, isReference);
3212         assert( res != NULL); //*** MUST always return a defined expression
3213         if( res == param)
3214             guard.release();
3215         return res;
3216     }
3217     catch( GDLException& ex)
3218     {
3219         // annotate exception
3220         throw GDLException(this, this->libFun->ObjectName()+": "+ ex.getMessage(),false,false);
3221     }
3222 }
3223 
EvalRefCheck(BaseGDL * & rEval)3224 BaseGDL** FCALL_LIBNode::EvalRefCheck( BaseGDL*& rEval)
3225 {
3226     EnvT* newEnv=new EnvT( this, this->libFun);//libFunList[fl->funIx]);
3227 
3228     ProgNode::interpreter->parameter_def_nocheck(this->getFirstChild(), newEnv);
3229     Guard<EnvT> guardEnv( newEnv);
3230 
3231     // make the call
3232     static DSub* scopeVarfetchPro = libFunList[ LibFunIx("SCOPE_VARFETCH")];
3233     static DSub* routine_namesPro = libFunList[ LibFunIx("ROUTINE_NAMES")];
3234     if( scopeVarfetchPro == this->libFun)//newEnv->GetPro())
3235     {
3236         BaseGDL**  sV = lib::scope_varfetch_reference( newEnv);
3237         if( sV == NULL)
3238 	{
3239 	  rEval = lib::scope_varfetch_value( newEnv);
3240 	  return NULL;
3241 	}
3242 	rEval = *sV;
3243 	if( newEnv->InLoc(sV))
3244 	{
3245 	  *sV = NULL; // steal local value
3246 	  return NULL; // return as not global
3247 	}
3248 	return sV;
3249     }
3250     if( routine_namesPro == this->libFun)// newEnv->GetPro())
3251     {
3252         BaseGDL**  sV = lib::routine_names_reference( newEnv);
3253         if( sV == NULL)
3254 	{
3255 	  rEval = lib::routine_names_value( newEnv);
3256 	  return NULL;
3257 	}
3258 	rEval = *sV;
3259 	if( newEnv->InLoc(sV))
3260 	{
3261 	  *sV = NULL; // steal local value
3262 	  return NULL; // return as not global
3263 	}
3264 	return sV;
3265     }
3266 
3267     // make the call
3268 //     rEval = static_cast<DLibFun*>(newEnv->GetPro())->Fun()(newEnv);
3269     rEval = this->libFunFun(newEnv);
3270 //     BaseGDL** res = ProgNode::interpreter->CallStackBack()->GetPtrTo( rEval);
3271     BaseGDL** res = newEnv->GetPtrToReturnValue();
3272     return res; // NULL ok, rEval set properly
3273 
3274 }
3275 
LEval()3276 BaseGDL** FCALL_LIBNode::LEval()
3277 {
3278     EnvT* newEnv=new EnvT( this, this->libFun);//libFunList[fl->funIx]);
3279 
3280     ProgNode::interpreter->parameter_def_nocheck(this->getFirstChild(), newEnv);
3281     Guard<EnvT> guardEnv( newEnv);
3282 
3283     // make the call
3284     static DSub* scopeVarfetchPro = libFunList[ LibFunIx("SCOPE_VARFETCH")];
3285     if( scopeVarfetchPro == this->libFun)//newEnv->GetPro())
3286     {
3287         BaseGDL**  sV = lib::scope_varfetch_reference( newEnv);
3288         if( sV != NULL)
3289             return sV;
3290         // should never happen
3291         throw GDLException( this, "Internal error: SCOPE_VARFETCH returned no left-value: "+this->getText());
3292     }
3293     static DSub* routine_namesPro = libFunList[ LibFunIx("ROUTINE_NAMES")];
3294     if( routine_namesPro == this->libFun)// newEnv->GetPro())
3295     {
3296         BaseGDL**  sV = lib::routine_names_reference( newEnv);
3297         if( sV != NULL)
3298             return sV;
3299         // should never happen
3300         throw GDLException( this, "Internal error: ROUTINE_NAMES returned no left-value: "+this->getText());
3301     }
3302 //     BaseGDL* libRes = static_cast<DLibFun*>(newEnv->GetPro())->Fun()(newEnv);
3303     BaseGDL* libRes = this->libFunFun(newEnv);
3304     BaseGDL** res = newEnv->GetPtrToReturnValue();
3305     if( res == NULL)
3306     {
3307         GDLDelete( libRes);
3308 
3309         throw GDLException( this, "Library function must return a "
3310                             "left-value in this context: "+this->getText());
3311     }
3312     return res;
3313 }
3314 
3315 // returns new or existing variable
EvalFCALL_LIB(BaseGDL ** & retValPtr)3316 BaseGDL* FCALL_LIBNode::EvalFCALL_LIB(BaseGDL**& retValPtr)
3317 {
3318 
3319     EnvT* newEnv=new EnvT( this, this->libFun);//libFunList[fl->funIx]);
3320 
3321     ProgNode::interpreter->parameter_def_nocheck(this->getFirstChild(), newEnv);
3322 
3323     Guard<EnvT> guardEnv( newEnv);
3324 
3325 //     assert( dynamic_cast<EnvUDT*>(ProgNode::interpreter->CallStackBack()) != NULL);
3326 //     EnvUDT* callStackBack = static_cast<EnvUDT*>(ProgNode::interpreter->CallStackBack());
3327 
3328 //     BaseGDL* res=static_cast<DLibFun*>(newEnv->GetPro())->Fun()(newEnv);
3329     BaseGDL* res=this->libFunFun(newEnv);
3330     // *** MUST always return a defined expression or !NULL
3331     assert( res != NULL);
3332 
3333     //     ProgNode::interpreter->CallStackBack()->SetPtrToReturnValue( newEnv->GetPtrToReturnValueNull());
3334     retValPtr = newEnv->GetPtrToReturnValue();
3335     return res;
3336 }
3337 
3338 // returns always a new variable - see EvalFCALL_LIB
Eval()3339 BaseGDL* FCALL_LIBNode::Eval()
3340 {
3341     // 	match(antlr::RefAST(_t),FCALL_LIB);
3342     EnvT* newEnv=new EnvT( this, this->libFun);//libFunList[fl->funIx]);
3343 
3344     ProgNode::interpreter->parameter_def_nocheck(this->getFirstChild(), newEnv);
3345 
3346     Guard<EnvT> guardEnv( newEnv);
3347 
3348 //     // push id.pro onto call stack
3349 //     ProgNode::interpreter->CallStack().push_back(newEnv);
3350     // make the call
3351     BaseGDL* res=this->libFunFun(newEnv);
3352     // *** MUST always return a defined expression
3353     assert( res != NULL);
3354     //       throw GDLException( _t, "");
3355 
3356     if( newEnv->GetPtrToReturnValue() != NULL)
3357         return res->Dup();
3358 
3359     return res;
3360 }
3361 
EvalRefCheck(BaseGDL * & rEval)3362 BaseGDL** MFCALLNode::EvalRefCheck( BaseGDL*& rEval)
3363 {
3364     StackGuard<EnvStackT> guard(ProgNode::interpreter->CallStack());
3365 
3366     ProgNodeP _t = this->getFirstChild();
3367 
3368     BaseGDL* self=_t->Eval(); //ProgNode::interpreter->expr(_t);
3369     Guard<BaseGDL> self_guard(self);
3370 
3371     _t = _t->getNextSibling();
3372     //match(antlr::RefAST(_t),IDENTIFIER);
3373 
3374     EnvUDT* newEnv=new EnvUDT( self, _t, "", EnvUDT::LRFUNCTION);
3375 
3376     self_guard.release();
3377 
3378     _t = _t->getNextSibling();
3379 
3380     ProgNode::interpreter->parameter_def(_t, newEnv); // temporary owns newEnv (-> no guard necessary)
3381 
3382     // push environment onto call stack
3383     ProgNode::interpreter->CallStack().push_back(newEnv); // now guarded by "guard"
3384 
3385     // make the call
3386     rEval=ProgNode::interpreter->call_fun(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
3387 
3388     BaseGDL** res = newEnv->GetPtrToGlobalReturnValue();
3389     return res; // NULL ok, rEval set properly
3390 }
3391 
LEval()3392 BaseGDL** MFCALLNode::LEval()
3393 {
3394     // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack
3395     StackGuard<EnvStackT> guard(ProgNode::interpreter->CallStack());
3396 
3397 //		match(antlr::RefAST(_t),MFCALL);
3398     ProgNodeP _t = this->getFirstChild();
3399     BaseGDL* self=_t->Eval(); //ProgNode::interpreter->expr(_t);
3400     Guard<BaseGDL> self_guard(self);
3401 
3402     ProgNodeP mp = _t->getNextSibling();
3403 //		match(antlr::RefAST(_t),IDENTIFIER);
3404     _t = mp->getNextSibling();
3405 
3406     EnvUDT* newEnv=new EnvUDT( self, mp, "", EnvUDT::LFUNCTION);
3407 
3408     self_guard.release();
3409 
3410     ProgNode::interpreter->parameter_def(_t, newEnv);
3411 
3412     // push environment onto call stack
3413     ProgNode::interpreter->CallStack().push_back(newEnv);
3414 
3415     // make the call
3416     BaseGDL**	res=ProgNode::interpreter->
3417                     call_lfun(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
3418 
3419     //ProgNode::interpreter->SetRetTree( this->getNextSibling());
3420     return res;
3421 }
3422 
Eval()3423 BaseGDL* MFCALLNode::Eval()
3424 {
3425     // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack
3426     StackGuard<EnvStackT> guard(ProgNode::interpreter->CallStack());
3427 
3428     ProgNodeP _t = this->getFirstChild();
3429 
3430     BaseGDL* self=_t->Eval(); //ProgNode::interpreter->expr(_t);
3431     Guard<BaseGDL> self_guard(self);
3432 
3433     _t = _t->getNextSibling();
3434     //match(antlr::RefAST(_t),IDENTIFIER);
3435 
3436     EnvUDT* newEnv=new EnvUDT( self, _t);
3437 
3438     self_guard.release();
3439 
3440     _t = _t->getNextSibling();
3441 
3442     ProgNode::interpreter->parameter_def(_t, newEnv);
3443 
3444     // push environment onto call stack
3445     ProgNode::interpreter->CallStack().push_back(newEnv);
3446 
3447     // make the call
3448     BaseGDL* res=ProgNode::interpreter->call_fun(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
3449 
3450     //ProgNode::interpreter->SetRetTree( this->getNextSibling());
3451     return res;
3452 }
3453 
EvalRefCheck(BaseGDL * & rEval)3454 BaseGDL** MFCALL_PARENTNode::EvalRefCheck( BaseGDL*& rEval)
3455 {
3456     StackGuard<EnvStackT> guard(ProgNode::interpreter->CallStack());
3457 //  match(antlr::RefAST(_t),MFCALL_PARENT);
3458     ProgNodeP _t = this->getFirstChild();
3459     BaseGDL* self=_t->Eval(); //ProgNode::interpreter->expr(_t);
3460     Guard<BaseGDL> self_guard(self);
3461 
3462     _t = _t->getNextSibling();
3463     ProgNodeP parent = _t;
3464 // 		match(antlr::RefAST(_t),IDENTIFIER);
3465     _t = _t->getNextSibling();
3466     ProgNodeP p = _t;
3467 // 		match(antlr::RefAST(_t),IDENTIFIER);
3468     _t = _t->getNextSibling();
3469 
3470     EnvUDT* newEnv=new EnvUDT( self, p, parent->getText(), EnvUDT::LRFUNCTION);
3471 
3472     self_guard.release();
3473 
3474     ProgNode::interpreter->parameter_def(_t, newEnv);
3475 
3476     // push environment onto call stack
3477     ProgNode::interpreter->CallStack().push_back(newEnv);
3478 
3479     // make the call
3480     rEval=ProgNode::interpreter->call_fun(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
3481     BaseGDL** res = newEnv->GetPtrToGlobalReturnValue();
3482     return res; // NULL ok, rEval set properly
3483 }
3484 
LEval()3485 BaseGDL** MFCALL_PARENTNode::LEval()
3486 {
3487     // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack
3488     StackGuard<EnvStackT> guard(ProgNode::interpreter->CallStack());
3489 //			match(antlr::RefAST(_t),MFCALL_PARENT);
3490     ProgNodeP _t = this->getFirstChild();
3491     BaseGDL* self=_t->Eval(); //ProgNode::interpreter->expr(_t);
3492     Guard<BaseGDL> self_guard(self);
3493 
3494     _t = _t->getNextSibling();
3495     ProgNodeP parent = _t;
3496 // 		match(antlr::RefAST(_t),IDENTIFIER);
3497     _t = _t->getNextSibling();
3498     ProgNodeP p = _t;
3499 // 		match(antlr::RefAST(_t),IDENTIFIER);
3500     _t = _t->getNextSibling();
3501 
3502     EnvUDT* newEnv=new EnvUDT( self, p,	parent->getText(), EnvUDT::LFUNCTION);
3503 
3504     self_guard.release();
3505 
3506     ProgNode::interpreter->parameter_def(_t, newEnv);
3507 
3508     // push environment onto call stack
3509     ProgNode::interpreter->CallStack().push_back(newEnv);
3510 
3511     // make the call
3512     BaseGDL** res=ProgNode::interpreter->
3513                   call_lfun(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
3514 
3515     //ProgNode::interpreter->SetRetTree( this->getNextSibling());
3516     return res;
3517 }
3518 
Eval()3519 BaseGDL* MFCALL_PARENTNode::Eval()
3520 {
3521     // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack
3522     StackGuard<EnvStackT> guard(ProgNode::interpreter->CallStack());
3523 //  match(antlr::RefAST(_t),MFCALL_PARENT);
3524     ProgNodeP _t = this->getFirstChild();
3525     BaseGDL* self=_t->Eval(); //ProgNode::interpreter->expr(_t);
3526     Guard<BaseGDL> self_guard(self);
3527 
3528     _t = _t->getNextSibling();
3529     ProgNodeP parent = _t;
3530 // 		match(antlr::RefAST(_t),IDENTIFIER);
3531     _t = _t->getNextSibling();
3532     ProgNodeP p = _t;
3533 // 		match(antlr::RefAST(_t),IDENTIFIER);
3534     _t = _t->getNextSibling();
3535 
3536     EnvUDT* newEnv=new EnvUDT( self, p,	parent->getText());
3537 
3538     self_guard.release();
3539 
3540     ProgNode::interpreter->parameter_def(_t, newEnv);
3541 
3542     // push environment onto call stack
3543     ProgNode::interpreter->CallStack().push_back(newEnv);
3544 
3545     // make the call
3546     BaseGDL* res=ProgNode::interpreter->call_fun(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
3547 
3548     //ProgNode::interpreter->SetRetTree( this->getNextSibling());
3549     return res;
3550 }
3551 
EvalRefCheck(BaseGDL * & rEval)3552 BaseGDL** FCALLNode::EvalRefCheck( BaseGDL*& rEval)
3553 {
3554     StackGuard<EnvStackT> guard(ProgNode::interpreter->CallStack());
3555     ProgNode::interpreter->SetFunIx( this);
3556 	if( this->funIx < -1) throw GDLException(this," FCALLNode::EvalRefcheck - AutoObj",true,false);
3557     EnvUDT* newEnv=new EnvUDT( this, funList[this->funIx], EnvUDT::LRFUNCTION);
3558 
3559     ProgNode::interpreter->parameter_def(this->getFirstChild(), newEnv);
3560 
3561     // push environment onto call stack
3562     ProgNode::interpreter->CallStack().push_back(newEnv);
3563 
3564     // make the call
3565     rEval=ProgNode::interpreter->call_fun(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
3566     BaseGDL** res = newEnv->GetPtrToGlobalReturnValue();
3567     return res; // NULL ok, rEval set properly
3568 }
3569 
EvalRefCheck(BaseGDL * & rEval)3570 BaseGDL** ARRAYEXPR_FCALLNode::EvalRefCheck( BaseGDL*& rEval)
3571 {
3572     if( fcallNodeFunIx >= 0)
3573         return fcallNode->FCALLNode::EvalRefCheck( rEval);
3574     else if( fcallNodeFunIx == -2)
3575     {
3576         rEval = arrayExprNode->ARRAYEXPRNode::Eval();
3577         return NULL;
3578     }
3579 
3580     assert( fcallNodeFunIx == -1);
3581     // 1st try arrayexpr
3582     try {
3583         rEval = arrayExprNode->ARRAYEXPRNode::Eval();
3584         assert( rEval != NULL);
3585         fcallNodeFunIx = -2; // mark as ARRAYEXPR succeeded
3586         return NULL;
3587     }
3588     catch( GDLException& ex)
3589     {
3590         if( !ex.GetArrayexprIndexeeFailed())
3591         {
3592             fcallNodeFunIx = -2; // mark as ARRAYEXPR succeeded
3593             throw ex;
3594         }
3595         // then try fcall
3596         try {
3597             BaseGDL** res = fcallNode->FCALLNode::EvalRefCheck( rEval);
3598             fcallNodeFunIx = fcallNode->funIx;
3599             return res;
3600         }
3601         catch( GDLException& innerEx)
3602         {
3603             // keep FCALL if already compiled (but runtime error)
3604             if(fcallNode->funIx >= 0)
3605             {
3606                 fcallNodeFunIx = fcallNode->funIx;
3607                 throw innerEx;
3608             }
3609             string msg = "Ambiguous: " + ex.ANTLRException::toString() +
3610                          " or: " + innerEx.ANTLRException::toString();
3611             throw GDLException(this,msg,true,false);
3612         }
3613     }
3614 }
3615 
LEval()3616 BaseGDL** FCALLNode::LEval()
3617 {
3618     // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack
3619     StackGuard<EnvStackT> guard(ProgNode::interpreter->CallStack());
3620     //	match(antlr::RefAST(_t),FCALL);
3621     ProgNodeP	_t = this->getFirstChild();
3622 
3623     ProgNode::interpreter->SetFunIx( this);
3624 	if( this->funIx < -1) throw GDLException(this," FCALLNode::LEval- AutoObj",true,false);
3625     EnvUDT* newEnv=new EnvUDT( this, funList[this->funIx], EnvUDT::LFUNCTION);
3626 
3627     ProgNode::interpreter->parameter_def(_t, newEnv);
3628 
3629     // push environment onto call stack
3630     ProgNode::interpreter->CallStack().push_back(newEnv);
3631 
3632     // make the call
3633     BaseGDL** res=
3634         ProgNode::interpreter->call_lfun(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
3635 
3636     //ProgNode::interpreter->SetRetTree( this->getNextSibling());
3637     return res;
3638 }
3639 
LEval()3640 BaseGDL** ARRAYEXPR_FCALLNode::LEval()
3641 {
3642     // already succeeded
3643     if( fcallNodeFunIx >= 0)
3644         return fcallNode->FCALLNode::LEval();
3645     else if( fcallNodeFunIx == -2)
3646     {
3647         return arrayExprNode->ARRAYEXPRNode::LEval();
3648     }
3649 
3650     // both possible
3651     assert( fcallNodeFunIx == -1);
3652     // 1st try arrayexpr
3653     try {
3654         BaseGDL** res = arrayExprNode->ARRAYEXPRNode::LEval();
3655         fcallNodeFunIx = -2; // mark as ARRAYEXPR succeeded
3656         return res;
3657     }
3658     catch( GDLException& ex)
3659     {
3660         if( !ex.GetArrayexprIndexeeFailed())
3661         {
3662             fcallNodeFunIx = -2; // mark as ARRAYEXPR succeeded
3663             throw ex;
3664         }
3665         // then try fcall
3666         try {
3667             BaseGDL** res = fcallNode->FCALLNode::LEval();
3668             fcallNodeFunIx = fcallNode->funIx;
3669             return res;
3670         }
3671         catch( GDLException& innerEx)
3672         {
3673             // keep FCALL if already compiled (but runtime error)
3674             if(fcallNode->funIx >= 0)
3675             {
3676                 fcallNodeFunIx = fcallNode->funIx;
3677                 throw innerEx;
3678             }
3679             string msg = "Ambiguous: " + ex.ANTLRException::toString() +
3680                          " or: " + innerEx.ANTLRException::toString();
3681             throw GDLException(this,msg,true,false);
3682         }
3683     }
3684 }
3685 
Eval()3686 BaseGDL* FCALLNode::Eval()
3687 {
3688     // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack
3689     StackGuard<EnvStackT> guard(ProgNode::interpreter->CallStack());
3690     ProgNode::interpreter->SetFunIx( this);
3691 	if( this->funIx < -1) throw GDLException(this," FCALLNode::Eval - AutoObj",true,false);
3692     EnvUDT* newEnv=new EnvUDT( this, funList[this->funIx]);
3693 
3694     ProgNode::interpreter->parameter_def(this->getFirstChild(), newEnv);
3695 
3696     // push environment onto call stack
3697     ProgNode::interpreter->CallStack().push_back(newEnv);
3698 
3699     // make the call
3700     BaseGDL*
3701     res=ProgNode::interpreter->call_fun(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
3702 
3703     //ProgNode::interpreter->SetRetTree( this->getNextSibling());
3704     return res;
3705 }
3706 
Eval()3707 BaseGDL* ARRAYEXPR_FCALLNode::Eval()
3708 {
3709     if( fcallNodeFunIx >= 0)
3710         return fcallNode->FCALLNode::Eval();
3711     else if( fcallNodeFunIx == -2)
3712     {
3713         return arrayExprNode->ARRAYEXPRNode::Eval();
3714     }
3715 
3716     assert( fcallNodeFunIx == -1);
3717 
3718     // 1st try arrayexpr
3719     try {
3720         BaseGDL* res = arrayExprNode->ARRAYEXPRNode::Eval();
3721         fcallNodeFunIx = -2; // mark as ARRAYEXPR succeeded
3722         return res;
3723     }
3724     catch( GDLException& ex)
3725     {
3726         // then try fcall
3727         // Problem here: we don't know, why arrayexpr failed
3728         // if it is just because of the index, we should not
3729         // try the function here
3730         if( !ex.GetArrayexprIndexeeFailed())
3731         {
3732             fcallNodeFunIx = -2; // mark as ARRAYEXPR succeeded
3733             throw ex;
3734         }
3735         try {
3736             BaseGDL* res = fcallNode->FCALLNode::Eval();
3737             fcallNodeFunIx = fcallNode->funIx;
3738             return res;
3739         }
3740         catch( GDLException& innerEx)
3741         {
3742             // keep FCALL if already compiled (but runtime error)
3743             if(fcallNode->funIx >= 0)
3744             {
3745                 fcallNodeFunIx = fcallNode->funIx;
3746                 throw innerEx;
3747             }
3748             string msg = "Ambiguous: " + ex.ANTLRException::toString() +
3749                          " or: " + innerEx.ANTLRException::toString();
3750             throw GDLException(this,msg,true,false);
3751         }
3752     }
3753 }
3754 
3755 
EvalRefCheck(BaseGDL * & rEval)3756 BaseGDL** ARRAYEXPR_MFCALLNode::EvalRefCheck( BaseGDL*& rEval)
3757 {
3758     StackGuard<EnvStackT> guard(ProgNode::interpreter->CallStack());
3759 //		match(antlr::RefAST(_t),ARRAYEXPR_MFCALL);
3760     ProgNodeP mark = this->getFirstChild();
3761 
3762     ProgNodeP _t = mark->getNextSibling(); // skip DOT
3763 
3764     BaseGDL* self=_t->Eval(); //ProgNode::interpreter->expr(_t);
3765     Guard<BaseGDL> self_guard(self);
3766 
3767     ProgNodeP mp2 = _t->getNextSibling();
3768     //match(antlr::RefAST(_t),IDENTIFIER);
3769 
3770     _t = mp2->getNextSibling();
3771 
3772     BaseGDL** res;
3773 
3774     EnvUDT* newEnv;
3775     try {
3776         newEnv=new EnvUDT( self, mp2, "", EnvUDT::LRFUNCTION);
3777         self_guard.release();
3778     }
3779     catch( GDLException& ex)
3780     {
3781         goto tryARRAYEXPR;
3782     }
3783 
3784     ProgNode::interpreter->parameter_def(_t, newEnv);
3785 
3786     // push environment onto call stack
3787     ProgNode::interpreter->CallStack().push_back(newEnv);
3788 
3789     // make the call
3790     rEval= ProgNode::interpreter->
3791            call_fun(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
3792     res = newEnv->GetPtrToGlobalReturnValue();
3793     return res; // NULL ok, rEval set properly
3794 
3795 tryARRAYEXPR:
3796     ;
3797     //_t = mark;
3798 
3799     ProgNodeP dot = mark;
3800     // 	match(antlr::RefAST(_t),DOT);
3801     _t = mark->getFirstChild();
3802 
3803     SizeT nDot=dot->nDot;
3804     Guard<DotAccessDescT> aD( new DotAccessDescT(nDot+1));
3805 
3806     ProgNode::interpreter->r_dot_array_expr(_t, aD.get());
3807     _t = _t->getNextSibling();
3808     for (; _t != NULL;) {
3809         ProgNode::interpreter->tag_array_expr(_t, aD.get());
3810         _t = _t->getNextSibling();
3811     }
3812     rEval= aD->ADResolve();
3813     return NULL;  // always r-value
3814 }
3815 
3816 // from  l_arrayexpr_mfcall_as_mfcall
LEval()3817 BaseGDL** ARRAYEXPR_MFCALLNode::LEval()
3818 {
3819     // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack
3820     StackGuard<EnvStackT> guard(ProgNode::interpreter->CallStack());
3821     BaseGDL *self;
3822     EnvUDT*   newEnv;
3823 
3824     ProgNodeP _t = this->getFirstChild();
3825     _t = _t->getNextSibling(); // skip DOT
3826 
3827     self= _t->Eval(); //interpreter->expr(_t);
3828     ProgNodeP mp2 = _t->getNextSibling(); // interpreter->GetRetTree();
3829     //match(antlr::RefAST(_t),IDENTIFIER);
3830 
3831     Guard<BaseGDL> self_guard(self);
3832 
3833     newEnv=new EnvUDT( self, mp2, "", EnvUDT::LFUNCTION);
3834 
3835     self_guard.release();
3836 
3837     ProgNode::interpreter->parameter_def( mp2->getNextSibling(), newEnv);
3838 
3839     // push environment onto call stack
3840     ProgNode::interpreter->CallStack().push_back(newEnv);
3841 
3842     // make the call
3843     return ProgNode::interpreter->call_lfun(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
3844 }
3845 
3846 
3847 
Eval()3848 BaseGDL* ARRAYEXPR_MFCALLNode::Eval()
3849 {
3850     // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack
3851     StackGuard<EnvStackT> guard(ProgNode::interpreter->CallStack());
3852 //		match(antlr::RefAST(_t),ARRAYEXPR_MFCALL);
3853     ProgNodeP mark = this->getFirstChild();
3854 
3855     ProgNodeP _t = mark->getNextSibling(); // skip DOT
3856 
3857     BaseGDL* self=_t->Eval(); //ProgNode::interpreter->expr(_t);
3858     Guard<BaseGDL> self_guard(self);
3859 
3860     ProgNodeP mp2 = _t->getNextSibling();
3861     //match(antlr::RefAST(_t),IDENTIFIER);
3862 
3863     _t = mp2->getNextSibling();
3864 
3865     BaseGDL* res;
3866 
3867     EnvUDT* newEnv;
3868     try {
3869         newEnv=new EnvUDT( self, mp2);
3870         self_guard.release();
3871     }
3872     catch( GDLException& ex)
3873     {
3874         goto tryARRAYEXPR;
3875     }
3876 
3877     ProgNode::interpreter->parameter_def(_t, newEnv);
3878 
3879     // push environment onto call stack
3880     ProgNode::interpreter->CallStack().push_back(newEnv);
3881 
3882     // make the call
3883     res=
3884         ProgNode::interpreter->
3885         call_fun(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
3886 
3887     //ProgNode::interpreter->SetRetTree( this->getNextSibling());
3888     return res;
3889 
3890 tryARRAYEXPR:
3891     ;
3892     //_t = mark;
3893 
3894     ProgNodeP dot = mark;
3895     // 	match(antlr::RefAST(_t),DOT);
3896     _t = mark->getFirstChild();
3897 
3898     SizeT nDot=dot->nDot;
3899     Guard<DotAccessDescT> aD( new DotAccessDescT(nDot+1));
3900 
3901     ProgNode::interpreter->r_dot_array_expr(_t, aD.get());
3902     _t = _t->getNextSibling();
3903     for (; _t != NULL;) {
3904         ProgNode::interpreter->tag_array_expr(_t, aD.get());
3905         _t = _t->getNextSibling();
3906     }
3907     res= aD->ADResolve();
3908 
3909     //ProgNode::interpreter->SetRetTree( this->getNextSibling());
3910     return res;
3911 }
3912 
3913 //   BaseGDL** ARRAYEXPR_MFCALLNode::LEval()
3914 //   {
3915 //       // better than auto_ptr: auto_ptr wouldn't remove newEnv from the stack
3916 //     StackGuard<EnvStackT> guard(ProgNode::interpreter->CallStack());
3917 //   }
3918 
EvalRefCheck(BaseGDL * & rEval)3919 BaseGDL** VARNode::EvalRefCheck( BaseGDL*& rEval)
3920 {
3921     BaseGDL** res = this->LEval();
3922     return res;
3923 }
LEval()3924 BaseGDL** VARNode::LEval()
3925 {
3926 //   	ProgNode::interpreter->SetRetTree( this->getNextSibling());
3927 //     BaseGDL* v = ProgNode::interpreter->CallStackBack()->GetKW(this->varIx);
3928 //     BaseGDL** vv = &(ProgNode::interpreter->CallStackBack()->GetKW(this->varIx));
3929 //     cout << "vv = " << vv << "  *vv = " << *vv << "  v = " << v << endl;
3930     return &(ProgNode::interpreter->CallStackBack()->GetKW(this->varIx));
3931 }
EvalRefCheck(BaseGDL * & rEval)3932 BaseGDL** VARPTRNode::EvalRefCheck( BaseGDL*& rEval)
3933 {
3934     return this->LEval();
3935 }
LEval()3936 BaseGDL** VARPTRNode::LEval()
3937 {
3938 //   	ProgNode::interpreter->SetRetTree( this->getNextSibling());
3939     return &this->var->Data();
3940 }
3941 
3942 
EvalRefCheck(BaseGDL * & rEval)3943 BaseGDL** EXPRNode::EvalRefCheck( BaseGDL*& rEval)
3944 {
3945     return this->LEval();
3946 }
LEval()3947 BaseGDL** EXPRNode::LEval()
3948 {
3949     return this->getFirstChild()->LExpr( NULL); //interpreter->l_expr( this->getFirstChild(), NULL);
3950 }
3951 
Eval()3952 BaseGDL* DOTNode::Eval()
3953 {
3954     BaseGDL* r;
3955     // clears aL when destroyed
3956     ArrayIndexListGuard guard;
3957 
3958     DotAccessDescT aD( nDot+1);
3959 
3960     ProgNodeP _t = this->getFirstChild();
3961     if( _t->getType() == GDLTokenTypes::ARRAYEXPR)
3962     {
3963         _t = _t->getFirstChild();
3964 
3965         // r = interpreter->r_dot_indexable_expr(_t, &aD);
3966         // _t = interpreter->GetRetTree();
3967         if( _t->getType() == GDLTokenTypes::EXPR)
3968         {
3969             r = _t->getFirstChild()->Eval();
3970             aD.SetOwner( true);
3971             _t = _t->getNextSibling();
3972         }
3973         else if( _t->getType() == GDLTokenTypes::SYSVAR)
3974         {
3975             r = _t->EvalNC();
3976             _t = _t->getNextSibling();
3977         }
3978         else
3979         {
3980             assert( _t->getType() == GDLTokenTypes::VAR
3981                     || _t->getType() == GDLTokenTypes::VARPTR);
3982             BaseGDL** e = _t->LEval();
3983             if( *e == NULL)
3984             {
3985                 if( _t->getType() == GDLTokenTypes::VAR)
3986                     throw GDLException( _t, "Variable is undefined: "+
3987                                         interpreter->CallStackBack()->GetString(_t->GetVarIx()),true,false);
3988                 else
3989                     throw GDLException( _t, "Common block variable is undefined: "+
3990                                         interpreter->CallStackBack()->GetString( /* reference! */ *e),true,false);
3991             }
3992             r = *e;
3993             _t = _t->getNextSibling();
3994         }
3995 
3996 
3997         bool handled = false;
3998         if( !r->IsAssoc() && r->Type() == GDL_OBJ && r->StrictScalar())
3999         {
4000             // check for _overloadBracketsRightSide
4001             DObj s = (*static_cast<DObjGDL*>(r))[0]; // is StrictScalar()
4002 //       if( s != 0)  // no overloads for null object
4003 //       {
4004 // 	DStructGDL* oStructGDL= GDLInterpreter::GetObjHeapNoThrow( s);
4005 // 	if( oStructGDL != NULL) // if object not valid -> default behaviour
4006 // 	  {
4007 // 	    DStructDesc* desc = oStructGDL->Desc();
4008 //
4009 // 	    DFun* bracketsRightSideOverload = static_cast<DFun*>(desc->GetOperator( OOBracketsRightSide));
4010             DSubUD* bracketsRightSideOverload = static_cast<DSubUD*>(GDLInterpreter::GetObjHeapOperator( s, OOBracketsRightSide));
4011             if( bracketsRightSideOverload != NULL)
4012             {
4013                 // _overloadBracketsRightSide
4014                 bool internalDSubUD = bracketsRightSideOverload->GetTree()->IsWrappedNode();
4015 
4016                 DObjGDL* self = static_cast<DObjGDL*>(r);
4017                 Guard<BaseGDL> selfGuard;
4018                 if( aD.IsOwner())
4019                 {
4020                     aD.SetOwner( false);
4021                     // WE are now the proud owner of 'self'
4022                     selfGuard.Init( self);
4023                     // so it might be overwritten
4024                 }
4025                 else
4026                 {
4027                     if( !internalDSubUD) // internal beahve well
4028                     {
4029                         self = self->Dup(); // res should be not changeable via SELF
4030                         selfGuard.Init( self);
4031                     }
4032                 }
4033 
4034 
4035                 IxExprListT indexList;
4036                 // uses arrIxListNoAssoc
4037                 interpreter->arrayindex_list_overload( _t, indexList);
4038                 ArrayIndexListGuard guard(_t->arrIxListNoAssoc);
4039 
4040                 // hidden SELF is counted as well
4041                 int nParSub = bracketsRightSideOverload->NPar();
4042                 assert( nParSub >= 1); // SELF
4043                 // indexList.size() > regular paramters w/o SELF
4044                 if( indexList.size() > nParSub - 1)
4045                 {
4046                     indexList.Cleanup();
4047                     throw GDLException( this, bracketsRightSideOverload->ObjectName() +
4048                                         ": Incorrect number of arguments.",
4049                                         false, false);
4050                 }
4051 
4052                 // adds already SELF parameter
4053                 EnvUDT* newEnv= new EnvUDT( this, bracketsRightSideOverload, &self);
4054                 // no guarding of newEnv here (no exceptions until push_back())
4055 
4056                 // parameters
4057                 for( SizeT p=0; p<indexList.size(); ++p)
4058                     newEnv->SetNextParUnchecked( indexList[p]); // takes ownership
4059 
4060                 StackGuard<EnvStackT> stackGuard(interpreter->CallStack());
4061                 interpreter->CallStack().push_back( newEnv);
4062 
4063                 // make the call, return the result
4064                 BaseGDL* res = interpreter->call_fun(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
4065 
4066                 if( selfGuard.Get() != NULL && self != selfGuard.Get())
4067                 {
4068                     // always put out warning first, in case of a later crash
4069                     Warning( "WARNING: " + bracketsRightSideOverload->ObjectName() +
4070                              ": Assignment to SELF detected (GDL session still ok).");
4071                     // assignment to SELF -> self was deleted and points to new variable
4072                     // which it owns
4073                     selfGuard.Release();
4074                     if( static_cast<BaseGDL*>(self) != NullGDL::GetSingleInstance())
4075                         selfGuard.Reset(self);
4076                 }
4077 
4078                 aD.SetOwner( true); // aD owns res here
4079                 interpreter->SetRootR( this, &aD, res, NULL);
4080                 handled = true;
4081             }
4082         }
4083         if( !handled)
4084         {
4085             // regular (non-object) case
4086             ArrayIndexListT* aL = interpreter->arrayindex_list(_t,!r->IsAssoc());
4087 
4088             guard.reset(aL);
4089 
4090             // check here for object and get struct
4091             //structR=dynamic_cast<DStructGDL*>(r);
4092             // this is much faster than a dynamic_cast
4093             interpreter->SetRootR( this, &aD, r, aL);
4094         }
4095         _t = this->getFirstChild()->getNextSibling();
4096     }
4097     else // ! ARRAYEXPR
4098 // 	case EXPR:
4099 // 	case SYSVAR:
4100 // 	case VAR:
4101 // 	case VARPTR:
4102     {
4103 //     r=interpreter->r_dot_indexable_expr(_t, &aD);
4104 //     _t = interpreter->GetRetTree();
4105         if( _t->getType() == GDLTokenTypes::EXPR)
4106         {
4107             r = _t->getFirstChild()->Eval();
4108             aD.SetOwner( true);
4109             _t = _t->getNextSibling();
4110         }
4111         else if( _t->getType() == GDLTokenTypes::SYSVAR)
4112         {
4113             r = _t->EvalNC();
4114             _t = _t->getNextSibling();
4115         }
4116         else
4117         {
4118             assert( _t->getType() == GDLTokenTypes::VAR || _t->getType() == GDLTokenTypes::VARPTR);
4119             BaseGDL** e = _t->LEval();
4120             if( *e == NULL)
4121             {
4122                 if( _t->getType() == GDLTokenTypes::VAR)
4123                     throw GDLException( _t, "Variable is undefined: "+
4124                                         interpreter->CallStackBack()->GetString(_t->GetVarIx()),true,false);
4125                 else
4126                     throw GDLException( _t, "Common block variable is undefined: "+
4127                                         interpreter->CallStackBack()->GetString( /* reference */ *e),true,false);
4128             }
4129             r = *e;
4130             _t = _t->getNextSibling();
4131         }
4132 
4133         interpreter->SetRootR( this, &aD, r, NULL);
4134     }
4135 
4136     for (; _t != NULL;) {
4137         interpreter->tag_array_expr(_t, &aD); // nDot times
4138         _t = interpreter->GetRetTree();
4139     }
4140     return aD.ADResolve();
4141 } // DOTNode::Eval
4142 
Eval()4143 BaseGDL* ARRAYEXPRNode::Eval()
4144 {
4145     BaseGDL* res;
4146 
4147     ExprListT        exprList; // for cleanup
4148     IxExprListT      ixExprList;
4149     SizeT nExpr;
4150     BaseGDL* s;
4151 
4152     //	match(antlr::RefAST(_t),ARRAYEXPR);
4153     ProgNodeP	_t = this->getFirstChild();
4154 
4155     BaseGDL* r;
4156     Guard<BaseGDL> rGuard;
4157     try {
4158         if( NonCopyNode(_t->getType()))
4159         {
4160             r=_t->EvalNC();
4161         }
4162         else
4163         {
4164             BaseGDL** ref =_t->EvalRefCheck(r);
4165             if( ref == NULL)
4166                 rGuard.Init( r);
4167             else
4168                 r = *ref;
4169         }
4170     }
4171     catch( GDLException& ex)
4172     {
4173         ex.SetArrayexprIndexeeFailed( true);
4174         throw ex;
4175     }
4176 
4177     ProgNodeP ixListNode = _t->getNextSibling();
4178 
4179     if( r->Type() == GDL_OBJ && r->StrictScalar())
4180     {
4181         // check for _overloadBracketsRightSide
4182 
4183         DObj s = (*static_cast<DObjGDL*>(r))[0]; // is StrictScalar()
4184 //       if( s != 0)  // no overloads for null object
4185 //       {
4186 // 	DStructGDL* oStructGDL= GDLInterpreter::GetObjHeapNoThrow( s);
4187 // 	if( oStructGDL != NULL) // if object not valid -> default behaviour
4188 // 	  {
4189 // 	    DStructDesc* desc = oStructGDL->Desc();
4190 //
4191 // 	    DFun* bracketsRightSideOverload = static_cast<DFun*>(desc->GetOperator( OOBracketsRightSide));
4192         DSubUD* bracketsRightSideOverload =
4193 	  static_cast<DSubUD*>(GDLInterpreter::GetObjHeapOperator( s, OOBracketsRightSide));
4194         if( bracketsRightSideOverload != NULL)
4195         {
4196             // _overloadBracketsRightSide
4197             DObjGDL* self = static_cast<DObjGDL*>(rGuard.Get());
4198             if( self == NULL)
4199             {
4200                 self = static_cast<DObjGDL*>(r->Dup()); // not set -> not owner
4201                 rGuard.Reset( self);
4202             }
4203             // we are now the proud owner of 'self'
4204 
4205             IxExprListT indexList;
4206             // uses arrIxListNoAssoc
4207             interpreter->arrayindex_list_overload( ixListNode, indexList);
4208             ArrayIndexListGuard guard(ixListNode->arrIxListNoAssoc);
4209 
4210             // hidden SELF is counted as well
4211             int nParSub = bracketsRightSideOverload->NPar();
4212             assert( nParSub >= 1); // SELF
4213             // indexList.size() > regular paramters w/o SELF
4214             if( indexList.size() > nParSub - 1)
4215             {
4216                 indexList.Cleanup();
4217                 throw GDLException( this, bracketsRightSideOverload->ObjectName() +
4218                                     ": Incorrect number of arguments.",
4219                                     false, false);
4220             }
4221 
4222             // adds already SELF parameter
4223             EnvUDT* newEnv= new EnvUDT( this, bracketsRightSideOverload, &self);
4224             // no guarding of newEnv here (no exceptions until push_back())
4225 
4226             // parameters
4227             for( SizeT p=0; p<indexList.size(); ++p)
4228                 newEnv->SetNextParUnchecked( indexList[p]); // takes ownership
4229 
4230             StackGuard<EnvStackT> stackGuard(interpreter->CallStack());
4231             interpreter->CallStack().push_back( newEnv);
4232 
4233             // make the call, return the result
4234             BaseGDL* res = interpreter->call_fun(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
4235 
4236             if( self != rGuard.Get())
4237             {
4238                 // always put out warning first, in case of a later crash
4239                 Warning( "WARNING: " + bracketsRightSideOverload->ObjectName() +
4240                          ": Assignment to SELF detected (GDL session still ok).");
4241                 // assignment to SELF -> self was deleted and points to new variable
4242                 // which it owns
4243                 rGuard.Release();
4244                 if( static_cast<BaseGDL*>(self) != NullGDL::GetSingleInstance())
4245                     rGuard.Reset(self);
4246             }
4247 
4248             return res;
4249         }
4250     }
4251 
4252     // first use NoAssoc case (just to get nExpr)
4253     ArrayIndexListT* aL = ixListNode->arrIxListNoAssoc;
4254     assert( aL != NULL);
4255     nExpr = aL->NParam();
4256 
4257     _t = ixListNode->getFirstChild();
4258 
4259     if( nExpr == 0)
4260     {
4261         goto empty;
4262     }
4263 
4264     while( true)
4265     {
4266         if( NonCopyNode(_t->getType()))
4267         {
4268             s=_t->EvalNC();//indexable_expr(_t);
4269             assert(s != NULL);
4270             assert( s->Type() != GDL_UNDEF);
4271         }
4272         else
4273         {
4274             BaseGDL** ref =_t->EvalRefCheck(s); //ProgNode::interpreter->indexable_tmp_expr(_t);
4275             if( ref == NULL)
4276                 exprList.push_back( s);
4277             else
4278                 s = *ref;
4279             assert(s != NULL);
4280             assert( s->Type() != GDL_UNDEF);
4281         }
4282 
4283 
4284         ixExprList.push_back( s); // already owned (s. a.)
4285         if( ixExprList.size() == nExpr)
4286             break; // while( true) -> finish
4287 
4288         _t = _t->getNextSibling(); // set to next index
4289     } // while( true)
4290 
4291 empty:
4292 
4293     if( r->IsAssoc())
4294     {
4295         ArrayIndexListT* aLAssoc = ixListNode->arrIxList;
4296         assert( aLAssoc != NULL);
4297         ArrayIndexListGuard guardAssoc(aLAssoc);
4298         return aLAssoc->Index( r, ixExprList);
4299     }
4300     else
4301     {
4302         ArrayIndexListGuard guard(aL);
4303         return aL->Index( r, ixExprList);
4304     }
4305     assert( false);
4306     return NULL;
4307 }
4308