home *** CD-ROM | disk | FTP | other *** search
- /*******************************************************
-
- The CalcPlus Class Library Version 1.0,
- Author: Vladimir Schipunov, Copyright (C) 1996
-
- This library is free software. Permission to use,
- copy, modify and redistribute the CalcPlus library
- for any purpose is hereby granted without fee,
- provided that the above copyright notice appear
- in all copies.
-
- *******************************************************/
-
- #include <iostream.h>
- #include <string.h>
- #include <stdarg.h>
- #include "calcexpr.h"
- #include "calctype.h"
-
- //
- // The definitions below are intended to decrease dynamic
- // memory allocation for the slight speed optimization.
- // This is the same as:
- //
- // #define COPY_VALUE(v,x) { delete v; v = x ? x->copy() : 0; }
- //
-
- #define TYPEID id
- #define VCLEAR( v, x ) { delete v; v = ((x)?(x)->copy():0); break; }
- #define COPY_ID(v,x,t,q) if(t==id##q){((C##q*)v)->n=((C##q*)x)->n;break;}
- #define COPY_VALUE( v, x ) \
- while( x ) \
- { \
- if( !v ) \
- VCLEAR(v,x); \
- int t = (v)->TYPEID; \
- if( t != (x)->TYPEID) \
- VCLEAR(v,x); \
- COPY_ID(v,x,t,Long) \
- COPY_ID(v,x,t,Bool) \
- COPY_ID(v,x,t,Double) \
- if(t==idNil)break; \
- if( (v)->size() != \
- (x)->size() ) \
- VCLEAR(v,x); \
- *(v) = *(x); \
- break; \
- }
- /*
- #undef COPY_VALUE
- #define COPY_VALUE( v, x )\
- { delete v; v = x ? x->copy() : 0; }
- */
-
- int Expression::Debug;
-
- Expression::Expression( int order, Expression *p... ) :
- n( order ), v( 0 ), flags( 0 )
- {
- child = n ? new Expression*[order] : 0;
- father = 0;
- va_list l;
- va_start( l, p );
- Expression *e = p;
- for( int i = 0; i < n; i++ )
- {
- child[i] = e;
- child[i]->father = this;
- e = va_arg( l, Expression* );
- }
- va_end( l );
- }
-
- Expression::Expression( int order ) :
- n( order ), v( 0 ), flags( 0 )
- {
- child = n ? new Expression*[order] : 0;
- father = 0;
- for( int i = 0; i < n; i++ )
- child[i] = 0;
- }
-
- Expression::~Expression()
- {
- delete v;
- for( int i = 0; i < n; i++ )
- delete child[i];
- delete[] child;
- }
-
- void Expression::Calc()
- {
- if( !v )
- v = new CNil;
- }
-
- Expression::CheckType( int t... )
- {
- va_list l;
- va_start( l, t );
- int v = t;
- for( int i = 0; i < n; i++ )
- {
- Expression *&e = child[i];
- if( !e || !e->v || e->v->TYPEID!=v )
- return 0;
- v = va_arg( l, int );
- }
- va_end( l );
- return 1;
- }
-
- Expression::precedence( const Expression &e ) const
- {
- return op() > e.op() ||
- op() == e.op() && range() > e.range();
- }
-
- void Expression::print( ostream &s ) const
- {
- if( (flags & exError) || !v )
- s << "ERROR";
- else
- s << *v;
- }
-
- void Expression::printx( ostream &s, Expression *e ) const
- {
- int p = precedence(*e);
- if ( p ) s << '(';
- s << *e;
- if ( p ) s << ')';
- }
-
- #define REC_STACK 0x1FFF
- void PtrStack::Push( CType* t )
- {
- if( !stack )
- stack = new CType*[ REC_STACK ];
- if( i>=REC_STACK )
- {
- cerr << "Recursion stack overflow!" << endl;
- return;
- }
- stack[i++] = t;
- }
-
- CType* PtrStack::Pop()
- {
- if( --i < 0 )
- {
- cerr << "Recursion stack underflow!" << endl;
- return 0;
- }
- return stack[i];
- }
-
- void Expression::RecDebug()
- {
- cout << *this << endl << "/// ";
- Expression::print( cout );
- cout << endl;
- }
-
- PtrStack RecStack;
- void Expression::Push()
- {
- RecStack.Push( v );
- v = 0;
- }
-
- void Expression::Pop()
- {
- delete v;
- v = RecStack.Pop();
- flags = 0;
- }
-
- Expression::loop( Expression *x ) const
- {
- if( this == x )
- return 1;
- return father ? father->loop( x ) : 0;
- }
-
- #define SPACE(s) e->Space( cout );\
- if( !e->AutoSpace()) cout << s;\
- else cout << s << endl;\
- cout << *e << endl;
-
- static void Before( Expression* e )
- {
- SPACE("-> ");
- }
-
- static void After( Expression* e )
- {
- SPACE("<- ");
- e->Space( cout );
- cout << " = ";
- static CString end("\n");
- if( e->v && e->v->TYPEID==idString &&
- !e->v->compare( end ))
- cout << "ENDL";
- else
- e->Expression::print( cout );
- cout << endl;
- }
-
- void Expression::Calculate()
- {
- flags = 0;
- for( int i = 0; i < n && !flags; i++ )
- {
- Expression *e = child[i];
- if( Debug )
- {
- Before( e );
- e->Expression::Calculate();
- After( e );
- }
- else
- e->Calculate();
- if( e->flags )
- flags = e->flags;
- }
- if( flags )
- {
- if( father )
- father->flags =
- father->flags | flags;
- return;
- }
- Calc();
- }
-
- void Expression::Iterate()
- {
- static Expression **stack[512];
- static i;
- Expression *p = this;
- int sav = i;
- while( 1 )
- {
- while( p->n )
- p = *( stack[i++] = p->child );
- p->flags = 0; p->Calc();
- if( p->flags ){ flags = p->flags; i = sav; return; }
- if( i==sav )
- return;
- while( 1 )
- {
- if( p->father->n > stack[i-1] -
- p->father->child + 1 )
- {
- p = *(++stack[i-1]);
- break;
- }
- p = p->father;
- p->flags = 0; p->Calc();
- if( p->flags ){ flags = p->flags; i = sav; return; }
- if( --i==sav )
- return;
- }
- }
- }
-
- const Expression* Expression::LocateError( int mask ) const
- {
- if( !(flags & mask))
- return 0;
- for( int i = 0; i < n; i++ )
- if( child[i] && (child[i]->flags & mask))
- return child[i]->LocateError( mask );
- return this;
- }
-
- Expression* Expression::Add( Expression* e )
- {
- Expression** p = new Expression*[n+1];
- for( int i = 0; i < n; i++ )
- p[i] = child[i];
- p[n++] = e;
- e->father = this;
- delete[] child;
- child = p;
- return this;
- }
-
- void Expression::Space( ostream& o ) const
- {
- int n = Depth();
- if( !father )
- n--;
- for( int i = 0; i < n; i++ )
- o << " ";
- }
-
- void Expression::RecStep( ExprF f, int check )
- {
- if( !check || !flags )
- (this->*f)();
- if( check && flags && father )
- father->flags = father->flags | flags;
- }
-
- void Expression::Recursion(
- ExprF f, int direction, int check )
- {
- if( direction )
- {
- RecStep( f, check );
- for( int i = n-1; i>=0 && ( !check || !flags ); i-- )
- if( child[i] )
- child[i]->Recursion( f, direction, check );
- }
- else
- {
- for( int i = 0; i<n && ( !check || !flags ); i++ )
- if( child[i] )
- child[i]->Recursion( f, direction, check );
- RecStep( f, check );
- }
- }
-
- void XImmediate::print( ostream& o ) const
- {
- if( v->TYPEID!=idString )
- {
- Expression::print( o );
- return;
- }
- o << "'";
- Expression::print( o );
- o << "'";
- }
-
- XEndl::XEndl() : XImmediate( new CString("\n")){}
- void XEndl::print( ostream& o ) const { o << "ENDL"; }
- void XBreak::print( ostream& o ) const { o << "EXIT"; }
-
- void XAr1::print( ostream &o ) const
- {
- o << sign;
- printx( o, child[0]);
- }
-
- void XAr2::print( ostream &o ) const
- {
- printx( o, child[0]);
- if( sign == '}' ) o << ">=";
- else if( sign == '{' ) o << "<=";
- else if( sign == '~' ) o << "!=";
- else if( sign == 'i' ) o << "->";
- else if( sign == '&' ) o << " AND ";
- else if( sign == '|' ) o << " OR ";
- else o << sign;
- printx( o, child[1]);
- }
-
- #define AR1(type) \
- if( id==id##type ) \
- { ((C##type*)v)->n = -((C##type*)(e->v))->n; return; }
-
- void XAr1::Calc()
- {
- Expression *e = child[0];
- int id = e->v->TYPEID;
- if( v->TYPEID != id )
- {
- delete v;
- v = e->v->copy();
- }
- AR1( Long );
- AR1( Double );
- cerr << SyntaxError("Wrong type for unary "
- "arithmetic operation: ",v->name()) << endl;
- flags = exError;
- }
-
- #define A2START \
- Expression *c1 = child[0], *c2 = child[1];\
- int id = v ? v->TYPEID : -1 ;\
- int id1 = /*c1->v ?*/ c1->v->TYPEID /*: -1*/;\
- int id2 = /*c2->v ?*/ c2->v->TYPEID /*: -1*/;
-
- //if( id1==i1 && id2==i2 )
- #define A2(t1,i1,t2,i2,t,i,r)\
- case( i1*0x10+i2 ): \
- { \
- t1& v1 = (t1&)(*c1->v); \
- t2& v2 = (t2&)(*c2->v); \
- if( id!=i ) \
- { delete v; v = new t; } \
- t& t0 = (t&)(*v); \
- switch( sign ){ \
- case '+': t0.n = v1.n + v2.n ; return;\
- case '-': t0.n = v1.n - v2.n ; return;\
- case '*': t0.n = v1.n * v2.n ; return;\
- case '/': t0.n = v1.n / v2.n ; return;}\
- return;\
- }
-
- #define C2(t1,i1,t2,i2,t,i,r)\
- case( i1*0x10+i2 ): \
- { \
- t1& v1 = (t1&)(*c1->v); \
- t2& v2 = (t2&)(*c2->v); \
- if( id!=i ) \
- { delete v; v = new t; } \
- t& t0 = (t&)(*v); \
- switch( sign ){ \
- case '<': t0.n = v1.n < v2.n ; return;\
- case '>': t0.n = v1.n > v2.n ; return;\
- case '}': t0.n = v1.n >= v2.n ; return;\
- case '{': t0.n = v1.n <= v2.n ; return;\
- case '=': t0.n = v1.n == v2.n ; return;\
- case '~': t0.n = v1.n != v2.n ; return;}\
- return;\
- }
-
- void XAr2::Calc()
- {
- A2START;
- switch( id1*0x10+id2 ){
- A2( CLong, idLong, CLong, idLong, CLong, idLong, long )
- A2( CDouble, idDouble, CDouble, idDouble, CDouble, idDouble, double )
- A2( CLong, idLong, CDouble, idDouble, CDouble, idDouble, double )
- A2( CDouble, idDouble, CLong, idLong, CDouble, idDouble, double )}
- CType* t1 = child[0]->v;
- CType* t2 = child[1]->v;
- if( sign!='+' || id1!=idString || id2!=idString )
- {
- cerr << SyntaxError("Wrong types for binary "
- "arithmetic operation!") << endl;
- flags = exError;
- return;
- }
- unsigned n = t1->size()+t2->size();
- delete v;
- v = new CString( n+1 );
- t1->s( (char*)v->ptr() );
- t2->s( (char*)v->ptr()+t1->size());
- }
-
- void XComparison::Calc()
- {
- A2START;
- switch( id1*0x10+id2 ){
- C2( CLong, idLong, CLong, idLong, CBool, idBool, long )
- C2( CDouble, idDouble, CDouble, idDouble, CBool, idBool, double )
- C2( CLong, idLong, CDouble, idDouble, CBool, idBool, double )
- C2( CDouble, idDouble, CLong, idLong, CBool, idBool, double )}
- if( !v )
- v = new CBool;
- if( sign=='=' && id1==idString && id2==idString )
- {
- CBool& b = (CBool&)(*v);
- b = !child[0]->v->compare( *child[1]->v );
- return;
- }
- if( sign=='~' && id1==idString && id2==idString )
- {
- CBool& b = (CBool&)(*v);
- b = child[0]->v->compare( *child[1]->v );
- return;
- }
- cerr << SyntaxError("ìÑóÑα¡δÑ Γ¿»δ ñ½∩ «»Ñαᵿ¿ ßαáó¡Ñ¡¿∩!") << endl;
- flags = exError;
- }
-
- void XBool1::Calc()
- {
- if( child[0]->v->TYPEID != idBool )
- {
- cerr << SyntaxError("Wrong type for boolean operation: ",
- child[0]->v->name()) << endl;
- flags = exError;
- return;
- }
- if( !v || v->TYPEID!=idBool )
- {
- delete v;
- v = new CBool;
- }
- ((CBool*)v)->n = ((CBool*)(child[0]->v))->n ? 0 : 1;
- }
-
- void XBool2::Calc()
- {
- if( child[0]->v->TYPEID != idBool ||
- child[1]->v->TYPEID != idBool )
- {
- cerr << SyntaxError("Wrong types for boolean operations!") << endl;
- flags = exError;
- return;
- }
- CBool& b1 = (CBool&)(*child[0]->v);
- CBool& b2 = (CBool&)(*child[1]->v);
- int n1 = b1 ? 1 : 0;
- int n2 = b2 ? 1 : 0;
- int k = sign=='&' ? (n1 && n2) :
- sign=='|' ? (n1 || n2) :
- sign=='=' ? (n1 == n2) :
- sign=='~' ? (n1 != n2) : 0;
- if( !v || v->TYPEID!=idBool )
- {
- delete v;
- v = new CBool;
- }
- CBool& b = (CBool&)(*v);
- b = k ? 1 : 0;
- }
-
- Var::Var( const char* s, int c ) :
- v( new CNil ), isConst( c )
- {
- name = new char[ strlen(s)+1 ];
- strcpy( name, s );
- }
-
- Var::~Var()
- {
- delete[] name;
- delete v;
- }
-
- void Var::print( ostream& o ) const
- {
- o << name;
- }
-
- void XVariable::Push(){ Expression::Push(); v = 0; }
- void XVariable::Pop(){ v = 0; Expression::Pop(); }
-
- void XVariable::print( ostream& o ) const
- {
- o << *obj;
- if( !n )
- return;
- if( n==2 )
- o << "[" << *child[1] << "]";
- if( n%2 )
- o << ":=" << *child[n-1];
- }
-
- void XVariable::Calc()
- {
- if( !n )
- {
- v = *ptr;
- return;
- }
- if( n==1 )
- {
- v = *ptr;
- COPY_VALUE( v, child[0]->v );
- *ptr = v;
- return;
- }
- CType *x = child[1]->v;
- int t = x->TYPEID;
- if( t!=idLong && t!=idString )
- {
- cerr << "Wrong type in array access: " << x->name() << endl;
- flags = exError;
- return;
- }
- CType *w = child[0]->v;
- if( w->TYPEID!=idArray )
- {
- cerr << *w << " is not array!" << endl;
- flags = exError;
- return;
- }
- CArray *a = (CArray*)w;
- long n = 0;
- if( t==idLong ) n = *(CLong*)x;
- if( t==idString ) n = a->index(x->s());
- if( n < 0 || n >= a->n )
- {
- cerr << *w << ": out of array!" << endl;
- flags = exError;
- return;
- }
- v = a->array[ (int)n ];
- if( XVariable::n<3 )
- return;
- COPY_VALUE( v, child[2]->v );
- a->array[ (int)n ] = v;
- }
-
- void XEcho::Calc()
- {
- if( !v )
- v = new CNil;
- for( int i = 0; i < n; i++ )
- cout << *child[i]->v;
- }
-
- void XEcho::print( ostream& o ) const
- {
- o << "ECHO ";
- for( int i = 0; i < n; i++ )
- {
- Expression *e = child[i];
- if( e )
- o << *e;
- if( i!=n-1 )
- o << ",";
- }
- }
-
- void XConditional::print( ostream& o ) const
- {
- Space( o );
- o << "IF " << *child[0] << " THEN" << endl;
- if( !Then->AutoSpace())
- Then->Space( o );
- o << *Then << ";" << endl;
- if( Else )
- {
- Space( o );
- o << "ELSE" << endl;
- if( !Else->AutoSpace())
- Else->Space( o );
- o << *Else << ";" << endl;
- }
- Space( o );
- o << "END";
- }
-
- void XLoop::print( ostream& o ) const
- {
- o << "LOOP";
- }
-
- void XWhile::print( ostream& o ) const
- {
- Space( o );
- if( !Step )
- o << "WHILE " << *Cond;
- else
- o << "FOR " << *(((XVariable*)Step)->obj) << " CYCLE"
- << " TO " << *Cond->child[1] << " STEP "
- << *(((XVariable*)Step)->child[0]->child[1]);
- o << " DO" << endl << *Action << ";" << endl;
- Space( o );
- o << "END";
- }
-
- void XConditional::Calc()
- {
- Expression *p = child[0];
- if( !p || !p->v || p->v->TYPEID!=idBool )
- {
- flags = exError;
- return;
- }
- COPY_VALUE( v, p->v );
- CBool& b = (CBool&)(*p->v);
- if( !b && !Else )
- return;
- p = b ? Then : Else;
- p->Calculate();
- if( p->flags )
- flags = p->flags;
- }
-
- XBlock::XBlock()
- {
- v = new CNil;
- }
-
- void XBlock::print( ostream& o ) const
- {
- LexObj *p;
- Space( o );
- o << "BEGIN" << endl;
- for( p = structs.FirstInList; p; p = p->NextInList )
- {
- LexStruct *lex = (LexStruct*)p;
- Space( o );
- o << " STRUCT " << *lex << " " << *lex->data << ";" << endl;
- }
- for( p = vars.FirstInList; p; p = p->NextInList )
- {
- const char* s = ((LexVar*)p)->data->isConst ?
- "CONST" : "VAR";
- Space( o );
- o << " " << s << " " << *p << ";" << endl;
- }
- for( int i = 0; i < n; i++ )
- {
- if( !child[i] )
- continue;
- if( !child[i]->AutoSpace())
- child[i]->Space( o );
- o << *child[i] << ';' << endl;
- }
- Space( o );
- o << "END";
- }
-
- LexFunc::~LexFunc(){ delete data; }
- LexVar::~LexVar(){ delete data; }
- LexStruct::~LexStruct(){ delete data; }
-
- const Expression* XBlock::LocateError( int mask ) const
- {
- for( LexObj* p = funcs.FirstInList; p; p = p->NextInList )
- {
- const Expression *e = ((LexFunc*)p)->data->LocateError( mask );
- if( e )
- return e;
- }
- return Expression::LocateError( mask );
- }
-
- void XBlock::Push()
- {
- Expression::Push();
- ListIdx i( vars );
- for( ; i; i++ )
- {
- Var *v = ((LexVar*)(i.obj))->data;
- RecStack.Push( v->v );
- //v->v = v->v ? v->v->copy() : 0;
- v->v = 0;
- }
- }
-
- void XBlock::Pop()
- {
- ListIdx i( vars, 0 );
- for( ; i; i-- )
- {
- Var *v = ((LexVar*)(i.obj))->data;
- delete v->v;
- v->v = RecStack.Pop();
- }
- Expression::Pop();
- }
-
- void XLoop::Calc()
- {
- if( !v )
- v = new CBool( 1 );
- flags = exLoop;
- }
-
- void XBreak::Calc()
- {
- if( !v )
- v = new CBool( 1 );
- flags = exExit;
- }
-
- XWhile::XWhile( Expression* e, Expression *p, Expression *s ) :
- Cond( e ), Action( p ), Step( s )
- {
- Descendor( Cond );
- Descendor( Action );
- Descendor( Step );
- }
-
- #define LCHECK(x) if(x){ flags = exError; return; }
- void XWhile::Calc()
- {
- LCHECK( !Cond );
- while( 1 )
- {
- Cond->Calculate();
- LCHECK( !Cond->v || (Cond->flags & exError ));
- flags = 0;
- COPY_VALUE( v, Cond->v );
- LCHECK( v->TYPEID!=idBool )
- if( !(*(CBool*)v))
- break;
- Action->Calculate();
- LCHECK( Action->flags & exError );
- if( flags & exExit ){ flags = 0; return; }
- if( flags & exDone ) return;
- if( !Step )
- continue;
- Step->Calculate();
- LCHECK( Step->flags & exError );
- }
- }
-
- XFunction::XFunction( int proc, const char* s ) :
- name( 0 ), isProc( proc ), busy( 0 )
- {
- SetName( s );
- }
-
- void XFunction::SetName( const char* s )
- {
- if( !s )
- return;
- delete[] name;
- name = new char[ strlen(s)+1 ];
- strcpy( name, s );
- }
-
- void XFunction::print( ostream& o ) const
- {
- o << (isProc ? "PROCEDURE ":"FUNCTION ") << name;
- if( !child )
- return;
- o << "(";
- for( LexObj* p = vars.FirstInList; p; p = p->NextInList )
- {
- o << *p;
- if( p->NextInList )
- o << ",";
- }
- o << ")" << endl;
- if( child[0] )
- child[0]->print( o );
- }
-
- void XFunction::AddLocal( const char* s, int token )
- {
- Var *v = new Var( s );
- vars.Add( new LexVar( s, v, token ));
- }
-
- void XCall::print( ostream& o ) const
- {
- o << Func->name << "(";
- for( int i = 0; i < n; i++ )
- {
- if( !child[i] )
- continue;
- if( child[i]->xref() )
- o << "*";
- o << *child[i];
- if( i!=n-1 )
- o << ",";
- }
- o << ")";
- }
-
- void XDynamic::print( ostream& o ) const
- {
- o << "&(" << *Ptr << ")(";
- for( int i = 0; i < n; i++ )
- {
- if( !child[i] )
- continue;
- if( child[i]->xref() )
- o << "*";
- o << *child[i];
- if( i!=n-1 )
- o << ",";
- }
- o << ")";
- }
-
- void XReturn::print( ostream& o ) const
- {
- o << "RETURN";
- if( n )
- o << " " << *child[0];
- }
-
- void XReturn::Calc()
- {
- flags = exDone;
- if( !n && !v )
- v = new CBool( 1 );
- if( n )
- COPY_VALUE( v, child[0]->v );
- XFunction *f = xfunction();
- if( !f )
- return;
- COPY_VALUE( f->v, v );
- }
-
- void XReturn::Link()
- {
- flags = 0;
- XFunction *f = xfunction();
- if( !f || f->isProc && n || !f->isProc && !n )
- flags = exRet;
- }
-
- void XCall::TieArgs( int before )
- {
- int i = 0;
- for( LexObj* p = Func->vars.FirstInList;
- p && i<n; p = p->NextInList, i++ )
- {
- Var *var = ((LexVar*)p)->data;
- int ref = child[i]->xref();
- if( before )
- {
- if( !ref && child[i]->v->TYPEID!=idArray || ref < 0 )
- {
- COPY_VALUE( var->v, child[i]->v );
- continue;
- }
- child[i]->xref( 1 );
- delete var->v;
- var->v = child[i]->v;
- }
- else
- {
- if( ref <= 0 )
- continue;
- XVariable* x = (XVariable*)child[i];
- *x->ptr = x->v = var->v;
- var->v = 0;
- }
- }
- if( !before )
- COPY_VALUE( v, Func->v );
- }
-
- void XCall::Calc()
- {
- Expression* ffather = Func->father;
- Func->father = this;
- int fbusy = Func->busy;
- Func->busy = 1;
- if( fbusy )
- Func->Recursion( &Expression::Push, 1, 0 );
- else
- TieArgs( 1 );
- Func->Calculate();
- if( fbusy )
- Func->Recursion( &Expression::Pop, 0, 0 );
- else
- TieArgs( 0 );
- Func->father = ffather;
- Func->busy = fbusy;
- flags &= ~exDone;
- }
-
- void XFunction::Push()
- {
- XBlock::Push();
- if( father )
- ((XCall*)father)->TieArgs( 1 );
- }
-
- void XFunction::Pop()
- {
- if( father )
- ((XCall*)father)->TieArgs( 0 );
- XBlock::Pop();
- }
-
- void XCall::Link()
- {
- if( loop( this ))
- return;
- Func->flags = 0;
- if( !Func )
- return;
- if( !Func->Defined())
- {
- Func->flags = Func->flags | exLink;
- return;
- }
- if( Func->vars.NumObj != n )
- Func->flags = Func->flags | exArgs;
- Func->Recursion( &Expression::Link );
- }
-
- #define DYNEXIT(x,y) { cerr<<x<<y<<endl; flags = exError; return; }
- void XDynamic::Calc()
- {
- Ptr->Calculate();
- if( Ptr->flags )
- return;
- if( Ptr->v->TYPEID!=idString )
- DYNEXIT("string expression expected: ", (*Ptr));
- LexObj *o = (*Table)( Ptr->v->s());
- if( !o )
- DYNEXIT("function not found ", (*Ptr->v));
- Func = ((LexFunc*)o)->data;
- Func->flags = 0;
- Link();
- Func->flags &= ~exDone;
- if( Func->flags )
- DYNEXIT("error in calling ", (*Ptr->v));
- XCall::Calc();
- }
-
- const Expression* XCall::LocateError( int mask ) const
- {
- const Expression *e = Expression::LocateError( mask );
- if( e && e!= this )
- return e;
- return Func->LocateError( mask );
- }
-
- void XSet::Calc()
- {
- if( v )
- {
- CArray* a = (CArray*)v;
- if( a->n==n )
- {
- for( int i = 0; i < n; i++ )
- COPY_VALUE( a->array[i], child[i]->v );
- return;
- }
- }
- delete v;
- CArray *a = new CArray;
- v = a;
- for( int i = 0; i < n; i++ )
- a->add( child[i]->v->copy());
- }
-
- XSet::Contains( CType* t ) const
- {
- for( int i = 0; i < n; i++ )
- if( !t->compare( *child[i]->v ))
- return 1;
- return 0;
- }
-
- void XSet::print( ostream& o ) const
- {
- o << "{";
- for( int i = 0; i < n; i++ )
- {
- o << *child[i];
- if( i!=n-1 )
- o << ",";
- }
- o << "}";
- }
-
- LexList XUserFunction::funcs;
- int XUserFunction::Argc;
- const char** XUserFunction::Argv;
-
- XUserFunction::XUserFunction( const char* name, DefFunction f,
- int order, int proc ) : XFunction( proc, name ), Func( f )
- {
- for( int i = 0; i < order; i++ )
- AddLocal( CLong( i ).s(), 0 );
- }
-
- void XUserFunction::Calc()
- {
- if( (*Func)( this ))
- flags = exError;
- if( !v )
- v = new CBool( 1 );
- }
-
- XUserFunction::CheckArgs( int t... ) const
- {
- va_list l;
- va_start( l, t );
- int v = t;
- for( LexObj *o = vars.FirstInList; o; o = o->NextInList )
- {
- Var *var = ((LexVar*)o)->data;
- if( !var || !var->v ||
- v>=0 && var->v->TYPEID!=v )
- return 1;
- v = va_arg( l, int );
- }
- va_end( l );
- return 0;
- }
-
- CType* XUserFunction::Arg( int i ) const
- {
- LexObj *o;
- for( o = vars.FirstInList;
- o && i; o = o->NextInList )
- i--;
- if( !o || i )
- return 0;
- return ((LexVar*)o)->data->v;
- }
-
- void RegFunc( const char* name, DefFunction p, int order, int proc )
- {
- XFunction *f = new XUserFunction( name, p, order, proc );
- XUserFunction::funcs.Add( new LexFunc(
- f->name, f, YLex::TokenProc( f->isProc )));
- }
-
- void RegProc( const char* name, DefFunction p, int order )
- {
- RegFunc( name, p, order, 1 );
- }
-