6432 lines
173 KiB
C++
6432 lines
173 KiB
C++
/*
|
|
----
|
|
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 <iostream>
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <algorithm>
|
|
|
|
#include "SecMath.h"
|
|
#include <cstdlib>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <cerrno>
|
|
#include <time.h> //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("(<intvalue>)"),
|
|
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<CcInt>,
|
|
SaveAttribute<CcInt>, // 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("(<realvalue>)"),
|
|
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<CcReal>,
|
|
SaveAttribute<CcReal>, // 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("(<boolvalue>)"),
|
|
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<CcBool>,
|
|
SaveAttribute<CcBool>, // 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("(<stringvalue>)"),
|
|
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<CcString>,
|
|
SaveAttribute<CcString>, // object open and save
|
|
CloseCcString, CloneCcString,
|
|
CastString, SizeOfCcString, CheckString );
|
|
|
|
|
|
|
|
GenTC<LongInt> longint;
|
|
GenTC<Rational> 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<CcReal>();
|
|
}
|
|
|
|
/*
|
|
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 ) && (sum<a)) || ((b<0) && (sum)>a)){
|
|
((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<CcString*>( args[0].addr );
|
|
CcString* wstr2 = reinterpret_cast<CcString*>( args[1].addr );
|
|
|
|
string str1 = reinterpret_cast<const char*>( wstr1->GetStringval() );
|
|
string str2 = reinterpret_cast<const char*>( wstr2->GetStringval() );
|
|
|
|
CcString* wres = reinterpret_cast<CcString*>( 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<class T>
|
|
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<class T>
|
|
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<class T>
|
|
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<class T>
|
|
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) && (diff<a)))
|
|
{
|
|
((CcInt *)result.addr)->Set(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<class T>
|
|
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<class T>
|
|
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<class T>
|
|
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<class T>
|
|
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<class T>
|
|
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<class T>
|
|
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<class T>
|
|
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<class T>
|
|
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<class T>
|
|
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<class T>
|
|
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<class T>
|
|
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<class T>
|
|
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<class A, class B>
|
|
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<class T>
|
|
int
|
|
CcLess( Word* args, Word& result, int message, Word& local, Supplier s )
|
|
{
|
|
result = qp->ResultStorage( s );
|
|
const T* a = static_cast<const T*>( args[0].addr );
|
|
const T* b = static_cast<const T*>( args[1].addr );
|
|
|
|
((CcBool *)result.addr)->Set( true, a->Compare(b) == -1 );
|
|
return (0);
|
|
}
|
|
|
|
template<class T>
|
|
int
|
|
CcGreater( Word* args, Word& result, int message, Word& local, Supplier s )
|
|
{
|
|
result = qp->ResultStorage( s );
|
|
const T* a = static_cast<const T*>( args[0].addr );
|
|
const T* b = static_cast<const T*>( args[1].addr );
|
|
|
|
((CcBool *)result.addr)->Set( true, a->Compare(b) == 1 );
|
|
return (0);
|
|
}
|
|
|
|
template<class T>
|
|
int
|
|
CcEqual( Word* args, Word& result, int message, Word& local, Supplier s )
|
|
{
|
|
result = qp->ResultStorage( s );
|
|
const T* a = static_cast<const T*>( args[0].addr );
|
|
const T* b = static_cast<const T*>( args[1].addr );
|
|
|
|
((CcBool *)result.addr)->Set( true, a->Compare(b) == 0 );
|
|
return (0);
|
|
}
|
|
|
|
|
|
template<class S, class T>
|
|
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<class T>
|
|
int
|
|
CcLessEqual( Word* args, Word& result, int message, Word& local, Supplier s )
|
|
{
|
|
result = qp->ResultStorage( s );
|
|
const T* a = static_cast<const T*>( args[0].addr );
|
|
const T* b = static_cast<const T*>( args[1].addr );
|
|
|
|
((CcBool *)result.addr)->Set( true, a->Compare(b) <= 0 );
|
|
return (0);
|
|
}
|
|
|
|
|
|
template<class S, class T>
|
|
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<class S, class T>
|
|
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<class T>
|
|
int
|
|
CcGreaterEqual( Word* args, Word& result, int message, Word& local, Supplier s )
|
|
{
|
|
result = qp->ResultStorage( s );
|
|
const T* a = static_cast<const T*>( args[0].addr );
|
|
const T* b = static_cast<const T*>( args[1].addr );
|
|
|
|
((CcBool *)result.addr)->Set( true, a->Compare(b) >= 0 );
|
|
return (0);
|
|
}
|
|
|
|
|
|
|
|
template<class S, class T>
|
|
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<class S, class T>
|
|
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<class T>
|
|
int
|
|
CcDiff( Word* args, Word& result, int message, Word& local, Supplier s )
|
|
{
|
|
result = qp->ResultStorage( s );
|
|
const T* a = static_cast<const T*>( args[0].addr );
|
|
const T* b = static_cast<const T*>( args[1].addr );
|
|
|
|
((CcBool *)result.addr)->Set( true, a->Compare(b) != 0 );
|
|
return (0);
|
|
}
|
|
|
|
|
|
template<class S, class T>
|
|
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<CcString*>( args[0].addr );
|
|
CcInt* wpos1 = reinterpret_cast<CcInt*>( args[1].addr );
|
|
CcInt* wpos2 = reinterpret_cast<CcInt*>( args[2].addr );
|
|
|
|
string str1 = reinterpret_cast<const char*>( wstr->GetStringval() );
|
|
int p1 = wpos1->GetIntval();
|
|
int p2 = wpos2->GetIntval();
|
|
|
|
CcString* wres = reinterpret_cast<CcString*>( 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<long unsigned int>(p2-p1),
|
|
static_cast<long unsigned int>(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<class T>
|
|
int
|
|
IsEmpty( Word* args, Word& result, int message, Word& local, Supplier s )
|
|
{
|
|
result = qp->ResultStorage( s );
|
|
const T* arg = static_cast<const T*>( 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<class T1, class T2, class T3>
|
|
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<CcInt*>(result.addr);
|
|
CcString* a = static_cast<CcString*>(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<CcString*>( 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<class S, class T>
|
|
int
|
|
abs_vm( Word* args, Word& result, int message, Word& local, Supplier s )
|
|
{
|
|
// args[0] : real
|
|
S* arg0 = static_cast<S*>(args[0].addr);
|
|
result = qp->ResultStorage(s);
|
|
S* res = static_cast<S*>(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<class T>
|
|
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<CcInt>,
|
|
CcRoundValueMapT<CcReal>
|
|
};
|
|
|
|
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<class T, bool lengthGiven>
|
|
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;i<s;i++){
|
|
unsigned char c = ((char*)&value)[(s-i)-1];
|
|
if(c>0 || written>0){
|
|
v[written] = c;
|
|
written++;
|
|
}
|
|
}
|
|
} else {
|
|
for(uint32_t i=0;i<s;i++){
|
|
unsigned char c = value &0xFF;
|
|
value = value >> 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<bool ismin>
|
|
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;i<noArgs; i++){
|
|
Attribute* Obj1 = (Attribute*) args[i].addr;
|
|
Attribute* Obj2 = (Attribute*) args[resultIndex].addr;
|
|
int cmp = Obj1->Compare(Obj2);
|
|
if((ismin && cmp<0) || (!ismin && cmp>0)){
|
|
resultIndex = i;
|
|
}
|
|
}
|
|
(static_cast<Attribute*>(result.addr))->
|
|
CopyFrom(static_cast<Attribute*>(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<class T, int OP>
|
|
int CCtrigonVM (Word* args, Word& result, int message, Word& local, Supplier s )
|
|
{
|
|
T* arg = static_cast<T*>(args[0].addr);
|
|
result = qp->ResultStorage( s );
|
|
CcReal* res = static_cast<CcReal*>(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<CcReal*>(args[0].addr);
|
|
CcReal* xarg = static_cast<CcReal*>(args[1].addr);
|
|
result = qp->ResultStorage( s );
|
|
CcReal* res = static_cast<CcReal*>(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<CcReal*>(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<CcReal*>(result.addr);
|
|
res->Set(true,M_E);
|
|
return 0;
|
|
}
|
|
|
|
template<class T1, class T2>
|
|
int CClogBVM (Word* args, Word& result, int message, Word& local, Supplier s )
|
|
{
|
|
T1* v = static_cast<T1*>(args[0].addr);
|
|
T2* b = static_cast<T2*>(args[1].addr);
|
|
result = qp->ResultStorage( s );
|
|
CcReal* res = static_cast<CcReal*>(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<class T1, class T2>
|
|
int CCpowVM (Word* args, Word& result, int message, Word& local, Supplier s )
|
|
{
|
|
T1* b = static_cast<T1*>(args[0].addr);
|
|
T2* e = static_cast<T2*>(args[1].addr);
|
|
result = qp->ResultStorage( s );
|
|
CcReal* res = static_cast<CcReal*>(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<class T1, class T2, class T3>
|
|
int CCdms2degVM (Word* args, Word& result, int message, Word& local,
|
|
Supplier s )
|
|
{
|
|
result = qp->ResultStorage( s );
|
|
CcReal* res = static_cast<CcReal*>(result.addr);
|
|
|
|
int noargs = qp->GetNoSons(s);
|
|
assert( (noargs==3) || (noargs==4) );
|
|
T1* ccDeg = static_cast<T1*>(args[0].addr);
|
|
T2* ccMin = static_cast<T2*>(args[1].addr);
|
|
T3* ccSec = (noargs==4)?(static_cast<T3*>(args[2].addr)):0;
|
|
CcBool* ccCheckrange = static_cast<CcBool*>(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.0<min) && (min<60.0)) || !((-60.0<sec) && (sec<60.0)) ){
|
|
ok = false;
|
|
}
|
|
ok = ok && AlmostEqual(modf(deg,°),0.0); // deg must be integral
|
|
if(noargs==4){
|
|
ok = ok && AlmostEqual(modf(min,&min),0.0); // min must be integral
|
|
}
|
|
degres = fabs(deg) + fabs(min/60.0) + fabs(sec/3600.0);
|
|
if( (deg<0.0) || (min<0.0) || (sec<0.0) ){ // negative result!
|
|
degres *= -1.0;
|
|
}
|
|
} else { // sum up all components
|
|
degres = deg + (min/60.0) + (sec/3600.0);
|
|
}
|
|
res->Set(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<CcInt>();
|
|
}
|
|
|
|
ListExpr CCBinAndSTM (ListExpr args)
|
|
{
|
|
string err = "expected stream(int) ";
|
|
if(!nl->HasLength(args,1)){
|
|
return listutils::typeError(err);
|
|
}
|
|
if(!Stream<CcInt>::checkType(nl->First(args))){
|
|
return listutils::typeError(err);
|
|
}
|
|
return listutils::basicSymbol<CcInt>();;
|
|
}
|
|
|
|
/*
|
|
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<CcInt*> (result.addr);
|
|
|
|
CcInt* int1 = static_cast<CcInt*>(args[0].addr);
|
|
CcInt* int2 = static_cast<CcInt*>(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<CcInt*> (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<CcInt*> (wint.addr);
|
|
int inter = curInt->GetIntval();
|
|
curInt->DeleteIfAllowed();
|
|
qp->Request(args[0].addr, wint);
|
|
while (qp->Received(args[0].addr)){
|
|
curInt = static_cast<CcInt*> (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<CcInt>, CcPlus_long<LongInt>,
|
|
CcPlus_long2<CcInt>,
|
|
CcPlus_rat<CcInt>, CcPlus_rat<LongInt>,
|
|
CcPlus_rat<Rational>, CcPlus_rat2<CcInt>,
|
|
CcPlus_rat2<LongInt> };
|
|
|
|
|
|
ValueMapping ccminusmap[] =
|
|
{ CcMinus_ii, CcMinus_ir, CcMinus_ri, CcMinus_rr,
|
|
CcMinus_long<CcInt>, CcMinus_long<LongInt>, CcMinus_long2<CcInt>,
|
|
CcMinus_rat<CcInt>, CcMinus_rat<LongInt>, CcMinus_rat<Rational>,
|
|
CcMinus_rat2<CcInt>, CcMinus_rat2<LongInt> };
|
|
ValueMapping ccproductmap[] =
|
|
{ CcProduct_ii, CcProduct_ir, CcProduct_ri, CcProduct_rr,
|
|
CcProduct_long<CcInt>, CcProduct_long<LongInt>,
|
|
CcProduct_long2<CcInt>,
|
|
CcProduct_rat<CcInt>, CcProduct_rat<LongInt>,
|
|
CcProduct_rat<Rational>,
|
|
CcProduct_rat2<CcInt>, CcProduct_rat2<LongInt>
|
|
};
|
|
ValueMapping ccdivisionmap[] =
|
|
{ CcDivision_ii, CcDivision_ir, CcDivision_ri, CcDivision_rr,
|
|
CcDivision_long<CcInt>, CcDivision_long<LongInt>,
|
|
CcDivision_long2<CcInt>,
|
|
CcDivision_rat<CcInt>, CcDivision_rat<LongInt>,
|
|
CcDivision_rat<Rational>,
|
|
CcDivision_rat2<CcInt>, CcDivision_rat2<LongInt>
|
|
};
|
|
|
|
ValueMapping ccmodmap[] = { CcMod };
|
|
|
|
|
|
/*
|
|
Value Mapping array and Selection for div
|
|
|
|
*/
|
|
ValueMapping ccdivmap[] = { CcDiv<CcInt, CcInt>,
|
|
CcDiv<CcInt, LongInt>,
|
|
CcDiv<LongInt, CcInt>,
|
|
CcDiv<LongInt,LongInt> };
|
|
|
|
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<CcInt>,
|
|
CcLess2<CcInt, CcReal>,
|
|
CcLess2<CcInt, LongInt>,
|
|
CcLess2<CcReal, CcInt>,
|
|
CcLess<CcReal>,
|
|
CcLess2<CcReal, LongInt>,
|
|
CcLess2<LongInt, CcInt>,
|
|
CcLess2<LongInt, CcReal>,
|
|
CcLess<LongInt>,
|
|
CcLess<CcBool>,
|
|
CcLess<CcString> };
|
|
|
|
ValueMapping cclessequalmap[] = { CcLessEqual<CcInt>,
|
|
CcLessEqual2<CcInt, CcReal>,
|
|
CcLessEqual2<CcInt, LongInt>,
|
|
CcLessEqual2<CcReal, CcInt>,
|
|
CcLessEqual<CcReal>,
|
|
CcLessEqual2<CcReal,LongInt>,
|
|
CcLessEqual2<LongInt, CcInt>,
|
|
CcLessEqual2<LongInt, CcReal>,
|
|
CcLessEqual<LongInt>,
|
|
CcLessEqual<CcBool>,
|
|
CcLessEqual<CcString> };
|
|
|
|
ValueMapping ccgreatermap[] = { CcGreater<CcInt>,
|
|
CcGreater2<CcInt, CcReal>,
|
|
CcGreater2<CcInt, LongInt>,
|
|
CcGreater2<CcReal, CcInt>,
|
|
CcGreater<CcReal>,
|
|
CcGreater2<CcReal, LongInt>,
|
|
CcGreater2<LongInt, CcInt>,
|
|
CcGreater2<LongInt, CcReal>,
|
|
CcGreater<LongInt>,
|
|
CcGreater<CcBool>,
|
|
CcGreater<CcString> };
|
|
|
|
ValueMapping ccgreaterequalmap[] = { CcGreaterEqual<CcInt>,
|
|
CcGreaterEqual2<CcInt, CcReal>,
|
|
CcGreaterEqual2<CcInt, LongInt>,
|
|
CcGreaterEqual2<CcReal, CcInt>,
|
|
CcGreaterEqual<CcReal>,
|
|
CcGreaterEqual2<CcReal, LongInt>,
|
|
CcGreaterEqual2<LongInt, CcInt>,
|
|
CcGreaterEqual2<LongInt, CcReal>,
|
|
CcGreaterEqual<LongInt>,
|
|
CcGreaterEqual<CcBool>,
|
|
CcGreaterEqual<CcString> };
|
|
|
|
ValueMapping ccequalmap[] = { CcEqual<CcInt>,
|
|
CcEqual2<CcInt, CcReal>,
|
|
CcEqual2<CcInt, LongInt>,
|
|
CcEqual2<CcReal, CcInt>,
|
|
CcEqual<CcReal>,
|
|
CcEqual2<CcReal, LongInt>,
|
|
CcEqual2<LongInt, CcInt>,
|
|
CcEqual2<LongInt, CcReal>,
|
|
CcEqual<LongInt>,
|
|
CcEqual<CcBool>,
|
|
CcEqual<CcString> };
|
|
|
|
ValueMapping ccdiffmap[] = { CcDiff<CcInt>,
|
|
CcDiff2<CcInt, CcReal>,
|
|
CcDiff2<CcInt, LongInt>,
|
|
CcDiff2<CcReal, CcInt>,
|
|
CcDiff<CcReal>,
|
|
CcDiff2<CcReal, LongInt>,
|
|
CcDiff2<LongInt, CcInt>,
|
|
CcDiff2<LongInt,CcReal>,
|
|
CcDiff<LongInt>,
|
|
CcDiff<CcBool>,
|
|
CcDiff<CcString> };
|
|
|
|
ValueMapping cccontainsmap[] = { ContainsFun };
|
|
ValueMapping ccandmap[] = { AndFun };
|
|
ValueMapping ccandSmap[] = { AndSFun };
|
|
ValueMapping ccormap[] = { OrFun };
|
|
ValueMapping ccorSmap[] = { OrSFun };
|
|
ValueMapping ccnotmap[] = { NotFun };
|
|
ValueMapping ccisemptymap[] = { IsEmpty<CcBool>,
|
|
IsEmpty<CcInt>,
|
|
IsEmpty<CcReal>,
|
|
IsEmpty<CcString> };
|
|
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<CcInt,CcInt,CcInt>,
|
|
CcBetween<CcReal,CcReal, CcReal>,
|
|
CcBetween<CcString, CcString, CcString>,
|
|
CcBetween<CcBool,CcBool,CcBool>,
|
|
CcBetween<CcInt,CcInt,CcReal>,
|
|
CcBetween<CcInt,CcReal,CcInt>,
|
|
CcBetween<CcInt,CcReal,CcReal>,
|
|
CcBetween<CcReal,CcInt,CcInt>,
|
|
CcBetween<CcReal,CcInt,CcReal>,
|
|
CcBetween<CcReal, CcReal, CcInt>};
|
|
|
|
//ValueMapping cchashvaluemap[] = { CcHashValue<CcInt>, CcHashValue<CcReal>,
|
|
//CcHashValue<CcString>, CcHashValue<CcBool> };
|
|
ValueMapping cchashvaluemap[] = { CcHashValue };
|
|
ValueMapping ccint2realvaluemap[] = { CcInt2realValueMap };
|
|
ValueMapping ccreal2intvaluemap[] = { CcReal2intValueMap };
|
|
ValueMapping ccint2boolvaluemap[] = { CcInt2boolValueMap };
|
|
ValueMapping ccbool2intvaluemap[] = { CcBool2intValueMap };
|
|
ValueMapping ccfloorvaluemap[] = { CcFloorValueMap };
|
|
ValueMapping ccceilvaluemap[] = { CcCeilValueMap };
|
|
ValueMapping ccnum2stringvaluemap[] =
|
|
{ CcNum2String<CcReal, false>,
|
|
CcNum2String<CcInt, false>,
|
|
CcNum2String<LongInt, false>,
|
|
CcNum2String<CcReal, true>,
|
|
CcNum2String<CcInt, true>,
|
|
CcNum2String<LongInt, true>};
|
|
ValueMapping abs_vms[] = { abs_vm<CcReal, double>, abs_vm<CcInt, int>, 0 };
|
|
ValueMapping cccharvaluemap[] = { CcCharFun };
|
|
|
|
ValueMapping CCsinVM[] = {
|
|
CCtrigonVM<CcInt, sin_op>,
|
|
CCtrigonVM<CcReal, sin_op>, 0};
|
|
ValueMapping CCcosVM[] = {
|
|
CCtrigonVM<CcInt, cos_op>,
|
|
CCtrigonVM<CcReal, cos_op>, 0};
|
|
ValueMapping CCtanVM[] = {
|
|
CCtrigonVM<CcInt, tan_op>,
|
|
CCtrigonVM<CcReal, tan_op>, 0};
|
|
ValueMapping CCarcsinVM[] = {
|
|
CCtrigonVM<CcInt, arcsin_op>,
|
|
CCtrigonVM<CcReal, arcsin_op>, 0};
|
|
ValueMapping CCarccosVM[] = {
|
|
CCtrigonVM<CcInt, arccos_op>,
|
|
CCtrigonVM<CcReal, arccos_op>, 0};
|
|
ValueMapping CCarctanVM[] = {
|
|
CCtrigonVM<CcInt, arctan_op>,
|
|
CCtrigonVM<CcReal, arctan_op>, 0};
|
|
ValueMapping CCdeg2radVM[] = {
|
|
CCtrigonVM<CcInt, deg2rad_op>,
|
|
CCtrigonVM<CcReal, deg2rad_op>, 0};
|
|
ValueMapping CCrad2degVM[] = {
|
|
CCtrigonVM<CcInt, rad2deg_op>,
|
|
CCtrigonVM<CcReal, rad2deg_op>, 0};
|
|
ValueMapping CClogBmap[] = {
|
|
CClogBVM<CcInt, CcInt>,
|
|
CClogBVM<CcInt, CcReal>,
|
|
CClogBVM<CcReal, CcInt>,
|
|
CClogBVM<CcReal, CcReal>, 0};
|
|
ValueMapping CCpowmap[] = {
|
|
CCpowVM<CcInt, CcInt>,
|
|
CCpowVM<CcInt, CcReal>,
|
|
CCpowVM<CcReal, CcInt>,
|
|
CCpowVM<CcReal, CcReal>, 0};
|
|
|
|
ValueMapping CCdms2degmap[] = {
|
|
CCdms2degVM<CcInt, CcInt, CcInt>,
|
|
CCdms2degVM<CcInt, CcInt, CcReal>,
|
|
CCdms2degVM<CcInt, CcReal, CcInt>,
|
|
CCdms2degVM<CcInt, CcReal, CcReal>,
|
|
CCdms2degVM<CcReal, CcInt, CcInt>,
|
|
CCdms2degVM<CcReal, CcInt, CcReal>,
|
|
CCdms2degVM<CcReal, CcReal, CcInt>,
|
|
CCdms2degVM<CcReal, CcReal, CcReal>, 0};
|
|
|
|
const string CCSpecAdd = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(int int) -> int, (int real) -> real, "
|
|
"(real int)"
|
|
" -> real, (real real) -> real "
|
|
"(string string) -> string</text--->"
|
|
"<text>_ + _</text--->"
|
|
"<text>Addition. Strings are concatenated.</text--->"
|
|
"<text>query -1.2 + 7</text--->"
|
|
") )";
|
|
|
|
const string CCSpecSub = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(int int) -> int, (int real) -> real, "
|
|
"(real int) -> real, (real real) -> real</text--->"
|
|
"<text>_ - _</text--->"
|
|
"<text>Subtraction</text--->"
|
|
"<text>query -.2 - 4</text--->"
|
|
") )";
|
|
|
|
const string CCSpecMul = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(int int) -> int, (int real) -> real, "
|
|
"(real int) -> real, (real real) -> real</text--->"
|
|
"<text>_ * _</text--->"
|
|
"<text>Multiplication.</text--->"
|
|
"<text>query 5 * 1.4 </text--->"
|
|
") )";
|
|
|
|
const string CCSpecDiv = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(int int) -> real, (int real) -> real, "
|
|
"(real int) -> real, (real real) -> real</text--->"
|
|
"<text>_ / _</text--->"
|
|
"<text>Division.</text--->"
|
|
"<text>query 5 / 2 </text--->"
|
|
") )";
|
|
|
|
const string CCSpecMod = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(int int) -> int</text--->"
|
|
"<text>_ mod _</text--->"
|
|
"<text>Modulo.</text--->"
|
|
"<text>query 8 mod 3 </text--->"
|
|
") )";
|
|
|
|
const string CCSpecDiv2 = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>({int, longint} {int,longint}) "
|
|
"-> {int, longint}</text--->"
|
|
"<text>_ div _</text--->"
|
|
"<text>Integer Division.</text--->"
|
|
"<text>query 5 div 2 </text--->"
|
|
") )";
|
|
|
|
const string CCSpecSqrt = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>real -> real</text--->"
|
|
"<text>sqrt( _ )</text--->"
|
|
"<text>Extract a root.</text--->"
|
|
"<text>query sqrt(2.1)</text--->"
|
|
") )";
|
|
|
|
const string CCSpecRandInt = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>int -> int </text--->"
|
|
"<text>randint ( _ )</text--->"
|
|
"<text>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. </text--->"
|
|
"<text>query randint (9)</text--->"
|
|
") )";
|
|
|
|
|
|
const string CCSpecRandSeed = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>int -> bool </text--->"
|
|
"<text>randseed ( _ )</text--->"
|
|
"<text>initializes the randon number generator with "
|
|
"a defined value. </text--->"
|
|
"<text>query randseed(8000)</text--->"
|
|
") )";
|
|
|
|
const string CCSpecMaxRand = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text> -> int </text--->"
|
|
"<text>randmax()</text--->"
|
|
"<text>Returns the value of MAX_RAND </text--->"
|
|
"<text>query randmax()</text--->"
|
|
") )";
|
|
|
|
|
|
const string CCSpecInitSeq = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>int -> bool </text--->"
|
|
"<text>seqinit ( _ ) </text--->"
|
|
"<text>Returns true and sets the start value "
|
|
" of the sequence to the argument value</text--->"
|
|
"<text>query seqinit(100)</text--->"
|
|
") )";
|
|
|
|
const string CCSpecNextSeq = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text> -> int </text--->"
|
|
"<text>seqnext ()</text--->"
|
|
"<text>Returns s+n-1 at the n-th call when the sequence"
|
|
" was initialized with initseq (s) "
|
|
"otherwise s defaults to 0.</text--->"
|
|
"<text>query seqnext ()</text--->"
|
|
") )";
|
|
|
|
const string CCSpecLog = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>int -> int </text--->"
|
|
"<text>log ( _ )</text--->"
|
|
"<text>Computes the logarithmus of base 2."
|
|
" The argument must be greater"
|
|
"than 0.</text--->"
|
|
"<text>query log (256)</text--->"
|
|
") )";
|
|
|
|
const string CCSpecLT = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(int int) -> bool, (int real) -> bool, "
|
|
"(real int) -> bool, (real real) -> bool, (bool bool)"
|
|
" -> bool, (string string) -> bool</text--->"
|
|
"<text>_ < _</text--->"
|
|
"<text>Less.</text--->"
|
|
"<text>query \"house\" < \"hotel\"</text--->"
|
|
") )";
|
|
|
|
const string CCSpecLE = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(int int) -> bool, (int real) -> bool, "
|
|
"(real int) -> bool, (real real) -> bool, (bool bool)"
|
|
" -> bool, (string string) -> bool</text--->"
|
|
"<text>_ <= _</text--->"
|
|
"<text>Less or equal.</text--->"
|
|
"<text>query 8.2 <= 8.2</text--->"
|
|
") )";
|
|
|
|
const string CCSpecGT = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(int int) -> bool, (int real) -> bool, "
|
|
"(real int) -> bool, (real real) -> bool, (bool bool)"
|
|
" -> bool, (string string) -> bool</text--->"
|
|
"<text>_ > _</text--->"
|
|
"<text>Greater.</text--->"
|
|
"<text>query 3 > 4.1</text--->"
|
|
") )";
|
|
|
|
const string CCSpecGE = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(int int) -> bool, (int real) -> bool, "
|
|
"(real int) -> bool, (real real) -> bool, (bool bool)"
|
|
" -> bool, (string string) -> bool</text--->"
|
|
"<text>_ >= _</text--->"
|
|
"<text>Greater or equal.</text--->"
|
|
"<text>query 3 >= 5</text--->"
|
|
") )";
|
|
|
|
const string CCSpecEQ = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(int int) -> bool, (int real) -> bool, "
|
|
"(real int) -> bool, (real real) -> bool, (bool bool)"
|
|
" -> bool, (string string) -> bool</text--->"
|
|
"<text>_ = _</text--->"
|
|
"<text>Equal.</text--->"
|
|
"<text>query 2.1 = 2.01</text--->"
|
|
") )";
|
|
|
|
const string CCSpecNE = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(int int) -> bool, (int real) -> bool, "
|
|
"(real int) -> bool, (real real) -> bool, (bool bool)"
|
|
" -> bool, (string string) -> bool</text--->"
|
|
"<text>_ # _</text--->"
|
|
"<text>Not equal.</text--->"
|
|
"<text>query 2.1 # 2.01</text--->"
|
|
") )";
|
|
|
|
const string CCSpecBeg = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(string string) -> bool</text--->"
|
|
"<text>_ starts _</text--->"
|
|
"<text>Starts.</text--->"
|
|
"<text>query \"starts\" starts \"st\"</text--->"
|
|
") )";
|
|
|
|
const string CCSpecCon = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(string string) -> bool</text--->"
|
|
"<text>_ contains _</text--->"
|
|
"<text>Contains.</text--->"
|
|
"<text>query \"contains\" contains \"tai\""
|
|
"</text--->"
|
|
") )";
|
|
|
|
const string CCSpecNot = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>bool -> bool</text--->"
|
|
"<text>not ( _ )</text--->"
|
|
"<text>Logical Not.</text--->"
|
|
"<text>query not ( 4=4 )</text--->"
|
|
" ) )";
|
|
|
|
const string CCSpecAnd =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(bool bool) -> bool</text--->"
|
|
"<text>_ and _</text--->"
|
|
"<text>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. </text--->"
|
|
"<text>query (8 = 8) and (3 < 4)</text--->"
|
|
") )";
|
|
|
|
const string CCSpecAndS =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(bool bool) -> bool</text--->"
|
|
"<text>_ sand _</text--->"
|
|
"<text>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.</text--->"
|
|
"<text>query (8 = 8) sand (3 < 4)</text--->"
|
|
") )";
|
|
|
|
const string CCSpecOr = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(bool bool) -> bool</text--->"
|
|
"<text>_ or _</text--->"
|
|
"<text>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. </text--->"
|
|
"<text>query (3 <= 4) or (\"hotel\" > "
|
|
"\"house\")"
|
|
"</text--->"
|
|
") )";
|
|
|
|
const string CCSpecOrS =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(bool bool) -> bool</text--->"
|
|
"<text>_ sor _</text--->"
|
|
"<text>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.</text--->"
|
|
"<text>query (8 = 8) sor (3 < 4)</text--->"
|
|
") )";
|
|
|
|
const string CCSpecIsEmpty = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>bool -> bool, int -> bool, real -> bool,"
|
|
" string -> bool</text--->"
|
|
"<text>isempty ( _ )</text--->"
|
|
"<text>Returns whether the value is defined or "
|
|
"not.</text--->"
|
|
"<text>query isempty ( 8 )</text--->"
|
|
") )";
|
|
|
|
const string CCSpecPlusPlus = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>string -> string</text--->"
|
|
"<text> _ ++</text--->"
|
|
"<text>Returns successor for the passed string "
|
|
"</text--->"
|
|
"<text>query \"hello\"++</text--->"
|
|
") )";
|
|
|
|
const string CCSpecSetIntersection = "( ( \"Signature\" \"Meaning\" )"
|
|
"( <text> (int int) -> int, (real real) -> real,"
|
|
"(bool bool) -> bool, (string string) -> string</text--->"
|
|
"<text> Set intersection. </text--->"
|
|
") )";
|
|
|
|
const string CCSpecSetMinus = "( ( \"Signature\" \"Meaning\" )"
|
|
"( <text> (int int) -> int, (real real) -> real, "
|
|
"(bool bool) -> bool, (string string) -> string</text--->"
|
|
"<text> Set minus. </text--->"
|
|
") )";
|
|
|
|
|
|
const string CCSpecKeywords = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(string) -> (stream string)</text--->"
|
|
"<text>_ keywords</text--->"
|
|
"<text>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.</text--->"
|
|
"<text>query ten feed extendstream(name: mystring keywords) "
|
|
"consume</text--->"
|
|
") )";
|
|
|
|
const string CCSpecIfthenelse = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(bool x T x T) -> T, T in DATA, "
|
|
"or T = stream(...) </text--->"
|
|
"<text>ifthenelse(P, R1, R2)</text--->"
|
|
"<text> 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."
|
|
"</text--->"
|
|
"<text>query ifthenelse(3 < 5,[const string value \"less\"],"
|
|
"[const string value \"greater\"])</text--->"
|
|
") )";
|
|
|
|
|
|
const string CCSpecBetween = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
|
"\"Example\" )"
|
|
"( <text>(T x T x T) -> bool</text--->"
|
|
"<text>_ between[_, _]</text--->"
|
|
"<text>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.</text--->"
|
|
"<text>query 5 between [3, 8], query \"house\" "
|
|
"between [\"ha\", \"hu\"]</text--->"
|
|
") )";
|
|
|
|
const string specListHeader =
|
|
"( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )";
|
|
const string ST = "<text>";
|
|
const string ET = "</text--->";
|
|
|
|
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\" )"
|
|
"( <text>string x string -> int</text--->"
|
|
"<text>ldistance ( _ _ )</text--->"
|
|
"<text>compute the distance between two strings </text--->"
|
|
"<text>query ldistance( \"hello\" \"world\" )</text--->"
|
|
") )";
|
|
|
|
const string CCHashValueSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" )"
|
|
"( <text>T in DATA, y in int, T x y -> int</text--->"
|
|
"<text>hashvalue ( _, _ )</text--->"
|
|
"<text>computes the hashvalue from object of type T, "
|
|
"assuming that hashtable has size y.</text--->"
|
|
"<text>query hashvalue( \"Test\", 9997 )</text--->"
|
|
") )";
|
|
|
|
const string CCRoundSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text>({real,int} x int) -> real</text--->"
|
|
"<text>round(_, _)</text--->"
|
|
"<text>Rounds a real value with a precision of n decimals."
|
|
"</text--->"
|
|
"<text>query round(10.7367, 3)</text--->"
|
|
") )";
|
|
|
|
const string CCint2realSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text>int -> real</text--->"
|
|
"<text>int2real( _ )</text--->"
|
|
"<text>Creates a real value from an integer value using "
|
|
"C++ casting logic.</text--->"
|
|
"<text>query int2real(12)</text--->"
|
|
") )";
|
|
|
|
const string CCreal2intSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text>real -> int</text--->"
|
|
"<text>real2int( _ )</text--->"
|
|
"<text>Creates an int value from a real value</text--->"
|
|
"<text>query real2int(12.345)</text--->"
|
|
") )";
|
|
|
|
const string CCint2boolSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text>int -> bool</text--->"
|
|
"<text>int2bool( _ )</text--->"
|
|
"<text>Creates a bool value from an integer value. '0' will be "
|
|
"translated to 'FALSE', all other values to 'TRUE'</text--->"
|
|
"<text>query int2bool(0)</text--->"
|
|
") )";
|
|
|
|
const string CCbool2intSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text>bool -> int</text--->"
|
|
"<text>bool2int( _ )</text--->"
|
|
"<text>Creates an inteer value from a bool value. 'TRUE' will be "
|
|
"translated to '1', 'FALSE' to '0'</text--->"
|
|
"<text>query bool2int(TRUE)</text--->"
|
|
") )";
|
|
|
|
const string CCfloorSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text>real -> real</text--->"
|
|
"<text>floor( _ )</text--->"
|
|
"<text>Returns the largest integer not greater than the "
|
|
"argument.</text--->"
|
|
"<text>query floor(12.345)</text--->"
|
|
") )";
|
|
|
|
const string CCceilSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text>real -> real</text--->"
|
|
"<text>ceil( _ )</text--->"
|
|
"<text>Returns the smallest integer not less than the "
|
|
"argument.</text--->"
|
|
"<text>query ceil(12.345)</text--->"
|
|
") )";
|
|
|
|
const string CCnum2stringSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text>{real, int, longint} -> string</text--->"
|
|
"<text>num2string( num )</text--->"
|
|
"<text>Returns the string representation of numeric argument "
|
|
"'num'.</text--->"
|
|
"<text>query num2string(12.345)</text--->"
|
|
") )";
|
|
|
|
const string CCcharSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text>int -> string</text--->"
|
|
"<text>char( Code )</text--->"
|
|
"<text>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 \"''\".</text--->"
|
|
"<text>query char(25)</text--->"
|
|
") )";
|
|
|
|
const string CCisdefinedSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text>DATA -> bool</text--->"
|
|
"<text>isdefined( v )</text--->"
|
|
"<text>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.</text--->"
|
|
"<text>query isdefined(987)</text--->"
|
|
") )";
|
|
|
|
|
|
const string CCassertSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text>bool -> bool</text--->"
|
|
"<text>assert( v )</text--->"
|
|
"<text>Invokes a assertion if the argument is not defined or false "
|
|
"This operator is for debugging only !!! "
|
|
"</text--->"
|
|
"<text>query assert(987 = 987)</text--->"
|
|
") )";
|
|
|
|
|
|
const string CCcompareSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text>T x T -> int, T in DATA</text--->"
|
|
"<text>compare( v1, v2 )</text--->"
|
|
"<text>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.</text--->"
|
|
"<text>query compare(-987, [const int value undef])</text--->"
|
|
") )";
|
|
|
|
const string CCgetminvalSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text>T^n -> T, T in DATA, n >= 1</text--->"
|
|
"<text>getMinVal( v1, v2, ... )</text--->"
|
|
"<text>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.</text--->"
|
|
"<text>query getMinVal(45, -45, 12, 0, -75, 5)</text--->"
|
|
") )";
|
|
|
|
const string CCgetmaxvalSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text>T^n -> T, T in DATA, n >= 1</text--->"
|
|
"<text>getMaxVal( v1, v2, ... )</text--->"
|
|
"<text>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.</text--->"
|
|
"<text>query getMaxVal(45, -45, 12, 0, -75, 5)</text--->"
|
|
") )";
|
|
|
|
const string CClengthSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> string -> int </text--->"
|
|
"<text>length(_)</text--->"
|
|
"<text> Returns the length of the argument</text--->"
|
|
"<text>query length(\"Hello World\")</text--->"
|
|
") )";
|
|
|
|
/*
|
|
Trigonometric functions
|
|
|
|
*/
|
|
const string CCsinSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> int | real -> real </text--->"
|
|
"<text>sin( v )</text--->"
|
|
"<text>Returns the sinus of v (v is given in rad).</text--->"
|
|
"<text>query sin(deg2rad(90))</text--->"
|
|
") )";
|
|
|
|
const string CCcosSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> int | real -> real </text--->"
|
|
"<text>cos( v )</text--->"
|
|
"<text>Returns the cosinus of v (v is given in rad).</text--->"
|
|
"<text>query cos(deg2rad(90))</text--->"
|
|
") )";
|
|
|
|
const string CCtanSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> int | real -> real </text--->"
|
|
"<text>tan( v )</text--->"
|
|
"<text>Returns the tangens of v (v is given in rad).</text--->"
|
|
"<text>query tan(deg2rad(90))</text--->"
|
|
") )";
|
|
|
|
const string CCarcsinSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> int | real -> real </text--->"
|
|
"<text>arcsin( v )</text--->"
|
|
"<text>Returns the principal value of the arc sine of x, expressed "
|
|
"in radians, in the interval [-pi/2,+pi/2] radians.</text--->"
|
|
"<text>query arcsin(sin(deg2rad(90)))</text--->"
|
|
") )";
|
|
|
|
const string CCarccosSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> int | real -> real </text--->"
|
|
"<text>arccos( v )</text--->"
|
|
"<text>Returns the principal value of the arc cosine of x, "
|
|
"expressed in radians, in the interval [0,pi] radians.</text--->"
|
|
"<text>query arccos(sin(deg2rad(90)))</text--->"
|
|
") )";
|
|
|
|
const string CCarctanSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> int | real -> real </text--->"
|
|
"<text>arctan( v )</text--->"
|
|
"<text>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).</text--->"
|
|
"<text>query arctan(tan(deg2rad(90)))</text--->"
|
|
") )";
|
|
|
|
const string CCarctan2Spec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> real x real -> real </text--->"
|
|
"<text>arctan2( dy, dx )</text--->"
|
|
"<text>Returns the principal value of the arc tangent of y/x, "
|
|
"expressed in radians, in the interval [-pi,+pi] radians.</text--->"
|
|
"<text>query arctan2(tan(deg2rad(90)))</text--->"
|
|
") )";
|
|
|
|
const string CCpiSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> -> real </text--->"
|
|
"<text>const_pi()</text--->"
|
|
"<text>Returns pi (= 3.14159...)</text--->"
|
|
"<text>query sin(const_pi())</text--->"
|
|
") )";
|
|
|
|
const string CCdeg2radSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> int | real -> real </text--->"
|
|
"<text>deg2rad( v )</text--->"
|
|
"<text>Convert angle from degrees to radians.</text--->"
|
|
"<text>query arctan(tan(deg2rad(90)))</text--->"
|
|
") )";
|
|
|
|
const string CCrad2degSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> int | real -> real </text--->"
|
|
"<text>rad2deg( v )</text--->"
|
|
"<text>Convert angle from radians to degrees.</text--->"
|
|
"<text>query rad2deg(const_pi())</text--->"
|
|
") )";
|
|
|
|
const string CCeSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> -> real </text--->"
|
|
"<text>const_e()</text--->"
|
|
"<text>Returns E (= 2.718281828459...)</text--->"
|
|
"<text>query const_e()</text--->"
|
|
") )";
|
|
|
|
const string CClogBSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> {int | real} x {int | real} -> real </text--->"
|
|
"<text>logB( val , base)</text--->"
|
|
"<text>Returns the logarithm of 'val' to the given 'base'.</text--->"
|
|
"<text>query logB(const_e()*const_e(),const_e())</text--->"
|
|
") )";
|
|
|
|
const string CCpowSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> {int | real} x {int | real} -> real </text--->"
|
|
"<text>pow( Base , Exponent)</text--->"
|
|
"<text>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.</text--->"
|
|
"<text>query pow(2.0, 10)</text--->"
|
|
") )";
|
|
|
|
const string CCdms2degSpec =
|
|
"( ( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> {int|real} x {int|real} [x {int|real}] [x bool] -> real</text--->"
|
|
"<text>dms2deg( Deg , Min [, Sec] [, CheckRange] )</text--->"
|
|
"<text>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<Min<60,"
|
|
" and -60<Sec<60 must hold to avoid an UNDEF result. If CheckRange=TRUE, "
|
|
"the result is calculated using the absolute values of the numeric "
|
|
"parameters. Then, iff any numeric parameter is negative, the result is "
|
|
"negative.</text--->"
|
|
"<text>query dms2deg(7, -17.1, 64, FALSE)</text--->"
|
|
") )";
|
|
|
|
/*
|
|
binary and of integer values and streams of integer values
|
|
|
|
*/
|
|
|
|
const string CCBinAndSpec =
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> int X int -> int </text--->"
|
|
"<text> _ binand _ </text--->"
|
|
"<text>Computes the binary and conjunction of the two given int as int value."
|
|
"</text--->"
|
|
"<text>query 15 binand 4 </text--->"
|
|
") )";
|
|
|
|
const string CCBinAndSSpec =
|
|
"(( \"Signature\" \"Syntax\" \"Meaning\" \"Example\" )"
|
|
"( <text> stream(int) -> int </text--->"
|
|
"<text> _ binands </text--->"
|
|
"<text>Computes the binary conjunction of the stream of int values."
|
|
"</text--->"
|
|
"<text>query intstream(1,5) binands </text--->"
|
|
") )";
|
|
|
|
/*
|
|
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<true>,
|
|
Operator::SimpleSelect, CcTypeMapTinDATAexpplus2TinDATA);
|
|
|
|
Operator ccgetmaxval( "getMaxVal", CCgetmaxvalSpec, CCgetminmaxvaluemap<false>,
|
|
Operator::SimpleSelect, CcTypeMapTinDATAexpplus2TinDATA);
|
|
|
|
Operator cclength( "length", CClengthSpec, CcLengthvaluemap,
|
|
Operator::SimpleSelect, TypeMap1<CcString, CcInt>);
|
|
|
|
/*
|
|
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;i<noArgs-1 && ! found; i += 2){
|
|
Attribute* v = (Attribute*) args[i].addr;
|
|
int cmp = sw->Compare(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;i<noArgs-1 && ! found; i += 2){
|
|
Attribute* v = (Attribute*) args[i].addr;
|
|
int cmp = sw->Compare(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<LongInt>();
|
|
}
|
|
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<CcInt>();
|
|
}
|
|
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<Rational>();
|
|
}
|
|
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<Rational>();
|
|
}
|
|
|
|
template<class S>
|
|
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<class S1, class S2>
|
|
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<CcInt>, ratVM1<LongInt>, ratVM1<CcString>,
|
|
ratVM2<CcInt,CcInt>, ratVM2<CcInt,LongInt>,
|
|
ratVM2<LongInt,CcInt>, ratVM2<LongInt,LongInt>
|
|
};
|
|
|
|
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<Stream<CcInt> >(),
|
|
listutils::basicSymbol<CcInt>());
|
|
}
|
|
|
|
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<CcBool>();
|
|
}
|
|
|
|
/*
|
|
5.16.2 Value Mapping
|
|
|
|
*/
|
|
template<bool v>
|
|
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<true>,
|
|
Operator::SimpleSelect,
|
|
true_falseTM);
|
|
|
|
Operator falseOp(
|
|
"false",
|
|
falseSpec.getStr(),
|
|
true_falseVM<false>,
|
|
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<CcBool>();
|
|
}
|
|
|
|
|
|
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<CcBool>();
|
|
}
|
|
|
|
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<CcInt, int>(w);
|
|
}
|
|
|
|
|
|
SEC_STD_REAL
|
|
StdTypes::GetReal(const Word& w) {
|
|
return Attribute::GetValue<CcReal, SEC_STD_REAL>(w);
|
|
}
|
|
|
|
|
|
bool
|
|
StdTypes::GetBool(const Word& w) {
|
|
return Attribute::GetValue<CcBool, bool>(w);
|
|
}
|
|
|
|
string
|
|
StdTypes::GetString(const Word& w) {
|
|
return Attribute::GetValue<CcString, string>(w);
|
|
}
|