home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 27 / IOPROG_27.ISO / SOFT / CALCPLUS.ZIP / CALCEXPR.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-02  |  24.5 KB  |  1,097 lines

  1. /*******************************************************
  2.  
  3.     The CalcPlus Class Library Version 1.0,
  4.     Author: Vladimir Schipunov, Copyright (C) 1996
  5.  
  6.     This library is free software. Permission to use,
  7.     copy, modify and redistribute the CalcPlus library
  8.     for any purpose is hereby granted without fee,
  9.     provided that the above copyright notice appear
  10.     in all copies.
  11.  
  12. *******************************************************/
  13.  
  14. #include <iostream.h>
  15. #include <string.h>
  16. #include <stdarg.h>
  17. #include "calcexpr.h"
  18. #include "calctype.h"
  19.  
  20. //
  21. // The definitions below are intended to decrease dynamic
  22. // memory allocation for the slight speed optimization.
  23. // This is the same as:
  24. //
  25. //  #define COPY_VALUE(v,x) { delete v; v = x ? x->copy() : 0; }
  26. //
  27.  
  28. #define TYPEID id
  29. #define VCLEAR( v, x ) { delete v; v = ((x)?(x)->copy():0); break; }
  30. #define COPY_ID(v,x,t,q) if(t==id##q){((C##q*)v)->n=((C##q*)x)->n;break;}
  31. #define COPY_VALUE( v, x ) \
  32. while( x )                 \
  33. {                          \
  34.     if( !v )               \
  35.         VCLEAR(v,x);       \
  36.     int t = (v)->TYPEID;   \
  37.     if( t != (x)->TYPEID)  \
  38.         VCLEAR(v,x);       \
  39.     COPY_ID(v,x,t,Long)    \
  40.     COPY_ID(v,x,t,Bool)    \
  41.     COPY_ID(v,x,t,Double)  \
  42.     if(t==idNil)break;     \
  43.     if( (v)->size() !=     \
  44.         (x)->size() )      \
  45.         VCLEAR(v,x);       \
  46.     *(v) = *(x);           \
  47.     break;                 \
  48. }
  49. /*
  50. #undef COPY_VALUE
  51. #define COPY_VALUE( v, x )\
  52.     { delete v; v = x ? x->copy() : 0; }
  53. */
  54.  
  55. int Expression::Debug;
  56.  
  57. Expression::Expression( int order, Expression *p... ) :
  58.     n( order ), v( 0 ), flags( 0 )
  59. {
  60.     child = n ? new Expression*[order] : 0;
  61.     father = 0;
  62.     va_list l;
  63.     va_start( l, p );
  64.     Expression *e = p;
  65.     for( int i = 0; i < n; i++ )
  66.     {
  67.         child[i] = e;
  68.         child[i]->father = this;
  69.         e = va_arg( l, Expression* );
  70.     }
  71.     va_end( l );
  72. }
  73.  
  74. Expression::Expression( int order ) :
  75.     n( order ), v( 0 ), flags( 0 )
  76. {
  77.     child = n ? new Expression*[order] : 0;
  78.     father = 0;
  79.     for( int i = 0; i < n; i++ )
  80.         child[i] = 0;
  81. }
  82.  
  83. Expression::~Expression()
  84. {
  85.     delete v;
  86.     for( int i = 0; i < n; i++ )
  87.         delete child[i];
  88.     delete[] child;
  89. }
  90.  
  91. void Expression::Calc()
  92. {
  93.     if( !v )
  94.         v = new CNil;
  95. }
  96.  
  97. Expression::CheckType( int t... )
  98. {
  99.     va_list l;
  100.     va_start( l, t );
  101.     int v = t;
  102.     for( int i = 0; i < n; i++ )
  103.     {
  104.         Expression *&e = child[i];
  105.         if( !e || !e->v || e->v->TYPEID!=v )
  106.             return 0;
  107.         v = va_arg( l, int );
  108.     }
  109.     va_end( l );
  110.     return 1;
  111. }
  112.  
  113. Expression::precedence( const Expression &e ) const
  114. {
  115.     return op() >  e.op() ||
  116.            op() == e.op() && range() > e.range();
  117. }
  118.  
  119. void Expression::print( ostream &s ) const
  120. {
  121.     if( (flags & exError) || !v )
  122.         s << "ERROR";
  123.     else
  124.         s << *v;
  125. }
  126.  
  127. void Expression::printx( ostream &s, Expression *e ) const
  128. {
  129.     int p = precedence(*e);
  130.     if ( p ) s << '(';
  131.     s << *e;
  132.     if ( p ) s << ')';
  133. }
  134.  
  135. #define REC_STACK 0x1FFF
  136. void PtrStack::Push( CType* t )
  137. {
  138.     if( !stack )
  139.         stack = new CType*[ REC_STACK ];
  140.     if( i>=REC_STACK )
  141.     {
  142.         cerr << "Recursion stack overflow!" << endl;
  143.         return;
  144.     }
  145.     stack[i++] = t;
  146. }
  147.  
  148. CType* PtrStack::Pop()
  149. {
  150.     if( --i < 0 )
  151.     {
  152.         cerr << "Recursion stack underflow!" << endl;
  153.         return 0;
  154.     }
  155.     return stack[i];
  156. }
  157.  
  158. void Expression::RecDebug()
  159. {
  160.     cout << *this << endl << "/// ";
  161.     Expression::print( cout );
  162.     cout << endl;
  163. }
  164.  
  165. PtrStack RecStack;
  166. void Expression::Push()
  167. {
  168.     RecStack.Push( v );
  169.     v = 0;
  170. }
  171.  
  172. void Expression::Pop()
  173. {
  174.     delete v;
  175.     v = RecStack.Pop();
  176.     flags = 0;
  177. }
  178.  
  179. Expression::loop( Expression *x ) const
  180. {
  181.     if( this == x )
  182.         return 1;
  183.     return father ? father->loop( x ) : 0;
  184. }
  185.  
  186. #define SPACE(s) e->Space( cout );\
  187.     if( !e->AutoSpace()) cout << s;\
  188.     else cout << s << endl;\
  189.     cout << *e << endl;
  190.  
  191. static void Before( Expression* e )
  192. {
  193.     SPACE("-> ");
  194. }
  195.  
  196. static void After( Expression* e )
  197. {
  198.     SPACE("<- ");
  199.     e->Space( cout );
  200.     cout << " = ";
  201.     static CString end("\n");
  202.     if( e->v && e->v->TYPEID==idString &&
  203.         !e->v->compare( end ))
  204.             cout << "ENDL";
  205.     else
  206.         e->Expression::print( cout );
  207.     cout << endl;
  208. }
  209.  
  210. void Expression::Calculate()
  211. {
  212.     flags = 0;
  213.     for( int i = 0; i < n && !flags; i++ )
  214.     {
  215.         Expression *e = child[i];
  216.         if( Debug )
  217.         {
  218.             Before( e );
  219.             e->Expression::Calculate();
  220.             After( e );
  221.         }
  222.         else
  223.             e->Calculate();
  224.         if( e->flags )
  225.             flags = e->flags;
  226.     }
  227.     if( flags )
  228.     {
  229.         if( father )
  230.             father->flags =
  231.             father->flags | flags;
  232.         return;
  233.     }
  234.     Calc();
  235. }
  236.  
  237. void Expression::Iterate()
  238. {
  239.     static Expression **stack[512];
  240.     static i;
  241.     Expression *p = this;
  242.     int sav = i;
  243.     while( 1 )
  244.     {
  245.         while( p->n )
  246.             p = *( stack[i++] = p->child );
  247.         p->flags = 0; p->Calc();
  248.         if( p->flags ){ flags = p->flags; i = sav; return; }
  249.         if( i==sav )
  250.             return;
  251.         while( 1 )
  252.         {
  253.             if( p->father->n > stack[i-1] -
  254.                 p->father->child + 1 )
  255.             {
  256.                 p = *(++stack[i-1]);
  257.                 break;
  258.             }
  259.             p = p->father;
  260.             p->flags = 0; p->Calc();
  261.             if( p->flags ){ flags = p->flags; i = sav; return; }
  262.             if( --i==sav )
  263.                 return;
  264.         }
  265.     }
  266. }
  267.  
  268. const Expression* Expression::LocateError( int mask ) const
  269. {
  270.     if( !(flags & mask))
  271.         return 0;
  272.     for( int i = 0; i < n; i++ )
  273.         if( child[i] && (child[i]->flags & mask))
  274.             return child[i]->LocateError( mask );
  275.     return this;
  276. }
  277.  
  278. Expression* Expression::Add( Expression* e )
  279. {
  280.     Expression** p = new Expression*[n+1];
  281.     for( int i = 0; i < n; i++ )
  282.         p[i] = child[i];
  283.     p[n++] = e;
  284.     e->father = this;
  285.     delete[] child;
  286.     child = p;
  287.     return this;
  288. }
  289.  
  290. void Expression::Space( ostream& o ) const
  291. {
  292.     int n = Depth();
  293.     if( !father )
  294.         n--;
  295.     for( int i = 0; i < n; i++ )
  296.         o << "  ";
  297. }
  298.  
  299. void Expression::RecStep( ExprF f, int check )
  300. {
  301.     if( !check || !flags )
  302.         (this->*f)();
  303.     if( check && flags && father )
  304.         father->flags = father->flags | flags;
  305. }
  306.  
  307. void Expression::Recursion(
  308.     ExprF f, int direction, int check )
  309. {
  310.     if( direction )
  311.     {
  312.         RecStep( f, check );
  313.         for( int i = n-1; i>=0 && ( !check || !flags ); i-- )
  314.             if( child[i] )
  315.                 child[i]->Recursion( f, direction, check );
  316.     }
  317.     else
  318.     {
  319.         for( int i = 0; i<n && ( !check || !flags ); i++ )
  320.             if( child[i] )
  321.                 child[i]->Recursion( f, direction, check );
  322.         RecStep( f, check );
  323.     }
  324. }
  325.  
  326. void XImmediate::print( ostream& o ) const
  327. {
  328.     if( v->TYPEID!=idString )
  329.     {
  330.         Expression::print( o );
  331.         return;
  332.     }
  333.     o << "'";
  334.     Expression::print( o );
  335.     o << "'";
  336. }
  337.  
  338. XEndl::XEndl() : XImmediate( new CString("\n")){}
  339. void XEndl::print( ostream& o ) const { o << "ENDL"; }
  340. void XBreak::print( ostream& o ) const { o << "EXIT"; }
  341.  
  342. void XAr1::print( ostream &o ) const
  343. {
  344.     o << sign;
  345.     printx( o, child[0]);
  346. }
  347.  
  348. void XAr2::print( ostream &o ) const
  349. {
  350.     printx( o, child[0]);
  351.     if(       sign == '}' ) o << ">=";
  352.     else if(  sign == '{' ) o << "<=";
  353.     else if(  sign == '~' ) o << "!=";
  354.     else if(  sign == 'i' ) o << "->";
  355.     else if(  sign == '&' ) o << " AND ";
  356.     else if(  sign == '|' ) o << " OR ";
  357.     else                    o << sign;
  358.     printx( o, child[1]);
  359. }
  360.  
  361. #define AR1(type) \
  362.     if( id==id##type ) \
  363.     { ((C##type*)v)->n = -((C##type*)(e->v))->n; return; }
  364.  
  365. void XAr1::Calc()
  366. {
  367.     Expression *e = child[0];
  368.     int id = e->v->TYPEID;
  369.     if( v->TYPEID != id )
  370.     {
  371.         delete v;
  372.         v = e->v->copy();
  373.     }
  374.     AR1( Long );
  375.     AR1( Double );
  376.     cerr << SyntaxError("Wrong type for unary "
  377.         "arithmetic operation: ",v->name()) << endl;
  378.     flags = exError;
  379. }
  380.  
  381. #define A2START \
  382.     Expression *c1 = child[0], *c2 = child[1];\
  383.     int id  =       v ?       v->TYPEID   : -1  ;\
  384.     int id1 = /*c1->v ?*/ c1->v->TYPEID /*: -1*/;\
  385.     int id2 = /*c2->v ?*/ c2->v->TYPEID /*: -1*/;
  386.  
  387. //if( id1==i1 && id2==i2 )
  388. #define A2(t1,i1,t2,i2,t,i,r)\
  389. case( i1*0x10+i2 ):          \
  390. {                            \
  391.     t1& v1 = (t1&)(*c1->v);  \
  392.     t2& v2 = (t2&)(*c2->v);  \
  393.     if( id!=i )              \
  394.     { delete v; v = new t; } \
  395.     t& t0 = (t&)(*v);        \
  396.     switch( sign ){          \
  397.     case '+': t0.n = v1.n +  v2.n ; return;\
  398.     case '-': t0.n = v1.n -  v2.n ; return;\
  399.     case '*': t0.n = v1.n *  v2.n ; return;\
  400.     case '/': t0.n = v1.n /  v2.n ; return;}\
  401.     return;\
  402. }
  403.  
  404. #define C2(t1,i1,t2,i2,t,i,r)\
  405. case( i1*0x10+i2 ):          \
  406. {                            \
  407.     t1& v1 = (t1&)(*c1->v);  \
  408.     t2& v2 = (t2&)(*c2->v);  \
  409.     if( id!=i )              \
  410.     { delete v; v = new t; } \
  411.     t& t0 = (t&)(*v);        \
  412.     switch( sign ){          \
  413.     case '<': t0.n = v1.n <  v2.n ; return;\
  414.     case '>': t0.n = v1.n >  v2.n ; return;\
  415.     case '}': t0.n = v1.n >= v2.n ; return;\
  416.     case '{': t0.n = v1.n <= v2.n ; return;\
  417.     case '=': t0.n = v1.n == v2.n ; return;\
  418.     case '~': t0.n = v1.n != v2.n ; return;}\
  419.     return;\
  420. }
  421.  
  422. void XAr2::Calc()
  423. {
  424.     A2START;
  425.     switch( id1*0x10+id2 ){
  426.     A2( CLong,   idLong,   CLong,   idLong,   CLong,   idLong,   long   )
  427.     A2( CDouble, idDouble, CDouble, idDouble, CDouble, idDouble, double )
  428.     A2( CLong,   idLong,   CDouble, idDouble, CDouble, idDouble, double )
  429.     A2( CDouble, idDouble, CLong,   idLong,   CDouble, idDouble, double )}
  430.     CType* t1 = child[0]->v;
  431.     CType* t2 = child[1]->v;
  432.     if( sign!='+' || id1!=idString || id2!=idString )
  433.     {
  434.         cerr << SyntaxError("Wrong types for binary "
  435.             "arithmetic operation!") << endl;
  436.         flags = exError;
  437.         return;
  438.     }
  439.     unsigned n = t1->size()+t2->size();
  440.     delete v;
  441.     v = new CString( n+1 );
  442.     t1->s( (char*)v->ptr() );
  443.     t2->s( (char*)v->ptr()+t1->size());
  444. }
  445.  
  446. void XComparison::Calc()
  447. {
  448.     A2START;
  449.     switch( id1*0x10+id2 ){
  450.     C2( CLong,   idLong,   CLong,   idLong,   CBool,   idBool,  long   )
  451.     C2( CDouble, idDouble, CDouble, idDouble, CBool,   idBool,  double )
  452.     C2( CLong,   idLong,   CDouble, idDouble, CBool,   idBool,  double )
  453.     C2( CDouble, idDouble, CLong,   idLong,   CBool,   idBool,  double )}
  454.     if( !v )
  455.         v = new CBool;
  456.     if( sign=='=' && id1==idString && id2==idString )
  457.     {
  458.         CBool& b = (CBool&)(*v);
  459.         b = !child[0]->v->compare( *child[1]->v );
  460.         return;
  461.     }
  462.     if( sign=='~' && id1==idString && id2==idString )
  463.     {
  464.         CBool& b = (CBool&)(*v);
  465.         b = child[0]->v->compare( *child[1]->v );
  466.         return;
  467.     }
  468.     cerr << SyntaxError("ìÑóÑα¡δÑ Γ¿»δ ñ½∩ «»Ñαᵿ¿ ßαáó¡Ñ¡¿∩!") << endl;
  469.     flags = exError;
  470. }
  471.  
  472. void XBool1::Calc()
  473. {
  474.     if( child[0]->v->TYPEID != idBool )
  475.     {
  476.         cerr << SyntaxError("Wrong type for boolean operation: ",
  477.             child[0]->v->name()) << endl;
  478.         flags = exError;
  479.         return;
  480.     }
  481.     if( !v || v->TYPEID!=idBool )
  482.     {
  483.         delete v;
  484.         v = new CBool;
  485.     }
  486.     ((CBool*)v)->n = ((CBool*)(child[0]->v))->n ? 0 : 1;
  487. }
  488.  
  489. void XBool2::Calc()
  490. {
  491.     if( child[0]->v->TYPEID != idBool ||
  492.         child[1]->v->TYPEID != idBool )
  493.     {
  494.         cerr << SyntaxError("Wrong types for boolean operations!") << endl;
  495.         flags = exError;
  496.         return;
  497.     }
  498.     CBool& b1 = (CBool&)(*child[0]->v);
  499.     CBool& b2 = (CBool&)(*child[1]->v);
  500.     int n1 = b1 ? 1 : 0;
  501.     int n2 = b2 ? 1 : 0;
  502.     int k = sign=='&' ? (n1 && n2) :
  503.             sign=='|' ? (n1 || n2) :
  504.             sign=='=' ? (n1 == n2) :
  505.             sign=='~' ? (n1 != n2) : 0;
  506.     if( !v || v->TYPEID!=idBool )
  507.     {
  508.         delete v;
  509.         v = new CBool;
  510.     }
  511.     CBool& b = (CBool&)(*v);
  512.     b = k ? 1 : 0;
  513. }
  514.  
  515. Var::Var( const char* s, int c ) :
  516.     v( new CNil ), isConst( c )
  517. {
  518.     name = new char[ strlen(s)+1 ];
  519.     strcpy( name, s );
  520. }
  521.  
  522. Var::~Var()
  523. {
  524.     delete[] name;
  525.     delete v;
  526. }
  527.  
  528. void Var::print( ostream& o ) const
  529. {
  530.     o << name;
  531. }
  532.  
  533. void XVariable::Push(){ Expression::Push(); v = 0; }
  534. void XVariable::Pop(){ v = 0; Expression::Pop(); }
  535.  
  536. void XVariable::print( ostream& o ) const
  537. {
  538.     o << *obj;
  539.     if( !n )
  540.         return;
  541.     if( n==2 )
  542.         o << "[" << *child[1] << "]";
  543.     if( n%2 )
  544.         o << ":=" << *child[n-1];
  545. }
  546.  
  547. void XVariable::Calc()
  548. {
  549.     if( !n )
  550.     {
  551.         v = *ptr;
  552.         return;
  553.     }
  554.     if( n==1 )
  555.     {
  556.         v = *ptr;
  557.         COPY_VALUE( v, child[0]->v );
  558.         *ptr = v;
  559.         return;
  560.     }
  561.     CType *x = child[1]->v;
  562.     int t = x->TYPEID;
  563.     if( t!=idLong && t!=idString )
  564.     {
  565.         cerr << "Wrong type in array access: " << x->name() << endl;
  566.         flags = exError;
  567.         return;
  568.     }
  569.     CType *w = child[0]->v;
  570.     if( w->TYPEID!=idArray )
  571.     {
  572.         cerr << *w << " is not array!" << endl;
  573.         flags = exError;
  574.         return;
  575.     }
  576.     CArray *a = (CArray*)w;
  577.     long n = 0;
  578.     if( t==idLong )    n = *(CLong*)x;
  579.     if( t==idString  ) n = a->index(x->s());
  580.     if( n < 0 || n >= a->n )
  581.     {
  582.         cerr << *w << ": out of array!" << endl;
  583.         flags = exError;
  584.         return;
  585.     }
  586.     v = a->array[ (int)n ];
  587.     if( XVariable::n<3 )
  588.         return;
  589.     COPY_VALUE( v, child[2]->v );
  590.     a->array[ (int)n ] = v;
  591. }
  592.  
  593. void XEcho::Calc()
  594. {
  595.     if( !v )
  596.         v = new CNil;
  597.     for( int i = 0; i < n; i++ )
  598.         cout << *child[i]->v;
  599. }
  600.  
  601. void XEcho::print( ostream& o ) const
  602. {
  603.     o << "ECHO ";
  604.     for( int i = 0; i < n; i++ )
  605.     {
  606.         Expression *e = child[i];
  607.         if( e )
  608.             o << *e;
  609.         if( i!=n-1 )
  610.             o << ",";
  611.     }
  612. }
  613.  
  614. void XConditional::print( ostream& o ) const
  615. {
  616.     Space( o );
  617.     o << "IF " << *child[0] << " THEN" << endl;
  618.     if( !Then->AutoSpace())
  619.         Then->Space( o );
  620.     o << *Then << ";" << endl;
  621.     if( Else )
  622.     {
  623.         Space( o );
  624.         o << "ELSE" << endl;
  625.         if( !Else->AutoSpace())
  626.             Else->Space( o );
  627.         o << *Else << ";" << endl;
  628.     }
  629.     Space( o );
  630.     o << "END";
  631. }
  632.  
  633. void XLoop::print( ostream& o ) const
  634. {
  635.     o << "LOOP";
  636. }
  637.  
  638. void XWhile::print( ostream& o ) const
  639. {
  640.     Space( o );
  641.     if( !Step )
  642.         o << "WHILE " << *Cond;
  643.     else
  644.         o << "FOR " << *(((XVariable*)Step)->obj) << " CYCLE"
  645.           << " TO " << *Cond->child[1] << " STEP "
  646.           << *(((XVariable*)Step)->child[0]->child[1]);
  647.     o << " DO" << endl << *Action << ";" << endl;
  648.     Space( o );
  649.     o << "END";
  650. }
  651.  
  652. void XConditional::Calc()
  653. {
  654.     Expression *p = child[0];
  655.     if( !p || !p->v || p->v->TYPEID!=idBool )
  656.     {
  657.         flags = exError;
  658.         return;
  659.     }
  660.     COPY_VALUE( v, p->v );
  661.     CBool& b = (CBool&)(*p->v);
  662.     if( !b && !Else )
  663.         return;
  664.     p = b ? Then : Else;
  665.     p->Calculate();
  666.     if( p->flags )
  667.         flags = p->flags;
  668. }
  669.  
  670. XBlock::XBlock()
  671. {
  672.     v = new CNil;
  673. }
  674.  
  675. void XBlock::print( ostream& o ) const
  676. {
  677.     LexObj *p;
  678.     Space( o );
  679.     o << "BEGIN" << endl;
  680.     for( p = structs.FirstInList; p; p = p->NextInList )
  681.     {
  682.         LexStruct *lex =  (LexStruct*)p;
  683.         Space( o );
  684.         o << "  STRUCT " << *lex << " " << *lex->data << ";" << endl;
  685.     }
  686.     for( p = vars.FirstInList; p; p = p->NextInList )
  687.     {
  688.         const char* s = ((LexVar*)p)->data->isConst ?
  689.             "CONST" : "VAR";
  690.         Space( o );
  691.         o << "  " << s << " " << *p << ";" << endl;
  692.     }
  693.     for( int i = 0; i < n; i++ )
  694.     {
  695.         if( !child[i] )
  696.             continue;
  697.         if( !child[i]->AutoSpace())
  698.             child[i]->Space( o );
  699.         o << *child[i] << ';' << endl;
  700.     }
  701.     Space( o );
  702.     o << "END";
  703. }
  704.  
  705. LexFunc::~LexFunc(){ delete data; }
  706. LexVar::~LexVar(){ delete data; }
  707. LexStruct::~LexStruct(){ delete data; }
  708.  
  709. const Expression* XBlock::LocateError( int mask ) const
  710. {
  711.     for( LexObj* p = funcs.FirstInList; p; p = p->NextInList )
  712.     {
  713.         const Expression *e = ((LexFunc*)p)->data->LocateError( mask );
  714.         if( e )
  715.             return e;
  716.     }
  717.     return Expression::LocateError( mask );
  718. }
  719.  
  720. void XBlock::Push()
  721. {
  722.     Expression::Push();
  723.     ListIdx i( vars );
  724.     for( ; i; i++ )
  725.     {
  726.         Var *v = ((LexVar*)(i.obj))->data;
  727.         RecStack.Push( v->v );
  728.         //v->v = v->v ? v->v->copy() : 0;
  729.         v->v = 0;
  730.     }
  731. }
  732.  
  733. void XBlock::Pop()
  734. {
  735.     ListIdx i( vars, 0 );
  736.     for( ; i; i-- )
  737.     {
  738.         Var *v = ((LexVar*)(i.obj))->data;
  739.         delete v->v;
  740.         v->v = RecStack.Pop();
  741.     }
  742.     Expression::Pop();
  743. }
  744.  
  745. void XLoop::Calc()
  746. {
  747.     if( !v )
  748.         v = new CBool( 1 );
  749.     flags = exLoop;
  750. }
  751.  
  752. void XBreak::Calc()
  753. {
  754.     if( !v )
  755.         v = new CBool( 1 );
  756.     flags = exExit;
  757. }
  758.  
  759. XWhile::XWhile( Expression* e, Expression *p, Expression *s ) :
  760.     Cond( e ), Action( p ), Step( s )
  761. {
  762.     Descendor( Cond );
  763.     Descendor( Action );
  764.     Descendor( Step );
  765. }
  766.  
  767. #define LCHECK(x) if(x){ flags = exError; return; }
  768. void XWhile::Calc()
  769. {
  770.     LCHECK( !Cond );
  771.     while( 1 )
  772.     {
  773.         Cond->Calculate();
  774.         LCHECK( !Cond->v || (Cond->flags & exError ));
  775.         flags = 0;
  776.         COPY_VALUE( v, Cond->v );
  777.         LCHECK( v->TYPEID!=idBool )
  778.         if( !(*(CBool*)v))
  779.             break;
  780.         Action->Calculate();
  781.         LCHECK( Action->flags & exError );
  782.         if( flags & exExit ){ flags = 0; return; }
  783.         if( flags & exDone ) return;
  784.         if( !Step )
  785.             continue;
  786.         Step->Calculate();
  787.         LCHECK( Step->flags & exError );
  788.     }
  789. }
  790.  
  791. XFunction::XFunction( int proc, const char* s ) :
  792.     name( 0 ), isProc( proc ), busy( 0 )
  793. {
  794.     SetName( s );
  795. }
  796.  
  797. void XFunction::SetName( const char* s )
  798. {
  799.     if( !s )
  800.         return;
  801.     delete[] name;
  802.     name = new char[ strlen(s)+1 ];
  803.     strcpy( name, s );
  804. }
  805.  
  806. void XFunction::print( ostream& o ) const
  807. {
  808.     o << (isProc ? "PROCEDURE ":"FUNCTION ") << name;
  809.     if( !child )
  810.         return;
  811.     o << "(";
  812.     for( LexObj* p = vars.FirstInList; p; p = p->NextInList )
  813.     {
  814.         o << *p;
  815.         if( p->NextInList )
  816.             o << ",";
  817.     }
  818.     o << ")" << endl;
  819.     if( child[0] )
  820.         child[0]->print( o );
  821. }
  822.  
  823. void XFunction::AddLocal( const char* s, int token )
  824. {
  825.     Var *v = new Var( s );
  826.     vars.Add( new LexVar( s, v, token ));
  827. }
  828.  
  829. void XCall::print( ostream& o ) const
  830. {
  831.     o << Func->name << "(";
  832.     for( int i = 0; i < n; i++ )
  833.     {
  834.         if( !child[i] )
  835.             continue;
  836.         if( child[i]->xref() )
  837.             o << "*";
  838.         o << *child[i];
  839.         if( i!=n-1 )
  840.             o << ",";
  841.     }
  842.     o << ")";
  843. }
  844.  
  845. void XDynamic::print( ostream& o ) const
  846. {
  847.     o << "&(" << *Ptr << ")(";
  848.     for( int i = 0; i < n; i++ )
  849.     {
  850.         if( !child[i] )
  851.             continue;
  852.         if( child[i]->xref() )
  853.             o << "*";
  854.         o << *child[i];
  855.         if( i!=n-1 )
  856.             o << ",";
  857.     }
  858.     o << ")";
  859. }
  860.  
  861. void XReturn::print( ostream& o ) const
  862. {
  863.     o << "RETURN";
  864.     if( n )
  865.         o << " " << *child[0];
  866. }
  867.  
  868. void XReturn::Calc()
  869. {
  870.     flags = exDone;
  871.     if( !n && !v )
  872.         v = new CBool( 1 );
  873.     if( n )
  874.         COPY_VALUE( v, child[0]->v );
  875.     XFunction *f = xfunction();
  876.     if( !f )
  877.         return;
  878.     COPY_VALUE( f->v, v );
  879. }
  880.  
  881. void XReturn::Link()
  882. {
  883.     flags = 0;
  884.     XFunction *f = xfunction();
  885.     if( !f || f->isProc && n || !f->isProc && !n )
  886.         flags = exRet;
  887. }
  888.  
  889. void XCall::TieArgs( int before )
  890. {
  891.     int i = 0;
  892.     for( LexObj* p = Func->vars.FirstInList;
  893.         p && i<n; p = p->NextInList, i++ )
  894.     {
  895.         Var *var = ((LexVar*)p)->data;
  896.         int ref = child[i]->xref();
  897.         if( before )
  898.         {
  899.             if( !ref && child[i]->v->TYPEID!=idArray || ref < 0 )
  900.             {
  901.                 COPY_VALUE( var->v, child[i]->v );
  902.                 continue;
  903.             }
  904.             child[i]->xref( 1 );
  905.             delete var->v;
  906.             var->v = child[i]->v;
  907.         }
  908.         else
  909.         {
  910.             if( ref <= 0 )
  911.                 continue;
  912.             XVariable* x = (XVariable*)child[i];
  913.             *x->ptr = x->v = var->v;
  914.             var->v = 0;
  915.         }
  916.     }
  917.     if( !before )
  918.         COPY_VALUE( v, Func->v );
  919. }
  920.  
  921. void XCall::Calc()
  922. {
  923.     Expression* ffather = Func->father;
  924.     Func->father = this;
  925.     int fbusy = Func->busy;
  926.     Func->busy = 1;
  927.     if( fbusy )
  928.         Func->Recursion( &Expression::Push, 1, 0 );
  929.     else
  930.         TieArgs( 1 );
  931.     Func->Calculate();
  932.     if( fbusy )
  933.         Func->Recursion( &Expression::Pop, 0, 0 );
  934.     else
  935.         TieArgs( 0 );
  936.     Func->father = ffather;
  937.     Func->busy = fbusy;
  938.     flags &= ~exDone;
  939. }
  940.  
  941. void XFunction::Push()
  942. {
  943.     XBlock::Push();
  944.     if( father )
  945.         ((XCall*)father)->TieArgs( 1 );
  946. }
  947.  
  948. void XFunction::Pop()
  949. {
  950.     if( father )
  951.         ((XCall*)father)->TieArgs( 0 );
  952.     XBlock::Pop();
  953. }
  954.  
  955. void XCall::Link()
  956. {
  957.     if( loop( this ))
  958.         return;
  959.     Func->flags = 0;
  960.     if( !Func )
  961.         return;
  962.     if( !Func->Defined())
  963.     {
  964.         Func->flags = Func->flags | exLink;
  965.         return;
  966.     }
  967.     if( Func->vars.NumObj != n )
  968.         Func->flags = Func->flags | exArgs;
  969.     Func->Recursion( &Expression::Link );
  970. }
  971.  
  972. #define DYNEXIT(x,y) { cerr<<x<<y<<endl; flags = exError; return; }
  973. void XDynamic::Calc()
  974. {
  975.     Ptr->Calculate();
  976.     if( Ptr->flags )
  977.         return;
  978.     if( Ptr->v->TYPEID!=idString )
  979.         DYNEXIT("string expression expected: ", (*Ptr));
  980.     LexObj *o = (*Table)( Ptr->v->s());
  981.     if( !o )
  982.         DYNEXIT("function not found ", (*Ptr->v));
  983.     Func = ((LexFunc*)o)->data;
  984.     Func->flags = 0;
  985.     Link();
  986.     Func->flags &= ~exDone;
  987.     if( Func->flags )
  988.         DYNEXIT("error in calling ", (*Ptr->v));
  989.     XCall::Calc();
  990. }
  991.  
  992. const Expression* XCall::LocateError( int mask ) const
  993. {
  994.     const Expression *e = Expression::LocateError( mask );
  995.     if( e && e!= this )
  996.         return e;
  997.     return Func->LocateError( mask );
  998. }
  999.  
  1000. void XSet::Calc()
  1001. {
  1002.     if( v )
  1003.     {
  1004.         CArray* a = (CArray*)v;
  1005.         if( a->n==n )
  1006.         {
  1007.             for( int i = 0; i < n; i++ )
  1008.                 COPY_VALUE( a->array[i], child[i]->v );
  1009.             return;
  1010.         }
  1011.     }
  1012.     delete v;
  1013.     CArray *a = new CArray;
  1014.     v = a;
  1015.     for( int i = 0; i < n; i++ )
  1016.         a->add( child[i]->v->copy());
  1017. }
  1018.  
  1019. XSet::Contains( CType* t ) const
  1020. {
  1021.     for( int i = 0; i < n; i++ )
  1022.         if( !t->compare( *child[i]->v ))
  1023.             return 1;
  1024.     return 0;
  1025. }
  1026.  
  1027. void XSet::print( ostream& o ) const
  1028. {
  1029.     o << "{";
  1030.     for( int i = 0; i < n; i++ )
  1031.     {
  1032.         o << *child[i];
  1033.         if( i!=n-1 )
  1034.             o << ",";
  1035.     }
  1036.     o << "}";
  1037. }
  1038.  
  1039. LexList         XUserFunction::funcs;
  1040. int             XUserFunction::Argc;
  1041. const char**    XUserFunction::Argv;
  1042.  
  1043. XUserFunction::XUserFunction( const char* name, DefFunction f,
  1044.     int order, int proc ) : XFunction( proc, name ), Func( f )
  1045. {
  1046.     for( int i = 0; i < order; i++ )
  1047.         AddLocal( CLong( i ).s(), 0 );
  1048. }
  1049.  
  1050. void XUserFunction::Calc()
  1051. {
  1052.     if( (*Func)( this ))
  1053.         flags = exError;
  1054.     if( !v )
  1055.         v = new CBool( 1 );
  1056. }
  1057.  
  1058. XUserFunction::CheckArgs( int t... ) const
  1059. {
  1060.     va_list l;
  1061.     va_start( l, t );
  1062.     int v = t;
  1063.     for( LexObj *o = vars.FirstInList; o; o = o->NextInList )
  1064.     {
  1065.         Var *var = ((LexVar*)o)->data;
  1066.         if( !var || !var->v ||
  1067.             v>=0 && var->v->TYPEID!=v )
  1068.                 return 1;
  1069.         v = va_arg( l, int );
  1070.     }
  1071.     va_end( l );
  1072.     return 0;
  1073. }
  1074.  
  1075. CType* XUserFunction::Arg( int i ) const
  1076. {
  1077.     LexObj *o;
  1078.     for( o = vars.FirstInList;
  1079.         o && i; o = o->NextInList )
  1080.             i--;
  1081.     if( !o || i )
  1082.         return 0;
  1083.     return ((LexVar*)o)->data->v;
  1084. }
  1085.  
  1086. void RegFunc( const char* name, DefFunction p, int order, int proc )
  1087. {
  1088.     XFunction *f = new XUserFunction( name, p, order, proc );
  1089.     XUserFunction::funcs.Add( new LexFunc(
  1090.         f->name, f, YLex::TokenProc( f->isProc )));
  1091. }
  1092.  
  1093. void RegProc( const char* name, DefFunction p, int order )
  1094. {
  1095.     RegFunc( name, p, order, 1 );
  1096. }
  1097.