1 /***************************************************************************
2 			prognode_lexpr.cpp  -  LExpr functions
3 			-------------------
4 begin                : July 22 2002
5 copyright            : (C) 2011 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 // from GDLInterpreter::l_expr
21 #include <cassert>
22 #include <string>
23 
24 #include "dinterpreter.hpp"
25 #include "prognodeexpr.hpp"
26 #include "basegdl.hpp"
27 #include "arrayindexlistt.hpp"
28 //#include "envt.hpp"
29 #include "gdlexception.hpp"
30 #include "nullgdl.hpp"
31 
32 // illegal
LExpr(BaseGDL * right)33 BaseGDL** ProgNode::LExpr( BaseGDL* right)
34 //	default:
35 {
36 	//   case ARRAYDEF:
37 	//   case EXPR:
38 	//   case NSTRUC:
39 	//   case NSTRUC_REF:
40 	//   case POSTDEC:
41 	//   case POSTINC:
42 	//   case STRUC:
43 	//   case DEC:
44 	//   case INC:
45 	//   case CONSTANT:
46 	throw GDLException( this, "Expression not allowed as l-value.",
47 				  true,false);
48 	return NULL; // avoid compiler warning
49 }
50 
51 
LExpr(BaseGDL * right)52 BaseGDL** QUESTIONNode::LExpr( BaseGDL* right)
53 		//case QUESTION:
54 {
55     ProgNodeP branch = this->GetThisBranch();
56     return branch->LExpr( right);
57 }
58 
LExpr(BaseGDL * right)59 BaseGDL** ARRAYEXPRNode::LExpr( BaseGDL* right) // 'right' is not owned
60 	//case ARRAYEXPR:
61   {
62   //res=l_array_expr(_t, right);
63   if( right == NULL)
64     throw GDLException( this, "Indexed expression not allowed in this context.", true,false);
65 
66   ArrayIndexListT* aL;
67   ArrayIndexListGuard guard;
68   BaseGDL** res;
69 //   try{
70 // 	res=interpreter->l_indexable_expr( this->getFirstChild());
71   res = this->getFirstChild()->LEval(); // throws
72   if( *res == NULL)
73   { // ERROR
74       // check not needed for SYSVAR
75       ProgNodeP _t = this->getFirstChild();
76       assert( _t->getType() != GDLTokenTypes::SYSVAR);
77       if( _t->getType() == GDLTokenTypes::VARPTR)
78       {
79 	  GDLException ex( _t, "Common block variable is undefined: "+
80 			      interpreter->CallStackBack()->GetString( *res),true,false);
81 	  ex.SetArrayexprIndexeeFailed( true);
82 	  throw ex;
83       }
84       if( _t->getType() == GDLTokenTypes::VAR)
85       {
86 	  GDLException ex( _t, "Variable is undefined: "+
87 			interpreter->CallStackBack()->GetString(_t->varIx),true,false);
88 	  ex.SetArrayexprIndexeeFailed( true);
89 	  throw ex;
90       }
91       GDLException ex( _t, "Heap variable is undefined: "+interpreter->Name(res),true,false);
92       ex.SetArrayexprIndexeeFailed( true);
93       throw ex;
94   }
95 
96   if( (*res)->IsAssoc())
97   {
98     aL=interpreter->arrayindex_list( this->getFirstChild()->getNextSibling(), false);
99   }
100   else
101   {
102     if( (*res)->Type() == GDL_OBJ && (*res)->StrictScalar())
103     {
104 	// check for _overloadBracketsLeftSide
105 	DObj s = (*static_cast<DObjGDL*>(*res))[0]; // is StrictScalar()
106 // 	      if( s != 0)  // no overloads for null object
107 // 	      {
108 // 		DStructGDL* oStructGDL= GDLInterpreter::GetObjHeapNoThrow( s);
109 // 		if( oStructGDL != NULL) // if object not valid -> default behaviour
110 // 		  {
111 // 		    DStructDesc* desc = oStructGDL->Desc();
112 // 		    DPro* bracketsLeftSideOverload = static_cast<DPro*>(desc->GetOperator( OOBracketsLeftSide));
113 	DSubUD* bracketsLeftSideOverload = static_cast<DSubUD*>(GDLInterpreter::GetObjHeapOperator( s, OOBracketsLeftSide));
114 	if( bracketsLeftSideOverload != NULL)
115 	{
116 	  bool internalDSubUD = bracketsLeftSideOverload->GetTree()->IsWrappedNode();
117 
118 	    // _overloadBracketsLeftSide
119 	  IxExprListT indexList;
120 	  interpreter->arrayindex_list_overload( this->getFirstChild()->getNextSibling(), indexList);
121 	  ArrayIndexListGuard guard(this->getFirstChild()->getNextSibling()->arrIxListNoAssoc);
122 
123 	  // hidden SELF is counted as well
124 	  int nParSub = bracketsLeftSideOverload->NPar();
125 	  assert( nParSub >= 1); // SELF
126 //  		      int indexListSizeDebug = indexList.size();
127 	  // indexList.size() + OBJREF + RVALUE > regular paramters w/o SELF
128 	  if( (indexList.size() + 2) > nParSub - 1)
129 	  {
130 	    indexList.Cleanup();
131 	    throw GDLException( this, bracketsLeftSideOverload->ObjectName() +
132 			    ": Incorrect number of arguments.",
133 			    false, false);
134 	  }
135 
136 	  DObjGDL* self;
137 	  Guard<BaseGDL> selfGuard;
138 	  if( internalDSubUD)
139 	  {
140 	    self = static_cast<DObjGDL*>(*res); // internal subroutines behave well
141 	  }
142 	  else
143 	  {
144 	    self = static_cast<DObjGDL*>(*res)->Dup(); // res should be not changeable via SELF
145 	    selfGuard.Reset( self);
146 	  }
147 
148 	  // adds already SELF parameter
149 	  EnvUDT* newEnv= new EnvUDT( this, bracketsLeftSideOverload, &self);
150 // 		      Guard<EnvUDT> newEnvGuard( newEnv);
151 
152 	  // parameters
153 	  newEnv->SetNextParUnchecked( res); // OBJREF  parameter
154 	  // Dup() here is not optimal
155 	  // avoid at least for internal overload routines (which do/must not change RVALUE)
156 	  if( internalDSubUD)
157 	    newEnv->SetNextParUnchecked( &right); // RVALUE  parameter, as reference to prevent cleanup in newEnv
158 	  else
159 	    newEnv->SetNextParUnchecked( right->Dup()); // RVALUE parameter, as value
160 	  // pass as reference would be more efficient, but as the data might
161 	  // be deleted in bracketsLeftSideOverload it is not possible.
162 	  // BaseGDL* rightCopy = right;
163 	  // newEnv->SetNextParUnchecked( &rightCopy); // RVALUE  parameter
164 	  for( SizeT p=0; p<indexList.size(); ++p)
165 	    newEnv->SetNextParUnchecked( indexList[p]); // takes ownership
166 
167 	  StackGuard<EnvStackT> stackGuard(interpreter->CallStack());
168 	  interpreter->CallStack().push_back( newEnv);
169 
170 	  // make the call
171 	  interpreter->call_pro(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
172 
173 	  if( !internalDSubUD && self != selfGuard.Get())
174 	  {
175 	    // always put out warning first, in case of a later crash
176 	    Warning( "WARNING: " + bracketsLeftSideOverload->ObjectName() +
177 		  ": Assignment to SELF detected (GDL session still ok).");
178 	    // assignment to SELF -> self was deleted and points to new variable
179 	    // which it owns
180 	    selfGuard.Release();
181 	    if( static_cast<BaseGDL*>(self) != NullGDL::GetSingleInstance())
182 	      selfGuard.Reset(self);
183 	  }
184 
185 	  return res;
186 	}
187     }
188 
189 // aL=interpreter->arrayindex_list_noassoc( this->getFirstChild()->getNextSibling());
190 
191 //       IxExprListT      cleanupList; // for cleanup
192     ProgNodeP ax = this->getFirstChild()->getNextSibling();
193     aL=interpreter->arrayindex_list( ax, true);
194 
195   }
196   guard.reset(aL);
197 
198   try {
199     aL->AssignAt( *res, right);
200   }
201   catch( GDLException& ex)
202   {
203     ex.SetErrorNodeP( this);
204     throw ex;
205   }
206   //_retTree = _t->getNextSibling();
207   return res;
208 }
209 // default ...Grab version
210 
LExpr(BaseGDL * right)211 BaseGDL** SYSVARNode::LExpr( BaseGDL* right)
212 		//case SYSVAR:
213 	{
214 	if( right == NULL)
215 	throw GDLException( this, "System variable not allowed in this context.",
216 		true,false);
217 
218 	BaseGDL** res=this->LEval(); //l_sys_var(this);
219 	Guard<BaseGDL> conv_guard; //( rConv);
220 	BaseGDL* rConv = right;
221 	if( !(*res)->EqType( right))
222 	{
223 		rConv = right->Convert2( (*res)->Type(), BaseGDL::COPY);
224 		conv_guard.Reset( rConv);
225 	}
226 	if( right->N_Elements() != 1 && ((*res)->N_Elements() != right->N_Elements()))
227 	{
228 		throw GDLException( this, "Conflicting data structures: <"+
229 			right->TypeStr()+" "+right->Dim().ToString()+">, !"+
230 			this->getText(),true,false);
231 	}
232 	(*res)->AssignAt( rConv); // linear copy
233   this->var->DoCallback();
234 	return res;
235 	}
236 // default ...Grab version
237 
238 // BaseGDL** XXXNode::LExpr( BaseGDL* right)
239 // // 	case FCALL:
240 // // 	case FCALL_LIB:
241 // // 	case MFCALL:
242 // // 	case MFCALL_PARENT:
243 // // 	case DEREF:
244 // // 	case VAR:
245 // // 	case VARPTR:
246 // 	{
247 // 	BaseGDL** res=this->LEval(); //l_simple_var(_t);
248 // 	//_retTree = _t->getNextSibling();
249 // 	if( right != NULL && right != (*res))
250 // 	{
251 // 		delete *res;
252 // 		*res = right->Dup();
253 // 	}
254 // 	return res;
255 // 	}
256 
257 // #define LEXPRGRAB \
258 // 	{	BaseGDL** res=this->LEval(); \
259 // 	if( right != NULL && right != (*res)) \
260 // 	{	delete *res; *res = right;} \
261 // 	return res;}
262 //
263 // BaseGDL** FCALLNode::LExprGrab( BaseGDL* right)
264 // LEXPRGRAB
265 // BaseGDL** MFCALLNode::LExprGrab( BaseGDL* right)
266 // LEXPRGRAB
267 // BaseGDL** MFCALL_PARENTNode::LExprGrab( BaseGDL* right)
268 // LEXPRGRAB
269 // BaseGDL** FCALL_LIBNode::LExprGrab( BaseGDL* right)
270 // LEXPRGRAB
271 // BaseGDL** DEREFNode::LExprGrab( BaseGDL* right)
272 // LEXPRGRAB
273 // BaseGDL** VARNode::LExprGrab( BaseGDL* right)
274 // LEXPRGRAB
275 // BaseGDL** VARPTRNode::LExprGrab( BaseGDL* right)
276 // LEXPRGRAB
277 // #undef LEXPRGRAB
278 
279 #define LEXPR \
280 	{	BaseGDL** res=this->LEval(); \
281 	if( right != NULL && right != (*res)) \
282 	{	GDLDelete(*res); *res = right->Dup();} \
283 	return res;}
284 
LExpr(BaseGDL * right)285 BaseGDL** FCALLNode::LExpr( BaseGDL* right)
286 LEXPR
287 BaseGDL** MFCALLNode::LExpr( BaseGDL* right)
288 LEXPR
289 BaseGDL** MFCALL_PARENTNode::LExpr( BaseGDL* right)
290 LEXPR
291 BaseGDL** FCALL_LIBNode::LExpr( BaseGDL* right)
292 LEXPR
293 BaseGDL** DEREFNode::LExpr( BaseGDL* right)
294 LEXPR
295 BaseGDL** VARNode::LExpr( BaseGDL* right)
296 LEXPR
297 BaseGDL** VARPTRNode::LExpr( BaseGDL* right)
298 LEXPR
299 #undef LEXPR
300 
301 BaseGDL** ARRAYEXPR_FCALLNode::LExpr( BaseGDL* right)
302 {
303   if( fcallNodeFunIx >= 0)
304       return fcallNode->FCALLNode::LExpr( right);
305   else if( fcallNodeFunIx == -2)
306   {
307     return arrayExprNode->ARRAYEXPRNode::LExpr( right);
308   }
309 
310   assert( fcallNodeFunIx == -1);
311   try{
312     BaseGDL** res = arrayExprNode->ARRAYEXPRNode::LExpr( right);
313     fcallNodeFunIx = -2; // mark as ARRAYEXPR succeeded
314     return res;
315   }
316   catch( GDLException& ex)
317   {
318     if( !ex.GetArrayexprIndexeeFailed())
319     {
320       fcallNodeFunIx = -2; // mark as ARRAYEXPR succeeded
321       throw ex;
322     }
323     try{
324 	BaseGDL** res = fcallNode->FCALLNode::LExpr( right);
325 	fcallNodeFunIx = fcallNode->funIx;
326 	return res;
327     }    // keep FCALL if already compiled (but runtime error)
328     catch( GDLException& innerEx)
329     {
330       if(fcallNode->funIx >= 0)
331       {
332 	fcallNodeFunIx = fcallNode->funIx;
333 	throw innerEx;
334       }
335 	std::string msg = "Ambiguous: " + ex.ANTLRException::toString() +
336 	" or: " + innerEx.ANTLRException::toString();
337 	throw GDLException(this,msg,true,false);
338     }
339   }
340 }
341 
342 
LExpr(BaseGDL * right)343 BaseGDL** ARRAYEXPR_MFCALLNode::LExpr( BaseGDL* right)
344 {
345   return interpreter->l_arrayexpr_mfcall(this, right);
346 }
347 // default ...Grab version
348 
LExpr(BaseGDL * right)349 BaseGDL** DOTNode::LExpr( BaseGDL* right)
350 {
351   if( right == NULL)
352       throw GDLException( this, "Struct expression not allowed in this context.",
353 			  true,false);
354 
355   ProgNodeP _t = this->getFirstChild();
356 
357   //SizeT nDot = tIn->nDot;
358   Guard<DotAccessDescT> aD( new DotAccessDescT(nDot+1));
359 
360   //interpreter->l_dot_array_expr(_t, aD.get());
361 
362   ArrayIndexListT* aL;
363   BaseGDL**        rP;
364   if( _t->getType() == GDLTokenTypes::ARRAYEXPR)
365   {
366 // 	  rP=l_indexable_expr(_t->getFirstChild());
367       rP = _t->getFirstChild()->LEval(); // throws
368       if( *rP == NULL)
369       {   // ERROR
370 	  BaseGDL** res = rP;
371 	  _t = _t->getFirstChild();
372 	  // check not needed for SYSVAR
373 	  assert( _t->getType() != GDLTokenTypes::SYSVAR);
374 	  if( _t->getType() == GDLTokenTypes::VARPTR)
375 	  {
376 	      GDLException ex( _t, "Common block variable is undefined: "+
377 				interpreter->CallStackBack()->GetString( *res),true,false);
378 	      ex.SetArrayexprIndexeeFailed( true);
379 	      throw ex;
380 	  }
381 	  if( _t->getType() == GDLTokenTypes::VAR)
382 	  {
383 	      GDLException ex( _t, "Variable is undefined: "+
384 				interpreter->CallStackBack()->GetString(_t->GetVarIx()),true,false);
385 	      ex.SetArrayexprIndexeeFailed( true);
386 	      throw ex;
387 	  }
388 	  GDLException ex( _t, "Variable is undefined: "+interpreter->Name(res),true,false);
389 	  ex.SetArrayexprIndexeeFailed( true);
390 	  throw ex;
391       }
392 
393       // aL=arrayindex_list(_t->getFirstChild()->getNextSibling());
394       bool handled = false;
395       if( !(*rP)->IsAssoc() && (*rP)->Type() == GDL_OBJ && (*rP)->StrictScalar())
396       {
397 
398 	  // check for _overloadBracketsLeftSide
399 	  DObj s = (*static_cast<DObjGDL*>(*rP))[0]; // is StrictScalar()
400 	  DSubUD* bracketsLeftSideOverload = static_cast<DSubUD*>(GDLInterpreter::GetObjHeapOperator( s, OOBracketsLeftSide));
401 	  if( bracketsLeftSideOverload != NULL)
402 	  {
403 	      bool internalDSubUD = bracketsLeftSideOverload->GetTree()->IsWrappedNode();
404 
405 	      // _overloadBracketsLeftSide
406 	      IxExprListT indexList;
407 	      interpreter->arrayindex_list_overload( _t->getFirstChild()->getNextSibling(), indexList);
408 	      ArrayIndexListGuard guard(_t->getFirstChild()->getNextSibling()->arrIxListNoAssoc);
409 
410 	      // hidden SELF is counted as well
411 	      int nParSub = bracketsLeftSideOverload->NPar();
412 	      assert( nParSub >= 1); // SELF
413 
414 	      // indexList.size() + OBJREF + RVALUE > regular paramters w/o SELF
415 	      if( (indexList.size() + 2) > nParSub - 1)
416 	      {
417 		  indexList.Cleanup();
418 		  throw GDLException( this, bracketsLeftSideOverload->ObjectName() +
419 				      ": Incorrect number of arguments.",
420 				      false, false);
421 	      }
422 
423 	      DObjGDL* self;
424 	      Guard<BaseGDL> selfGuard;
425 	      if( internalDSubUD)
426 	      {
427 		  self = static_cast<DObjGDL*>(*rP); // internal subroutines behave well
428 	      }
429 	      else
430 	      {
431 		  self = static_cast<DObjGDL*>(*rP)->Dup(); // res should be not changeable via SELF
432 		  selfGuard.Reset( self);
433 	      }
434 
435 	      // adds already SELF parameter
436 	      EnvUDT* newEnv= new EnvUDT( this, bracketsLeftSideOverload, &self);
437 	      // Guard<EnvUDT> newEnvGuard( newEnv);
438 
439 	      // parameters
440 	      // special: we are in dot access here
441 	      // signal to _overloadBracketsLeftSide by setting OBJREF to NULL
442 	      BaseGDL* returnOBJREF = NULL;
443 	      newEnv->SetNextParUnchecked( &returnOBJREF); // OBJREF  parameter
444 	      // Dup() here is not optimal
445 	      // avoid at least for internal overload routines (which do/must not change RVALUE)
446 
447 	      BaseGDL* rValueNull = NULL;
448 	      newEnv->SetNextParUnchecked( rValueNull); // RVALUE parameter NULL, as value
449 
450 	      for( SizeT p=0; p<indexList.size(); ++p)
451 		  newEnv->SetNextParUnchecked( indexList[p]); // takes ownership
452 
453 	      StackGuard<EnvStackT> stackGuard(interpreter->CallStack());
454 	      interpreter->CallStack().push_back( newEnv);
455 
456 	      // make the call
457 	      interpreter->call_pro(static_cast<DSubUD*>(newEnv->GetPro())->GetTree());
458 
459 	      if( !internalDSubUD && self != selfGuard.Get())
460 	      {
461 		  // always put out warning first, in case of a later crash
462 		  Warning( "WARNING: " + bracketsLeftSideOverload->ObjectName() +
463 			    ": Assignment to SELF detected (GDL session still ok).");
464 		  // assignment to SELF -> self was deleted and points to new variable
465 		  // which it owns
466 		  selfGuard.Release();
467 		  if( static_cast<BaseGDL*>(self) != NullGDL::GetSingleInstance())
468 		      selfGuard.Reset(self);
469 	      }
470 
471 	      if( returnOBJREF == NULL || returnOBJREF->Type() != GDL_PTR)
472 		  GDLException ex( _t, "OBJREF must return a PTR to the STRUCT to access.",true,false);
473 
474 	      DPtr vID = (*static_cast<DPtrGDL*>(returnOBJREF))[0];
475 	      delete returnOBJREF;
476 
477 	      BaseGDL* structToAccess = interpreter->GetHeap( vID);
478 
479 	      interpreter->SetRootL( _t, aD.get(), structToAccess, NULL);
480 	      handled = true;
481 	  }
482       } //  	  if( (*rP)->Type() == GDL_OBJ && (*rP)->StrictScalar())
483       if( !handled)
484       {
485 	  // regular (non-object) case
486 	  aL=interpreter->arrayindex_list( _t->getFirstChild()->getNextSibling(),!(*rP)->IsAssoc());
487 	  interpreter->SetRootL( _t, aD.get(), *rP, aL);
488       }
489   }
490   else
491       // case ARRAYEXPR_MFCALL:
492       // case DEREF:
493       // case EXPR:
494       // case FCALL:
495       // case FCALL_LIB:
496       // case MFCALL:
497       // case MFCALL_PARENT:
498       // case SYSVAR:
499       // case VAR:
500       // case VARPTR:
501   {
502       // rP=l_indexable_expr(_t);
503       rP = _t->LEval(); // throws
504       if( *rP == NULL)
505       {   // ERROR
506 	  BaseGDL** res = rP;
507 	  // check not needed for SYSVAR
508 	  assert( _t->getType() != GDLTokenTypes::SYSVAR);
509 	  if( _t->getType() == GDLTokenTypes::VARPTR)
510 	  {
511 	      GDLException ex( _t, "Common block variable is undefined: "+
512 				interpreter->CallStackBack()->GetString( *res),true,false);
513 	      ex.SetArrayexprIndexeeFailed( true);
514 	      throw ex;
515 	  }
516 	  if( _t->getType() == GDLTokenTypes::VAR)
517 	  {
518 	      GDLException ex( _t, "Variable is undefined: "+
519 				interpreter->CallStackBack()->GetString(_t->GetVarIx()),true,false);
520 	      ex.SetArrayexprIndexeeFailed( true);
521 	      throw ex;
522 	  }
523 	  GDLException ex( _t, "Variable is undefined: "+interpreter->Name(res),true,false);
524 	  ex.SetArrayexprIndexeeFailed( true);
525 	  throw ex;
526       }
527       interpreter->SetRootL( _t, aD.get(), *rP, NULL);
528   }
529   ProgNodeP left=_t;
530   _t = _t->getNextSibling();
531   for( int d=0; d<nDot; ++d)
532   {
533       // if ((_t->getType() == ARRAYEXPR || _t->getType() == EXPR ||
534       // _t->getType() == IDENTIFIER)) {
535       interpreter->tag_array_expr(_t, aD.get());
536       _t = interpreter->GetRetTree();
537       //       }
538       //       else {
539       // 	break;
540       //       }
541   }
542   aD->ADAssign( right);
543       // case SYSVAR: sysvar is now updated, run callback.
544    if( left->getType() == GDLTokenTypes::SYSVAR) left->var->DoCallback();
545   //res=NULL;
546   //SetRetTree( tIn->getNextSibling());
547   return NULL;
548 }
549 // default ...Grab version
550 
LExpr(BaseGDL * right)551 BaseGDL** ASSIGNNode::LExpr( BaseGDL* right)
552 {
553   ProgNodeP _t = this->getFirstChild();
554   if( NonCopyNode(_t->getType()))
555   {
556     BaseGDL* e1 = _t->EvalNC();
557     _t = _t->getNextSibling();
558   }
559   else
560   {
561     BaseGDL* e1;
562     BaseGDL** ref =_t->EvalRefCheck(e1);
563     if( ref == NULL)
564       GDLDelete(e1);
565     _t = _t->getNextSibling();
566   }
567   return _t->LExpr( right); //l_expr(_t, right);
568 }
569 
570 // something like: (( ((aFUNorVAR(aVAR))) =e1 ))=right
LExpr(BaseGDL * right)571 BaseGDL** ASSIGN_ARRAYEXPR_MFCALLNode::LExpr( BaseGDL* right)
572 {
573   ProgNodeP _t = this->getFirstChild();
574 
575   if( NonCopyNode(_t->getType()))
576   {
577     BaseGDL* e1 = _t->EvalNC();
578     _t = _t->getNextSibling();
579   }
580   else
581   {
582     // e1 must be calculated due to possible side effects, but the result isn't used or even accessible
583     BaseGDL* e1;
584     BaseGDL** ref =_t->EvalRefCheck(e1);
585     if( ref == NULL)
586       GDLDelete(e1);
587     _t = _t->getNextSibling();
588   }
589   ProgNodeP l = _t;
590   BaseGDL** res;
591   // try MFCALL
592   try
593   {
594     res=interpreter->l_arrayexpr_mfcall_as_mfcall( l);
595     if( right != (*res))
596     {
597       GDLDelete(*res);
598       *res = right->Dup();
599     }
600   }
601   catch( GDLException& ex)
602   {
603     // try ARRAYEXPR
604     try
605     {
606       res=interpreter->l_arrayexpr_mfcall_as_arrayexpr(l, right);
607     }
608     catch( GDLException& ex2)
609     {
610       throw GDLException(ex.toString() + " or "+ex2.toString());
611     }
612   }
613   //SetRetTree( tIn->getNextSibling());
614   return res;
615 }
616 
617 
LExpr(BaseGDL * right)618 BaseGDL** ASSIGN_REPLACENode::LExpr( BaseGDL* right)
619 //	case ASSIGN_REPLACE:
620 {
621   ProgNodeP _t = this->getFirstChild();
622 
623   BaseGDL** res;
624   {
625     BaseGDL* e1;
626     BaseGDL** ref =_t->EvalRefCheck(e1);
627     if( ref != NULL)
628 	e1 = *ref;
629 
630     _t =_t->getNextSibling();
631 
632     res =_t->LEval(); //l_function_call(_t);
633     if( *res != e1 && ref == NULL)
634       GDLDelete(e1);
635   }
636 
637   if( right != (*res))
638   {
639     GDLDelete(*res);
640     assert( right != NULL);
641     *res = right->Dup();
642   }
643   return res;
644 }
645 
646 
647 
648 // l_expr finish /////////////////////////////////////////////
649 
650 
651