1 /***************************************************************************
2                           prognode.hpp  -  the node used for the running program
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 #ifndef prognode_hpp__
19 #define prognode_hpp__
20 
21 #include "dnode.hpp"
22 
23 //#include "GDLInterpreter.hpp"
24 
25 enum RetCode {
26   RC_OK=0,
27   RC_BREAK,
28   RC_CONTINUE,
29   RC_RETURN,
30   RC_ABORT, // checked as retCode >= RC_RETURN
31 };
32 
33 class EnvT;
34 typedef void     (*LibPro)(EnvT*);
35 typedef BaseGDL* (*LibFun)(EnvT*);
36 typedef BaseGDL* (*LibFunDirect)(BaseGDL* param,bool canGrab);
37 
38 class ProgNode;
39 typedef ProgNode* ProgNodeP;
40 
41 // inline bool* GetNonCopyNodeLookupArray()
42 // {
43 // static bool nonCopyNodeLookupArray[ GDLTokenTypes::MAX_TOKEN_NUMBER];
44 // for( int i=0; i<GDLTokenTypes::MAX_TOKEN_NUMBER; ++i)
45 // 	nonCopyNodeLookupArray[ i] = false;
46 // nonCopyNodeLookupArray[ GDLTokenTypes::VAR] = true;
47 // nonCopyNodeLookupArray[ GDLTokenTypes::VARPTR] = true;
48 // nonCopyNodeLookupArray[ GDLTokenTypes::DEREF] = true;
49 // nonCopyNodeLookupArray[ GDLTokenTypes::CONSTANT] = true;
50 // nonCopyNodeLookupArray[ GDLTokenTypes::SYSVAR] = true;
51 // return nonCopyNodeLookupArray;
52 // }
53 bool* GetNonCopyNodeLookupArray();
54 
NonCopyNode(int type)55 inline bool NonCopyNode( int type)
56 {
57   static bool* nonCopyNodeLookupArray = GetNonCopyNodeLookupArray();
58   return nonCopyNodeLookupArray[ type];
59   //   return
60   //     (type == GDLTokenTypes::VAR) ||
61   //     (type == GDLTokenTypes::VARPTR) ||
62   //     (type == GDLTokenTypes::DEREF) ||
63   //     (type == GDLTokenTypes::CONSTANT) ||
64   //     (type == GDLTokenTypes::SYSVAR) ;
65 
66   // are always copy nodes:
67   //     (type == GDLTokenTypes::ARRAYDEF)
68   //     (type == GDLTokenTypes::STRUC)
69   //     (type == GDLTokenTypes::NSTRUC)
70   //     (type == GDLTokenTypes::NSTRUC_REF)
71 }
72 
73 class BreakableNode;
74 
75 // the nodes the programs are made of
76 class ProgNode
77 {
78 protected:
79   static DInterpreter* interpreter;
80 
81 private:
82   int ttype;
83   std::string text;
84 
85 protected:
86   bool keepRight;
87   bool keepDown;
88 
89   ProgNodeP breakTarget;
90 
91   ProgNodeP down;
92   ProgNodeP right;
93 
94   static void AdjustTypes(Guard<BaseGDL>& a,
95 			  Guard<BaseGDL>& b);
96   // for overloaded operators
97   static void AdjustTypesObj(Guard<BaseGDL>& a,
98 			  Guard<BaseGDL>& b);
99 
100   BaseGDL*   cData;           // constant data
101   DVar*      var;             // ptr to variable
102 
103   DLibFun*     libFun;
104   DLibPro*     libPro;
105   LibFun       libFunFun;
106   LibPro       libProPro;
107 
108   union {
109     int        initInt;    // for c-i not actually used
110     int        numBranch;  // number of branches in switch/case statements
111     int        nDot;       // nesting level for tag access
112     int        nParam;     // number of parameters in this parameter list (stored in 1st par)
113     int        arrayDepth; // dimension to cat
114     int        proIx;      // Index into proList
115     int        funIx;      // Index into funList
116     int        varIx;      // Index into variable list
117     int        targetIx;   // Index into label list
118     int        structDefined; // struct contains entry with no tag name
119     int        compileOpt; // for PRO and FUNCTION nodes
120     int        forLoopIx; // acessing loop variables
121   };
122 
SetType(int tt,const std::string & txt)123   void SetType( int tt, const std::string& txt) { ttype = tt; text = txt;}
124 
125   static ProgNodeP GetNULLProgNodeP();
126 
127 public:
GetVarIx() const128   int GetVarIx() const { return varIx;}
129 
130 private:
131   // from DNode (see there)
132   int lineNumber;
133   ArrayIndexListT* arrIxList; // ptr to array index list
134   ArrayIndexListT* arrIxListNoAssoc; // ptr to array index list
135   int labelStart; // for loops to determine if to bail out
136   int labelEnd; // for loops to determine if to bail out
137 
138   // disable usage
ProgNode(const ProgNode & p)139   ProgNode( const ProgNode& p) {}
140 
141 public:
142   ProgNode();
143 
144   explicit ProgNode( const RefDNode& refNode);
145 
146   // tree translation takes place here
147   // see newprognode.cpp
148   static ProgNodeP NewProgNode( const RefDNode& refNode);
NumberForLoops(ProgNodeP tree,int offset=0)149   static int NumberForLoops( ProgNodeP tree, int offset = 0)
150   {
151     if( tree == NULL)
152       return offset;
153 
154     return tree->NumberForLoops( offset);
155   }
156 
NumberForLoops(int actNum)157   virtual int NumberForLoops( int actNum)
158   {
159     if( down != NULL && !keepDown)
160       {
161 	actNum = down->NumberForLoops( actNum);
162       }
163 
164     if( right != NULL && !keepRight)
165       {
166 	actNum = right->NumberForLoops( actNum);
167       }
168     return actNum;
169   }
170 
171   virtual ~ProgNode();
172 
173   void SetRightDown( const ProgNodeP right, const ProgNodeP down);
174 
IsWrappedNode()175   virtual bool IsWrappedNode() { return false;} // internally defined UD subroutine (overloads)
176 
177   virtual BaseGDL** LExpr( BaseGDL* right);
178   //   virtual BaseGDL** LExprGrab( BaseGDL* right); // take ownership of right
179   virtual BaseGDL** LEval();
180   virtual BaseGDL** EvalRefCheck( BaseGDL*& rEval); // returns NULL if r-value with rEval set
181   virtual BaseGDL* Eval(); // caller receives ownership
182   virtual BaseGDL* EvalNC(); // non-copy used by all operators (and in other places)
183   virtual BaseGDL* EvalNCNull(); // non-copy might return NULL
184   virtual RetCode    Run();
185 
186   //   RetCode  (*RunP)();
187 
188   bool ConstantNode();
189 
getFirstChild() const190   ProgNodeP getFirstChild() const
191   {
192     return down;
193   }
GetFirstChild() const194   ProgNodeP GetFirstChild() const
195   {
196     return down;//getFirstChild();
197   }
SetFirstChild(ProgNodeP d)198   void SetFirstChild( ProgNodeP d)
199   {
200     down = d;
201   }
getNextSibling() const202   ProgNodeP getNextSibling() const
203   {
204     return right;
205   }
GetLastSibling() const206   ProgNodeP GetLastSibling() const
207   {
208     ProgNodeP act = const_cast<ProgNodeP>(this);
209     while(!act->KeepRight() && act->GetNextSibling() != NULL) act = act->GetNextSibling();
210     return act;
211   }
GetNextSibling() const212   ProgNodeP GetNextSibling() const
213   {
214     return right;//getNextSibling();
215   }
SetNextSibling(ProgNodeP r)216   void SetNextSibling( ProgNodeP r)
217   {
218     right = r;
219   }
220 
StealCData()221   BaseGDL* StealCData()
222   {
223     BaseGDL* d = cData;
224     cData = NULL;
225     return d;
226   }
CData()227   BaseGDL* CData()
228   {
229     return cData;
230   }
231 
StealNextSibling()232   ProgNodeP StealNextSibling()
233   {
234     ProgNodeP n = right;
235     right = NULL;
236     return n;
237   }
StealFirstChild()238   ProgNodeP StealFirstChild()
239   {
240     ProgNodeP n = down;
241     down = NULL;
242     return n;
243   }
244 
KeepRight() const245   bool KeepRight() const { return keepRight;}
KeepDown() const246   bool KeepDown() const { return keepDown;}
247 
KeepDown(ProgNodeP d)248   void KeepDown( ProgNodeP d)
249   {
250     down = d;
251     keepDown = true;
252   }
KeepRight(ProgNodeP r)253   virtual void KeepRight( ProgNodeP r)
254   {
255     right = r;
256     keepRight = true;
257   }
258 
SetRight(ProgNodeP r)259   void SetRight( ProgNodeP r)
260   {
261     right = r;
262     // 	keepRight = false;
263   }
264 
SetAllBreak(ProgNodeP target)265   virtual void SetAllBreak( ProgNodeP target)
266   {
267     if( down != NULL && !keepDown)
268       {
269 	down->SetAllBreak( target);
270       }
271 
272     if( right != NULL && !keepRight)
273       {
274 	right->SetAllBreak( target);
275       }
276   }
SetAllContinue(ProgNodeP target)277   virtual void SetAllContinue( ProgNodeP target)
278   {
279     if( down != NULL && !keepDown)
280       {
281 	down->SetAllContinue( target);
282       }
283 
284     if( right != NULL && !keepRight)
285       {
286 	right->SetAllContinue( target);
287       }
288   }
289 
getType() const290   int getType() const { return ttype;}
setType(int t)291   void setType( int t) { ttype=t;}
292 //   std::string getText() { return text;}
getText() const293   const std::string& getText() const { return text;}
setText(const std::string & t)294   void setText(const std::string& t) { text = t;} // (performance) Function parameter 't' should be passed by reference.
getLine() const295   int getLine() const { return lineNumber;}
setLine(int l)296   void setLine( int l) { lineNumber = l;}
SetGotoIx(int ix)297   void SetGotoIx( int ix) { targetIx=ix;}
298 
GetNParam() const299   int GetNParam() const { return nParam;}
300 
BreakTarget() const301   ProgNodeP BreakTarget() const { return breakTarget;}
302 
303 //   bool LabelInRange( int lIx) const
304 //   {
305 //     // 	std::cout << "LabelInRange: " << ((lIx >= labelStart) && (lIx < labelEnd)) << "     " << lIx << "   [" << labelStart << "," << labelEnd << ")" << std::endl;
306 //     return (lIx >= labelStart) && (lIx < labelEnd);
307 //   }
308 
309   friend class GDLInterpreter;
310   friend class DInterpreter;
311 
312   friend class NSTRUCNode;
313   friend class ASSIGNNode;
314   friend class ASSIGN_REPLACENode;
315   friend class PCALL_LIBNode;//: public CommandNode
316   friend class MPCALLNode;//: public CommandNode
317   friend class MPCALL_PARENTNode;//: public CommandNode
318   friend class PCALLNode;//: public CommandNode
319   friend class ARRAYEXPR_MFCALLNode;
320   friend class KEYDEF_Node;
321   friend class KEYDEF_REFNode;
322   friend class KEYDEF_REF_CHECKNode;
323   friend class KEYDEF_REF_EXPRNode;
324   friend class REFNode;
325   friend class REF_CHECKNode;
326   friend class REF_EXPRNode;
327   friend class ParameterNode;
328   friend class ARRAYEXPRNode;
329   friend class ARRAYEXPR_FCALLNode;
330   friend class EXPRNode;
331   friend class SYSVARNode;
332   friend class DOTNode;
333 };
334 
335 
336 
337 class DefaultNode: public ProgNode
338 {
339 public:
DefaultNode()340   DefaultNode(): ProgNode()  {}
341 
DefaultNode(const RefDNode & refNode)342   explicit DefaultNode( const RefDNode& refNode): ProgNode( refNode)
343   {
344     if( refNode->GetFirstChild() != RefDNode(antlr::nullAST))
345       {
346 	down = NewProgNode( refNode->GetFirstChild());
347       }
348     if( refNode->GetNextSibling() != RefDNode(antlr::nullAST))
349       {
350 	right = NewProgNode( refNode->GetNextSibling());
351       }
352   }
353 };
354 
355 class RETPNode: public DefaultNode
356 {
357 public:
358   RetCode      Run();
359 
360 public:
RETPNode()361   RETPNode(): DefaultNode()  {}
362 
RETPNode(const RefDNode & refNode)363   explicit RETPNode( const RefDNode& refNode): DefaultNode( refNode)
364   {}
365 };
366 class RETFNode: public DefaultNode
367 {
368 public:
369   RetCode      Run();
370 
371 public:
RETFNode()372   RETFNode(): DefaultNode()  {}
373 
RETFNode(const RefDNode & refNode)374   explicit RETFNode( const RefDNode& refNode): DefaultNode( refNode)
375   {}
376 };
377 class GOTONode: public DefaultNode
378 {
379 public:
380   RetCode      Run();
381 
SetAllBreak(ProgNodeP target)382   void SetAllBreak( ProgNodeP target)
383   {
384     // 		breakTarget = target;
385 
386     if( right != NULL && !keepRight)
387       {
388 	right->SetAllBreak( target);
389       }
390   }
391 public:
GOTONode()392   GOTONode(): DefaultNode()  {}
393 
GOTONode(const RefDNode & refNode)394   explicit GOTONode( const RefDNode& refNode): DefaultNode( refNode)
395   {}
396 };
397 class CONTINUENode: public DefaultNode
398 {
399 public:
400   RetCode      Run();
401 
402 
SetAllContinue(ProgNodeP target)403   void SetAllContinue( ProgNodeP target)
404   {
405     assert( target != NULL);
406     breakTarget = target;
407 
408     if( right != NULL && !keepRight)
409       {
410 	right->SetAllContinue( target);
411       }
412   }
413 public:
CONTINUENode()414   CONTINUENode(): DefaultNode()  {}
415 
CONTINUENode(const RefDNode & refNode)416   explicit CONTINUENode( const RefDNode& refNode): DefaultNode( refNode)
417   {}
418 };
419 class BREAKNode: public DefaultNode
420 {
421 private:
422   bool breakTargetSet;
423 
424 public:
425   RetCode      Run();
426 
427 
SetAllBreak(ProgNodeP target)428   void SetAllBreak( ProgNodeP target)
429   {
430     breakTarget = target;
431     breakTargetSet = true;
432 
433     if( right != NULL && !keepRight)
434       {
435 	right->SetAllBreak( target);
436       }
437   }
438 public:
BREAKNode()439   BREAKNode(): DefaultNode(), breakTargetSet(false)  {}
440 
BREAKNode(const RefDNode & refNode)441   explicit BREAKNode( const RefDNode& refNode): DefaultNode( refNode), breakTargetSet(false)
442   {}
443 };
444 class LABELNode: public DefaultNode
445 {
446 public:
447   RetCode      Run();
448 
449 
450 public:
LABELNode()451   LABELNode(): DefaultNode()  {}
452 
LABELNode(const RefDNode & refNode)453   explicit LABELNode( const RefDNode& refNode): DefaultNode( refNode)
454   {}
455 };
456 class ON_IOERROR_NULLNode: public DefaultNode
457 {
458 public:
459   RetCode      Run();
460 
461 
462 public:
ON_IOERROR_NULLNode()463   ON_IOERROR_NULLNode(): DefaultNode()  {}
464 
ON_IOERROR_NULLNode(const RefDNode & refNode)465   explicit ON_IOERROR_NULLNode( const RefDNode& refNode): DefaultNode( refNode)
466   {}
467 };
468 class ON_IOERRORNode: public DefaultNode
469 {
470 public:
471   RetCode      Run();
472 
473 
474 public:
ON_IOERRORNode()475   ON_IOERRORNode(): DefaultNode()  {}
476 
ON_IOERRORNode(const RefDNode & refNode)477   explicit ON_IOERRORNode( const RefDNode& refNode): DefaultNode( refNode)
478   {}
479 };
480 
481 
482 class BreakableNode: public ProgNode
483 {
484 public:
SetAllBreak(ProgNodeP target)485   void SetAllBreak( ProgNodeP target)
486   {
487     // down: do NOT descent into own loop tree here
488 
489     if( right != NULL && !keepRight)
490       {
491 	right->SetAllBreak( target);
492       }
493   }
SetAllContinue(ProgNodeP target)494   void SetAllContinue( ProgNodeP target)
495   {
496     // down: do NOT descent into own loop tree here
497 
498     if( right != NULL && !keepRight)
499       {
500 	right->SetAllContinue( target);
501       }
502   }
503 
504 public:
BreakableNode()505   BreakableNode(): ProgNode()  {}
506 
BreakableNode(const RefDNode & refNode)507   explicit BreakableNode( const RefDNode& refNode): ProgNode( refNode)
508   {
509     if( refNode->GetFirstChild() != RefDNode(antlr::nullAST))
510       {
511 	down = NewProgNode( refNode->GetFirstChild());
512       }
513     if( refNode->GetNextSibling() != RefDNode(antlr::nullAST))
514       {
515 	right = NewProgNode( refNode->GetNextSibling());
516       }
517   }
518 };
519 
520 
521 
522 
523 class FOR_LOOPNode: public BreakableNode
524 {
525 public:
526   RetCode      Run();
527 
528   ProgNodeP statementList;
529 
GetStatementList()530   ProgNodeP GetStatementList()
531   {
532     return down->GetNextSibling();//->GetNextSibling()->GetNextSibling();
533   }
534 
535 public:
KeepRight(ProgNodeP r)536   void KeepRight( ProgNodeP r)
537   {
538     right = r;
539     keepRight = true;
540     assert( this->GetStatementList() != NULL);
541     // 		if( this->GetStatementList() != NULL)
542     this->GetStatementList()->SetAllBreak( right);
543   }
544 
NumberForLoops(int actNum)545   int NumberForLoops( int actNum)
546   {
547     this->forLoopIx = actNum;
548     actNum++;
549     ProgNodeP statementList = this->GetStatementList();
550     if( statementList != NULL && !down->KeepRight())
551       {
552 	actNum = statementList->NumberForLoops( actNum);
553       }
554     if( right != NULL && !keepRight)
555       {
556 	actNum = right->NumberForLoops( actNum);
557       }
558     return actNum;
559   }
560 
561 public:
FOR_LOOPNode(ProgNodeP r,ProgNodeP d)562   FOR_LOOPNode( ProgNodeP r, ProgNodeP d): BreakableNode()
563   {
564     SetType( GDLTokenTypes::FOR_LOOP, "for_loop");
565     SetRightDown( r, d);
566 
567     assert( down != NULL);
568 
569     statementList = this->GetStatementList();
570     if( statementList != NULL)
571       {
572 	statementList->SetAllContinue( this);
573 	statementList->GetLastSibling()->KeepRight( this);
574 	// also NULL is fine for "right" when the FOR statement
575 	// is the last in the subroutine
576 	// it is important, that breakTargetSet is set hence
577 	// this call must be done even with right == NULL
578 	statementList->SetAllBreak( right);
579 	// 			if( right != NULL) statementList->SetAllBreak( right);
580       }
581     else
582       {
583 	down->KeepRight( this);
584 	statementList = this;
585       }
586   }
587 
588 };
589 
590 
591 class FORNode: public BreakableNode
592 {
593 public:
594   RetCode      Run();
595 
596   void KeepRight( ProgNodeP r);
597 
NumberForLoops(int actNum)598   int NumberForLoops( int actNum)
599   {
600     this->forLoopIx = actNum;
601 
602     // 	assert( down == NULL);
603 
604     assert( right != NULL && !keepRight);
605 
606     actNum = right->NumberForLoops( actNum);
607 
608     return actNum;
609   }
610 
611 public:
FORNode()612   FORNode(): BreakableNode()  {}
613 
FORNode(const RefDNode & refNode)614   explicit FORNode( const RefDNode& refNode): BreakableNode( refNode)
615   {
616     ProgNodeP keep = down->GetNextSibling();
617     down->SetRight( down->GetNextSibling()->GetNextSibling()->GetNextSibling());
618 
619     keep->GetNextSibling()->SetRight( NULL);
620 
621     FOR_LOOPNode* forLoop = new FOR_LOOPNode( right, down);
622     forLoop->setLine( getLine());
623 
624     down = keep;
625 
626     right = forLoop;
627     //   		if( this->GetStatementList() != NULL && right != NULL)
628     // 			this->GetStatementList()->GetLastSibling()->KeepRight( right);
629   }
630 };
631 
632 
633 
634 class FOR_STEP_LOOPNode: public BreakableNode
635 {
636 public:
637   RetCode      Run();
638 
GetStatementList()639   ProgNodeP GetStatementList()
640   {
641     return down->GetNextSibling();//->GetNextSibling()->GetNextSibling()->GetNextSibling();
642   }
643 
644 public:
KeepRight(ProgNodeP r)645   void KeepRight( ProgNodeP r)
646   {
647     right = r;
648     keepRight = true;
649     if( this->GetStatementList() != NULL)
650       this->GetStatementList()->SetAllBreak( right);
651   }
652 
NumberForLoops(int actNum)653   int NumberForLoops( int actNum)
654   {
655     this->forLoopIx = actNum;
656     actNum++;
657     ProgNodeP statementList = this->GetStatementList();
658     if( statementList != NULL && !down->KeepRight())
659       {
660 	actNum = statementList->NumberForLoops( actNum);
661       }
662     if( right != NULL && !keepRight)
663       {
664 	actNum = right->NumberForLoops( actNum);
665       }
666     return actNum;
667   }
668 
669 public:
FOR_STEP_LOOPNode(ProgNodeP r,ProgNodeP d)670   FOR_STEP_LOOPNode( ProgNodeP r, ProgNodeP d): BreakableNode()
671   {
672     SetType( GDLTokenTypes::FOR_STEP_LOOP, "for_step_loop");
673     SetRightDown( r, d);
674 
675     assert( down != NULL);
676 
677     ProgNodeP statementList = this->GetStatementList();
678     if( statementList != NULL)
679       {
680 	statementList->SetAllContinue( this);
681 	statementList->GetLastSibling()->KeepRight( this);
682 	// also NULL is fine for "right" when the FOR statement
683 	// is the last in the subroutine
684 	// it is important, that breakTargetSet is set hence
685 	// this call must be done even with right == NULL
686 	statementList->SetAllBreak( right);
687 	// 			if( right != NULL) statementList->SetAllBreak( right);
688       }
689     else
690       {
691 	down->KeepRight( this);
692       }
693   }
694 
695 };
696 
697 
698 
699 class FOR_STEPNode: public BreakableNode
700 {
701 public:
702   RetCode      Run();
703 
704   void KeepRight( ProgNodeP r);
705 
NumberForLoops(int actNum)706   int NumberForLoops( int actNum)
707   {
708     this->forLoopIx = actNum;
709 
710     //assert( down == NULL);
711 
712     assert( right != NULL && !keepRight);
713 
714     actNum = right->NumberForLoops( actNum);
715 
716     return actNum;
717   }
718 
719 public:
FOR_STEPNode()720   FOR_STEPNode(): BreakableNode()  {}
721 
FOR_STEPNode(const RefDNode & refNode)722   explicit FOR_STEPNode( const RefDNode& refNode): BreakableNode( refNode)
723   {
724     ProgNodeP keep = down->GetNextSibling();
725     down->SetRight( down->GetNextSibling()->GetNextSibling()->GetNextSibling()->GetNextSibling());
726 
727     keep->GetNextSibling()->GetNextSibling()->SetRight( NULL);
728 
729     FOR_STEP_LOOPNode* forLoop = new FOR_STEP_LOOPNode( right, down);
730     forLoop->setLine( getLine());
731 
732     down = keep;
733 
734     right = forLoop;
735 
736     //   		if( this->GetStatementList() != NULL && right != NULL)
737     // 			this->GetStatementList()->GetLastSibling()->KeepRight( right);
738   }
739 };
740 
741 class FOREACH_LOOPNode: public BreakableNode
742 {
743 public:
744   RetCode      Run();
745 
GetStatementList()746   ProgNodeP GetStatementList()
747   {
748     return down->GetNextSibling();
749   }
750 
751 public:
KeepRight(ProgNodeP r)752   void KeepRight( ProgNodeP r)
753   {
754     right = r;
755     keepRight = true;
756     if( this->GetStatementList() != NULL)
757       this->GetStatementList()->SetAllBreak( right);
758   }
759 
NumberForLoops(int actNum)760   int NumberForLoops( int actNum)
761   {
762     this->forLoopIx = actNum;
763     actNum++;
764     ProgNodeP statementList = this->GetStatementList();
765     if( statementList != NULL && !down->KeepRight())
766       {
767 	actNum = statementList->NumberForLoops( actNum);
768       }
769     if( right != NULL && !keepRight)
770       {
771 	actNum = right->NumberForLoops( actNum);
772       }
773     return actNum;
774   }
775 
776 public:
FOREACH_LOOPNode(ProgNodeP r,ProgNodeP d)777   FOREACH_LOOPNode( ProgNodeP r, ProgNodeP d): BreakableNode()
778   {
779     SetType( GDLTokenTypes::FOREACH_LOOP, "foreach_loop");
780     SetRightDown( r, d);
781 
782     assert( down != NULL);
783 
784     ProgNodeP statementList = this->GetStatementList();
785     if( statementList != NULL)
786       {
787 	statementList->SetAllContinue( this);
788 	statementList->GetLastSibling()->KeepRight( this);
789 	// must be called even with right == NULL, see FOR_LOOPNode
790 	statementList->SetAllBreak( right);
791 	// 			if( right != NULL) statementList->SetAllBreak( right);
792       }
793     else
794       {
795 	down->KeepRight( this);
796       }
797   }
798 
799 };
800 
801 
802 
803 class FOREACHNode: public BreakableNode
804 {
805 public:
806   RetCode      Run();
807 
808   void KeepRight( ProgNodeP r);
809 
NumberForLoops(int actNum)810   int NumberForLoops( int actNum)
811   {
812     this->forLoopIx = actNum;
813 
814     // 	assert( down == NULL);
815 
816     assert( right != NULL && !keepRight);
817 
818     actNum = right->NumberForLoops( actNum);
819 
820     return actNum;
821   }
822 
823 public:
FOREACHNode()824   FOREACHNode(): BreakableNode()  {}
825 
FOREACHNode(const RefDNode & refNode)826   explicit FOREACHNode( const RefDNode& refNode): BreakableNode( refNode)
827   {
828     ProgNodeP keep = down->GetNextSibling();
829     down->SetRight( down->GetNextSibling()->GetNextSibling());
830 
831     keep->SetRight( NULL);
832 
833     FOREACH_LOOPNode* forLoop = new FOREACH_LOOPNode( right, down);
834     forLoop->setLine( getLine());
835 
836     down = keep;
837 
838     right = forLoop;
839   }
840 };
841 
842 
843 
844 class FOREACH_INDEX_LOOPNode: public BreakableNode
845 {
846 public:
847   RetCode      Run();
848 
GetStatementList()849   ProgNodeP GetStatementList()
850   {
851     return down->GetNextSibling();
852   }
853 
854 public:
KeepRight(ProgNodeP r)855   void KeepRight( ProgNodeP r)
856   {
857     right = r;
858     keepRight = true;
859     if( this->GetStatementList() != NULL)
860       this->GetStatementList()->SetAllBreak( right);
861   }
862 
NumberForLoops(int actNum)863   int NumberForLoops( int actNum)
864   {
865     this->forLoopIx = actNum;
866     actNum++;
867     ProgNodeP statementList = this->GetStatementList();
868     if( statementList != NULL && !down->KeepRight())
869       {
870 	actNum = statementList->NumberForLoops( actNum);
871       }
872     if( right != NULL && !keepRight)
873       {
874 	actNum = right->NumberForLoops( actNum);
875       }
876     return actNum;
877   }
878 
879 public:
FOREACH_INDEX_LOOPNode(ProgNodeP r,ProgNodeP d)880   FOREACH_INDEX_LOOPNode( ProgNodeP r, ProgNodeP d): BreakableNode()
881   {
882     SetType( GDLTokenTypes::FOREACH_INDEX_LOOP, "foreach_index_loop");
883     SetRightDown( r, d);
884 
885     assert( down != NULL);
886 
887     ProgNodeP statementList = this->GetStatementList();
888     if( statementList != NULL)
889       {
890 	statementList->SetAllContinue( this);
891 	statementList->GetLastSibling()->KeepRight( this);
892 	// must be called even with right == NULL, see FOR_LOOPNode
893 	statementList->SetAllBreak( right);
894 	// 			if( right != NULL) statementList->SetAllBreak( right);
895       }
896     else
897       {
898 	down->KeepRight( this);
899       }
900   }
901 
902 };
903 
904 
905 
906 class FOREACH_INDEXNode: public BreakableNode
907 {
908 public:
909   RetCode      Run();
910 
911   void KeepRight( ProgNodeP r);
912 
NumberForLoops(int actNum)913   int NumberForLoops( int actNum)
914   {
915     this->forLoopIx = actNum;
916 
917     // 	assert( down == NULL);
918 
919     assert( right != NULL && !keepRight);
920 
921     actNum = right->NumberForLoops( actNum);
922 
923     return actNum;
924   }
925 
926 public:
FOREACH_INDEXNode()927   FOREACH_INDEXNode(): BreakableNode()  {}
928 
FOREACH_INDEXNode(const RefDNode & refNode)929   explicit FOREACH_INDEXNode( const RefDNode& refNode): BreakableNode( refNode)
930   {
931     // down is variable,array,variable
932     ProgNodeP keep = down->GetNextSibling(); // the array to loop over
933 
934     ProgNodeP index = down->GetNextSibling()->GetNextSibling(); // the index variable
935 
936     down->SetRight( index); // jump over array
937 
938     // cut away everything after the array from keep
939     keep->SetRight( NULL);
940 
941     FOREACH_INDEX_LOOPNode* forLoop = new FOREACH_INDEX_LOOPNode( right, down);
942     forLoop->setLine( getLine());
943 
944     down = keep;
945 
946     right = forLoop;
947   }
948 };
949 
950 
951 
952 class WHILENode: public BreakableNode
953 {
954 public:
955   RetCode      Run();
956 
GetStatementList()957   ProgNodeP GetStatementList()
958   {
959     return down->GetNextSibling();
960   }
961 
KeepRight(ProgNodeP r)962   void KeepRight( ProgNodeP r)
963   {
964     right = r;
965     keepRight = true;
966     if( this->GetStatementList() != NULL)
967       this->GetStatementList()->SetAllBreak( right);
968   }
969 
970 public:
WHILENode()971   WHILENode(): BreakableNode()  {}
972 
WHILENode(const RefDNode & refNode)973   explicit WHILENode( const RefDNode& refNode): BreakableNode( refNode)
974   {
975     assert( down != NULL);
976 
977     // 	down->GetLastSibling()->KeepRight( this); // for empty body
978 
979     ProgNodeP statementList = this->GetStatementList();
980     if( statementList != NULL)
981       {
982 	statementList->SetAllContinue( this);
983 	// must be called even with right == NULL, see FOR_LOOPNode
984 	statementList->SetAllBreak( right);
985 	// 			if( right != NULL) statementList->SetAllBreak( right);
986 	statementList->GetLastSibling()->KeepRight( this); // for empty body
987       }
988   }
989 };
990 
991 
992 
993 class REPEAT_LOOPNode: public BreakableNode
994 {
995 public:
996   RetCode      Run();
997 
GetStatementList()998   ProgNodeP GetStatementList()
999   {
1000     return down->GetNextSibling();
1001   }
1002 
1003 public:
KeepRight(ProgNodeP r)1004   void KeepRight( ProgNodeP r)
1005   {
1006     right = r;
1007     keepRight = true;
1008     if( this->GetStatementList() != NULL)
1009       this->GetStatementList()->SetAllBreak( right);
1010   }
1011 
1012 public:
REPEAT_LOOPNode(ProgNodeP r,ProgNodeP d)1013   REPEAT_LOOPNode( ProgNodeP r, ProgNodeP d): BreakableNode()
1014   {
1015     SetType( GDLTokenTypes::REPEAT_LOOP, "repeat_loop");
1016     SetRightDown( r, d);
1017 
1018     assert( down != NULL);
1019 
1020     ProgNodeP statementList = this->GetStatementList();
1021     if( statementList != NULL)
1022       {
1023 	statementList->SetAllContinue( this);
1024 	statementList->GetLastSibling()->KeepRight( this);
1025 	// must be called even with right == NULL, see FOR_LOOPNode
1026 	statementList->SetAllBreak( right);
1027 	// 			if( right != NULL) statementList->SetAllBreak( right);
1028       }
1029   }
1030 
1031 };
1032 
1033 
1034 
1035 class REPEATNode: public BreakableNode
1036 {
1037 public:
1038   RetCode      Run();
1039 
KeepRight(ProgNodeP r)1040   void KeepRight( ProgNodeP r)
1041   {
1042     right = r;
1043     keepRight = true;
1044     down->KeepRight( right); // REPEAT_LOOP
1045   }
1046 
1047 public:
REPEATNode()1048   REPEATNode(): BreakableNode()  {}
1049 
REPEATNode(const RefDNode & refNode)1050   explicit REPEATNode( const RefDNode& refNode): BreakableNode( refNode)
1051   {
1052     REPEAT_LOOPNode* repeatLoop = new REPEAT_LOOPNode( NULL, down);
1053     repeatLoop->KeepRight( right);
1054     repeatLoop->setLine( getLine());
1055 
1056     down = repeatLoop;
1057   }
1058 };
1059 
1060 
1061 
1062 class CASENode: public BreakableNode
1063 {
1064 public:
1065   RetCode      Run();
1066 
GetStatementList()1067   ProgNodeP GetStatementList()
1068   {
1069     return down->GetNextSibling();
1070   }
1071 
KeepRight(ProgNodeP r)1072   void KeepRight( ProgNodeP r)
1073   {
1074     assert( down != NULL);
1075     right = r;
1076     keepRight = true;
1077     // down is expr
1078     ProgNodeP csBlock = GetStatementList();
1079     while( csBlock != NULL)
1080       {
1081 	if( csBlock->getType() == GDLTokenTypes::ELSEBLK)
1082 	  {
1083 	    ProgNodeP statementList = csBlock->GetFirstChild();
1084 	    if( statementList != NULL)
1085 	      {
1086 		statementList->GetLastSibling()->KeepRight( right);
1087 	      }
1088 	  }
1089 	else
1090 	  {
1091 	    // keep expr in case of empty statement
1092 	    ProgNodeP statementList = csBlock->GetFirstChild()->GetNextSibling();
1093 	    if( statementList != NULL)
1094 	      {
1095 		statementList->GetLastSibling()->KeepRight( right);
1096 	      }
1097 	  }
1098 	csBlock = csBlock->GetNextSibling();
1099       }
1100     GetStatementList()->SetAllBreak( right);
1101   }
1102 
1103 public:
CASENode()1104   CASENode(): BreakableNode()  {}
1105 
CASENode(const RefDNode & refNode)1106   explicit CASENode( const RefDNode& refNode): BreakableNode( refNode)
1107   {
1108     assert( down != NULL);
1109 
1110     ProgNodeP statementList = this->GetStatementList();
1111     if( statementList == NULL) return; // we say nothing at the compilation
1112 
1113     statementList->SetAllBreak( right);
1114 
1115     // down is expr
1116     ProgNodeP csBlock = GetStatementList();
1117 
1118     while( csBlock != NULL)
1119       {
1120 	if( csBlock->getType() == GDLTokenTypes::ELSEBLK)
1121 	  {
1122 	    ProgNodeP statementList = csBlock->GetFirstChild();
1123 	    if( statementList != NULL)
1124 	      {
1125 		statementList->GetLastSibling()->KeepRight( right);
1126 	      }
1127 	  }
1128 	else
1129 	  {
1130 	    // keep expr in case of empty statement
1131 	    ProgNodeP statementList = csBlock->GetFirstChild()->GetNextSibling();
1132 	    if( statementList != NULL)
1133 	      {
1134 		statementList->GetLastSibling()->KeepRight( right);
1135 	      }
1136 	  }
1137 
1138 	// 		if( csBlock->GetNextSibling() == NULL)
1139 	// 		{
1140 	// 				csBlock->KeepRight( right);
1141 	// 				break;
1142 	// 		}
1143 
1144 	csBlock = csBlock->GetNextSibling();
1145       }
1146   }
1147 };
1148 
1149 
1150 
1151 class SWITCHNode: public BreakableNode
1152 {
1153 public:
1154   RetCode      Run();
1155 
GetStatementList()1156   ProgNodeP GetStatementList()
1157   {
1158     return down->GetNextSibling();
1159   }
1160 
KeepRight(ProgNodeP r)1161   void KeepRight( ProgNodeP r)
1162   {
1163     right = r;
1164     keepRight = true;
1165     ProgNodeP csBlock = GetStatementList();
1166     ProgNodeP lastStatementList = NULL;
1167     while( csBlock != NULL)
1168       {
1169 	if( csBlock->getType() == GDLTokenTypes::ELSEBLK)
1170 	  {
1171 	    ProgNodeP statementList = csBlock->GetFirstChild();
1172 	    if( statementList != NULL)
1173 	      {
1174 		lastStatementList = statementList;
1175 	      }
1176 	  }
1177 	else
1178 	  {
1179 	    // keep expr in case of empty statement
1180 	    ProgNodeP statementList = csBlock->GetFirstChild()->GetNextSibling();
1181 	    if( statementList != NULL)
1182 	      {
1183 		lastStatementList = statementList;
1184 	      }
1185 	  }
1186 	csBlock = csBlock->GetNextSibling();
1187       }
1188     if( lastStatementList != NULL)
1189       lastStatementList->GetLastSibling()->KeepRight( right);
1190     GetStatementList()->SetAllBreak( right);
1191   }
1192 
1193 public:
SWITCHNode()1194   SWITCHNode(): BreakableNode()  {}
1195 
SWITCHNode(const RefDNode & refNode)1196   explicit SWITCHNode( const RefDNode& refNode): BreakableNode( refNode)
1197   {
1198     assert( down != NULL);
1199 
1200     ProgNodeP statementList = this->GetStatementList();
1201     statementList->SetAllBreak( right);
1202 
1203     // down is expr
1204     ProgNodeP csBlock = GetStatementList();
1205 
1206     ProgNodeP lastStatementList = NULL;
1207 
1208     while( csBlock != NULL)
1209       {
1210 	if( csBlock->getType() == GDLTokenTypes::ELSEBLK)
1211 	  {
1212 	    ProgNodeP statementList = csBlock->GetFirstChild();
1213 	    if( statementList != NULL)
1214 	      {
1215 		if( lastStatementList != NULL)
1216 		  lastStatementList->GetLastSibling()->KeepRight( statementList);
1217 
1218 		lastStatementList = statementList;
1219 	      }
1220 	  }
1221 	else
1222 	  {
1223 	    // keep expr in case of empty statement
1224 	    ProgNodeP statementList = csBlock->GetFirstChild()->GetNextSibling();
1225 	    if( statementList != NULL)
1226 	      {
1227 		if( lastStatementList != NULL)
1228 		  lastStatementList->GetLastSibling()->KeepRight( statementList);
1229 
1230 		lastStatementList = statementList;
1231 	      }
1232 	  }
1233 	if( csBlock->GetNextSibling() == NULL)
1234 	  {
1235 	    if( lastStatementList != NULL)
1236 	      lastStatementList->GetLastSibling()->KeepRight( right);
1237 	    break;
1238 	  }
1239 	csBlock = csBlock->GetNextSibling();
1240       }
1241   }
1242 
1243 };
1244 
1245 
1246 
1247 class BLOCKNode: public ProgNode
1248 {
1249 public:
1250   RetCode      Run();
1251 
KeepRight(ProgNodeP r)1252   void KeepRight( ProgNodeP r)
1253   {
1254     right = r;
1255     keepRight = true;
1256     // 	must recursively set dependents here
1257     if( down != NULL && !KeepDown())
1258       down->GetLastSibling()->KeepRight( right);
1259     else
1260       this->KeepDown( right);
1261   }
1262 
1263 public:
BLOCKNode()1264   BLOCKNode(): ProgNode()  {}
1265 
BLOCKNode(const RefDNode & refNode)1266   explicit BLOCKNode( const RefDNode& refNode): ProgNode( refNode)
1267   {
1268     if( refNode->GetFirstChild() != RefDNode(antlr::nullAST))
1269       {
1270 	down = NewProgNode( refNode->GetFirstChild());
1271       }
1272     if( refNode->GetNextSibling() != RefDNode(antlr::nullAST))
1273       {
1274 	right = NewProgNode( refNode->GetNextSibling());
1275 
1276 	// first statement
1277 	if( down != NULL)
1278 	  down->GetLastSibling()->KeepRight( right);
1279 	else
1280 	  this->KeepDown( right);
1281       }
1282   }
1283 
1284 };
1285 
1286 
1287 
1288 class IFNode: public ProgNode
1289 {
1290 public:
1291   RetCode      Run();
1292 
KeepRight(ProgNodeP r)1293   void KeepRight( ProgNodeP r)
1294   {
1295     assert( down != NULL);
1296     right = r;
1297     keepRight = true;
1298     down->GetLastSibling()->KeepRight( right);
1299   }
1300 public:
IFNode()1301   IFNode(): ProgNode()  {}
1302 
IFNode(const RefDNode & refNode)1303   explicit IFNode( const RefDNode& refNode): ProgNode( refNode)
1304   {
1305     if( refNode->GetFirstChild() != RefDNode(antlr::nullAST))
1306       {
1307 	down = NewProgNode( refNode->GetFirstChild());
1308       }
1309     if( refNode->GetNextSibling() != RefDNode(antlr::nullAST))
1310       {
1311 	right = NewProgNode( refNode->GetNextSibling());
1312       }
1313 
1314     assert( down != NULL);
1315 
1316     // first alternative
1317     if( right != NULL)
1318       {
1319 	ProgNodeP s1 = down->GetNextSibling(); // skip expr
1320 	s1->GetLastSibling()->KeepRight( right);
1321       }
1322   }
1323 };
1324 
1325 
1326 
1327 class IF_ELSENode: public ProgNode
1328 {
1329 public:
1330   RetCode      Run();
1331 
KeepRight(ProgNodeP r)1332   void KeepRight( ProgNodeP r)
1333   {
1334     // 	must recursively set dependents here
1335     assert( down != NULL);
1336 
1337     right = r;
1338     keepRight = true;
1339 
1340     ProgNodeP s1 = down->GetNextSibling(); // skip expr
1341     if( s1->GetFirstChild() == NULL || s1->KeepDown())
1342       {
1343 	s1->KeepDown( right);
1344       }
1345     else
1346       {
1347 	s1->GetFirstChild()->GetLastSibling()->KeepRight( right);
1348       }
1349 
1350     // 2nd alternative
1351     ProgNodeP s2 = s1->GetNextSibling();
1352     s2->GetLastSibling()->KeepRight( right);
1353   }
1354 
1355 public:
IF_ELSENode()1356   IF_ELSENode(): ProgNode()  {}
1357 
IF_ELSENode(const RefDNode & refNode)1358   explicit IF_ELSENode( const RefDNode& refNode): ProgNode( refNode)
1359   {
1360     // 	std::cout << "IF_ELSENode" << std::endl;
1361     if( refNode->GetFirstChild() != RefDNode(antlr::nullAST))
1362       {
1363 	down = NewProgNode( refNode->GetFirstChild());
1364       }
1365     if( refNode->GetNextSibling() != RefDNode(antlr::nullAST))
1366       {
1367 	right = NewProgNode( refNode->GetNextSibling());
1368       }
1369 
1370     assert( down != NULL);
1371 
1372     // IF expr s1 s2
1373     // first alternative
1374     // s1 is always a BLOCK (gdlc.tree.g, if_statement)
1375     // right MUST be set here even if NULL as it IS set to 2nd alternative
1376     ProgNodeP s1 = down->GetNextSibling(); // skip expr
1377     if( s1->GetFirstChild() == NULL || s1->KeepDown())
1378       {
1379 	s1->KeepDown( right);
1380       }
1381     else
1382       {
1383 	s1->GetFirstChild()->GetLastSibling()->KeepRight( right);
1384       }
1385 
1386     if( right != NULL)
1387       {
1388 	// 2nd alternative
1389 	ProgNodeP s2 = s1->GetNextSibling();
1390 
1391 	s2->GetLastSibling()->KeepRight( right); // disconnect s2
1392       }
1393   }
1394 };
1395 
1396 //#undef GDL_UNDEF
1397 //#ifdef GDL_UNDEF
1398 class EnvBaseT;
1399 
1400 class ParameterNode: public DefaultNode
1401 {
1402 public:
ParameterNode(const RefDNode & refNode)1403   explicit ParameterNode( const RefDNode& refNode): DefaultNode( refNode) {}
1404   virtual void Parameter( EnvBaseT* actEnv);
1405   virtual bool ParameterDirect( BaseGDL*& paramP); // returns isReference
1406   //   virtual void ParameterVarNum( EnvBaseT* actEnv); // for variable number of parameters
1407 };
1408 
1409 class ParameterVNNode: public ParameterNode
1410 {
1411 public:
ParameterVNNode(const RefDNode & refNode)1412   explicit ParameterVNNode( const RefDNode& refNode): ParameterNode( refNode) {}
1413   void Parameter( EnvBaseT* actEnv);
1414   //   virtual void ParameterVarNum( EnvBaseT* actEnv); // for variable number of parameters
1415 };
1416 
1417 class KEYDEF_REFNode: public ParameterNode
1418 {
1419 public:
KEYDEF_REFNode(const RefDNode & refNode)1420   explicit KEYDEF_REFNode( const RefDNode& refNode): ParameterNode( refNode) {}
1421   void Parameter( EnvBaseT* actEnv);
1422   //   void ParameterVarNum( EnvBaseT* actEnv); // for variable number of parameters
1423 };
1424 
1425 class KEYDEF_REF_EXPRNode: public ParameterNode
1426 {
1427 public:
KEYDEF_REF_EXPRNode(const RefDNode & refNode)1428   explicit KEYDEF_REF_EXPRNode( const RefDNode& refNode): ParameterNode( refNode) {}
1429   void Parameter( EnvBaseT* actEnv);
1430   //   void ParameterVarNum( EnvBaseT* actEnv); // for variable number of parameters
1431 };
1432 
1433 class KEYDEF_REF_CHECKNode: public ParameterNode
1434 {
1435 public:
KEYDEF_REF_CHECKNode(const RefDNode & refNode)1436   explicit KEYDEF_REF_CHECKNode( const RefDNode& refNode): ParameterNode( refNode) {}
1437   void Parameter( EnvBaseT* actEnv);
1438   //   void ParameterVarNum( EnvBaseT* actEnv); // for variable number of parameters
1439 };
1440 
1441 class KEYDEFNode: public ParameterNode
1442 {
1443 public:
KEYDEFNode(const RefDNode & refNode)1444   explicit KEYDEFNode( const RefDNode& refNode): ParameterNode( refNode) {}
1445   void Parameter( EnvBaseT* actEnv);
1446   //   void ParameterVarNum( EnvBaseT* actEnv); // for variable number of parameters
1447 };
1448 
1449 class REF_EXPRNode: public ParameterNode
1450 {
1451 public:
REF_EXPRNode(const RefDNode & refNode)1452   explicit REF_EXPRNode( const RefDNode& refNode): ParameterNode( refNode) {}
1453   void Parameter( EnvBaseT* actEnv);
1454   bool ParameterDirect( BaseGDL*& paramP);// returns isReference
1455   //   void ParameterVarNum( EnvBaseT* actEnv); // for variable number of parameters
1456 };
1457 class REF_EXPRVNNode: public ParameterNode
1458 {
1459 public:
REF_EXPRVNNode(const RefDNode & refNode)1460   explicit REF_EXPRVNNode( const RefDNode& refNode): ParameterNode( refNode) {}
1461   void Parameter( EnvBaseT* actEnv);
1462   //   void ParameterVarNum( EnvBaseT* actEnv); // for variable number of parameters
1463 };
1464 
1465 class REF_CHECKNode: public ParameterNode
1466 {
1467 public:
REF_CHECKNode(const RefDNode & refNode)1468   explicit REF_CHECKNode( const RefDNode& refNode): ParameterNode( refNode) {}
1469   void Parameter( EnvBaseT* actEnv);
1470   bool ParameterDirect( BaseGDL*& paramP);// returns isReference
1471   //   void ParameterVarNum( EnvBaseT* actEnv); // for variable number of parameters
1472 };
1473 class REF_CHECKVNNode: public ParameterNode
1474 {
1475 public:
REF_CHECKVNNode(const RefDNode & refNode)1476   explicit REF_CHECKVNNode( const RefDNode& refNode): ParameterNode( refNode) {}
1477   void Parameter( EnvBaseT* actEnv);
1478   //   void ParameterVarNum( EnvBaseT* actEnv); // for variable number of parameters
1479 };
1480 
1481 class REFNode: public ParameterNode
1482 {
1483 public:
REFNode(const RefDNode & refNode)1484   explicit REFNode( const RefDNode& refNode): ParameterNode( refNode) {}
1485   void Parameter( EnvBaseT* actEnv);
1486   bool ParameterDirect( BaseGDL*& paramP);// returns isReference
1487   //   void ParameterVarNum( EnvBaseT* actEnv); // for variable number of parameters
1488 };
1489 class REFVNNode: public ParameterNode
1490 {
1491 public:
REFVNNode(const RefDNode & refNode)1492   explicit REFVNNode( const RefDNode& refNode): ParameterNode( refNode) {}
1493   void Parameter( EnvBaseT* actEnv);
1494   //   void ParameterVarNum( EnvBaseT* actEnv); // for variable number of parameters
1495 };
1496 
1497 
1498 
1499 class CommandNode: public DefaultNode
1500 {
1501 protected:
CommandNode()1502   CommandNode(): DefaultNode() {}
1503 public:
CommandNode(const RefDNode & refNode)1504   explicit CommandNode( const RefDNode& refNode): DefaultNode( refNode) {}
1505 };
1506 
1507 // call C++ function as GDL FUNCTION
1508 // for internal member functions (like GDL_OBJECT::_overload...)
1509 // this has some overhead compared to calling library subroutines,
1510 // but this way, only one list of functions has to be searched.
1511 // Otherwise we would need an additional list for library member functions
1512 // For member calls this search must be done a runtime (as the object
1513 // definition is not available at compile time).
1514 // While library subroutine calls are resolved at compile time.
1515 class EnvUDT;
1516 class WRAPPED_FUNNode: public CommandNode
1517 {
1518   BaseGDL* (*fun)( EnvUDT*);
1519 public:
IsWrappedNode()1520   bool IsWrappedNode() { return true;}
WRAPPED_FUNNode(BaseGDL * (* fun_)(EnvUDT *))1521   explicit WRAPPED_FUNNode( BaseGDL* (*fun_)( EnvUDT*)): CommandNode(), fun(fun_) {}
1522   RetCode Run();
1523 };
1524 // call C++ function as GDL PRO
1525 class WRAPPED_PRONode: public CommandNode
1526 {
1527   void (*pro)( EnvUDT*);
1528 public:
IsWrappedNode()1529   bool IsWrappedNode() { return true;}
WRAPPED_PRONode(void (* pro_)(EnvUDT *))1530   explicit WRAPPED_PRONode( void (*pro_)( EnvUDT*)): CommandNode(), pro(pro_) {}
1531   RetCode Run();
1532 };
1533 
1534 class ASSIGNNode: public CommandNode
1535 {
1536 public:
ASSIGNNode(const RefDNode & refNode)1537   explicit ASSIGNNode( const RefDNode& refNode): CommandNode( refNode) {}
1538   RetCode Run();
1539   BaseGDL** LExpr( BaseGDL* right);
1540   //   BaseGDL** LExprGrab( BaseGDL* right);
1541   BaseGDL* Eval();
1542 };
1543 class ASSIGN_ARRAYEXPR_MFCALLNode: public CommandNode
1544 {
1545 public:
ASSIGN_ARRAYEXPR_MFCALLNode(const RefDNode & refNode)1546   explicit ASSIGN_ARRAYEXPR_MFCALLNode( const RefDNode& refNode): CommandNode( refNode) {}
1547   RetCode Run();
1548   BaseGDL** LExpr( BaseGDL* right);
1549   //   BaseGDL** LExprGrab( BaseGDL* right);
1550   BaseGDL* Eval();
1551 };
1552 class ASSIGN_REPLACENode: public CommandNode
1553 {
1554 public:
ASSIGN_REPLACENode(const RefDNode & refNode)1555   explicit ASSIGN_REPLACENode( const RefDNode& refNode): CommandNode( refNode) {}
1556   RetCode Run();
1557   BaseGDL** LExpr( BaseGDL* right);
1558   //   BaseGDL** LExprGrab( BaseGDL* right);
1559   BaseGDL* Eval();
1560   BaseGDL** LEval();
1561 };
1562 class PCALL_LIBNode: public CommandNode
1563 {
1564 public:
PCALL_LIBNode(const RefDNode & refNode)1565   explicit PCALL_LIBNode( const RefDNode& refNode): CommandNode( refNode) {}
1566   RetCode Run();
1567 };
1568 class MPCALLNode: public CommandNode
1569 {
1570 public:
MPCALLNode(const RefDNode & refNode)1571   explicit MPCALLNode( const RefDNode& refNode): CommandNode( refNode) {}
1572   RetCode Run();
1573 };
1574 class MPCALL_PARENTNode: public CommandNode
1575 {
1576 public:
MPCALL_PARENTNode(const RefDNode & refNode)1577   explicit MPCALL_PARENTNode( const RefDNode& refNode): CommandNode( refNode) {}
1578   RetCode Run();
1579 };
1580 class PCALLNode: public CommandNode
1581 {
1582 public:
PCALLNode(const RefDNode & refNode)1583   explicit PCALLNode( const RefDNode& refNode): CommandNode( refNode) {}
1584   RetCode Run();
1585 };
1586 class DECNode: public CommandNode
1587 { public:
DECNode(const RefDNode & refNode)1588   explicit DECNode( const RefDNode& refNode): CommandNode( refNode){}
1589   BaseGDL** EvalRefCheck( BaseGDL*& res);
1590   BaseGDL** LEval();
1591   BaseGDL* Eval();
1592   RetCode Run();
1593 };
1594 class INCNode: public CommandNode
1595 { public:
INCNode(const RefDNode & refNode)1596   explicit INCNode( const RefDNode& refNode): CommandNode( refNode){}
1597   BaseGDL** EvalRefCheck( BaseGDL*& res);
1598   BaseGDL** LEval();
1599   BaseGDL* Eval();
1600   RetCode Run();
1601 };
1602 class POSTDECNode: public CommandNode
1603 { public:
POSTDECNode(const RefDNode & refNode)1604   explicit POSTDECNode( const RefDNode& refNode): CommandNode( refNode){}
1605   BaseGDL* Eval();
1606 //   BaseGDL** LEval();
1607 };
1608 class POSTINCNode: public CommandNode
1609 { public:
POSTINCNode(const RefDNode & refNode)1610   explicit POSTINCNode( const RefDNode& refNode): CommandNode( refNode){}
1611   BaseGDL* Eval();
1612 //   BaseGDL** LEval();
1613 };
1614 
1615 class ARRAYEXPRNode: public DefaultNode
1616 {
1617 public:
ARRAYEXPRNode(const RefDNode & refNode)1618   explicit ARRAYEXPRNode( const RefDNode& refNode): DefaultNode( refNode) {}
1619   BaseGDL* Eval(); // caller receives ownership
1620   BaseGDL** LExpr(BaseGDL* r);
1621   //BaseGDL** LEval();
1622 };
1623 
1624 class EXPRNode: public DefaultNode
1625 {
1626 public:
EXPRNode(const RefDNode & refNode)1627   explicit EXPRNode( const RefDNode& refNode): DefaultNode( refNode) {}
1628   BaseGDL** EvalRefCheck( BaseGDL*& rEval); // calls LEval()
1629   BaseGDL** LEval();
1630 };
1631 
1632 class DOTNode: public DefaultNode
1633 {
1634 public:
DOTNode(const RefDNode & refNode)1635   explicit DOTNode( const RefDNode& refNode): DefaultNode( refNode) {}
1636   BaseGDL* Eval();
1637   BaseGDL** LExpr( BaseGDL* right);
1638 
1639 };
1640 
1641 #endif
1642