/* ---- This file is part of SECONDO. Copyright (C) 2004, University in Hagen, Department of Computer Science, Database Systems for New Applications. SECONDO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SECONDO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with SECONDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---- //paragraph [1] Title: [{\Large \bf ] [}] //[->] [\ensuremath{\rightarrow}] [1] Secondo Standardalgebra Nov 1998. Friedhelm Becker. August 16, 2000. RHG Changed includes to show dependencies more clearly. March 2002. Ulrich Telle Port to C++ November 9, 2002. RHG Added operators ~randint~ and ~log~. Some other slight revisions. February 2004. F. Hoffmann added operators ~relcount~ and ~relcount2~. April 28, 2004. M. Spiekermann added operators ~nextint~ and ~randmax~. The calculation of random numbers in an specified range was revised according to the recommendations documented in the rand() manpage. July 08, 2004. M. Spiekermann changed the IN-function of data type ~real~. Integer atoms are now also accepted. November 2004. M. Spiekermann. Some small functions were moved to the header file in order to implement them as inline functions. November 2004. M. Spiekermann. Implementation of the operator ~substr~. Moreover, the add operator was overloaded once more in order to concatenate strings. December 2005, Victor Almeida deleted the deprecated algebra levels (~executable~, ~descriptive~, and ~hibrid~). Only the executable level remains. Models are also removed from type constructors. January 2006, M. Spiekermann new operator ~elapsedtime~ implemented. May 2006, M. Spiekermann new operator ~setoption~ implemented. May 11, 2006, M. Spiekermann. Most of the value mappings are replaced by template functions using the generic ~Compare~ function. This reduces the code a lot (about 400 lines of code) and there are still some functions left which may be replaced by template implementations. December 06, 2006 C. Duentgen added operators int2real, real2int, int2bool, bool2int, ceil, floor.7 May 2007, M. Spiekermann. New operator abs and introduction of generic type mappings. \begin{center} \footnotesize \tableofcontents \end{center} 1 Overview In this algebra the standard types and functions are defined. Standard types are ~int~, ~real~, ~bool~ and ~string~. These types are represented In Classes of C++ whith a boolean flag which shows whether this value is defined or not (e.g it could be undefined because it is the result of a divivion by zero). Following operators are defined: * + (add) ---- int x int --> int int x real --> real real x int --> real real x real --> real string x string --> string ---- * - (subtract) ---- int x int --> int int x real --> real real x int --> real real x real --> real ---- * [*] (multiply) ---- int x int --> int int x real --> real real x int --> real real x real --> real ---- * / (divide) ---- int x int --> real int x real --> real real x int --> real real x real --> real ---- * mod (remainder) ---- int x int --> int ---- * div (integer division) ---- int x int --> int ---- * randint * randmax ---- int -> int -> int ---- Computes a random integer within the range [0, arg-1]. The argument must be greater than 0. Otherwise it is set to 2. * seqinit * seqnext ---- int -> bool -> int ---- The seqinit operator can be used to create sequences of numbers starting by arg. The n-th call of seqnext will return arg+n-1 * log ---- int -> int ---- Computes the base 2 logarithm of the first argument (i.e., the integer part of it). * \verb+<+ , \verb+>+ , =, \verb+<=+ , \verb+>=+ , \# ---- int x int --> bool int x real --> bool real x int --> bool real x real --> bool bool x bool --> bool string x string --> bool ---- * starts, contains ---- string x string --> bool ---- * not ---- bool --> bool ---- * or, and ---- bool x bool --> bool ---- * int2real ---- int --> real ---- * real2int ---- real --> int ---- * int2bool ---- int --> bool ---- * bool2int ---- boot --> int ---- * ceil ---- real --> real ---- * floor ---- real --> real ---- 2 Includes In addition to the normal CC includes we have to include header files for QueryProcessor and Tuplemanager and the file which contains the definitions of our four classes: ~CcInt~, ~CcReal~, ~CcBool~, ~CcString~. */ #undef TRACE_ON #include "Trace.h" #include "Algebra.h" #include "NestedList.h" #include "QueryProcessor.h" #include "StandardTypes.h" #include "SecondoSystem.h" //operator queries #include "Counter.h" #include "StopWatch.h" #include "NList.h" #include "GenOps.h" #include "ListUtils.h" #include "AlmostEqual.h" #include "Progress.h" #include "Symbols.h" #include "Stream.h" #include #include #include #include #include "SecMath.h" #include #include #include #include #include //needed for random number generator #include "LongInt.h" #include "RationalAttr.h" extern NestedList* nl; extern QueryProcessor *qp; extern AlgebraManager *am; /* 4.1 Type investigation auxiliaries For a standard type T, its type name string is available using static class function const string T::BasicType(). For type mappings some auxiliary helper functions are defined in the file "TypeMapUtils.h" which defines a namespace mappings. */ #include "TypeMapUtils.h" #include "Symbols.h" using namespace std; using namespace mappings; /* 3 Type constructors A type constructor is created by defining an instance of class ~TypeConstructor~. Before this instance definition may take place we have to define some functions which are passed as constructor arguments during ~TypeConstructor~ instantiation. 3.1 Type constructor *CcInt* Each instance of below defined class CcInt will be the main memory representation of a value of type ~INT~. It consists of a boolean flag, ~defined~, and an integer value, ~intval~. ~defined~ may be used to indicate whether an instance of class CcInt represents a valid value or not. E.g., a division by zero might result in a CcInt object with ~defined~ set to false. Within this implementation, we don't use the flag but maintain it in order to demonstrate how to handle complex objects. */ long CcInt::intsCreated = 0; long CcInt::intsDeleted = 0; /* The next function defines the type property of type constructor ~CcInt~. */ ListExpr CcIntProperty() { return (nl->TwoElemList( nl->FourElemList(nl->StringAtom("Signature"), nl->StringAtom("Example Type List"), nl->StringAtom("List Rep"), nl->StringAtom("Example List")), nl->FourElemList(nl->StringAtom("-> DATA"), nl->StringAtom(CcInt::BasicType()), nl->StringAtom("()"), nl->StringAtom("12 or -32 or 0")))); } /* Now we define a function, ~OutInt~, that takes as inputs a type description and a pointer to a value of this type. The representation of this value in nested list format is returned. For the simple types int, real, string, bool we don't use the type description at all. We will need it in the case of more complex type constructors, e.g. to be able to compute the nested list representation of a tuple value we must know the types of the respective attribute values. */ ListExpr OutCcInt( ListExpr typeinfo, Word value ) { if( ((CcInt*)value.addr)->IsDefined() ) { return (nl->IntAtom( ((CcInt*)value.addr)->GetIntval() )); } else { return (nl->SymbolAtom(Symbol::UNDEFINED())); } } /* The function ~InInt~ provides a functionality complementary to ~OutInt~: A pointer to a value's main memory representation is returned. It is calculated by taking the value's nested list representation and its type description as input parameters. */ Word InCcInt( ListExpr typeInfo, ListExpr value, int errorPos, ListExpr& errorInfo, bool& correct ) { if ( nl->IsAtom( value ) && nl->AtomType( value ) == IntType ) { correct = true; return (SetWord( new CcInt( true, nl->IntValue( value ) ) )); } else if ( nl->IsAtom( value ) && nl->AtomType( value ) == SymbolType && listutils::isSymbolUndefined(value) ) { correct = true; return (SetWord( new CcInt( false, 0) )); } else { correct = false; return (SetWord( Address( 0 ) )); } } /* */ ListExpr CcInt::Out(const ListExpr typeInfo, Word value) { return OutCcInt(typeInfo, value); } Word CcInt::In(ListExpr typeInfo, ListExpr value, int errorPos, ListExpr& errorInfo, bool& correct) { return InCcInt(typeInfo, value, errorPos, errorInfo, correct); } Word CreateCcInt( const ListExpr typeInfo ) { return (SetWord( new CcInt( false, 0 ) )); } void DeleteCcInt( const ListExpr typeInfo, Word& w ) { ((CcInt*) w.addr)->DeleteIfAllowed(); w.addr = 0; } void CloseCcInt( const ListExpr typeInfo, Word& w ) { ((CcInt*) w.addr)->DeleteIfAllowed(); w.addr = 0; } Word CloneCcInt( const ListExpr typeInfo, const Word& w ) { return SetWord( ((CcInt*)w.addr)->Clone() ); } int SizeOfCcInt() { return sizeof(CcInt); } /* 3.2.5 {\em Cast}-function of type constructor {\tt INT} */ void* CastInt( void* addr ) { return (new (addr) CcInt); } /* 3.2.6 {\em Type check} function of type constructor {\tt INT} */ bool CheckInt( ListExpr type, ListExpr& errorInfo ) { return (listutils::isSymbol( type, CcInt::BasicType() )); } /* A type constructor is created by constructing an instance of class ~TypeConstructor~. Constructor arguments are the type constructor's name and the four functions previously defined. */ TypeConstructor ccInt( CcInt::BasicType(), CcIntProperty, OutCcInt, InCcInt, 0, 0, CreateCcInt, DeleteCcInt, OpenAttribute, SaveAttribute, // object open and save CloseCcInt, CloneCcInt, CastInt, SizeOfCcInt, CheckInt ); /* 3.2 Type constructor *ccreal* The following type constructor, ~REAL~, is defined in the same way as ~INT~. */ long CcReal::realsCreated = 0; long CcReal::realsDeleted = 0; /* The next function defines the type property of type constructor ~CcReal~. */ ListExpr CcRealProperty() { return (nl->TwoElemList( nl->FourElemList(nl->StringAtom("Signature"), nl->StringAtom("Example Type List"), nl->StringAtom("List Rep"), nl->StringAtom("Example List")), nl->FourElemList(nl->StringAtom("-> DATA"), nl->StringAtom(CcReal::BasicType()), nl->StringAtom("()"), nl->StringAtom("12.0 or -1.342 or 14e-3 " "or .23")))); } ListExpr OutCcReal( ListExpr typeinfo, Word value ) { if( ((CcReal*)value.addr)->IsDefined() ) { return (nl->RealAtom( ((CcReal*)value.addr)->GetRealval() )); } else { return (nl->SymbolAtom(Symbol::UNDEFINED())); } } Word InCcReal( ListExpr typeInfo, ListExpr value, int errorPos, ListExpr& errorInfo, bool& correct ) { if(listutils::isSymbolUndefined(value)){ // undefined correct=true; return SetWord(new CcReal(false,0.0)); } if(listutils::isNumeric(value)){ correct=true; return SetWord(new CcReal(true, listutils::getNumValue(value))); } correct = false; return (SetWord( Address( 0 ) )); } Word CreateCcReal( const ListExpr typeInfo ) { return (SetWord( new CcReal( false, 0 ) )); } void DeleteCcReal( const ListExpr typeInfo, Word& w ) { ((CcReal*)w.addr)->DeleteIfAllowed(); w.addr = 0; } void CloseCcReal( const ListExpr typeInfo, Word& w ) { ((CcReal*)w.addr)->DeleteIfAllowed(); w.addr = 0; } Word CloneCcReal( const ListExpr typeInfo, const Word& w ) { return SetWord( ((CcReal*)w.addr)->Clone() ); } int SizeOfCcReal() { return sizeof(CcReal); } /* 3.3.6 {\em Cast}-function of type constructor {\tt REAL} */ void* CastReal( void* addr ) { return new (addr) CcReal; } /* 3.3.7 {\em Type check} function of type constructor {\tt REAL} */ bool CheckReal( ListExpr type, ListExpr& errorInfo ) { return (listutils::isSymbol( type, CcReal::BasicType() )); } TypeConstructor ccReal( CcReal::BasicType(), CcRealProperty, OutCcReal, InCcReal, 0, 0, CreateCcReal, DeleteCcReal, OpenAttribute, SaveAttribute, // object open and save CloseCcReal, CloneCcReal, CastReal, SizeOfCcReal, CheckReal ); /* 3.3 Type constructor *ccbool* Each instance of below defined class CcBool will be the main memory representation of a value of type ~BOOL~. It consists of a boolean flag, ~defined~, and an boolean value, ~boolval~. ~defined~ may be used to indicate whether an instance of class CcBool represents a valid value or not. E.g., a division by zero might result in a CcBool object with ~defined~ set to false. Within this implementation, we don't use the flag but maintain it in order to demonstrate how to handle complex objects. */ long CcBool::boolsCreated = 0; long CcBool::boolsDeleted = 0; /* The next function defines the type property of type constructor ~CcBool~. */ ListExpr CcBoolProperty() { return (nl->TwoElemList( nl->FourElemList(nl->StringAtom("Signature"), nl->StringAtom("Example Type List"), nl->StringAtom("List Rep"), nl->StringAtom("Example List")), nl->FourElemList(nl->StringAtom("-> DATA"), nl->StringAtom(CcBool::BasicType()), nl->StringAtom("()"), nl->StringAtom("TRUE or FALSE")))); } /* Now we define a function, ~OutBool~, that takes as inputs a type description and a pointer to a value of this type. The representation of this value in nested list format is returned. */ ListExpr OutCcBool( ListExpr typeinfo, Word value ) { if( ((CcBool*)value.addr)->IsDefined() ) { return (nl->BoolAtom( ((CcBool*)value.addr)->GetBoolval() )); } else { return (nl->SymbolAtom(Symbol::UNDEFINED())); } } /* The function ~InBool~ provides a functionality complementary to ~OutBool~: A pointer to a value's main memory representation is returned. It is calculated by taking the value's nested list representation and its type description as input parameters. Again, we don't need the type information in this example due to simplicity of types used. The next three parameters are used to return error information. */ Word InCcBool( ListExpr typeInfo, ListExpr value, int errorPos, ListExpr& errorInfo, bool& correct ) { if ( nl->IsAtom( value ) && nl->AtomType( value ) == BoolType ) { correct = true; return (SetWord( new CcBool( true, nl->BoolValue( value ) ) )); } else if ( nl->IsAtom( value ) && nl->AtomType( value ) == SymbolType && listutils::isSymbolUndefined(value) ) { correct = true; return (SetWord( new CcBool( false, false) )); } else { correct = false; return (SetWord( Address( 0 ) )); } } Word CreateCcBool( const ListExpr typeInfo ) { return (SetWord( new CcBool( false, 0 ) )); } void DeleteCcBool( const ListExpr typeInfo, Word& w ) { ((CcBool*)w.addr)->DeleteIfAllowed(); w.addr = 0; } void CloseCcBool( const ListExpr typeInfo, Word& w ) { ((CcBool*)w.addr)->DeleteIfAllowed(); w.addr = 0; } Word CloneCcBool( const ListExpr typeInfo, const Word& w ) { return SetWord( ((CcBool*)w.addr)->Clone() ); } int SizeOfCcBool() { return sizeof(CcBool); } /* 3.3.6 {\em Cast}-function of type constructor {\tt REAL} */ void* CastBool( void* addr ) { return (new (addr) CcBool); } /* 3.2.5 {\em Type check} function of type constructor {\tt REAL} */ bool CheckBool( ListExpr type, ListExpr& errorInfo ) { return (listutils::isSymbol( type, CcBool::BasicType() )); } TypeConstructor ccBool( CcBool::BasicType(), CcBoolProperty, OutCcBool, InCcBool, 0, 0, CreateCcBool, DeleteCcBool, OpenAttribute, SaveAttribute, // object open and save CloseCcBool, CloneCcBool, CastBool, SizeOfCcBool, CheckBool ); /* 3.5 Type constructor *CcString* */ long CcString::stringsCreated = 0; long CcString::stringsDeleted = 0; bool CcString::Adjacent( const Attribute* arg ) const { const STRING_T* a = GetStringval(); const STRING_T* b = ((CcString *)arg)->GetStringval(); if( strcmp( *a, *b ) == 0 ) return 1; if( strlen( *a ) == strlen( *b ) ) { if( strncmp( *a, *b, strlen( *a ) - 1 ) == 0 ) { char cha = (*a)[strlen(*a)-1], chb = (*b)[strlen(*b)-1]; return( cha == chb + 1 || chb == cha + 1 ); } } else if( strlen( *a ) == strlen( *b ) + 1 ) { return( strncmp( *a, *b, strlen( *b ) ) == 0 && ( (*a)[strlen(*a)-1] == 'a' || (*a)[strlen(*a)-1] == 'A' ) ); } else if( strlen( *a ) + 1 == strlen( *b ) ) { return( strncmp( *a, *b, strlen( *a ) ) == 0 && ( (*b)[strlen(*b)-1] == 'a' || (*b)[strlen(*b)-1] == 'A' ) ); } return 0; } /* The next function defines the type property of type constructor ~CcString~. */ ListExpr CcStringProperty() { ListExpr examplelist = nl->TextAtom(); nl->AppendText(examplelist, "\"A piece of text up to 48 " "characters\""); return (nl->TwoElemList( nl->FourElemList(nl->StringAtom("Signature"), nl->StringAtom("Example Type List"), nl->StringAtom("List Rep"), nl->StringAtom("Example List")), nl->FourElemList(nl->StringAtom("-> DATA"), nl->StringAtom(CcString::BasicType()), nl->StringAtom("()"), examplelist))); } /* */ ListExpr OutCcString( ListExpr typeinfo, Word value ) { if( ((CcString*)value.addr)->IsDefined() ) { return (nl->StringAtom( *((CcString*)value.addr)->GetStringval() )); } else { return (nl->SymbolAtom(Symbol::UNDEFINED())); } } /* */ Word InCcString( ListExpr typeInfo, ListExpr value, int errorPos, ListExpr& errorInfo, bool& correct ) { if ( nl->IsAtom( value ) && nl->AtomType( value ) == StringType ) { correct = true; string s = nl->StringValue( value ); CcString* cs = new CcString( true, (STRING_T*)s.c_str() ); //cs->ShowMem(); return SetWord( cs ); } else if ( nl->IsAtom( value ) && nl->AtomType( value ) == SymbolType && listutils::isSymbolUndefined(value) ) { correct = true; return (SetWord( new CcString( false, (STRING_T*)"" ) )); } else { correct = false; return (SetWord( Address( 0 ) )); } } /* */ Word CreateCcString( const ListExpr typeInfo ) { char p[MAX_STRINGSIZE+1] = ""; return (SetWord( new CcString( false, (STRING_T*)&p ) )); } void DeleteCcString( const ListExpr typeInfo, Word& w ) { ((CcString*)w.addr)->DeleteIfAllowed(); w.addr = 0; } void CloseCcString( const ListExpr typeInfo, Word& w ) { ((CcString*)w.addr)->DeleteIfAllowed(); w.addr = 0; } Word CloneCcString( const ListExpr typeInfo, const Word& w ) { return SetWord( ((CcString*)w.addr)->Clone() ); } int SizeOfCcString() { return sizeof(CcString); } /* 3.3.6 {\em Cast}-function of type constructor {\tt REAL} */ void* CastString( void* addr ) { return (new (addr) CcString); } /* 3.2.5 {\em Type check} function of type constructor {\tt REAL} */ bool CheckString( ListExpr type, ListExpr& errorInfo ) { return (listutils::isSymbol( type, CcString::BasicType() )); } TypeConstructor ccString( CcString::BasicType(), CcStringProperty, OutCcString, InCcString, 0, 0, CreateCcString, DeleteCcString, OpenAttribute, SaveAttribute, // object open and save CloseCcString, CloneCcString, CastString, SizeOfCcString, CheckString ); GenTC longint; GenTC rational; /* 4 Operators Definition of operators is similar to definition of type constructors. An operator is defined by creating an instance of class ~Operator~. Again we have to define some functions before we are able to create an ~Operator~ instance. 4.2 Type Mapping A type mapping function takes a nested list as argument. Its contents are type descriptions of an operator's input parameters. A nested list describing the output type of the operator is returned. 4.2.1 Type mapping function CcMathTypeMap The function below is used for the operators +, - and [*]. For ~simple~ type mappings - those which map a list of atomic types to an atomic result type - a generic function called ~SimpleMap~ or ~SimpleMaps~ can be used. */ const string maps_arith[12][3] = { {CcInt::BasicType(), CcInt::BasicType(), CcInt::BasicType()}, {CcInt::BasicType(), CcReal::BasicType(), CcReal::BasicType()}, {CcReal::BasicType(), CcInt::BasicType(), CcReal::BasicType()}, {CcReal::BasicType(), CcReal::BasicType(), CcReal::BasicType()}, {LongInt::BasicType(), CcInt::BasicType(), LongInt::BasicType()}, {LongInt::BasicType(), LongInt::BasicType(), LongInt::BasicType()}, {CcInt::BasicType(), LongInt::BasicType(), LongInt::BasicType()}, {Rational::BasicType(), CcInt::BasicType(), Rational::BasicType()}, {Rational::BasicType(), LongInt::BasicType(), Rational::BasicType()}, {Rational::BasicType(), Rational::BasicType(), Rational::BasicType()}, {CcInt::BasicType(), Rational::BasicType(), Rational::BasicType()}, {LongInt::BasicType(), Rational::BasicType(), Rational::BasicType()}, }; ListExpr CcMathTypeMap( ListExpr args ) { return SimpleMaps<12,3>(maps_arith, args); } const string maps_plus[13][3] = { {CcInt::BasicType(), CcInt::BasicType(), CcInt::BasicType()}, {CcInt::BasicType(), CcReal::BasicType(), CcReal::BasicType()}, {CcReal::BasicType(), CcInt::BasicType(), CcReal::BasicType()}, {CcReal::BasicType(), CcReal::BasicType(), CcReal::BasicType()}, {CcString::BasicType(), CcString::BasicType(), CcString::BasicType()}, {LongInt::BasicType(), CcInt::BasicType(), LongInt::BasicType()}, {LongInt::BasicType(), LongInt::BasicType(), LongInt::BasicType()}, {CcInt::BasicType(), LongInt::BasicType(), LongInt::BasicType()}, {Rational::BasicType(), CcInt::BasicType(), Rational::BasicType()}, {Rational::BasicType(), LongInt::BasicType(), Rational::BasicType()}, {Rational::BasicType(), Rational::BasicType(), Rational::BasicType()}, {CcInt::BasicType(), Rational::BasicType(), Rational::BasicType()}, {LongInt::BasicType(), Rational::BasicType(), Rational::BasicType()}, }; ListExpr CcPlusTypeMap( ListExpr args ) { return SimpleMaps<13,3>(maps_plus, args); } /* 4.2.2 Selection Functions A selection function is quite similar to a type mapping function and is needed for operators which accept different variants of input parameters. The only difference is that it doesn't return a type but the index of a value mapping function being able to deal with the respective combination of input parameter types. Note that a selection function does not need to check the correctness of argument types; it has already been checked by the type mapping function that it is applied to correct arguments. 4.3.1 Selection function CcMathSelectCompute */ int CcMathSelectCompute( ListExpr args ) { return SimpleSelect<12,3>(maps_arith, args); } int CcPlusSelectCompute( ListExpr args ) { return SimpleSelect<13,3>(maps_plus, args); } int ifthenelseSelect(ListExpr args){ if(listutils::isStream(nl->Second(args))){ return 1; } else { return 0; } } /* 4.3.2 Selecttion Function for int | real */ int CcNumRealSelect( ListExpr args ){ return listutils::isSymbol(nl->First(args),CcInt::BasicType()) ? 0 : 1; } /* 4.3.3 Selecttion Function for {int | real} x {int | real} */ int CcNumNumRealSelect( ListExpr args ){ if(listutils::isSymbol(nl->First(args),CcInt::BasicType())){ return listutils::isSymbol(nl->Second(args),CcInt::BasicType()) ? 0 : 1; } else { return listutils::isSymbol(nl->Second(args),CcInt::BasicType()) ? 2 : 3; } } /* 4.3.4 Selection Function for {int | real} x {int | real} [x {int | real}] [x T] */ int CcNumNumNumRealSelect( ListExpr args ){ int res = 0; int noargs = nl->ListLength( args ); if(listutils::isSymbol(nl->First(args),CcReal::BasicType())) { res+=4; } if(listutils::isSymbol(nl->Second(args),CcReal::BasicType())) { res+=2; } if( (noargs > 2) && listutils::isSymbol(nl->Third(args),CcReal::BasicType())){ res +=1; } return res; } /* 4.2.2 Type mapping function CcMathTypeMapdiv It is for the operators /. the only difference between CCMathTypeMap and CcMathTypeMapdiv is that the latter give as resulttype REAL if the input type is INT ("normal division of int with result real", the other division of int is called div in this program). */ const string maps_div[12][3] = { {CcInt::BasicType(), CcInt::BasicType(), CcReal::BasicType()}, {CcInt::BasicType(), CcReal::BasicType(), CcReal::BasicType()}, {CcReal::BasicType(), CcInt::BasicType(), CcReal::BasicType()}, {CcReal::BasicType(), CcReal::BasicType(), CcReal::BasicType()}, {LongInt::BasicType(), CcInt::BasicType(), LongInt::BasicType()}, {LongInt::BasicType(), LongInt::BasicType(), LongInt::BasicType()}, {CcInt::BasicType(), LongInt::BasicType(), LongInt::BasicType()}, {Rational::BasicType(), CcInt::BasicType(), Rational::BasicType()}, {Rational::BasicType(), LongInt::BasicType(), Rational::BasicType()}, {Rational::BasicType(), Rational::BasicType(), Rational::BasicType()}, {CcInt::BasicType(), Rational::BasicType(), Rational::BasicType()}, {LongInt::BasicType(), Rational::BasicType(), Rational::BasicType()}, }; ListExpr CcMathTypeMapdiv( ListExpr args ) { return SimpleMaps<12,3>(maps_div, args); } /* 4.2.3 Type mapping function CcMathTypeMap1 It is for the operators mod and div which have ~int~ as input and ~int~ as result. */ ListExpr CcMathTypeMap1( ListExpr args ) { const string mapping[] = {CcInt::BasicType(), CcInt::BasicType(), CcInt::BasicType()}; return SimpleMap(mapping, 3, args); } /* 4.2.4 Type mapping function CcMathTypeMap2 It is for the operators ~intersection~ and ~minus~. */ const string maps_set[4][3] = { {CcInt::BasicType(), CcInt::BasicType(), CcInt::BasicType()}, {CcReal::BasicType(), CcReal::BasicType(), CcReal::BasicType()}, {CcBool::BasicType(), CcBool::BasicType(), CcBool::BasicType()}, {CcString::BasicType(), CcString::BasicType(), CcString::BasicType()} }; ListExpr CcMathTypeMap2( ListExpr args ) { return SimpleMaps<4,3>(maps_set, args); } int CcMathSelectSet( ListExpr args ) { return SimpleSelect<4,3>(maps_set, args); } /* 4.2.4 Type mapping functions IntInt, IntBool, BoolInt, EmptyInt, IntString Used for operators ~randint~, ~randmax~, ~initseq~, ~nextseq~ and ~log~. And for ~int2bool~, ~bool2int~, ~char~. */ ListExpr IntInt( ListExpr args ) { const string mapping[] = {CcInt::BasicType(), CcInt::BasicType()}; return SimpleMap(mapping, 2, args); } ListExpr RealReal( ListExpr args ) { const string mapping[] = {CcReal::BasicType(), CcReal::BasicType()}; return SimpleMap(mapping, 2, args); } ListExpr RealInt( ListExpr args ) { const string mapping[] = {CcReal::BasicType(), CcInt::BasicType()}; return SimpleMap(mapping, 2, args); } ListExpr IntReal( ListExpr args ) { const string mapping[] = {CcInt::BasicType(), CcReal::BasicType()}; return SimpleMap(mapping, 2, args); } ListExpr IntBool( ListExpr args ) { const string mapping[] = {CcInt::BasicType(), CcBool::BasicType()}; return SimpleMap(mapping, 2, args); } /* ~EmptyInt~ Some operators create integer result without any kind of input, they map ---- () -> (int) ---- */ ListExpr EmptyInt( ListExpr args ) { const string mapping[] = {CcInt::BasicType()}; return SimpleMap(mapping, 1, args); } ListExpr BoolInt( ListExpr args ) { const string mapping[] = {CcBool::BasicType(), CcInt::BasicType()}; return SimpleMap(mapping, 2, args); } ListExpr IntString( ListExpr args ) { const string mapping[] = {CcInt::BasicType(), CcString::BasicType()}; return SimpleMap(mapping, 2, args); } /* 4.2.5 Type mapping function CompareTypeMap It is for the Compare operators which have ~bool~ as resulttype. */ const string maps_comp[11][3] = { {CcInt::BasicType(), CcInt::BasicType(), CcBool::BasicType()}, {CcInt::BasicType(), CcReal::BasicType(), CcBool::BasicType()}, {CcInt::BasicType(), LongInt::BasicType(), CcBool::BasicType()}, {CcReal::BasicType(), CcInt::BasicType(), CcBool::BasicType()}, {CcReal::BasicType(), CcReal::BasicType(), CcBool::BasicType()}, {CcReal::BasicType(), LongInt::BasicType(), CcBool::BasicType()}, {LongInt::BasicType(), CcInt::BasicType(), CcBool::BasicType()}, {LongInt::BasicType(), CcReal::BasicType(), CcBool::BasicType()}, {LongInt::BasicType(), LongInt::BasicType(), CcBool::BasicType()}, {CcBool::BasicType(), CcBool::BasicType(), CcBool::BasicType()}, {CcString::BasicType(), CcString::BasicType(), CcBool::BasicType()}, }; ListExpr CompareTypeMap( ListExpr args ) { return SimpleMaps<11,3>(maps_comp, args); } /* 4.3.3 Selection function CcMathSelectCompare */ int CcMathSelectCompare( ListExpr args ) { return SimpleSelect<11,3>(maps_comp, args); } /* 4.2.6 Type mapping function CcMathTypeMapBool1 It is for the operator ~not~ which have ~bool~ as input and resulttype. */ ListExpr CcMathTypeMapBool1( ListExpr args ) { const string mapping[] = {CcBool::BasicType(), CcBool::BasicType()}; return SimpleMap(mapping, 2, args); } /* 4.2.7 Type mapping function CcMathTypeMapBool2 It is for the operators and and or which have bool as input and resulttype. */ ListExpr CcMathTypeMapBool2( ListExpr args ) { const string mapping[] = {CcBool::BasicType(), CcBool::BasicType(), CcBool::BasicType()}; return SimpleMap(mapping, 3, args); } /* 4.2.8 Type mapping function CcMathTypeMapBool3 It is for the operators ~starts~ and ~contains~ which have ~string~ as input and ~bool~ resulttype. */ ListExpr CcMathTypeMapBool3( ListExpr args ) { const string mapping[] = {CcString::BasicType(), CcString::BasicType(), CcBool::BasicType()}; return SimpleMap(mapping, 3, args); } /* 4.2.9 Type mapping function CcMathTypeMapBool4 It is for the operators ~isempty~ which have ~bool~, ~int~, ~real~, and ~string~ as input and ~bool~ resulttype. */ const string maps_isempty[4][2] = { {CcBool::BasicType(), CcBool::BasicType()}, {CcInt::BasicType(), CcBool::BasicType()}, {CcReal::BasicType(), CcBool::BasicType()}, {CcString::BasicType(), CcBool::BasicType()} }; ListExpr CcMathTypeMapBool4( ListExpr args ) { return SimpleMaps<4,2>(maps_isempty, args); } /* 4.3.3 Selection function CcMathSelectIsEmpty It is used for the ~isempty~ operator. */ int CcMathSelectIsEmpty( ListExpr args ) { return SimpleSelect<4,2>(maps_isempty, args); } /* 4.2.10 Type mapping function for the ~++~ operator: string ---> string. */ ListExpr CcStringMapCcString( ListExpr args ) { const string mapping[] = {CcString::BasicType(), CcString::BasicType()}; return SimpleMap(mapping, 2, args); } /* 4.2.10 Type mapping function for the ~substr~ operator: string x int x int -> string. */ ListExpr SubStrTypeMap( ListExpr args ) { const string mapping[] = { CcString::BasicType(), CcInt::BasicType(), CcInt::BasicType(), CcString::BasicType() }; return SimpleMap(mapping, 4, args); } /* 4.2.12 Type mapping function for the ~keywords~ operator: Type mapping for ~keywords~ is ---- (string) -> (stream string) ---- */ ListExpr keywordsType( ListExpr args ){ ListExpr arg; if ( nl->ListLength(args) == 1 ) { arg = nl->First(args); if ( listutils::isSymbol(arg, CcString::BasicType()) ) return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->SymbolAtom(CcString::BasicType())); } return nl->SymbolAtom(Symbol::TYPEERROR()); } /* 4.2.13 Type mapping function for the ~ifthenelse~ operator: Type mapping for ~ifthenelse~ is ---- (bool x T x T)) -> T , T in DATA or T = stream(...) ---- */ ListExpr ifthenelseType(ListExpr args) { ListExpr arg1, arg2, arg3; if(!nl->HasLength(args,3)){ return listutils::typeError("Expected three arguments."); } arg1 = nl->First( args ); arg2 = nl->Second( args ); arg3 = nl->Third( args ); if(!listutils::isSymbol(arg1, CcBool::BasicType())){ return listutils::typeError("The 1st argument must be of type bool."); } if(!listutils::isDATA(arg2) && !listutils::isStream(arg2)){ return listutils::typeError("The 2nd argument must be " "in kind DATA or must be a stream."); } if(!nl->Equal(arg2,arg3)){ return listutils::typeError("The 2nd and 3rd argument " "must be of the same type."); } return arg2; } /* 4.2.14 Type mapping function for the ~between~ operator: Type mapping for ~between~ is ---- (T x T x T) -> bool ---- */ const string maps_between[10][4] = { {CcInt::BasicType(), CcInt::BasicType(), CcInt::BasicType(), CcBool::BasicType()}, {CcReal::BasicType(), CcReal::BasicType(), CcReal::BasicType(), CcBool::BasicType()}, {CcString::BasicType(), CcString::BasicType(), CcString::BasicType(), CcBool::BasicType()}, {CcBool::BasicType(), CcBool::BasicType(), CcBool::BasicType(), CcBool::BasicType()}, {CcInt::BasicType(), CcInt::BasicType(), CcReal::BasicType(), CcBool::BasicType()}, {CcInt::BasicType(), CcReal::BasicType(), CcInt::BasicType(), CcBool::BasicType()}, {CcInt::BasicType(), CcReal::BasicType(), CcReal::BasicType(), CcBool::BasicType()}, {CcReal::BasicType(), CcInt::BasicType(), CcInt::BasicType(), CcBool::BasicType()}, {CcReal::BasicType(), CcInt::BasicType(), CcReal::BasicType(), CcBool::BasicType()}, {CcReal::BasicType(), CcReal::BasicType(), CcInt::BasicType(), CcBool::BasicType()} }; ListExpr CcBetweenTypeMap( ListExpr args ) { return SimpleMaps<10,4>(maps_between, args); } /* 4.3.3 Selection function CcBetweenSelect */ int CcBetweenSelect( ListExpr args ) { return SimpleSelect<10,4>(maps_between, args); } /* 4.2.14 Type mapping function for the ~hashvalue~ operator: Type mapping for ~hashvalue~ is ---- T in kind DATA, T x int -> int ---- */ ListExpr CcHashValueTypeMap( ListExpr args ) { if(nl->ListLength(args)!=2){ ErrorReporter::ReportError("DATA x int expected"); return nl->TypeError(); } ListExpr arg1 = nl->First(args); ListExpr arg2 = nl->Second(args); if(!listutils::isDATA(arg1) || !listutils::isSymbol(arg2,CcInt::BasicType())){ ErrorReporter::ReportError("DATA x int expected"); return nl->TypeError(); } return (nl->SymbolAtom( CcInt::BasicType() )); } /* 4.2.15 Type mapping function for the ~ldistance~ operator: Type mapping for ~ldistance~ is string x string [->] int */ ListExpr CcLDistTypeMap(ListExpr args) { const string mapping[] = {CcString::BasicType(), CcString::BasicType(), CcInt::BasicType()}; return SimpleMap(mapping, 3, args); } /* 4.2.16 Type mapping function CcRoundTypeMap It is for the operator ~round~. */ ListExpr CcRoundTypeMap( ListExpr args ) { if(!nl->HasLength(args,2)){ return listutils::typeError("2 args expected"); } if( !CcInt::checkType(nl->First(args)) && !CcReal::checkType(nl->First(args))){ return listutils::typeError("first arg must be of int or real"); } if(!CcInt::checkType(nl->Second(args))){ return listutils::typeError("second arg must be of type int"); } return listutils::basicSymbol(); } /* 4.2.17 Type mappig function ~NumStringTypeMap~ For operator ~num2string~ */ const string maps_num2str[3][2] = { {CcReal::BasicType(), CcString::BasicType()}, {CcInt::BasicType(), CcString::BasicType()}, {LongInt::BasicType(), CcString::BasicType()} }; ListExpr NumStringTypeMap(ListExpr args) { if (nl->ListLength(args) == 1) { if (CcInt::checkType(nl->First(args)) || CcReal::checkType(nl->First(args)) || LongInt::checkType(nl->First(args))) { return nl->SymbolAtom(CcString::BasicType()); } } if (nl->ListLength(args) == 2) { if ((CcInt::checkType(nl->First(args)) || CcReal::checkType(nl->First(args)) || LongInt::checkType(nl->First(args))) && CcInt::checkType(nl->Second(args))) { return nl->SymbolAtom(CcString::BasicType()); } } return NList::typeError("Expecting either int|real|longint or " "int|real|longint x int ."); } int ccnum2stringSelect(ListExpr args) { if (nl->ListLength(args) == 1) { if (CcReal::checkType(nl->First(args))) return 0; if (CcInt::checkType(nl->First(args))) return 1; if (LongInt::checkType(nl->First(args))) return 2; } if (CcReal::checkType(nl->First(args))) return 3; if (CcInt::checkType(nl->First(args))) return 4; if (LongInt::checkType(nl->First(args))) return 5; return -1; } /* 4.2.16 Type mapping function ~DATAbool~ Maps DATA [->] bool It is for the operator ~isdefined~. */ ListExpr DATAbool( ListExpr args ) { NList mArgs(args); ListExpr errorInfo = nl->OneElemList(nl->SymbolAtom("ERROR")); if( !mArgs.hasLength(1) || !SecondoSystem::GetAlgebraManager()-> CheckKind(Kind::DATA(), mArgs.first().listExpr(), errorInfo) ) { return NList::typeError("Expected single argument of kind DATA."); } return NList(CcBool::BasicType()).listExpr(); } /* 4.2.16 Type mapping function ~CcTypeMapTinDATA\_TinDATAint~ Maps ---- T x T --> bool, T in kind DATA ---- It is, e.g. for the operator ~compare~. */ ListExpr CcTypeMapTinDATA_TinDATAint( ListExpr args ) { NList mArgs(args); ListExpr errorInfo = nl->OneElemList(nl->SymbolAtom("ERROR")); if( !mArgs.hasLength(2) || ( mArgs.first() != mArgs.second() ) || !SecondoSystem::GetAlgebraManager()-> CheckKind(Kind::DATA(), mArgs.first().listExpr(), errorInfo) ) { return NList::typeError("Expected T x T for T in kind DATA."); } return NList(CcInt::BasicType()).listExpr(); } /* 4.2.17 Type mapping function ~CcTypeMapTinDATAexpplus2TinDATA~ For operators ~getMinVal~, ~getMaxVal~: ---- T [x T x T x ...] -> T, T in DATA ---- */ ListExpr CcTypeMapTinDATAexpplus2TinDATA( ListExpr args ) { NList mArgs(args); ListExpr errorInfo = nl->OneElemList(nl->SymbolAtom("ERROR")); int noArgs = mArgs.length(); if(noArgs < 1){ return NList::typeError("Expected T^n, T in kind DATA, n >= 1."); } NList type = mArgs.first(); if (!SecondoSystem::GetAlgebraManager()-> CheckKind(Kind::DATA(), type.listExpr(), errorInfo)){ return NList::typeError("Expected T^n, T in kind DATA, n >= 1."); } ListExpr first = nl->First(args); ListExpr rest = nl->Rest(args); while(!nl->IsEmpty(rest)){ if(!nl->Equal(first, nl->First(rest))){ return NList::typeError("Expected T^n, T in kind DATA, n >= 1."); } rest = nl->Rest(rest); } return type.listExpr(); } /* 4.2.18 Type mapping function for: int | real -> real */ ListExpr CcTypeMapNumReal( ListExpr args ){ if(!nl->HasLength(args, 1)){ return listutils::typeError("Expected real or int (only 1 argument!)."); } ListExpr arg = nl->First(args); if(listutils::isNumericType(arg)){ return nl->SymbolAtom(CcReal::BasicType()); } return listutils::typeError("Expected real or int."); } /* 4.2.18 Type mapping function for: int | real -> real */ ListExpr CcTypeMapEmptyReal( ListExpr args ){ if(!nl->HasLength(args,0)){ return listutils::typeError("Expected no argument."); } return nl->SymbolAtom(CcReal::BasicType()); } /* 4.2.19 Type mapping function for: {int | real} x {int | real} -> real */ ListExpr CcTypeMapNumNumReal( ListExpr args ){ if(!nl->HasLength(args,2)){ return listutils::typeError("Expected {int | real} x {int | real}"); } if( listutils::isNumericType(nl->First(args)) && listutils::isNumericType(nl->Second(args))){ return nl->SymbolAtom(CcReal::BasicType()); } return listutils::typeError("Expected {int | real} x {int | real}"); } /* 4.2.19 Type mapping function for: {int|real} x {int|real} [ x {int|real} ] [ x bool ]->real Appends a bool == FALSE, if the optional bool parameter is not present. */ ListExpr CcTypeMapNumNumOptNumOptBoolReal( ListExpr args ){ string errmsg = "Expected {int | real} x {int | real} [ x {int | real} ] " "[ x bool ]"; int noargs = nl->ListLength(args); if( (noargs<2) || (noargs>4)){ return listutils::typeError(errmsg); } //check first and second if(!listutils::isNumericType(nl->First(args)) || !listutils::isNumericType(nl->Second(args)) ){ return listutils::typeError(errmsg); } if( noargs== 2 ) { // numeric x numeric: OK, but APPEND bool parameter return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()), nl->OneElemList(nl->BoolAtom(false)), nl->SymbolAtom(CcReal::BasicType())); } // check third and fourth if( noargs==3 ){ if( listutils::isSymbol(nl->Third(args),CcBool::BasicType()) ) { // mumeric x numeric x bool: OK. return nl->SymbolAtom(CcReal::BasicType()); } if( !listutils::isNumericType(nl->Third(args)) ) { return listutils::typeError(errmsg); } // mumeric x numeric x numeric: OK, but APPEND bool parameter return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()), nl->OneElemList(nl->BoolAtom(false)), nl->SymbolAtom(CcReal::BasicType())); } if( noargs==4 ){ if( !listutils::isNumericType(nl->Third(args)) ) { return listutils::typeError(errmsg); } if( !listutils::isSymbol(nl->Fourth(args),CcBool::BasicType()) ) { return listutils::typeError(errmsg); } return nl->SymbolAtom(CcReal::BasicType()); // mun x num x num x bool: OK. } // should not be reached: return listutils::typeError(errmsg); } /* 4.2.20 Type mapping function for: real x real -> real */ ListExpr CcTypeMapRealRealReal( ListExpr args ){ if(!nl->HasLength(args,2)){ return listutils::typeError("Expected real x real"); } if( listutils::isSymbol(nl->First(args), CcReal::BasicType()) && listutils::isSymbol(nl->Second(args), CcReal::BasicType())){ return nl->SymbolAtom(CcReal::BasicType()); } return listutils::typeError("Expected real x real"); } /* 4.4 Value mapping functions of operator ~+~ A value mapping function implements an operator's main functionality: it takes input arguments and computes the result. Each operator consists of at least one value mapping function. In the case of overloaded operators --- like in this example --- there are several value mapping functions, one for each possible combination of input parameter types. We have to provide four functions for each of the operators ~+~, ~-~, ~[*]~ ....., since each of them accepts four input parameter combinations: ~INT~ $\times$ ~INT~, ~INT~ $\times$ ~REAL~, ~REAL~ $\times$ ~INT~, and ~REAL~ $\times$ ~REAL~. */ int CcPlus_ii( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcInt*)args[0].addr)->IsDefined() && ((CcInt*)args[1].addr)->IsDefined() ) { // overflow save implementation int a = ((CcInt*)args[0].addr)->GetIntval(); int b = ((CcInt*)args[1].addr)->GetIntval(); int sum = a+b; if( ((b>0 ) && (suma)){ ((CcInt*)result.addr)->Set(false,0); } else { ((CcInt *)result.addr)->Set( true, sum); } } else { ((CcInt *)result.addr)->Set( false, 0 ); } return (0); } int CcPlus_ir( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcInt*)args[0].addr)->IsDefined() && ((CcReal*)args[1].addr)->IsDefined() ) { ((CcReal *)result.addr)-> Set( true, ((CcInt*)args[0].addr)->GetIntval() + ((CcReal*)args[1].addr)->GetRealval() ); } else { ((CcReal *)result.addr)->Set( false, 0 ); } return (0); } int CcPlus_ri( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if( ((CcReal*)args[0].addr)->IsDefined() && ((CcInt*)args[1].addr)->IsDefined() ) { ((CcReal *)result.addr)-> Set( true, ((CcReal*)args[0].addr)->GetRealval() + ((CcInt*)args[1].addr)->GetIntval() ); } else { ((CcReal *)result.addr)->Set( false, 0 ); } return (0); } int CcPlus_rr( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcReal*)args[0].addr)->IsDefined() && ((CcReal*)args[1].addr)->IsDefined() ) { ((CcReal *)result.addr)-> Set( true, ((CcReal*)args[0].addr)->GetRealval() + ((CcReal*)args[1].addr)->GetRealval() ); } else { ((CcReal *)result.addr)->Set( false, 0 ); } return (0); } int CcPlus_ss( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); // extract arguments CcString* wstr1 = reinterpret_cast( args[0].addr ); CcString* wstr2 = reinterpret_cast( args[1].addr ); string str1 = reinterpret_cast( wstr1->GetStringval() ); string str2 = reinterpret_cast( wstr2->GetStringval() ); CcString* wres = reinterpret_cast( result.addr ); // compute result value if ( wstr1->IsDefined() && wstr2->IsDefined() ) { wres->Set( true, (STRING_T*)(str1 + str2).substr(0,MAX_STRINGSIZE).c_str() ); } else { STRING_T str = ""; wres->Set( false, &str ); } return (0); } template int CcPlus_long( Word* args, Word& result, int message, Word& local, Supplier s ) { LongInt* arg1 = (LongInt*) args[0].addr; T* arg2 = (T*) args[1].addr; result = qp->ResultStorage(s); LongInt* res = (LongInt*) result.addr; (*res) = (*arg1) + (*arg2); return 0; } template int CcPlus_long2( Word* args, Word& result, int message, Word& local, Supplier s ) { T* arg1 = (T*) args[0].addr; LongInt* arg2 = (LongInt*) args[1].addr; result = qp->ResultStorage(s); LongInt* res = (LongInt*) result.addr; (*res) = (*arg2) + (*arg1); return 0; } template int CcPlus_rat( Word* args, Word& result, int message, Word& local, Supplier s ) { Rational* arg1 = (Rational*) args[0].addr; T* arg2 = (T*) args[1].addr; Rational r2 (*arg2); result = qp->ResultStorage(s); Rational* res = (Rational*) result.addr; (*res) = (*arg1) + r2; return 0; } template int CcPlus_rat2( Word* args, Word& result, int message, Word& local, Supplier s ) { T* arg1 = (T*) args[0].addr; Rational* arg2 = (Rational*) args[1].addr; Rational r1 (*arg1); result = qp->ResultStorage(s); Rational* res = (Rational*) result.addr; (*res) = (*arg2) + r1; return 0; } /* 4.5 Value mapping functions of operator ~-~ */ int CcMinus_ii( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcInt*)args[0].addr)->IsDefined() && ((CcInt*)args[1].addr)->IsDefined() ) { int a = ((CcInt*)args[0].addr)->GetIntval(); int b = ((CcInt*)args[1].addr)->GetIntval(); int diff = a-b; if( ((b>0) && (diff>a) ) || ((b<0) && (diffSet(false, 0); } else { ((CcInt *)result.addr)->Set(true, diff); } } else { ((CcInt *)result.addr)->Set( false, 0 ); } return (0); } int CcMinus_ir( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcInt*)args[0].addr)->IsDefined() && ((CcReal*)args[1].addr)->IsDefined() ) { ((CcReal *)result.addr)-> Set( true, ((CcInt*)args[0].addr)->GetIntval() - ((CcReal*)args[1].addr)->GetRealval() ); } else { ((CcReal *)result.addr)->Set( false, 0 ); } return (0); } int CcMinus_ri( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcReal*)args[0].addr)->IsDefined() && ((CcInt*)args[1].addr)->IsDefined() ) { ((CcReal *)result.addr)-> Set( true, ((CcReal*)args[0].addr)->GetRealval() - ((CcInt*)args[1].addr)->GetIntval() ); } else { ((CcReal *)result.addr)->Set( false, 0 ); } return (0); } int CcMinus_rr( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcReal*)args[0].addr)->IsDefined() && ((CcReal*)args[1].addr)->IsDefined() ) { ((CcReal *)result.addr)-> Set( true, ((CcReal*)args[0].addr)->GetRealval() - ((CcReal*)args[1].addr)->GetRealval() ); } else { ((CcReal *)result.addr)->Set( false, 0 ); } return (0); } template int CcMinus_long( Word* args, Word& result, int message, Word& local, Supplier s ) { LongInt* arg1 = (LongInt*) args[0].addr; T* arg2 = (T*) args[1].addr; result = qp->ResultStorage(s); LongInt* res = (LongInt*) result.addr; LongInt t(*arg2); (*res) = (*arg1) - t; return 0; } template int CcMinus_long2(Word* args, Word& result, int message, Word& local, Supplier s ) { T* arg1 = (T*) args[0].addr; LongInt* arg2 = (LongInt*) args[1].addr; LongInt t(*arg1); result = qp->ResultStorage(s); LongInt* res = (LongInt*) result.addr; (*res) = t - (*arg2); return 0; } template int CcMinus_rat( Word* args, Word& result, int message, Word& local, Supplier s ) { Rational* arg1 = (Rational*) args[0].addr; T* arg2 = (T*) args[1].addr; result = qp->ResultStorage(s); Rational* res = (Rational*) result.addr; Rational t(*arg2); (*res) = (*arg1) - t; return 0; } template int CcMinus_rat2(Word* args, Word& result, int message, Word& local, Supplier s ) { T* arg1 = (T*) args[0].addr; Rational* arg2 = (Rational*) args[1].addr; Rational t(*arg1); result = qp->ResultStorage(s); Rational* res = (Rational*) result.addr; (*res) = t - (*arg2); return 0; } /* 4.6 Value mapping functions of operator ~[*]~ Value mapping functions of operator ~[*]~ are defined in the same way as value mapping functions of operator ~+~. */ int CcProduct_ii( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcInt*)args[0].addr)->IsDefined() && ((CcInt*)args[1].addr)->IsDefined() ) { int a = ((CcInt*)args[0].addr)->GetIntval(); int b = ((CcInt*)args[1].addr)->GetIntval(); int prod = a*b; if( (b!=0) && ((prod/b)!=a)) { ((CcInt *)result.addr)->Set( false, 0 ); } else { ((CcInt *)result.addr)->Set( true, prod ); } } else { ((CcInt *)result.addr)->Set( false, 0 ); } return (0); } int CcProduct_ir( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcInt*)args[0].addr)->IsDefined() && ((CcInt*)args[1].addr)->IsDefined() ) { ((CcReal *)result.addr)-> Set( true, ((CcInt*)args[0].addr)->GetIntval() * ((CcReal*)args[1].addr)->GetRealval() ); } else { ((CcReal *)result.addr)->Set( false, 0 ); } return (0); } int CcProduct_ri( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcReal*)args[0].addr)->IsDefined() && ((CcInt*)args[1].addr)->IsDefined() ) { ((CcReal *)result.addr)-> Set( true, ((CcReal*)args[0].addr)->GetRealval() * ((CcInt*)args[1].addr)->GetIntval() ); } else { ((CcReal *)result.addr)->Set( false, 0 ); } return (0); } int CcProduct_rr( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcReal*)args[0].addr)->IsDefined() && ((CcReal*)args[1].addr)->IsDefined() ) { ((CcReal *)result.addr)-> Set( true, ((CcReal*)args[0].addr)->GetRealval() * ((CcReal*)args[1].addr)->GetRealval() ); } else { ((CcReal *)result.addr)->Set( false, 0 ); } return (0); } template int CcProduct_long( Word* args, Word& result, int message, Word& local, Supplier s ){ LongInt* arg1 = (LongInt*) args[0].addr; T* arg2 = (T*) args[1].addr; result = qp->ResultStorage(s); LongInt* res = (LongInt*) result.addr; LongInt t(*arg2); (*res) = (*arg1) * t; return 0; } template int CcProduct_long2( Word* args, Word& result, int message, Word& local, Supplier s ){ T* arg1 = (T*) args[0].addr; LongInt* arg2 = (LongInt*) args[1].addr; result = qp->ResultStorage(s); LongInt* res = (LongInt*) result.addr; LongInt t(*arg1); (*res) = t * (*arg2); return 0; } template int CcProduct_rat( Word* args, Word& result, int message, Word& local, Supplier s ){ Rational* arg1 = (Rational*) args[0].addr; T* arg2 = (T*) args[1].addr; result = qp->ResultStorage(s); Rational* res = (Rational*) result.addr; Rational f2(*arg2); (*res) = (*arg1)*f2; return 0; } template int CcProduct_rat2( Word* args, Word& result, int message, Word& local, Supplier s ){ T* arg1 = (T*) args[0].addr; Rational* arg2 = (Rational*) args[1].addr; result = qp->ResultStorage(s); Rational* res = (Rational*) result.addr; Rational t(*arg1); (*res) = t * (*arg2); return 0; } /* 4.7 Value mapping functions of operator ~/~ */ int CcDivision_ii( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcInt*)args[0].addr)->IsDefined() && ((CcInt*)args[1].addr)->IsDefined() && ((CcInt*)args[1].addr)->GetIntval() ) { ((CcReal *)result.addr)-> Set( true, ((SEC_STD_REAL )((CcInt*)args[0].addr)->GetIntval()) / ((CcInt*)args[1].addr)->GetIntval() ); } else { ((CcReal *)result.addr)->Set( false, 0 ); } return (0); } int CcDivision_ir( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcInt*)args[0].addr)->IsDefined() && ((CcReal*)args[1].addr)->IsDefined() && ((CcReal*)args[1].addr)->GetRealval() ) { ((CcReal *)result.addr)-> Set( true, ((CcInt*)args[0].addr)->GetIntval() / ((CcReal*)args[1].addr)->GetRealval() ); } else { ((CcReal *)result.addr)->Set( false, 0 ); } return (0); } int CcDivision_ri( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcReal*)args[0].addr)->IsDefined() && ((CcInt*)args[1].addr)->IsDefined() && ((CcInt*)args[1].addr)->GetIntval() ) { ((CcReal *)result.addr)-> Set( true, ((CcReal*)args[0].addr)->GetRealval() / ((CcInt*)args[1].addr)->GetIntval() ); } else { ((CcReal *)result.addr)->Set( false, 0 ); } return (0); } int CcDivision_rr( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcReal*)args[0].addr)->IsDefined() && ((CcReal*)args[1].addr)->IsDefined() && ((CcReal*)args[1].addr)->GetRealval() ) { ((CcReal *)result.addr)-> Set( true, ((CcReal*)args[0].addr)->GetRealval() / ((CcReal*)args[1].addr)->GetRealval() ); } else { ((CcReal *)result.addr)->Set( false, 0 ); } return (0); } template int CcDivision_long( Word* args, Word& result, int message, Word& local, Supplier s ) { LongInt* arg1 = (LongInt*) args[0].addr; T* arg2 = (T*) args[1].addr; result = qp->ResultStorage(s); LongInt* res = (LongInt*) result.addr; LongInt t(*arg2); (*res) = (*arg1) / t; return 0; } template int CcDivision_long2( Word* args, Word& result, int message, Word& local, Supplier s ) { T* arg1 = (T*) args[0].addr; LongInt* arg2 = (LongInt*) args[1].addr; result = qp->ResultStorage(s); LongInt* res = (LongInt*) result.addr; LongInt t(*arg1); (*res) = t / (*arg2); return 0; } template int CcDivision_rat( Word* args, Word& result, int message, Word& local, Supplier s ) { Rational* arg1 = (Rational*) args[0].addr; T* arg2 = (T*) args[1].addr; result = qp->ResultStorage(s); Rational* res = (Rational*) result.addr; Rational t(*arg2); (*res) = (*arg1) / t; return 0; } template int CcDivision_rat2( Word* args, Word& result, int message, Word& local, Supplier s ) { T* arg1 = (T*) args[0].addr; Rational* arg2 = (Rational*) args[1].addr; result = qp->ResultStorage(s); Rational* res = (Rational*) result.addr; Rational t(*arg1); (*res) = t / (*arg2); return 0; } /* 4.8 Value mapping functions of operator ~mod~ */ int CcMod( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcInt*)args[0].addr)->IsDefined() && ((CcInt*)args[1].addr)->IsDefined() ) { ((CcInt *)result.addr)-> Set( true, ((CcInt*)args[0].addr)->GetIntval() % ((CcInt*)args[1].addr)->GetIntval() ); } else { ((CcInt *)result.addr)->Set( false, 0 ); } return (0); } /* 4.8 Type Mapping for operator ~div~ */ ListExpr divTM(ListExpr args){ if(!nl->HasLength(args,2)){ return listutils::typeError("invalid number of arguments"); } if( !CcInt::checkType(nl->First(args)) && !LongInt::checkType(nl->First(args))){ return listutils::typeError("first argument must be of type " "int or longint"); } if( !CcInt::checkType(nl->Second(args)) && !LongInt::checkType(nl->Second(args))){ return listutils::typeError("first argument must be of type " "int or longint"); } return nl->First(args); } /* 4.8 Value mapping functions of operator ~div~ */ template int CcDiv( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); A* a = (A*) args[0].addr; B* b = (B*) args[1].addr; A* res = (A*) result.addr; if(!a->IsDefined() || !b->IsDefined()){ res->SetDefined(false); return 0; } if(b->GetValue()==0){ res->SetDefined(false); return 0; } res->Set(true,(typename A::inttype) (a->GetValue() / b->GetValue())); return 0; } /* 4.8 Value mapping function of operators ~randint~, ~maxrand~, ~initseq~ and ~nextseq~ */ int randint(int u) //Computes a random integer in the range 0..u-1, //for u >= 2 { if ( u < 2 ) {u=2; srand ( time(NULL) );} // For u < 2 also initialize the random number generator // rand creates a value between [0,RAND_MAX]. The calculation procedure // below is recommended in the manpage of the rand() function. // Using rand() % u will yield poor results. double r = rand(); return (int) ( (float)u * r/(RAND_MAX+1.0) ); } int RandInt( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if( ((CcInt*)args[0].addr)->IsDefined() ) { int arg = ((CcInt*) args[0].addr)->GetValue(); int res = randint(arg); ((CcInt *)result.addr)-> Set( true, res); } else { ((CcInt *)result.addr)->Set( false, 0 ); } return (0); } int RandSeed( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if( ((CcInt*)args[0].addr)->IsDefined() ) { srand(((CcInt*)args[0].addr)->GetIntval()); ((CcBool *)result.addr)-> Set( true, true); } else { ((CcBool*)result.addr)->Set( false, false ); } return (0); } int MaxRand( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); ((CcInt *)result.addr)-> Set( true, RAND_MAX ); return (0); } static int SequenceCounter = 0; int InitSeq( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if( ((CcInt*)args[0].addr)->IsDefined() ) { ((CcBool *)result.addr)->Set( true, true ); SequenceCounter = ((CcInt*)args[0].addr)->GetIntval(); } else { ((CcBool *)result.addr)->Set( false, false ); } return (0); } int NextSeq( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); ((CcInt *)result.addr)-> Set( true, SequenceCounter ); SequenceCounter++; return (0); } /* 4.8 Value mapping function of operator ~log~ */ int intlog(int n) { int i = 0; while (n > 1) {n >>= 1; i++;} return i; } int LogFun( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if( ((CcInt*)args[0].addr)->IsDefined() && ((CcInt*)args[0].addr)->GetIntval() ) { int n = intlog(((CcInt*)args[0].addr)->GetIntval()); ((CcInt *)result.addr)-> Set( true, n ); } else { ((CcInt *)result.addr)-> Set( false, 0 ); } return (0); } /* 4.9 Value mappings for operator < */ template int CcLess( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); const T* a = static_cast( args[0].addr ); const T* b = static_cast( args[1].addr ); ((CcBool *)result.addr)->Set( true, a->Compare(b) == -1 ); return (0); } template int CcGreater( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); const T* a = static_cast( args[0].addr ); const T* b = static_cast( args[1].addr ); ((CcBool *)result.addr)->Set( true, a->Compare(b) == 1 ); return (0); } template int CcEqual( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); const T* a = static_cast( args[0].addr ); const T* b = static_cast( args[1].addr ); ((CcBool *)result.addr)->Set( true, a->Compare(b) == 0 ); return (0); } template int CcLess2( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((S*)args[0].addr)->IsDefined() && ((T*)args[1].addr)->IsDefined() ) { ((CcBool *)result.addr)-> Set( true, ((S*)args[0].addr)->GetValue() < ((T*)args[1].addr)->GetValue() ); } else { ((CcBool *)result.addr)->Set( false, false ); } return (0); } /* 4.10 Value mapping functions of operator $ <= $ */ template int CcLessEqual( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); const T* a = static_cast( args[0].addr ); const T* b = static_cast( args[1].addr ); ((CcBool *)result.addr)->Set( true, a->Compare(b) <= 0 ); return (0); } template int CcLessEqual2( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((S*)args[0].addr)->IsDefined() && ((T*)args[1].addr)->IsDefined() ) { ((CcBool *)result.addr)-> Set( true, ((S*)args[0].addr)->GetValue() <= ((T*)args[1].addr)->GetValue() ); } else { ((CcBool *)result.addr)->Set( false, false ); } return (0); } /* 4.11 Value mapping functions of operator $ > $ */ template int CcGreater2( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((S*)args[0].addr)->IsDefined() && ((T*)args[1].addr)->IsDefined() ) { ((CcBool *)result.addr)-> Set( true, ((S*)args[0].addr)->GetValue() > ((T*)args[1].addr)->GetValue() ); } else { ((CcBool *)result.addr)->Set( false, false ); } return (0); } /* 4.12 Value mapping functions of operator $ >= $ */ template int CcGreaterEqual( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); const T* a = static_cast( args[0].addr ); const T* b = static_cast( args[1].addr ); ((CcBool *)result.addr)->Set( true, a->Compare(b) >= 0 ); return (0); } template int CcGreaterEqual2( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((S*)args[0].addr)->IsDefined() && ((T*)args[1].addr)->IsDefined() ) { ((CcBool *)result.addr)-> Set( true, ((S*)args[0].addr)->GetValue() >= ((T*)args[1].addr)->GetValue() ); } else { ((CcBool *)result.addr)->Set( false, false ); } return (0); } /* 4.13 Value mapping functions of operator ~=~ */ template int CcEqual2( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((S*)args[0].addr)->IsDefined() && ((T*)args[1].addr)->IsDefined() ) { ((CcBool *)result.addr)-> Set( true, ((S*)args[0].addr)->GetValue() == ((T*)args[1].addr)->GetValue() ); } else { ((CcBool *)result.addr)->Set( false, false ); } return (0); } /* 4.14 Value mapping functions of operator ~\#~ */ template int CcDiff( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); const T* a = static_cast( args[0].addr ); const T* b = static_cast( args[1].addr ); ((CcBool *)result.addr)->Set( true, a->Compare(b) != 0 ); return (0); } template int CcDiff2( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((S*)args[0].addr)->IsDefined() && ((T*)args[1].addr)->IsDefined() ) { ((CcBool *)result.addr)-> Set( true, ((S*)args[0].addr)->GetValue() != ((T*)args[1].addr)->GetValue() ); } else { ((CcBool *)result.addr)->Set( false, false ); } return (0); } /* 4.14 Value mapping functions of operator ~contains~ */ int ContainsFun( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcString*)args[0].addr)->IsDefined() && ((CcString*)args[1].addr)->IsDefined() ) { string str1 = (string)(char*)((CcString*)args[0].addr)->GetStringval(); string str2 = (string)(char*)((CcString*)args[1].addr)->GetStringval(); ((CcBool *)result.addr)-> Set (true, str1.find(str2) != string::npos); //((CcBool *)result.addr)-> //Set( true, ((CcString*)args[0].addr)->GetStringval()->find( //*((CcString*)args[1].addr)->GetStringval() ) != string::npos ); } else { ((CcBool *)result.addr)->Set( false, false ); } return (0); } /* 4.15 type and value mapping functions of operator ~substr~ */ int SubStrFun( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); // extract arguments CcString* wstr = reinterpret_cast( args[0].addr ); CcInt* wpos1 = reinterpret_cast( args[1].addr ); CcInt* wpos2 = reinterpret_cast( args[2].addr ); string str1 = reinterpret_cast( wstr->GetStringval() ); int p1 = wpos1->GetIntval(); int p2 = wpos2->GetIntval(); CcString* wres = reinterpret_cast( result.addr ); int strlen = str1.length(); // compute result value if ( wstr->IsDefined() && wpos1->IsDefined() && wpos2->IsDefined() && (p2 >= p1) && (p1 >= 1) && (p1 <= strlen) ) { int n = min( static_cast(p2-p1), static_cast(strlen-p1) ); wres->Set( true, (STRING_T*)(str1.substr(p1-1, n+1).c_str()) ); } else { STRING_T str = ""; wres->Set( false, &str ); } return (0); } /* 4.15 Value mapping functions of operator ~not~ */ int NotFun( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcBool*)args[0].addr)->IsDefined() ) { ((CcBool *)result.addr) ->Set( true, !((CcBool*)args[0].addr)->GetBoolval() ); } else { ((CcBool *)result.addr)->Set( false, false ); } return (0); } /* 4.16 Value mapping functions of operators ~and~ and ~andS~ For ~and~ the arguments are evaluated lazy. The result is TRUE, iff both arguments are DEFINED and TRUE, otherwise the result is FALSE. The result is always DEFINED. ~andS~ has strict evaluation. If both arguments are DEFINED and TRUE, it returns TRUE. Otherwise if both arguments are DEFINED and at least one is FALSE, it returns FALSE. In all other cases, it returns UNDEFINED. */ int AndFun( Word* args, Word& result, int message, Word& local, Supplier s ) { Word res; result = qp->ResultStorage( s ); qp->Request(args[0].addr, res); if ( !((CcBool*)res.addr)->IsDefined() ) { ((CcBool*)result.addr)->Set(true,false); return 0; } if (! ((CcBool*)res.addr)->GetBoolval() ) { ((CcBool*)result.addr)->Set(true,false); return 0; } qp->Request(args[1].addr, res); if ( !((CcBool*)res.addr)->IsDefined() ) { ((CcBool*)result.addr)->Set(true,false); return 0; } if ( ((CcBool*)res.addr)->GetBoolval() ) ((CcBool*)result.addr)->Set(true,true); else ((CcBool*)result.addr)->Set(true,false); return 0; } int AndSFun( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( !((CcBool*)args[0].addr)->IsDefined() || !((CcBool*)args[1].addr)->IsDefined() ) ((CcBool*)result.addr)->Set(false,false); else if( ((CcBool*)args[0].addr)->GetBoolval() && ((CcBool*)args[1].addr)->GetBoolval() ) ((CcBool*)result.addr)->Set(true,true); else ((CcBool*)result.addr)->Set(true,false); return 0; } /* 4.17 Value mapping functions of operators ~or~ and ~orS~ For ~or~ the arguments are evaluated lazy. The result is TRUE, if at least one arguments is DEFINED and TRUE. Otherwise, it returns FALSE. ~orS~ has strict evaluation. If both arguments are DEFINED and at least one is TRUE, it returns TRUE. Otherwise if both arguments are DEFINED and both are FALSE, it returns FALSE. In all other cases, it returns UNDEFINED. */ int OrFun( Word* args, Word& result, int message, Word& local, Supplier s ) { Word res; result = qp->ResultStorage( s ); qp->Request(args[0].addr, res); if ( ((CcBool*)res.addr)->IsDefined() && ((CcBool*)res.addr)->GetBoolval() ) { ((CcBool*)result.addr)->Set(true,true); return 0; } qp->Request(args[1].addr, res); if ( ((CcBool*)res.addr)->IsDefined() && ((CcBool*)res.addr)->GetBoolval() ) { ((CcBool*)result.addr)->Set(true,true); return 0; } ((CcBool*)result.addr)->Set(true,false); return 0; } int OrSFun( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( !((CcBool*)args[0].addr)->IsDefined() || !((CcBool*)args[1].addr)->IsDefined() ) ((CcBool*)result.addr)->Set(false,false); else if( ((CcBool*)args[0].addr)->GetBoolval() || ((CcBool*)args[1].addr)->GetBoolval() ) ((CcBool*)result.addr)->Set(true,true); else ((CcBool*)result.addr)->Set(true,false); return 0; } /* 4.17 Value mapping functions of operator ~isempty~ */ template int IsEmpty( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); const T* arg = static_cast( args[0].addr ); if( arg->IsDefined() ) { ((CcBool*)result.addr)->Set( true, false ); } else { ((CcBool *)result.addr)->Set( true, true ); } return (0); } /* 4.18 Value mapping functions of operator ~++~ */ int PlusPlusFun( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); char * orgStr = (char*)((CcString*)args[0].addr)->GetStringval(); char newStr[256]; char *lastChar; if( ((CcString*)args[0].addr)->IsDefined() ) { strcpy(newStr, orgStr); if (strlen(newStr)>0) { lastChar= newStr + strlen(newStr) -1; *lastChar=*lastChar+1; } ((CcString *)result.addr)->Set( true, (STRING_T *)&newStr ); } else { ((CcString *)result.addr)->Set( false, ((CcString*)args[0].addr)->GetStringval()); } return (0); } /* 4.19 Value mapping functions of operator ~intersection~ */ int CcSetIntersection_ii( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcInt*)args[0].addr)->IsDefined() && ((CcInt*)args[1].addr)->IsDefined() ) { if( ((CcInt*)args[0].addr)->GetIntval() == ((CcInt*)args[1].addr)->GetIntval() ) { ((CcInt *)result.addr)->Set( true, ((CcInt*)args[0].addr)->GetIntval() ); return (0); } } ((CcInt *)result.addr)->Set( false, 0 ); return (0); } int CcSetIntersection_rr( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcReal*)args[0].addr)->IsDefined() && ((CcReal*)args[1].addr)->IsDefined() ) { if( ((CcReal*)args[0].addr)->GetRealval() == ((CcReal*)args[1].addr)->GetRealval() ) { ((CcReal *)result.addr)->Set( true, ((CcReal*)args[0].addr)->GetRealval() ); return (0); } } ((CcReal *)result.addr)->Set( false, 0.0 ); return (0); } int CcSetIntersection_bb( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcBool*)args[0].addr)->IsDefined() && ((CcBool*)args[1].addr)->IsDefined() ) { if( ((CcBool*)args[0].addr)->GetBoolval() == ((CcBool*)args[1].addr)->GetBoolval() ) { ((CcBool*)result.addr)->Set( true, ((CcBool*)args[0].addr)->GetBoolval() ); return (0); } } ((CcBool *)result.addr)->Set( false, false ); return (0); } int CcSetIntersection_ss( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcString*)args[0].addr)->IsDefined() && ((CcString*)args[1].addr)->IsDefined() ) { if( strcmp( *((CcString*)args[0].addr)->GetStringval(), *((CcString*)args[1].addr)->GetStringval() ) == 0 ) { ((CcString*)result.addr)->Set( true, ((CcString*)args[0].addr)->GetStringval() ); return (0); } } STRING_T nullStr = ""; ((CcString*)result.addr)->Set( false, &nullStr ); return (0); } /* 4.19 Value mapping functions of operator ~minus~ */ int CcSetMinus_ii( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcInt*)args[0].addr)->IsDefined() && ((CcInt*)args[1].addr)->IsDefined() ) { if( ((CcInt*)args[0].addr)->GetIntval() == ((CcInt*)args[1].addr)->GetIntval() ) { ((CcInt *)result.addr)->Set( false, 0 ); return (0); } } ((CcInt *)result.addr)->Set( true, ((CcInt*)args[0].addr)->GetIntval() ); return (0); } int CcSetMinus_rr( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcReal*)args[0].addr)->IsDefined() && ((CcReal*)args[1].addr)->IsDefined() ) { if( ((CcReal*)args[0].addr)->GetRealval() == ((CcReal*)args[1].addr)->GetRealval() ) { ((CcReal *)result.addr)->Set( false, 0.0 ); return (0); } } ((CcReal *)result.addr)->Set( true, ((CcReal*)args[0].addr)->GetRealval() ); return (0); } int CcSetMinus_bb( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcBool*)args[0].addr)->IsDefined() && ((CcBool*)args[1].addr)->IsDefined() ) { if( ((CcBool*)args[0].addr)->GetBoolval() == ((CcBool*)args[1].addr)->GetBoolval() ) { ((CcBool *)result.addr)->Set( false, false ); return (0); } } ((CcBool*)result.addr)->Set( true, ((CcBool*)args[0].addr)->GetBoolval() ); return (0); } int CcSetMinus_ss( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if ( ((CcString*)args[0].addr)->IsDefined() && ((CcString*)args[1].addr)->IsDefined() ) { if( strcmp( *((CcString*)args[0].addr)->GetStringval(), *((CcString*)args[1].addr)->GetStringval() ) == 0 ) { STRING_T nullStr = ""; ((CcString*)result.addr)->Set( false, &nullStr ); return (0); } } ((CcString*)result.addr)->Set( true, ((CcString*)args[0].addr)->GetStringval() ); return (0); } /* 4.21 Value mapping function of operator ~keywords~ The following auxiliary function ~trim~ removes any kind of space characters from the end of a string. */ int trim (char s[]) { int n; for(n = strlen(s) - 1; n >= 0; n--) if ( !isspace(s[n]) ) break; s[n+1] = '\0'; return n; } int keywordsFun (Word* args, Word& result, int message, Word& local, Supplier s) /* Creates a stream of strings containing the single words of the origin string, on the assumption, that words in a string are separated by a space character. */ { struct Subword {int start, nochr, strlength; STRING_T* subw;}* subword; CcString* elem, *str; //CcString* str; int i; string teststr, tmpstr; STRING_T outstr; Word arg0; switch( message ) { case OPEN: // cout << "open" << endl; arg0 = args[0]; str = ((CcString*)arg0.addr); subword = new Subword; subword->start = 0; subword->nochr = 0; subword->subw = (STRING_T*)malloc(strlen(*str->GetStringval()) + 1); // copy input string to allocated memory strcpy(*subword->subw, *str->GetStringval()); trim( *subword->subw ); //remove spaces from the end of the string subword->strlength = strlen(*subword->subw); (*subword->subw)[subword->strlength] = '\0'; // get the necessary values to determine the first single word in the // string, if it is not empty or contains only space characters. if ( subword->strlength > 0) { i=0; while ( isspace(*subword->subw[i]) ) i++; subword->start = i; i=subword->start; while ( (!(isspace(((*subword->subw)[i]))) && ((*subword->subw)[i]) != '\0') ) i++; subword->nochr = i - subword->start; } local.addr = subword; return 0; case REQUEST: // cout << "request" << endl; subword = ((Subword*) local.addr); // another single word in the string still exists if ( (subword->strlength > 0) && (subword->start < subword->strlength) ) { tmpstr = (((string)(*subword->subw)).substr(subword->start, subword->nochr)); strcpy(outstr, (char*)tmpstr.c_str()); trim(outstr); elem = new CcString(true, &outstr); result.addr = elem; // determine the necessary values to get the next word in the string, // if there is any. subword->start += subword->nochr; i = subword->start; if (i < subword->strlength ) { while ( isspace((*subword->subw)[i]) ) i++; subword->start = i; while ( (!isspace((*subword->subw)[i])) && (((*subword->subw)[i]) != '\0') ) i++; subword->nochr = i - subword->start + 1; } local.addr = subword; return YIELD; } // no more single words in the string else { // string is empty or contains only space characters if ( subword->strlength == 0 ) { outstr[0] = '\0'; elem = new CcString(true, &outstr); result.addr = elem; subword->start = subword->strlength = 1; local.addr = subword; return YIELD; } return CANCEL; } case CLOSE: // cout << "close" << endl; if(local.addr) { subword = ((Subword*) local.addr); free(subword->subw); delete subword; local.setAddr(0); } return 0; } /* should not happen */ return -1; } int ifthenelseDataFun(Word* args, Word& result, int message, Word& local, Supplier s) { if(message==OPEN || message==REQUEST){ result = qp->ResultStorage( s ); Word res; qp->Request(args[0].addr, res); CcBool* arg1 = (CcBool*) res.addr; if ( !arg1->IsDefined() ) { ((Attribute*)result.addr)->SetDefined( false ); return 0; } int index = ( arg1->GetBoolval() ? 1 : 2 ); qp->Request(args[index].addr, res); ((Attribute*)result.addr)->CopyFrom( (Attribute*) res.addr ); return 0; } else { return CANCEL; } } int ifthenelseStreamFun(Word* args, Word& result, int message, Word& local, Supplier s) { switch(message){ case OPEN:{ if(local.addr){ delete (int*) local.addr; local.addr = 0; } qp->Request(args[0].addr, result); CcBool* arg1 = (CcBool*) result.addr; if ( !arg1->IsDefined() ) { return 0; // create an empty stream } else { int index = ( arg1->GetBoolval() ? 1 : 2 ); local.addr = new int(index); qp->Open(args[index].addr); } return 0; } case REQUEST: { if(!local.addr){ return CANCEL; } int index = *((int *) local.addr); qp->Request(args[index].addr, result); return qp->Received(args[index].addr)?YIELD: CANCEL; } case CLOSE: { if(!local.addr){ return 0; } int index = *((int *) local.addr); qp->Close(args[index].addr); delete (int*) local.addr; local.addr=0; return 0; } case CLOSEPROGRESS:{ return 0; } case REQUESTPROGRESS:{ if(!local.addr){ return CANCEL; } int index = *((int *) local.addr); ProgressInfo p1; ProgressInfo *pRes; pRes = (ProgressInfo*) result.addr; if ( qp->RequestProgress(args[index].addr, &p1) ) { pRes->Copy(p1); return YIELD; } else { return CANCEL; } } default: abort(); } return 0; } ValueMapping ifthenelseVM[] = { ifthenelseDataFun, ifthenelseStreamFun, 0}; /* 4.21 Value mapping functions of operator ~between~ */ template int CcBetween( Word* args, Word& result, int message, Word& local, Supplier s) { result = qp->ResultStorage( s ); CcBool* res = (CcBool*) result.addr; if ( ((T1*)args[0].addr)->IsDefined() && ((T2*)args[1].addr)->IsDefined() && ((T3*)args[2].addr)->IsDefined() ) { if ( ((T2*)args[1].addr)->GetValue() <= ((T3*)args[2].addr)->GetValue() ) { ((CcBool *)result.addr)->Set( true, ( ((T1*)args[0].addr)->GetValue() >= ((T2*)args[1].addr)->GetValue()) && (((T1*)args[0].addr)->GetValue() <= ((T3*)args[2].addr)->GetValue())); } else { cerr << "ERROR in operator between: second argument must be less or" " equal third argument!" << endl; res->SetDefined(false); } } else { ((CcBool *)result.addr)->Set( false, false ); } return (0); } /* 4.21 Value mapping function of operator ~hashvalue~ */ int CcHashValue( Word* args, Word& result, int message, Word& local, Supplier s) { result = qp->ResultStorage( s ); if ( ((Attribute*)args[0].addr)->IsDefined() && ((CcInt*)args[1].addr)->IsDefined() && (((CcInt*)args[1].addr)->GetValue() > -1) ) { ((CcInt *)result.addr)->Set( true, ((Attribute*)args[0].addr)->HashValue() % ((CcInt*)args[1].addr)->GetValue() ); } else { ((CcInt *)result.addr)->Set( false, 0 ); } return (0); } /* 4.22 Value mapping function of operator ~sqrt~ */ int CcSqrt( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); if( ((CcReal*)args[0].addr)->IsDefined() ) { const double tmp = ((CcReal*)args[0].addr)->GetRealval(); if ( tmp >= 0 ) ((CcReal *)result.addr)-> Set( true, sqrt( tmp ) ); else { ((CcReal *)result.addr)-> Set( false, 0 ); } } else { ((CcReal *)result.addr)-> Set( false, 0 ); } return (0); } /* 4.22 Value mapping function of operator ~length~ */ int CcLengthvaluemap( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); CcInt* res = static_cast(result.addr); CcString* a = static_cast(args[0].addr); if(!a->IsDefined()){ res->SetDefined(false); } else { res->Set(true, a->GetValue().length()); } return (0); } int DistanceStrStrFun( Word* args, Word& result, int message, Word& local, Supplier s ){ result = qp->ResultStorage(s); CcString* source = (CcString*) args[0].addr; CcString* target = (CcString*) args[1].addr; string str1 = (const char*)(source->GetStringval()); string str2 = (const char*)(target->GetStringval()); int dist = stringutils::ld(str1,str2); ((CcInt*)result.addr)->Set(true,dist); return 0; } /* Map any type to a string */ ListExpr CcElapsedTypeMap( ListExpr args ) { const string mapping[] = {CcString::BasicType()}; return SimpleMap(mapping, 1, args); } int ccelapsedfun(Word* args, Word& result, int message, Word& local, Supplier s) { result = qp->ResultStorage( s ); CcString* resStr = reinterpret_cast( result.addr ); StopWatch& elapsedTime = qp->GetTimer(); elapsedTime.diffTimes(); stringstream estr; estr << elapsedTime.diffSecondsReal() << "/" << elapsedTime.diffSecondsCPU(); // reset timer elapsedTime.start(); resStr->Set(true, (STRING_T*) estr.str().c_str()); return 0; } /* 4.16 Operator ~setoption~ This operator maps ---- (string x int -> bool) ---- As a side effect internal configuration parameter of SECONDO are changed. 5.12.0 Specification */ struct setoptionInfo : OperatorInfo { setoptionInfo() : OperatorInfo() { name = "setoption"; signature = "string x int -> bool"; syntax = "setoption(key, n)"; meaning = "Changes the value for key to n. Currently, only " "the option \"MaxMemPerOperator\" is avalaible."; example = "setoption(\"MaxMemPerOperator\", 512*1024);"; } }; /* 5.12.1 Type mapping The type mapping uses the wrapper class ~NList~ which hides calls to class NestedList. Moreover, there are some useful functions for handling streams of tuples. */ static ListExpr setoption_tm(ListExpr args) { const string mapping[] = {CcString::BasicType(), CcInt::BasicType(), CcBool::BasicType()}; return SimpleMap(mapping, 3, args); } int setoption_vm( Word* args, Word& result, int message, Word& local, Supplier s ) { // args[0] : string // args[1] : int result = qp->ResultStorage( s ); //string key = StdTypes::GetString(args[0]); //int value = StdTypes::GetInt(args[1]); bool found=false; if( found ) { ((CcBool *)result.addr)->Set( true, true ); } else { ((CcBool *)result.addr)->Set( false, false ); } return (0); } /* 4.18 Operator ~abs~ */ struct absInfo : OperatorInfo { absInfo() : OperatorInfo() { name = "abs"; signature = "real -> real, int -> int"; syntax = "abs(_)"; meaning = "Returns the absolute value of its argument"; } }; const string maps_abs[2][2] = { {CcReal::BasicType(), CcReal::BasicType()}, {CcInt::BasicType(), CcInt::BasicType() } }; static ListExpr abs_tm(ListExpr args) { return SimpleMaps<2,2>(maps_abs, args); } int abs_sf( ListExpr args ) { return SimpleSelect<2,2>(maps_abs, args); } template int abs_vm( Word* args, Word& result, int message, Word& local, Supplier s ) { // args[0] : real S* arg0 = static_cast(args[0].addr); result = qp->ResultStorage(s); S* res = static_cast(result.addr); if(!arg0->IsDefined()){ res->Set(false,0); } else { res->Set(true,abs(arg0->GetValue())); } return (0); } /* 4.17 Operator ~round~ rounds a real with a given precision */ template int CcRoundValueMapT( Word* args, Word& result, int message, Word& local, Supplier s ) { T* Svalue = (T*) args[0].addr; CcInt* Sprecision = (CcInt*) args[1].addr; result = qp->ResultStorage( s ); CcReal* res = (CcReal*) result.addr; if ( !Svalue->IsDefined() || !Sprecision->IsDefined() ) { res->SetDefined( false ); } else { double value = Svalue->GetValue(); int precision = Sprecision->GetIntval(); static const double base = 10.0; double complete5, complete5i; complete5 = value * pow(base, (double) (precision + 1)); if(value < 0.0) complete5 -= 5.0; else complete5 += 5.0; complete5 /= base; modf(complete5, &complete5i); res->Set( true, complete5i / pow(base, (double) precision) ); } return 0; } ValueMapping roundVM[] = { CcRoundValueMapT, CcRoundValueMapT }; int roundSelect(ListExpr args){ return CcInt::checkType(nl->First(args))?0:1; } /* 4.18 Operator ~int2real~ */ int CcInt2realValueMap( Word* args, Word& result, int message, Word& local, Supplier s ) { CcInt* arg = (CcInt*) args[0].addr; result = qp->ResultStorage( s ); CcReal* res = (CcReal*) result.addr; if ( !arg->IsDefined() ) res->SetDefined( false ); else res->Set( true, (double) arg->GetIntval() ); return 0; } /* 4.19 Operator ~real2int~ */ int CcReal2intValueMap( Word* args, Word& result, int message, Word& local, Supplier s ) { CcReal* arg = (CcReal*) args[0].addr; result = qp->ResultStorage( s ); CcInt* res = (CcInt*) result.addr; if ( !arg->IsDefined() ) res->SetDefined( false ); else { double val = arg->GetRealval(); int ival = (int) val; if( abs((double)ival - val) >2) { res->Set(false,0); } else { res->Set( true, ival ); } } return 0; } /* 4.20 Operator ~int2bool~ */ int CcInt2boolValueMap( Word* args, Word& result, int message, Word& local, Supplier s ) { CcInt* arg = (CcInt*) args[0].addr; result = qp->ResultStorage( s ); CcBool* res = (CcBool*) result.addr; if ( !arg->IsDefined() ) res->SetDefined( false ); else res->Set( true, arg->GetIntval() != 0); return 0; } /* 4.21 Operator ~bool2int~ */ int CcBool2intValueMap( Word* args, Word& result, int message, Word& local, Supplier s ) { CcBool* arg = (CcBool*) args[0].addr; result = qp->ResultStorage( s ); CcInt* res = (CcInt*) result.addr; if ( !arg->IsDefined() ) res->SetDefined( false ); else res->Set( true, arg->GetBoolval() ? 1 : 0); return 0; } /* 4.22 Operator ~floor~ */ int CcFloorValueMap( Word* args, Word& result, int message, Word& local, Supplier s ) { CcReal* arg = (CcReal*) args[0].addr; result = qp->ResultStorage( s ); CcReal* res = (CcReal*) result.addr; if ( !arg->IsDefined() ) res->SetDefined( false ); else res->Set( true, floor(arg->GetRealval())); return 0; } /* 4.23 Operator ~ceil~ */ int CcCeilValueMap( Word* args, Word& result, int message, Word& local, Supplier s ) { CcReal* arg = (CcReal*) args[0].addr; result = qp->ResultStorage( s ); CcReal* res = (CcReal*) result.addr; if ( !arg->IsDefined() ) res->SetDefined( false ); else res->Set( true, ceil(arg->GetRealval())); return 0; } /* 4.24 Operator ~num2string~ */ template int CcNum2String(Word* args, Word& result, int message, Word& local, Supplier s) { T* arg = (T*)args[0].addr; int length = 47; result = qp->ResultStorage(s); CcString* res = (CcString*)result.addr; if (lengthGiven) { CcInt* len = (CcInt*)args[1].addr; if (len->IsDefined()) { length = len->GetValue(); if (length < 1) { length = 1; } else if (length > 47) { length = 47; } } else { res->SetDefined(false); } } if (!arg->IsDefined()) { res->SetDefined(false); } else{ ostringstream os; if (!lengthGiven) { length = arg->toText().length(); } os.precision(length); os << arg->GetValue(); string s = os.str().substr(0, MAX_STRINGSIZE); STRING_T S; strcpy(S,s.c_str()); res->Set(true, &S); } return 0; } /* 4.25 Operator ~char~ */ int CcCharFun( Word* args, Word& result, int message, Word& local, Supplier s ) { CcInt* Cccode = (CcInt*) args[0].addr; result = qp->ResultStorage( s ); CcString* res = (CcString*) result.addr; if ( !Cccode->IsDefined() ) res->SetDefined( false ); else{ STRING_T v; CcInt::inttype value = Cccode->GetValue(); if(value == 0){ v[0] = 0; v[1] = 0; } else { int written = 0; uint32_t s = sizeof(CcInt::inttype); if(WinUnix::isLittleEndian()){ for(uint32_t i=0;i0 || written>0){ v[written] = c; written++; } } } else { for(uint32_t i=0;i> 8; if(c>0 || written>0){ v[written] = c; written++; } } } v[written] = 0; cout << "v[" << written <<"] =0" << endl; } res->Set(true,v); } return 0; } /* 4.25 Operator ~isdefined~ */ int CCisdefinedValueMap( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); Attribute* Obj = (Attribute*) args[0].addr; ((CcBool *)result.addr)->Set( true, Obj->IsDefined() ); return 0; } /* 4.25 Operator ~assert~ */ int CCassertValueMap( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); CcBool* arg = (CcBool*)(args[0].addr); assert(arg->IsDefined()); assert(arg->GetValue()); CcBool* res = (CcBool*)(result.addr); res->CopyFrom(arg); return 0; } /* 4.25 Operator ~cccomparevaluemap~ */ int CCcomparevaluemap( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); Attribute* Obj1 = (Attribute*) args[0].addr; Attribute* Obj2 = (Attribute*) args[1].addr; ((CcInt *)result.addr)->Set( true, Obj1->Compare(Obj2) ); return 0; } /* 4.26 Operators ~getMinVal~ and ~getMaxVal~ A single template function is used to implement both operators. */ template int CCgetminmaxvaluemap( Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); int noArgs = qp->GetNoSons(s); // get number of parameters int resultIndex = 0; // index of the parameter holding the result // compare parameter with current result and update currentResult for(int i = 1;iCompare(Obj2); if((ismin && cmp<0) || (!ismin && cmp>0)){ resultIndex = i; } } (static_cast(result.addr))-> CopyFrom(static_cast(args[resultIndex].addr)); return 0; } /* 4.27 Trigonometric functions: sin, cos, tan, arcsin, arccos, arctan, pi */ enum TrigonOps {sin_op, cos_op, tan_op, arcsin_op, arccos_op, arctan_op, deg2rad_op, rad2deg_op}; template int CCtrigonVM (Word* args, Word& result, int message, Word& local, Supplier s ) { T* arg = static_cast(args[0].addr); result = qp->ResultStorage( s ); CcReal* res = static_cast(result.addr); if(!arg->IsDefined()){ res->SetDefined(false); return 0; } double a = arg->GetValue(); double r = 0.0; errno=0; switch(OP){ case sin_op : { r = sin(a); break; } case cos_op: { r = cos(a); break; } case tan_op: { r = tan(a); break; } case arcsin_op : { r = asin(a); break; } case arccos_op: { r = acos(a); break; } case arctan_op: { r = atan(a); break; } case deg2rad_op: { r = (a * M_PI)/180.0; break; } case rad2deg_op: { r = (180 * a)/M_PI; break; } default: assert( false ); } res->Set(errno==0,r); errno=0; return 0; } int CCArctan2VM ( Word* args, Word& result, int message, Word& local, Supplier s ) { CcReal* yarg = static_cast(args[0].addr); CcReal* xarg = static_cast(args[1].addr); result = qp->ResultStorage( s ); CcReal* res = static_cast(result.addr); if(!yarg->IsDefined() || !xarg->IsDefined()){ res->SetDefined(false); return 0; } double r= atan2(yarg->GetRealval(), xarg->GetRealval()); res->Set(true, r); return 0; } int CcPi (Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); CcReal* res = static_cast(result.addr); res->Set(true,M_PI); return 0; } int CcE (Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); CcReal* res = static_cast(result.addr); res->Set(true,M_E); return 0; } template int CClogBVM (Word* args, Word& result, int message, Word& local, Supplier s ) { T1* v = static_cast(args[0].addr); T2* b = static_cast(args[1].addr); result = qp->ResultStorage( s ); CcReal* res = static_cast(result.addr); if(!v->IsDefined() || !b->IsDefined()){ res->SetDefined(false); return 0; } double vd = v->GetValue(); double bd = b->GetValue(); if(vd<=0 || bd <=0){ res->SetDefined(false); return 0; } res->Set(true,log(vd)/log(bd)); return 0; } /* Value Mapping for the power operator ~pow~ */ template int CCpowVM (Word* args, Word& result, int message, Word& local, Supplier s ) { T1* b = static_cast(args[0].addr); T2* e = static_cast(args[1].addr); result = qp->ResultStorage( s ); CcReal* res = static_cast(result.addr); if(!b->IsDefined() || !e->IsDefined()){ res->SetDefined(false); return 0; } double base = b->GetValue(); double exponent = e->GetValue(); errno = 0; res->Set(true,pow(base,exponent)); res->SetDefined(errno == 0); return 0; } /* Value Mapping for the power operator ~dms2deg~ */ template int CCdms2degVM (Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage( s ); CcReal* res = static_cast(result.addr); int noargs = qp->GetNoSons(s); assert( (noargs==3) || (noargs==4) ); T1* ccDeg = static_cast(args[0].addr); T2* ccMin = static_cast(args[1].addr); T3* ccSec = (noargs==4)?(static_cast(args[2].addr)):0; CcBool* ccCheckrange = static_cast(args[noargs-1].addr); // last if(!ccDeg->IsDefined() || !ccMin->IsDefined() || (ccSec && !ccSec->IsDefined()) || !ccCheckrange->IsDefined() ){ res->Set(false,0.0); return 0; } double deg = ccDeg->GetValue(); double min = ccMin->GetValue(); double sec = (ccSec)?ccSec->GetValue():0.0; bool checkrange = ccCheckrange->GetBoolval(); bool ok = true; double degres = 0.0; if(checkrange){ if( !((-60.0Set(ok, degres); return 0; } /* TypeMapping for binand and binands operator */ ListExpr CCBinAndTM (ListExpr args) { if(!nl->HasLength(args,2)){ return listutils::typeError("Expected int x int "); } if(!CcInt::checkType(nl->First(args)) || !CcInt::checkType(nl->Second(args))){ return listutils::typeError("Expected int x int "); } return listutils::basicSymbol(); } ListExpr CCBinAndSTM (ListExpr args) { string err = "expected stream(int) "; if(!nl->HasLength(args,1)){ return listutils::typeError(err); } if(!Stream::checkType(nl->First(args))){ return listutils::typeError(err); } return listutils::basicSymbol();; } /* ValueMapping for binand and binands operators */ int CCBinAndVM (Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage(s); CcInt* res = static_cast (result.addr); CcInt* int1 = static_cast(args[0].addr); CcInt* int2 = static_cast(args[1].addr); if (!int1->IsDefined() || !int2->IsDefined()){ res->SetDefined(false); return 0; } res->Set(true, int1->GetIntval() & int2->GetIntval()); return 0; } int CCBinAndSVM (Word* args, Word& result, int message, Word& local, Supplier s) { result = qp->ResultStorage(s); CcInt* res = static_cast (result.addr); Word wint; qp->Open(args[0].addr); qp->Request(args[0].addr, wint); if (!qp->Received(args[0].addr)){ res->SetDefined(false); qp->Close(args[0].addr); return 0; } CcInt* curInt = static_cast (wint.addr); int inter = curInt->GetIntval(); curInt->DeleteIfAllowed(); qp->Request(args[0].addr, wint); while (qp->Received(args[0].addr)){ curInt = static_cast (wint.addr); if (curInt->IsDefined()){ inter = inter & curInt->GetIntval(); } curInt->DeleteIfAllowed(); qp->Request(args[0].addr, wint); } res->Set(true, inter); qp->Close(args[0].addr); return 0; } /* 5 Definition of operators Definition of operators is done in a way similar to definition of type constructors: an instance of class ~Operator~ is defined. Because almost all operators are overloaded, we have first do define an array of value mapping functions for each operator. For nonoverloaded operators there is also such and array defined, so it easier to make them overloaded. */ ValueMapping ccplusmap[] = { CcPlus_ii, CcPlus_ir, CcPlus_ri, CcPlus_rr, CcPlus_ss, CcPlus_long, CcPlus_long, CcPlus_long2, CcPlus_rat, CcPlus_rat, CcPlus_rat, CcPlus_rat2, CcPlus_rat2 }; ValueMapping ccminusmap[] = { CcMinus_ii, CcMinus_ir, CcMinus_ri, CcMinus_rr, CcMinus_long, CcMinus_long, CcMinus_long2, CcMinus_rat, CcMinus_rat, CcMinus_rat, CcMinus_rat2, CcMinus_rat2 }; ValueMapping ccproductmap[] = { CcProduct_ii, CcProduct_ir, CcProduct_ri, CcProduct_rr, CcProduct_long, CcProduct_long, CcProduct_long2, CcProduct_rat, CcProduct_rat, CcProduct_rat, CcProduct_rat2, CcProduct_rat2 }; ValueMapping ccdivisionmap[] = { CcDivision_ii, CcDivision_ir, CcDivision_ri, CcDivision_rr, CcDivision_long, CcDivision_long, CcDivision_long2, CcDivision_rat, CcDivision_rat, CcDivision_rat, CcDivision_rat2, CcDivision_rat2 }; ValueMapping ccmodmap[] = { CcMod }; /* Value Mapping array and Selection for div */ ValueMapping ccdivmap[] = { CcDiv, CcDiv, CcDiv, CcDiv }; int ccdivSelect(ListExpr args){ int n1 = CcInt::checkType(nl->First(args))?0:2; int n2 = CcInt::checkType(nl->Second(args))?0:1; return n1 + n2; } ValueMapping ccsqrtmap[] = { CcSqrt }; ValueMapping cclessmap[] = { CcLess, CcLess2, CcLess2, CcLess2, CcLess, CcLess2, CcLess2, CcLess2, CcLess, CcLess, CcLess }; ValueMapping cclessequalmap[] = { CcLessEqual, CcLessEqual2, CcLessEqual2, CcLessEqual2, CcLessEqual, CcLessEqual2, CcLessEqual2, CcLessEqual2, CcLessEqual, CcLessEqual, CcLessEqual }; ValueMapping ccgreatermap[] = { CcGreater, CcGreater2, CcGreater2, CcGreater2, CcGreater, CcGreater2, CcGreater2, CcGreater2, CcGreater, CcGreater, CcGreater }; ValueMapping ccgreaterequalmap[] = { CcGreaterEqual, CcGreaterEqual2, CcGreaterEqual2, CcGreaterEqual2, CcGreaterEqual, CcGreaterEqual2, CcGreaterEqual2, CcGreaterEqual2, CcGreaterEqual, CcGreaterEqual, CcGreaterEqual }; ValueMapping ccequalmap[] = { CcEqual, CcEqual2, CcEqual2, CcEqual2, CcEqual, CcEqual2, CcEqual2, CcEqual2, CcEqual, CcEqual, CcEqual }; ValueMapping ccdiffmap[] = { CcDiff, CcDiff2, CcDiff2, CcDiff2, CcDiff, CcDiff2, CcDiff2, CcDiff2, CcDiff, CcDiff, CcDiff }; ValueMapping cccontainsmap[] = { ContainsFun }; ValueMapping ccandmap[] = { AndFun }; ValueMapping ccandSmap[] = { AndSFun }; ValueMapping ccormap[] = { OrFun }; ValueMapping ccorSmap[] = { OrSFun }; ValueMapping ccnotmap[] = { NotFun }; ValueMapping ccisemptymap[] = { IsEmpty, IsEmpty, IsEmpty, IsEmpty }; ValueMapping ccsetintersectionmap[] = { CcSetIntersection_ii, CcSetIntersection_rr, CcSetIntersection_bb, CcSetIntersection_ss }; ValueMapping ccsetminusmap[] = { CcSetMinus_ii, CcSetMinus_rr, CcSetMinus_bb, CcSetMinus_ss }; ValueMapping cckeywordsmap[] = { keywordsFun }; ValueMapping ccbetweenmap[] = { CcBetween, CcBetween, CcBetween, CcBetween, CcBetween, CcBetween, CcBetween, CcBetween, CcBetween, CcBetween}; //ValueMapping cchashvaluemap[] = { CcHashValue, CcHashValue, //CcHashValue, CcHashValue }; ValueMapping cchashvaluemap[] = { CcHashValue }; ValueMapping ccint2realvaluemap[] = { CcInt2realValueMap }; ValueMapping ccreal2intvaluemap[] = { CcReal2intValueMap }; ValueMapping ccint2boolvaluemap[] = { CcInt2boolValueMap }; ValueMapping ccbool2intvaluemap[] = { CcBool2intValueMap }; ValueMapping ccfloorvaluemap[] = { CcFloorValueMap }; ValueMapping ccceilvaluemap[] = { CcCeilValueMap }; ValueMapping ccnum2stringvaluemap[] = { CcNum2String, CcNum2String, CcNum2String, CcNum2String, CcNum2String, CcNum2String}; ValueMapping abs_vms[] = { abs_vm, abs_vm, 0 }; ValueMapping cccharvaluemap[] = { CcCharFun }; ValueMapping CCsinVM[] = { CCtrigonVM, CCtrigonVM, 0}; ValueMapping CCcosVM[] = { CCtrigonVM, CCtrigonVM, 0}; ValueMapping CCtanVM[] = { CCtrigonVM, CCtrigonVM, 0}; ValueMapping CCarcsinVM[] = { CCtrigonVM, CCtrigonVM, 0}; ValueMapping CCarccosVM[] = { CCtrigonVM, CCtrigonVM, 0}; ValueMapping CCarctanVM[] = { CCtrigonVM, CCtrigonVM, 0}; ValueMapping CCdeg2radVM[] = { CCtrigonVM, CCtrigonVM, 0}; ValueMapping CCrad2degVM[] = { CCtrigonVM, CCtrigonVM, 0}; ValueMapping CClogBmap[] = { CClogBVM, CClogBVM, CClogBVM, CClogBVM, 0}; ValueMapping CCpowmap[] = { CCpowVM, CCpowVM, CCpowVM, CCpowVM, 0}; ValueMapping CCdms2degmap[] = { CCdms2degVM, CCdms2degVM, CCdms2degVM, CCdms2degVM, CCdms2degVM, CCdms2degVM, CCdms2degVM, CCdms2degVM, 0}; const string CCSpecAdd = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (int int) -> int, (int real) -> real, " "(real int)" " -> real, (real real) -> real " "(string string) -> string" "_ + _" "Addition. Strings are concatenated." "query -1.2 + 7" ") )"; const string CCSpecSub = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (int int) -> int, (int real) -> real, " "(real int) -> real, (real real) -> real" "_ - _" "Subtraction" "query -.2 - 4" ") )"; const string CCSpecMul = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (int int) -> int, (int real) -> real, " "(real int) -> real, (real real) -> real" "_ * _" "Multiplication." "query 5 * 1.4 " ") )"; const string CCSpecDiv = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (int int) -> real, (int real) -> real, " "(real int) -> real, (real real) -> real" "_ / _" "Division." "query 5 / 2 " ") )"; const string CCSpecMod = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (int int) -> int" "_ mod _" "Modulo." "query 8 mod 3 " ") )"; const string CCSpecDiv2 = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( ({int, longint} {int,longint}) " "-> {int, longint}" "_ div _" "Integer Division." "query 5 div 2 " ") )"; const string CCSpecSqrt = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( real -> real" "sqrt( _ )" "Extract a root." "query sqrt(2.1)" ") )"; const string CCSpecRandInt = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( int -> int " "randint ( _ )" "Returns a random integer between 0 and " "arg - 1, the argument must be at least 2 otherwise " "it is set to 2. Calling randint(n) for " "n < 2 initializes the " "random number generator with a seed value depending " "on the current time. " "query randint (9)" ") )"; const string CCSpecRandSeed = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( int -> bool " "randseed ( _ )" "initializes the randon number generator with " "a defined value. " "query randseed(8000)" ") )"; const string CCSpecMaxRand = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( -> int " "randmax()" "Returns the value of MAX_RAND " "query randmax()" ") )"; const string CCSpecInitSeq = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( int -> bool " "seqinit ( _ ) " "Returns true and sets the start value " " of the sequence to the argument value" "query seqinit(100)" ") )"; const string CCSpecNextSeq = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( -> int " "seqnext ()" "Returns s+n-1 at the n-th call when the sequence" " was initialized with initseq (s) " "otherwise s defaults to 0." "query seqnext ()" ") )"; const string CCSpecLog = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( int -> int " "log ( _ )" "Computes the logarithmus of base 2." " The argument must be greater" "than 0." "query log (256)" ") )"; const string CCSpecLT = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (int int) -> bool, (int real) -> bool, " "(real int) -> bool, (real real) -> bool, (bool bool)" " -> bool, (string string) -> bool" "_ < _" "Less." "query \"house\" < \"hotel\"" ") )"; const string CCSpecLE = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (int int) -> bool, (int real) -> bool, " "(real int) -> bool, (real real) -> bool, (bool bool)" " -> bool, (string string) -> bool" "_ <= _" "Less or equal." "query 8.2 <= 8.2" ") )"; const string CCSpecGT = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (int int) -> bool, (int real) -> bool, " "(real int) -> bool, (real real) -> bool, (bool bool)" " -> bool, (string string) -> bool" "_ > _" "Greater." "query 3 > 4.1" ") )"; const string CCSpecGE = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (int int) -> bool, (int real) -> bool, " "(real int) -> bool, (real real) -> bool, (bool bool)" " -> bool, (string string) -> bool" "_ >= _" "Greater or equal." "query 3 >= 5" ") )"; const string CCSpecEQ = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (int int) -> bool, (int real) -> bool, " "(real int) -> bool, (real real) -> bool, (bool bool)" " -> bool, (string string) -> bool" "_ = _" "Equal." "query 2.1 = 2.01" ") )"; const string CCSpecNE = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (int int) -> bool, (int real) -> bool, " "(real int) -> bool, (real real) -> bool, (bool bool)" " -> bool, (string string) -> bool" "_ # _" "Not equal." "query 2.1 # 2.01" ") )"; const string CCSpecBeg = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (string string) -> bool" "_ starts _" "Starts." "query \"starts\" starts \"st\"" ") )"; const string CCSpecCon = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (string string) -> bool" "_ contains _" "Contains." "query \"contains\" contains \"tai\"" "" ") )"; const string CCSpecNot = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( bool -> bool" "not ( _ )" "Logical Not." "query not ( 4=4 )" " ) )"; const string CCSpecAnd = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (bool bool) -> bool" "_ and _" "Lazy logical conjunction (AND). Returns TRUE iff both arguments are " "defined and TRUE. The result is always defined. Arguments are evaluated " "in a lazy fashion, first the left argument, then the right one. " "The second argument is only evaluated if the first one is defined and " "TRUE. " "query (8 = 8) and (3 < 4)" ") )"; const string CCSpecAndS = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (bool bool) -> bool" "_ sand _" "Strict logical conjunction (AND). Returns TRUE iff both arguments " "are defined and TRUE. If one of the arguments is UNDEFINED, so is the " "result. All arguments are always evaluated." "query (8 = 8) sand (3 < 4)" ") )"; const string CCSpecOr = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (bool bool) -> bool" "_ or _" "Lazy logical disjunction (OR). Returns TRUE iff at least one " "argument is defined and TRUE. The result is always defined. Arguments are " "evaluated in a lazy fashion, first the left argument, then the right one. " "The second argument is only evaluated if the first one is undefined or " "FALSE. " "query (3 <= 4) or (\"hotel\" > " "\"house\")" "" ") )"; const string CCSpecOrS = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (bool bool) -> bool" "_ sor _" "Strict logical disjunction (OR). Returns TRUE iff both arguments " "are defined and at least one is TRUE. If one of the arguments is " "UNDEFINED, so is the result. All arguments are always evaluated." "query (8 = 8) sor (3 < 4)" ") )"; const string CCSpecIsEmpty = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( bool -> bool, int -> bool, real -> bool," " string -> bool" "isempty ( _ )" "Returns whether the value is defined or " "not." "query isempty ( 8 )" ") )"; const string CCSpecPlusPlus = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( string -> string" " _ ++" "Returns successor for the passed string " "" "query \"hello\"++" ") )"; const string CCSpecSetIntersection = "( ( \"Signature\" \"Meaning\" )" "( (int int) -> int, (real real) -> real," "(bool bool) -> bool, (string string) -> string" " Set intersection. " ") )"; const string CCSpecSetMinus = "( ( \"Signature\" \"Meaning\" )" "( (int int) -> int, (real real) -> real, " "(bool bool) -> bool, (string string) -> string" " Set minus. " ") )"; const string CCSpecKeywords = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (string) -> (stream string)" "_ keywords" "Creates a stream of strings containing the single words" " of the origin string, on the assumption, that words in a string" " are separated by a space character." "query ten feed extendstream(name: mystring keywords) " "consume" ") )"; const string CCSpecIfthenelse = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (bool x T x T) -> T, T in DATA, " "or T = stream(...) " "ifthenelse(P, R1, R2)" " Evalutes and returns the second argument R1, if the " "boolean value expression, given as a first argument P, can be " "evaluated to TRUE. If P evaluates to FALSE, the third argument " "R2 is evaluated and returned. If P is undefined, so is the result" " undefined resp. an empty stream." "" "query ifthenelse(3 < 5,[const string value \"less\"]," "[const string value \"greater\"])" ") )"; const string CCSpecBetween = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( (T x T x T) -> bool" "_ between[_, _]" "Returns true, if the first argument is in the range " "of the second" " and third argument, otherwise false. " "T can be of type int, real, " "string or bool." " NOTE: The second argument must be less or equal than the " "third argument." "query 5 between [3, 8], query \"house\" " "between [\"ha\", \"hu\"]" ") )"; const string specListHeader = "( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"; const string ST = ""; const string ET = ""; const string CCSpecSubStr = "(" + specListHeader + "(" + "'(string x int x int) -> string.'" + "'substr(s, p, q)'" + "'Returns the part of a string s starting at " + "position p and ending at position q. Positions at 1.'" + "'query substr(\"test\",2,3)'))"; const string CCSpecElapsed = "(" + specListHeader + "(" + "'(any type) -> string.'" + "'_ elapsedtime'" + "'Returns the elpased time and the " + "cpu time in seconds encoded in a string'" + "'query plz feed elapsedtime'))"; const string CCLDistSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( string x string -> int" "ldistance ( _ _ )" "compute the distance between two strings " "query ldistance( \"hello\" \"world\" )" ") )"; const string CCHashValueSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )" "( T in DATA, y in int, T x y -> int" "hashvalue ( _, _ )" "computes the hashvalue from object of type T, " "assuming that hashtable has size y." "query hashvalue( \"Test\", 9997 )" ") )"; const string CCRoundSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( ({real,int} x int) -> real" "round(_, _)" "Rounds a real value with a precision of n decimals." "" "query round(10.7367, 3)" ") )"; const string CCint2realSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( int -> real" "int2real( _ )" "Creates a real value from an integer value using " "C++ casting logic." "query int2real(12)" ") )"; const string CCreal2intSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( real -> int" "real2int( _ )" "Creates an int value from a real value" "query real2int(12.345)" ") )"; const string CCint2boolSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( int -> bool" "int2bool( _ )" "Creates a bool value from an integer value. '0' will be " "translated to 'FALSE', all other values to 'TRUE'" "query int2bool(0)" ") )"; const string CCbool2intSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( bool -> int" "bool2int( _ )" "Creates an inteer value from a bool value. 'TRUE' will be " "translated to '1', 'FALSE' to '0'" "query bool2int(TRUE)" ") )"; const string CCfloorSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( real -> real" "floor( _ )" "Returns the largest integer not greater than the " "argument." "query floor(12.345)" ") )"; const string CCceilSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( real -> real" "ceil( _ )" "Returns the smallest integer not less than the " "argument." "query ceil(12.345)" ") )"; const string CCnum2stringSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( {real, int, longint} -> string" "num2string( num )" "Returns the string representation of numeric argument " "'num'." "query num2string(12.345)" ") )"; const string CCcharSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( int -> string" "char( Code )" "Returns a string corresponding with a single charater " "using ANSI-Coding. 'Code'. Code must be in {0, 32 - 126, 128 - 255}, " "otherwise an undefined string is returned. For '0', the string will be " "empty, and '34' ('\"') will be mapped to \"''\"." "query char(25)" ") )"; const string CCisdefinedSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( DATA -> bool" "isdefined( v )" "Tests, whether a value 'v' of a type in kind DATA is defined. " "Actually, the operator depends on the implementation of 'IsDefined()'. " "For several types with set-sementics, this is not implemented " "consequently." "query isdefined(987)" ") )"; const string CCassertSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( bool -> bool" "assert( v )" "Invokes a assertion if the argument is not defined or false " "This operator is for debugging only !!! " "" "query assert(987 = 987)" ") )"; const string CCcompareSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( T x T -> int, T in DATA" "compare( v1, v2 )" "Applies the internal 'Compare' function to both arguments. The " "result is always a defined integer. If both arguments are 'equal', " "the result is 0; if 'v1 < v2', the result is a negative integer, if " "'v1 > v2', the result is a positive integer. Undefined values are " "treated as 'infinitely small', two undefined values are 'equal'. Since " "this operator relies on the type's implementation of 'Compare', the " "behaviour may differ, if the implementation is non-canonical." "query compare(-987, [const int value undef])" ") )"; const string CCgetminvalSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( T^n -> T, T in DATA, n >= 1" "getMinVal( v1, v2, ... )" "Extracts the first (leftmost) minimum value from the parameter " "list, using the generic compare function. Since this operator relies on " "the type's implementation of 'Compare', the behaviour may differ, if the " "implementation is non-canonical." "query getMinVal(45, -45, 12, 0, -75, 5)" ") )"; const string CCgetmaxvalSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( T^n -> T, T in DATA, n >= 1" "getMaxVal( v1, v2, ... )" "Extracts the first (leftmost) maximum value from the parameter " "list, using the generic compare function. Since this operator relies on " "the type's implementation of 'Compare', the behaviour may differ, if the " "implementation is non-canonical." "query getMaxVal(45, -45, 12, 0, -75, 5)" ") )"; const string CClengthSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( string -> int " "length(_)" " Returns the length of the argument" "query length(\"Hello World\")" ") )"; /* Trigonometric functions */ const string CCsinSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( int | real -> real " "sin( v )" "Returns the sinus of v (v is given in rad)." "query sin(deg2rad(90))" ") )"; const string CCcosSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( int | real -> real " "cos( v )" "Returns the cosinus of v (v is given in rad)." "query cos(deg2rad(90))" ") )"; const string CCtanSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( int | real -> real " "tan( v )" "Returns the tangens of v (v is given in rad)." "query tan(deg2rad(90))" ") )"; const string CCarcsinSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( int | real -> real " "arcsin( v )" "Returns the principal value of the arc sine of x, expressed " "in radians, in the interval [-pi/2,+pi/2] radians." "query arcsin(sin(deg2rad(90)))" ") )"; const string CCarccosSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( int | real -> real " "arccos( v )" "Returns the principal value of the arc cosine of x, " "expressed in radians, in the interval [0,pi] radians." "query arccos(sin(deg2rad(90)))" ") )"; const string CCarctanSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( int | real -> real " "arctan( v )" "Returns the principal value of the arc tangent of x, expressed in " "radians, in the interval [-pi/2,+pi/2] radians" " of v (v is given in rad)." "query arctan(tan(deg2rad(90)))" ") )"; const string CCarctan2Spec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( real x real -> real " "arctan2( dy, dx )" "Returns the principal value of the arc tangent of y/x, " "expressed in radians, in the interval [-pi,+pi] radians." "query arctan2(tan(deg2rad(90)))" ") )"; const string CCpiSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( -> real " "const_pi()" "Returns pi (= 3.14159...)" "query sin(const_pi())" ") )"; const string CCdeg2radSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( int | real -> real " "deg2rad( v )" "Convert angle from degrees to radians." "query arctan(tan(deg2rad(90)))" ") )"; const string CCrad2degSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( int | real -> real " "rad2deg( v )" "Convert angle from radians to degrees." "query rad2deg(const_pi())" ") )"; const string CCeSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( -> real " "const_e()" "Returns E (= 2.718281828459...)" "query const_e()" ") )"; const string CClogBSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( {int | real} x {int | real} -> real " "logB( val , base)" "Returns the logarithm of 'val' to the given 'base'." "query logB(const_e()*const_e(),const_e())" ") )"; const string CCpowSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( {int | real} x {int | real} -> real " "pow( Base , Exponent)" "Returns Base to the power of Exponent. Returns UNDEF if any " "argument is UNDEF, type real cannot represent the result, or Base is " "negative and Exponent is not an integral value." "query pow(2.0, 10)" ") )"; const string CCdms2degSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( {int|real} x {int|real} [x {int|real}] [x bool] -> real" "dms2deg( Deg , Min [, Sec] [, CheckRange] )" "Converts an Angle with Deg degrees, Min minutes and Sec seconds into" " a single real value with fractional degrees. If CheckRange is FALSE " " (default), all arguments are converted to degrees and summed up. " "Otherwise only the last numeric argument may be fractional and -60" "query dms2deg(7, -17.1, 64, FALSE)" ") )"; /* binary and of integer values and streams of integer values */ const string CCBinAndSpec = "(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( int X int -> int " " _ binand _ " "Computes the binary and conjunction of the two given int as int value." "" "query 15 binand 4 " ") )"; const string CCBinAndSSpec = "(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )" "( stream(int) -> int " " _ binands " "Computes the binary conjunction of the stream of int values." "" "query intstream(1,5) binands " ") )"; /* Operator instance definitions */ Operator ccplus( "+", CCSpecAdd, 13, ccplusmap, CcPlusSelectCompute, CcPlusTypeMap ); Operator ccminus( "-", CCSpecSub, 12, ccminusmap, CcMathSelectCompute, CcMathTypeMap ); Operator ccproduct( "*", CCSpecMul, 12, ccproductmap, CcMathSelectCompute, CcMathTypeMap ); Operator ccdivision( "/", CCSpecDiv, 12, ccdivisionmap, CcMathSelectCompute, CcMathTypeMapdiv ); Operator ccmod( "mod", CCSpecMod, 1, ccmodmap, Operator::SimpleSelect, CcMathTypeMap1 ); Operator ccdiv( "div", CCSpecDiv2, 4, ccdivmap, ccdivSelect, divTM ); Operator ccsqrt( "sqrt", CCSpecSqrt, 1, ccsqrtmap, Operator::SimpleSelect, RealReal ); Operator ccrandint( "randint", CCSpecRandInt, RandInt, Operator::SimpleSelect, IntInt ); Operator ccrandseed( "randseed", CCSpecRandSeed, RandSeed, Operator::SimpleSelect, IntBool ); Operator ccrandmax( "randmax", CCSpecMaxRand, MaxRand, Operator::SimpleSelect, EmptyInt ); Operator ccseqinit( "seqinit", CCSpecInitSeq, InitSeq, Operator::SimpleSelect, IntBool ); Operator ccseqnext( "seqnext", CCSpecNextSeq, NextSeq, Operator::SimpleSelect, EmptyInt ); Operator cclog( "log", CCSpecLog, LogFun, Operator::SimpleSelect, IntInt ); Operator ccless( "<", CCSpecLT, 11, cclessmap, CcMathSelectCompare, CompareTypeMap); Operator cclessequal( "<=", CCSpecLE, 11, cclessequalmap, CcMathSelectCompare, CompareTypeMap ); Operator ccgreater( ">", CCSpecGT, 11, ccgreatermap, CcMathSelectCompare, CompareTypeMap ); Operator ccgreaterequal( ">=", CCSpecGE, 11, ccgreaterequalmap, CcMathSelectCompare, CompareTypeMap ); Operator ccequal( "=", CCSpecEQ, 11, ccequalmap, CcMathSelectCompare, CompareTypeMap ); Operator ccdiff( "#", CCSpecNE, 11, ccdiffmap, CcMathSelectCompare, CompareTypeMap ); Operator cccontains( "contains", CCSpecCon, 1, cccontainsmap, Operator::SimpleSelect, CcMathTypeMapBool3 ); Operator ccsubstr( "substr", CCSpecSubStr, SubStrFun, Operator::SimpleSelect, SubStrTypeMap ); Operator ccnot( "not", CCSpecNot, 1, ccnotmap, Operator::SimpleSelect, CcMathTypeMapBool1 ); Operator ccand( "and", CCSpecAnd, 1, ccandmap, Operator::SimpleSelect, CcMathTypeMapBool2 ); Operator ccandS( "sand", CCSpecAndS, 1, ccandSmap, Operator::SimpleSelect, CcMathTypeMapBool2 ); Operator ccor( "or", CCSpecOr, 1, ccormap, Operator::SimpleSelect, CcMathTypeMapBool2 ); Operator ccorS( "sor", CCSpecOrS, 1, ccorSmap, Operator::SimpleSelect, CcMathTypeMapBool2 ); Operator ccisempty( "isempty", CCSpecIsEmpty, 4, ccisemptymap, CcMathSelectIsEmpty, CcMathTypeMapBool4 ); Operator ccplusplus( "++", CCSpecPlusPlus, PlusPlusFun, Operator::SimpleSelect, CcStringMapCcString ); Operator ccsetintersection( "intersection", CCSpecSetIntersection, 4, ccsetintersectionmap, CcMathSelectSet, CcMathTypeMap2 ); Operator ccsetminus( "minus", CCSpecSetMinus, 4, ccsetminusmap, CcMathSelectSet, CcMathTypeMap2 ); Operator ccopkeywords( "keywords", CCSpecKeywords, 1, cckeywordsmap, Operator::SimpleSelect, keywordsType ); Operator ccopifthenelse( "ifthenelse", CCSpecIfthenelse, 2, ifthenelseVM, ifthenelseSelect, ifthenelseType ); Operator ccbetween( "between", CCSpecBetween, 10, ccbetweenmap, CcBetweenSelect, CcBetweenTypeMap ); Operator ccelapsedtime( "elapsedtime", CCSpecElapsed, ccelapsedfun, Operator::SimpleSelect, CcElapsedTypeMap ); Operator ccldistance( "ldistance", CCLDistSpec, DistanceStrStrFun, Operator::SimpleSelect, CcLDistTypeMap); //Operator cchashvalue( "hashvalue", CCHashValueSpec, 4, cchashvaluemap, //CcHashValueSelect, CcHashValueTypeMap); Operator cchashvalue( "hashvalue", CCHashValueSpec, 1, cchashvaluemap, Operator::SimpleSelect, CcHashValueTypeMap); Operator ccround( "round", CCRoundSpec, 2, roundVM, roundSelect, CcRoundTypeMap); Operator ccint2real( "int2real", CCint2realSpec, 1, ccint2realvaluemap, Operator::SimpleSelect, IntReal); Operator ccreal2int( "real2int", CCreal2intSpec, 1, ccreal2intvaluemap, Operator::SimpleSelect, RealInt); Operator ccint2bool( "int2bool", CCint2boolSpec, 1, ccint2boolvaluemap, Operator::SimpleSelect, IntBool); Operator ccbool2int( "bool2int", CCbool2intSpec, 1, ccbool2intvaluemap, Operator::SimpleSelect, BoolInt); Operator ccceil( "ceil", CCceilSpec, 1, ccceilvaluemap, Operator::SimpleSelect, RealReal); Operator ccfloor( "floor", CCfloorSpec, 1, ccfloorvaluemap, Operator::SimpleSelect, RealReal); Operator ccnum2string( "num2string", CCnum2stringSpec, 6, ccnum2stringvaluemap, ccnum2stringSelect, NumStringTypeMap); Operator ccchar( "char", CCcharSpec, 1, cccharvaluemap, Operator::SimpleSelect, IntString); Operator ccisdefined( "isdefined", CCisdefinedSpec, CCisdefinedValueMap, Operator::SimpleSelect, DATAbool); Operator ccassert( "assert", CCassertSpec, CCassertValueMap, Operator::SimpleSelect, CcMathTypeMapBool1); Operator cccompare( "compare", CCcompareSpec, CCcomparevaluemap, Operator::SimpleSelect, CcTypeMapTinDATA_TinDATAint); Operator ccgetminval( "getMinVal", CCgetminvalSpec, CCgetminmaxvaluemap, Operator::SimpleSelect, CcTypeMapTinDATAexpplus2TinDATA); Operator ccgetmaxval( "getMaxVal", CCgetmaxvalSpec, CCgetminmaxvaluemap, Operator::SimpleSelect, CcTypeMapTinDATAexpplus2TinDATA); Operator cclength( "length", CClengthSpec, CcLengthvaluemap, Operator::SimpleSelect, TypeMap1); /* Trigonometric functions */ Operator ccsin( "sin", CCsinSpec, 2, CCsinVM, CcNumRealSelect, CcTypeMapNumReal); Operator cccos( "cos", CCcosSpec, 2, CCcosVM, CcNumRealSelect, CcTypeMapNumReal); Operator cctan( "tan", CCtanSpec, 2, CCtanVM, CcNumRealSelect, CcTypeMapNumReal); Operator ccarcsin( "arcsin", CCarcsinSpec, 2, CCarcsinVM, CcNumRealSelect, CcTypeMapNumReal); Operator ccarccos( "arccos", CCarccosSpec, 2, CCarccosVM, CcNumRealSelect, CcTypeMapNumReal); Operator ccarctan( "arctan", CCarctanSpec, 2, CCarctanVM, CcNumRealSelect, CcTypeMapNumReal); Operator ccarctan2( "arctan2", CCarctan2Spec, CCArctan2VM, Operator::SimpleSelect, CcTypeMapRealRealReal); Operator ccpi( "const_pi", CCpiSpec, CcPi, Operator::SimpleSelect, CcTypeMapEmptyReal); Operator ccdeg2rad( "deg2rad", CCdeg2radSpec, 2, CCdeg2radVM, CcNumRealSelect, CcTypeMapNumReal); Operator ccrad2deg( "rad2deg", CCrad2degSpec, 2, CCrad2degVM, CcNumRealSelect, CcTypeMapNumReal); Operator cce( "const_e", CCeSpec, CcE, Operator::SimpleSelect, CcTypeMapEmptyReal); Operator cclogb("logB", CClogBSpec, 4, CClogBmap, CcNumNumRealSelect, CcTypeMapNumNumReal); Operator ccpow("pow", CCpowSpec, 4, CCpowmap, CcNumNumRealSelect, CcTypeMapNumNumReal); Operator ccdms2deg("dms2deg", CCdms2degSpec, 8, CCdms2degmap, CcNumNumNumRealSelect, CcTypeMapNumNumOptNumOptBoolReal); /* 1.1 binary and of two integers and binary and for a stream of integers */ Operator ccbinand("binand", CCBinAndSpec, CCBinAndVM, Operator::SimpleSelect, CCBinAndTM); Operator ccbinands("binands", CCBinAndSSpec, CCBinAndSVM, Operator::SimpleSelect, CCBinAndSTM); /* 5.98 Operator switch THis operator simulates a switch case statement. 5.98.1 TypeMapping */ ListExpr switchTM(ListExpr args){ int len = nl->ListLength(args); if(len < 4){ return listutils::typeError("at least four arguments required"); } bool isEven = (len & 1)==0; if(!isEven){ return listutils::typeError("even number of arguments required"); } ListExpr firstArg = nl->First(args); if(!listutils::isDATA(firstArg)){ return listutils::typeError("first argument must be in kind data"); } ListExpr rest = nl->Rest(args); bool isFirst = true; ListExpr resType = nl->TheEmptyList(); bool odd = true; int no = 1; while(!nl->IsEmpty(rest)){ ListExpr first = nl->First(rest); rest = nl->Rest(rest); no++; if(odd && (no!=len)){ // switch type if(!nl->Equal(firstArg,first)){ return listutils::typeError("One of the Cases has different " "type to first argument"); } } else { // result type if(isFirst){ resType = first; if(!listutils::isDATA(resType) && !listutils::isStream(resType)){ return listutils::typeError(nl->ToString(resType) + " is not in Kind Data"); } } else { if(!nl->Equal(resType,first)){ return listutils::typeError("Different result types detected"); } } } odd = !odd; } return resType; } /* 5.98.2 Value Mapping */ int switchVM0 (Word* args, Word& result, int message, Word& local, Supplier s ) { Attribute* sw = (Attribute*) args[0].addr; int noArgs = qp->GetNoSons(s); int index = noArgs - 1; // the default value // try to find a better index bool found = false; for(int i=1;iCompare(v); if(cmp==0){ found = true; index = i+1; } } result = qp->ResultStorage(s); Attribute* res = (Attribute*) result.addr; res->CopyFrom((Attribute*) args[index].addr); return 0; } int switchVM1 (Word* args, Word& result, int message, Word& local, Supplier s ) { int* li = (int*) local.addr; switch(message){ case OPEN: { if(li){ delete li; } Attribute* sw = (Attribute*) args[0].addr; int noArgs = qp->GetNoSons(s); int index = noArgs - 1; // the default value // try to find a better index bool found = false; for(int i=1;iCompare(v); if(cmp==0){ found = true; index = i+1; } } qp->Open(args[index].addr); local.addr = new int(index); return 0; } case REQUEST: { if(!li){ result.addr = 0; return CANCEL; } Word w; qp->Request(args[*li].addr,w); if(qp->Received(args[*li].addr)){ result = w; return YIELD; } else { result.addr = 0; return CANCEL; } } case CLOSE: { if(li){ qp->Close(args[*li].addr); delete li; local.addr = 0; } return 0; } } return -1; } /* 1.98.3 Selection function */ int switchSelect(ListExpr args){ int len = nl->ListLength(args); ListExpr resType; if(len==2){ resType = nl->Second(args); } else { resType = nl->Third(args); } if(listutils::isDATA(resType)){ return 0; } else { return 1; } } /* 1.98.4 Value Mapping array */ ValueMapping switchVM[]={ switchVM0, switchVM1 }; /* 1.98.5 Specification */ OperatorSpec switchSpec( "t x (t x r)* x r -> r. with t in DATA, r in DATA U STREAM", " switchvalue switch[ case1 , res1; case2 , res2 ; ... ; default] ", " Returns the first res_i for what holds case_i = switchvalue. If no such" " case exists, default is returned", " query randint(2) switch[ 0 , 'Null'; 1, 'One'; 2 , 'Two'; 'Unknown']" ); /* 1.98.6 Operator instance */ Operator switchOp( "switch", switchSpec.getStr(), 2, switchVM, switchSelect, switchTM); /* 1.99 Operator int2longint */ ListExpr int2longintTM(ListExpr args){ if(!nl->HasLength(args,1)){ return listutils::typeError("int expected"); } if(CcInt::checkType(nl->First(args))){ return listutils::basicSymbol(); } return listutils::typeError("int expected"); } int int2longintVM (Word* args, Word& result, int message, Word& local, Supplier s ) { CcInt* arg = (CcInt*) args[0].addr; result=qp->ResultStorage(s); LongInt* res = (LongInt*) result.addr; res->SetValue(*arg); return 0; } OperatorSpec int2longintSpec( "int -> longint", "int2longint(_) ", "Converts an int to a longint. ", " query int2longint(2)" ); Operator int2longint( "int2longint", int2longintSpec.getStr(), int2longintVM, Operator::SimpleSelect, int2longintTM); /* 1.99 Operator longint2int */ ListExpr longint2intTM(ListExpr args){ if(!nl->HasLength(args,1)){ return listutils::typeError("longint expected"); } if(LongInt::checkType(nl->First(args))){ return listutils::basicSymbol(); } return listutils::typeError("longint expected"); } int longint2intVM (Word* args, Word& result, int message, Word& local, Supplier s ) { LongInt* arg = (LongInt*) args[0].addr; result=qp->ResultStorage(s); CcInt* res = (CcInt*) result.addr; if(!arg->IsDefined()){ res->SetDefined(false); } else { int64_t v = arg->GetValue(); int32_t vi = (int32_t) v; if(v!=vi){ res->SetDefined(false); } else { res->Set(true,vi); } } return 0; } OperatorSpec longint2intSpec( "longint -> int", "longint2int(_) ", "Converts a longint to an int. ", " query longint2int(int2longint(2))" ); Operator longint2int( "longint2int", longint2intSpec.getStr(), longint2intVM, Operator::SimpleSelect, longint2intTM); /* Operator ~rat~ This operator converts several numeric types into a rational */ ListExpr ratTM(ListExpr args){ string err = "{int,long,string} or (i1 x i2) with ii int type expected"; if(!nl->HasLength(args,1) && !nl->HasLength(args,2)){ return listutils::typeError(err); } if(nl->HasLength(args,1)){ ListExpr arg1 = nl->First(args); if(CcInt::checkType(arg1) || LongInt::checkType(arg1) || CcString::checkType(arg1)){ return listutils::basicSymbol(); } return listutils::typeError(err); } // two arguments ListExpr arg1 = nl->First(args); ListExpr arg2 = nl->Second(args); if(!CcInt::checkType(arg1) && !LongInt::checkType(arg1)){ return listutils::typeError(err); } if(!CcInt::checkType(arg2) && !LongInt::checkType(arg2)){ return listutils::typeError(err); } return listutils::basicSymbol(); } template int ratVM1 (Word* args, Word& result, int message, Word& local, Supplier s ) { S* arg = (S*) args[0].addr; result = qp->ResultStorage(s); Rational* res = (Rational*) result.addr; Rational r(*arg); (*res) = r; return 0; } template int ratVM2 (Word* args, Word& result, int message, Word& local, Supplier s ) { S1* arg1 = (S1*) args[0].addr; S2* arg2 = (S2*) args[1].addr; result = qp->ResultStorage(s); Rational* res = (Rational*) result.addr; Rational r(*arg1, *arg2); (*res) = r; return 0; } ValueMapping ratVM[] ={ ratVM1, ratVM1, ratVM1, ratVM2, ratVM2, ratVM2, ratVM2 }; int ratSelect(ListExpr args){ if(nl->HasLength(args,1)){ ListExpr arg = nl->First(args); if(CcInt::checkType(arg)){ return 0; } if(LongInt::checkType(arg)){ return 1; } if(CcString::checkType(arg)){ return 2; } return -1; } // 2 arguments ListExpr arg1 = nl->First(args); ListExpr arg2 = nl->Second(args); int s1 = CcInt::checkType(arg1)?3:5; int s2 = CcInt::checkType(arg2)?0:1; return s1+s2; } OperatorSpec ratSpec( "{int, longint, string} -> rational " "or i1 x i2 -> rational , i1,i2 in {int,longint}", "rat(_) ", "Converts the argument(s) to a rational ", " query rat(-32,8)" ); Operator rat( "rat", ratSpec.getStr(), 7, ratVM, ratSelect, ratTM); /* Operator chars */ ListExpr charsTM(ListExpr args){ string err = "string expected"; if(!nl->HasLength(args,1)){ return listutils::typeError(err); } if(!CcString::checkType(nl->First(args))){ return listutils::typeError(err); } return nl->TwoElemList( listutils::basicSymbol >(), listutils::basicSymbol()); } class charsInfo{ public: charsInfo(CcString& s): str(""), pos(0), finished(false){ if(!s.IsDefined()){ finished=true; } str = s.GetValue(); finished = str.length()==pos; } CcInt* getNext(){ if(finished ){ return 0; } unsigned char s = str[pos]; pos++; finished = pos == str.length(); return new CcInt(true,s); } private: string str; size_t pos; bool finished; }; int charsVM (Word* args, Word& result, int message, Word& local, Supplier s ) { charsInfo* li = (charsInfo*) local.addr; switch(message){ case OPEN : if(li){ delete li; } local.addr = new charsInfo(*((CcString*)args[0].addr)); return 0; case REQUEST: result.addr = li?li->getNext():0; return result.addr?YIELD:CANCEL; case CLOSE: if(li){ delete li; local.addr = 0; } return 0; } return -1; } OperatorSpec charsSpec( "string -> stream(int)", "chars(_) ", "Returns the characters from the inputs codes as integers ", " query chars(\"test\") count" ); Operator chars( "chars", charsSpec.getStr(), charsVM, Operator::SimpleSelect, charsTM); /* 5.16 Operators ~true~ and ~false~ 5.16.1 Type Mapping */ ListExpr true_falseTM(ListExpr args){ if(!nl->IsEmpty(args)){ return listutils::typeError("no arguments exspected"); } return listutils::basicSymbol(); } /* 5.16.2 Value Mapping */ template int true_falseVM (Word* args, Word& result, int message, Word& local, Supplier s ) { result = qp->ResultStorage(s); CcBool* res = (CcBool*) result.addr; res->Set(true,v); return 0; } /* 5.16.3 Specification. */ OperatorSpec trueSpec( "-> bool", "true() ", "Returns the constant TRUE ", " query true()" ); OperatorSpec falseSpec( "-> bool", "false() ", "Returns the constant false ", " query false()" ); /* 5.16.4 Operator instances */ Operator trueOp( "true", trueSpec.getStr(), true_falseVM, Operator::SimpleSelect, true_falseTM); Operator falseOp( "false", falseSpec.getStr(), true_falseVM, Operator::SimpleSelect, true_falseTM); /* Operator isnan */ ListExpr isnanTM(ListExpr args){ if(!nl->HasLength(args,1)){ return listutils::typeError("one argumemnt expected"); } if(!CcReal::checkType(nl->First(args))){ return listutils::typeError("real expected"); } return listutils::basicSymbol(); } int isnanVM (Word* args, Word& result, int message, Word& local, Supplier s ) { CcReal* a = (CcReal*) args[0].addr; result = qp->ResultStorage(s); CcBool* res = (CcBool*) result.addr; if(!a->IsDefined()){ res->Set(true,false); } else { res->Set(true, isnan(a->GetValue())); } return 0; } OperatorSpec isnanSpec( "real -> bool", "isnan(_) ", "Checks whether the argument contains not a number. " "For undefined value, the result will be false.", " query isnan(1.0)" ); Operator isnanOp( "isnan", isnanSpec.getStr(), isnanVM, Operator::SimpleSelect, isnanTM); /* Operator outerjoin */ ListExpr outerjoinTM(ListExpr args){ if(!nl->HasLength(args,1)){ return listutils::typeError("one argumemnt expected"); } if(!CcBool::checkType(nl->First(args))){ return listutils::typeError("boolean expected as parameter"); } return listutils::basicSymbol(); } int outerjoinVM (Word* args, Word& result, int message, Word& local, Supplier s ) { CcBool* input = (CcBool*) args[0].addr; result = qp->ResultStorage(s); CcBool* res = (CcBool*) result.addr; res -> Set(input->IsDefined(), input -> GetValue()); return 0; } OperatorSpec outerjoinSpec( "bool -> bool", "outerjoin(_) ", "Helper operator for performing outer joins in the operator. " "The operator simply returns the provided boolean.", " query outerjoin(TRUE)" ); Operator outerjoinOp( "outerjoin", outerjoinSpec.getStr(), outerjoinVM, Operator::SimpleSelect, outerjoinTM); /* 6 Class ~CcAlgebra~ The last steps in adding an algebra to the Secondo system are * Associating value mapping functions with their operators * ``Bunching'' all type constructors and operators in one instance of class ~Algebra~. Therefore, a new subclass ~CcAlgebra~ of class ~Algebra~ is declared. The only specialization with respect to class ~Algebra~ takes place within the constructor: all type constructors and operators are registered at the actual algebra. After declaring the new class, its only instance ~ccalgebra1~ is defined. */ class CcAlgebra1 : public Algebra { public: CcAlgebra1() : Algebra() { AddTypeConstructor( &ccInt ); AddTypeConstructor( &ccReal ); AddTypeConstructor( &ccBool ); AddTypeConstructor( &ccString ); AddTypeConstructor( &longint); AddTypeConstructor( &rational); ccInt.AssociateKind( Kind::DATA() ); ccReal.AssociateKind( Kind::DATA() ); ccBool.AssociateKind( Kind::DATA() ); ccString.AssociateKind( Kind::DATA() ); longint.AssociateKind(Kind::DATA()); rational.AssociateKind(Kind::DATA()); ccInt.AssociateKind( Kind::BASE() ); ccReal.AssociateKind( Kind::BASE() ); ccBool.AssociateKind( Kind::BASE() ); ccString.AssociateKind( Kind::BASE() ); longint.AssociateKind( Kind::BASE() ); rational.AssociateKind( Kind::BASE() ); ccInt.AssociateKind( Kind::CSVEXPORTABLE() ); ccReal.AssociateKind( Kind::CSVEXPORTABLE() ); ccBool.AssociateKind( Kind::CSVEXPORTABLE() ); ccString.AssociateKind( Kind::CSVEXPORTABLE() ); longint.AssociateKind( Kind::CSVEXPORTABLE() ); rational.AssociateKind( Kind::CSVEXPORTABLE() ); ccInt.AssociateKind( Kind::CSVIMPORTABLE() ); ccReal.AssociateKind( Kind::CSVIMPORTABLE() ); ccBool.AssociateKind( Kind::CSVIMPORTABLE() ); ccString.AssociateKind( Kind::CSVIMPORTABLE() ); longint.AssociateKind( Kind::CSVIMPORTABLE() ); rational.AssociateKind( Kind::CSVIMPORTABLE() ); ccInt.AssociateKind( Kind::SQLEXPORTABLE() ); ccReal.AssociateKind( Kind::SQLEXPORTABLE() ); ccBool.AssociateKind( Kind::SQLEXPORTABLE() ); ccString.AssociateKind( Kind::SQLEXPORTABLE() ); ccInt.AssociateKind( Kind::DELIVERABLE() ); ccReal.AssociateKind( Kind::DELIVERABLE() ); ccBool.AssociateKind( Kind::DELIVERABLE() ); ccString.AssociateKind( Kind::DELIVERABLE() ); longint.AssociateKind(Kind::INDEXABLE()); AddOperator( &ccplus ); AddOperator( &ccminus ); AddOperator( &ccproduct ); AddOperator( &ccdivision ); AddOperator( &ccmod ); AddOperator( &ccdiv ); AddOperator( &ccsqrt ); AddOperator( &ccrandint ); AddOperator( &ccrandseed ); AddOperator( &ccrandmax ); AddOperator( &ccseqinit ); AddOperator( &ccseqnext ); AddOperator( &cclog ); AddOperator( &ccless ); AddOperator( &cclessequal ); AddOperator( &ccgreater ); AddOperator( &ccgreaterequal ); AddOperator( &ccequal ); AddOperator( &ccdiff ); AddOperator( &cccontains ); AddOperator( &ccsubstr ); AddOperator( &ccnot ); AddOperator( &ccand ); ccand.SetRequestsArguments(); AddOperator( &ccandS ); AddOperator( &ccor ); ccor.SetRequestsArguments(); AddOperator( &ccorS ); AddOperator( &ccisempty ); AddOperator( &ccplusplus ); AddOperator( &ccsetintersection ); AddOperator( &ccsetminus ); AddOperator( &ccopkeywords ); AddOperator( &ccopifthenelse ); ccopifthenelse.SetRequestsArguments(); AddOperator( &ccbetween ); //AddOperator( &ccelapsedtime ); AddOperator( &ccldistance ); AddOperator( &cchashvalue ) ; AddOperator( &ccround ); AddOperator( &ccint2real ); AddOperator( &ccreal2int ); AddOperator( &ccint2bool ); AddOperator( &ccbool2int ); AddOperator( &ccceil ); AddOperator( &ccfloor ); AddOperator( &ccchar ); AddOperator( &ccnum2string ); AddOperator( &ccisdefined ); AddOperator( &ccassert ); AddOperator( &cccompare ); AddOperator( &ccgetminval ); AddOperator( &ccgetmaxval ); AddOperator( &cclength ); AddOperator( &ccsin ); AddOperator( &cccos ); AddOperator( &cctan ); AddOperator( &ccarcsin ); AddOperator( &ccarccos ); AddOperator( &ccarctan ); AddOperator( &ccarctan2); AddOperator( &ccpi ); AddOperator( &ccdeg2rad ); AddOperator( &ccrad2deg ); AddOperator( &cce ); AddOperator( &cclogb ); AddOperator( &ccpow ); AddOperator( &ccdms2deg ); AddOperator( setoptionInfo(), setoption_vm, setoption_tm ); AddOperator( absInfo(), abs_vms, abs_sf, abs_tm ); AddOperator (&ccbinand); AddOperator( &ccbinands); AddOperator (&switchOp); AddOperator (&int2longint); AddOperator (&longint2int); AddOperator (&rat); AddOperator (&chars); AddOperator (&trueOp); AddOperator (&falseOp); AddOperator (&isnanOp); AddOperator (&outerjoinOp); #ifdef USE_PROGRESS ccopifthenelse.EnableProgress(); #endif } ~CcAlgebra1() {}; }; /* 7 Initialization Each algebra module needs an initialization function. The algebra manager has a reference to this function if this algebra is included in the list of required algebras, thus forcing the linker to include this module. The algebra manager invokes this function to get a reference to the instance of the algebra class and to provide references to the global nested list container (used to store constructor, type, operator and object information) and to the query processor. The function has a C interface to make it possible to load the algebra dynamically at runtime. */ extern "C" Algebra* InitializeStandardAlgebra( NestedList* nlRef, QueryProcessor* qpRef ) { nl = nlRef; qp = qpRef; srand ( time(NULL) ); return (new CcAlgebra1); } /* 8 Query examples Now we are ready to compile this algebra implementation and link the resulting object file with the Secondo library to a Secondo executable containing our example algebra. Here are some example queries: * "(list operators)"[1] Among others, the operators ~+~, ~-~, ~[*]~, and ~/~ are listed. * "(list type constructors)"[1] ~int~ , ~real~, ~bool~and ~string~ are part of the output. * "(query (+ 4 5))"[1] Result value 9 is returned. * "(query ([*] (+ 4 5.7)(- 2.5 4)))"[1] Result value -14.55 is returned. * "(query (or ( $ < $ 4 5.7)( $ > $ 2.5 4)))"[1] Result value TRUE is returned. */ void Statistics2Counters(bool reset, bool show) { if( reset ) { CcInt::intsCreated = 0; CcInt::intsDeleted = 0; CcReal::realsCreated = 0; CcReal::realsDeleted = 0; CcBool::boolsCreated = 0; CcBool::boolsDeleted = 0; CcString::stringsCreated = 0; CcString::stringsDeleted = 0; } Counter::getRef(Symbol::CTR_INT_Created()) = CcInt::intsCreated; Counter::getRef(Symbol::CTR_INT_Deleted()) = CcInt::intsDeleted; Counter::getRef(Symbol::CTR_REAL_Created()) = CcReal::realsCreated; Counter::getRef(Symbol::CTR_REAL_Deleted()) = CcReal::realsDeleted; Counter::getRef(Symbol::CTR_BOOL_Created()) = CcBool::boolsCreated; Counter::getRef(Symbol::CTR_BOOL_Deleted()) = CcBool::boolsDeleted; Counter::getRef(Symbol::CTR_STR_Created()) = CcString::stringsCreated; Counter::getRef(Symbol::CTR_STR_Deleted()) = CcString::stringsDeleted; Counter::reportValue(Symbol::CTR_INT_Created(), show); Counter::reportValue(Symbol::CTR_INT_Deleted(), show); Counter::reportValue(Symbol::CTR_REAL_Created(), show); Counter::reportValue(Symbol::CTR_REAL_Deleted(), show); Counter::reportValue(Symbol::CTR_BOOL_Created(), show); Counter::reportValue(Symbol::CTR_BOOL_Deleted(), show); Counter::reportValue(Symbol::CTR_STR_Created(), show); Counter::reportValue(Symbol::CTR_STR_Deleted(), show); } long StdTypes::UpdateBasicOps(bool reset/*=false*/) { long& basicOps = Counter::getRef(Symbol::CTR_ATTR_BASIC_OPS()); long& hashOps = Counter::getRef(Symbol::CTR_ATTR_HASH_OPS()); long& compareOps = Counter::getRef(Symbol::CTR_ATTR_COMPARE_OPS()); long& intHash = Counter::getRef(Symbol::CTR_INT_HASH()); long& intLess = Counter::getRef(Symbol::CTR_INT_LESS()); long& intEqual = Counter::getRef(Symbol::CTR_INT_EQUAL()); long& intCompare = Counter::getRef(Symbol::CTR_INT_COMPARE()); if (reset) { intHash = 0; intLess = 0; intEqual = 0; intCompare = 0; } hashOps += intHash; compareOps += (intLess + intEqual + intCompare); basicOps += hashOps + compareOps; return basicOps; } void StdTypes::ResetBasicOps() { UpdateBasicOps(true); } void StdTypes::InitCounters(bool show) { Statistics2Counters(true, show); } void StdTypes::SetCounterValues(bool show) { Statistics2Counters(false, show); } int StdTypes::GetInt(const Word& w) { return Attribute::GetValue(w); } SEC_STD_REAL StdTypes::GetReal(const Word& w) { return Attribute::GetValue(w); } bool StdTypes::GetBool(const Word& w) { return Attribute::GetValue(w); } string StdTypes::GetString(const Word& w) { return Attribute::GetValue(w); }