Files
secondo/Algebras/Collection/CollectionAlgebra.cpp
2026-01-23 17:03:45 +08:00

2167 lines
60 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 \begin{center}] [\end{center}}]
//characters [1] Type: [] []
//characters [2] Type: [] []
//[ae] [\"{a}]
//[oe] [\"{o}]
//[ue] [\"{u}]
//[ss] [{\ss}]
//[Ae] [\"{A}]
//[Oe] [\"{O}]
//[Ue] [\"{U}]
//[x] [$\times $]
//[->] [$\rightarrow $]
//[toc] [\tableofcontents]
[1] Implementation of datatypes vector, set and multiset and operators.
[1] Using Storage Manager Berkeley DB
December 2007 Ingmar G[oe]hr, Nicolai Voget, Peter Spindler, Sascha Bergmann
[toc]
1 Collection class implementation
1.1 Overview
1.1.1 Types
This Algebra provides three different types: vector, set, multiset.
All types are implemented in the class Collection, since they are all nearly
the same.
All types can be created from any number of elements as long as the elements
are all of the same type, which has to be from Kind DATA.
Since vector, set and multisets are of Kind DATA themselves, it is possible
to create a vector of vectors of integers for example.
In a vector, the elements are saved as they are added.
In a set, every element is only saved once, so duplicates are being removed.
Also, the elements will be saved ordered, smallest element first, using the
compare function of the elements. This implies that the type of which a vector,
set or multiset should be created has to implement a compare function.
A multiset is nearly the same as a set with the difference, that an element can
be added more than once.
1.1.2 Operators
Following operators are defined:
* create\_vector
* create\_set
* create\_multiset
(t)[*] [->] "vector(t)"[1]
(t)[*] [->] "set(t)"[1]
(t)[*] [->] "multiset(t)"[1]
t has to be of Kind DATA.
* insert
set(t) [x] t [->] "set(t)"[1]
multiset(t) [x] t [->] "multiset(t)"[1]
If set(t) already contains the element to be inserted, the result is the
original set.
* + (append)
vector(t) [x] t [->] "vector(t)"[1]
* delete
set(t) [x] t [->] "set(t)"[1]
multiset(t) [x] t [->] "multiset(t)"[1]
Removes the given element from the set/multiset. If the set/multiset does'nt
contain the element, the result is the original set/multiset. If the multiset
contains the element n times, the result contains the element (n-1) times.
* contains
vector(t) [x] t [->] "bool"[1]
set(t) [x] t [->] "bool"[1]
multiset(t) [x] t [->] CcInt::BasicType()[1]
Returns whether the collection contains the element. If the collection is a
multiset, the count of the element is returned.
* in
t [x] vector(t) [->] "bool"[1]
t [x] set(t) [->] "bool"[1]
t [x] multiset [->] CcInt::BasicType()[1]
Same as contains.
* union
* intersection
* difference
set(t) [x] set(t) [->] "set(t)"[1]
multiset(t) [x] multiset(t) [->] "multiset(t)"[1]
* concat
vector(t) [x] vector(t) [->] "vector(t)"[1]
Appends the elements of the second vector to the first vector.
* \verb+<+ (proper subset)
* \verb+<=+ (subset)
* = (equals)
* \verb+>=+ (superset)
* \verb+>+ (proper superset)
set(t) [x] set(t) [->] "bool"[1]
multiset(t) [x] multiset(t) [->] "bool"[1]
* get
vector(t) [x] int [->] "t"[1]
Returns the nth element of vector. If n is less than 0 or greater than size(
vector), an undefined element is returned.
* components
vector(t) [->] "stream(t)"[1]
set(t) [->] "stream(t)"[1]
multiset(t) [->] "stream(t)"[1]
* collect\_vector
* collect\_set
* collect\_multiset
stream(t) [->] "vector(t)"[1]
stream(t) [->] "set(t)"[1]
stream(t) [->] "multiset(t)"[1]
t has to be of Kind DATA.
* size
vector(t) [->] CcInt::BasicType()[1]
set(t) [->] CcInt::BasicType()[1]
multiset(t) [->] CcInt::BasicType()[1]
Returns the number of elements contained in the collection.
* is\_defined
vector(t) [->] "bool"[1]
set(t) [->] "bool"[1]
multiset(t) [->] "bool"[1]
Necessary to difference between an empty and an undefined collection.
2 Includes
*/
//#define DEBUG
//#define DEBUGHEAD
#ifdef DEBUGHEAD
#undef DEBUGHEAD
#endif
#include "CollectionAlgebra.h"
#include "IntSet.h"
#include "ListUtils.h"
#include "Symbols.h"
#include "Stream.h"
using namespace std;
using namespace collection;
/*
3.3 Implementation of Property functions and TypeConstructors
*/
ListExpr VectorProperty() {
#ifdef DEBUGHEAD
cout << "VectorProperty" << endl;
#endif
return (nl->TwoElemList(
nl->FiveElemList(nl->StringAtom("Signature"),
nl->StringAtom("Example Type List"),
nl->StringAtom("List Rep"),
nl->StringAtom("Example List"),
nl->StringAtom("Remarks")),
nl->FiveElemList(nl->StringAtom("-> DATA"),
nl->StringAtom("("+Vector::BasicType()+" real)"),
nl->StringAtom("(elem1 elem2 .. elem_n)"),
nl->StringAtom("(2.839 25.123 3.12 481.2)"),
nl->StringAtom("All elements must be of the"
"same type."))));
}
ListExpr SetProperty() {
#ifdef DEBUGHEAD
cout << "SetProperty" << endl;
#endif
return (nl->TwoElemList(
nl->FiveElemList(nl->StringAtom("Signature"),
nl->StringAtom("Example Type List"),
nl->StringAtom("List Rep"),
nl->StringAtom("Example List"),
nl->StringAtom("Remarks")),
nl->FiveElemList(nl->StringAtom("-> DATA"),
nl->StringAtom("("+Set::BasicType()+" real)"),
nl->StringAtom("(elem1 elem2 .. elem_n)"),
nl->StringAtom("(2.839 3.12 25.123 481.2)"),
nl->StringAtom("All elements must be of the"
"same type."))));
}
ListExpr MultisetProperty() {
#ifdef DEBUGHEAD
cout << "MultisetProperty" << endl;
#endif
return (nl->TwoElemList(
nl->FiveElemList(nl->StringAtom("Signature"),
nl->StringAtom("Example Type List"),
nl->StringAtom("List Rep"),
nl->StringAtom("Example List"),
nl->StringAtom("Remarks")),
nl->FiveElemList(nl->StringAtom("-> DATA"),
nl->StringAtom("("+Multiset::BasicType()+" real)"),
nl->StringAtom("((elem1 count1) .. "
"(elem_n count_n))"),
nl->StringAtom("((2.839 2) (3.12 1) (25.123 1))"),
nl->StringAtom("All elements must be of the"
"same type."))));
}
TypeConstructor vectorTC(
Vector::BasicType(), VectorProperty,
Collection::Out, Collection::In,
0, 0,
Collection::Create, Collection::Delete,
Collection::Open, Collection::Save,
Collection::Close, Collection::Clone,
Collection::Cast, Collection::SizeOfObj,
Collection::KindCheck);
TypeConstructor setTC(
Set::BasicType(), SetProperty,
Collection::Out, Collection::In,
0, 0,
Collection::Create, Collection::Delete,
Collection::Open, Collection::Save,
Collection::Close, Collection::Clone,
Collection::Cast, Collection::SizeOfObj,
Collection::KindCheck);
TypeConstructor multisetTC(
Multiset::BasicType(), MultisetProperty,
Collection::Out, Collection::In,
0, 0,
Collection::Create, Collection::Delete,
Collection::Open, Collection::Save,
Collection::Close, Collection::Clone,
Collection::Cast, Collection::SizeOfObj,
Collection::KindCheck);
TypeConstructor IntSetTC(
IntSet::BasicType(),
IntSet::Property, IntSet::Out, IntSet::In, 0,0,
IntSet::Create, IntSet::Delete,
IntSet::Open, IntSet::Save, IntSet::Close, IntSet::Clone,
IntSet::Cast, IntSet::Size, IntSet::TypeCheck
);
/*
4 Implementation of operators
4.1 Implementation of contains and in
*/
template<bool contains> ListExpr ContainsInTypeMap(ListExpr args) {
ListExpr errorInfo = nl->OneElemList(nl->SymbolAtom("ERROR"));
#ifdef DEBUGHEAD
cout << "ContainsTypeMapping:" << nl->ToString(args) << endl;
#endif
string opName = (contains?"contains":"in");
string pos1 = (contains?"first":"second");
string pos2 = (contains?"second":"first");
if(nl->ListLength(args)!=2) {
ErrorReporter::ReportError("Operator " + opName + " expects a list of"
+ " length two.");
return nl->TypeError();
}
ListExpr coll = (contains?nl->First(args):nl->Second(args));
ListExpr elem = (contains?nl->Second(args):nl->First(args));
if(!Collection::KindCheck(coll, errorInfo)) {
ErrorReporter::ReportError("Operator " + opName + " expects a vector, "
+ "set or multiset as " + pos1 + " argument.");
return nl->TypeError();
}
if(!nl->Equal(nl->Second(coll), elem)) {
ErrorReporter::ReportError("The " + pos2 + " argument of operator "
+ opName + " has to be of the same type as the"
+ " elements of the " + pos1 + " argument.");
return nl->TypeError();
}
string type = nl->SymbolValue(nl->First(coll));
if((type==Vector::BasicType())||(type==Set::BasicType())) {
return nl->SymbolAtom(CcBool::BasicType());
} else if(type==Multiset::BasicType()) {
return nl->SymbolAtom(CcInt::BasicType());
}
ErrorReporter::ReportError("Operator " + opName + " expects a vector"
+ ", set or multiset as " + pos1
+ " argument.");
return nl->TypeError();
}
template<bool contains> int ContainsInValueMap(Word* args, Word& result,
int message, Word& local, Supplier s) {
#ifdef DEBUGHEAD
cout << "ContainsInValueMap" << endl;
#endif
result = qp->ResultStorage(s);
Collection* coll;
Attribute* elem;
if(contains) {
coll = static_cast<Collection*>(args[0].addr);
elem = static_cast<Attribute*>(args[1].addr);
} else {
elem = static_cast<Attribute*>(args[0].addr);
coll = static_cast<Collection*>(args[1].addr);
}
if(!coll->IsDefined()){
(static_cast<Attribute*>(result.addr))->SetDefined(false);
return 0;
}
int contained = coll->Contains(elem);
if(coll->GetMyCollType()==collection::multiset) {
(static_cast<CcInt*>(result.addr))->Set(true, contained);
} else {
(static_cast<CcBool*>(result.addr))->Set(true, (contained==1));
}
return 0;
}
struct containsInfo : OperatorInfo {
containsInfo()
{
name = "contains";
signature = Vector::BasicType() + "(t) x t -> " + CcBool::BasicType();
appendSignature(Set::BasicType() + "(t) x t -> " + CcBool::BasicType());
appendSignature(Multiset::BasicType() + "(t) x t -> "+CcInt::BasicType());
syntax = "_ contains _";
meaning = "Contains predicate.";
}
};
struct inInfo : OperatorInfo {
inInfo()
{
name = "in";
signature = "t x "+Vector::BasicType() + "(t) -> " + CcBool::BasicType();
appendSignature("t x "+Set::BasicType() + "(t) -> "+CcBool::BasicType());
appendSignature("t x "+Multiset::BasicType()+"(t) -> "+
CcBool::BasicType());
syntax = "_ in _";
meaning = "Inverted contains predicate.";
}
};
/*
4.2 Implementation of add and insert
*/
template<bool insert> ListExpr InsertTypeMap(ListExpr args) {
ListExpr errorInfo = nl->OneElemList(nl->SymbolAtom("ERROR"));
#ifdef DEBUGHEAD
cout << "InsertTypeMapping:" << nl->ToString(args) << endl;
#endif
string opName = (insert?"insert":"+");
if(nl->ListLength(args)!=2) {
ErrorReporter::ReportError("Operator " + opName + " expects a list of"
+ " length two.");
return nl->TypeError();
}
ListExpr coll = nl->First(args);
ListExpr elem = nl->Second(args);
if(!Collection::KindCheck(coll, errorInfo)) {
if(insert) {
ErrorReporter::ReportError("Operator " + opName + " expects a "
+ "set or multiset as first argument.");
} else {
ErrorReporter::ReportError("Operator " + opName + " expects a "
+ "vector as first argument.");
}
return nl->TypeError();
}
if((nl->ListLength(coll)!=2) || !nl->Equal(nl->Second(coll), elem)) {
ErrorReporter::ReportError("The second argument of operator "
+ opName + " has to be of the same type as the"
+ " elements of the first argument.");
return nl->TypeError();
}
string type = nl->SymbolValue(nl->First(coll));
if((type==Vector::BasicType())==(!insert)) {
return coll;
}
if(insert) {
ErrorReporter::ReportError("Operator 'insert' expects a "
"set or multiset as first argument.");
} else {
ErrorReporter::ReportError("Operator '+' expects a "
"vector as first argument.");
}
return nl->TypeError();
}
template<bool insert> int InsertValueMap(Word* args, Word& result,
int message, Word& local, Supplier s) {
#ifdef DEBUGHEAD
cout << "InsertValueMap" << endl;
#endif
Collection* coll = static_cast<Collection*>(args[0].addr);
Attribute* elem = static_cast<Attribute*>(args[1].addr);
result = qp->ResultStorage(s);
Collection* resColl = static_cast<Collection*>(result.addr);
resColl->CopyFrom(static_cast<Attribute*>(coll));
resColl->Insert(elem, 1);
return 0;
}
struct insertInfo : OperatorInfo {
insertInfo()
{
name = "insert";
signature = Set::BasicType() + "(t) x t -> " + Set::BasicType() + "(t)";
appendSignature(Multiset::BasicType() + "(t) x t -> " +
Multiset::BasicType() + "(t)");
syntax = "_ insert _";
meaning = "Inserts the second argument in the first.";
}
};
struct addInfo : OperatorInfo {
addInfo()
{
name = "+";
signature = Vector::BasicType() + "(t) x t -> " +
Vector::BasicType() + "(t)";
syntax = "_ + _";
meaning = "Adds the element to the vector";
}
};
/*
4.3 Implementation of operator create
*/
template<CollectionType collType> ListExpr CreateTypeMap(ListExpr args) {
#ifdef DEBUGHEAD
cout << "CreateTypeMap: " << nl->ToString(args) << endl;
#endif
string resultType;
switch(collType) {
case collection::vector:
resultType = Vector::BasicType();
break;
case collection::set:
resultType = Set::BasicType();
break;
default:
resultType = Multiset::BasicType();
}
string opName = "create_" + resultType;
#ifdef DEBUG
cout << " Statusbericht CreateTypeMap:" << endl
<< " resultType: " << resultType << endl;
#endif
int length = nl->ListLength(args);
if(length==0) {
ErrorReporter::ReportError("Operator " + opName + " needs at least one "
+ "element to insert to know the type of the elements.");
return nl->TypeError();
}
ListExpr type = nl->First(args);
#ifdef DEBUG
cout << " Statusbericht CreateTypeMap:" << endl
<< " type: " << type << endl;
#endif
ListExpr errorInfo = nl->OneElemList(nl->SymbolAtom("ERROR"));
if(!am->CheckKind(Kind::DATA(), type, errorInfo)) {
ErrorReporter::ReportError("Operator " + opName + " expects elements of "
+ "Kind DATA.");
return nl->TypeError();
}
#ifdef DEBUG
cout << " Statusbericht CreateTypeMap:" << endl
<< " Wir sind hinter CheckKind!" << endl;
#endif
ListExpr rest = nl->Rest(args);
while(!nl->IsEmpty(rest)) {
if(!nl->Equal(nl->First(rest), type)) {
ErrorReporter::ReportError("All arguments of operator " + opName
+ " have to be of the same type.");
return nl->TypeError();
}
rest = nl->Rest(rest);
}
return nl->TwoElemList(nl->SymbolAtom(resultType), type);
}
int CreateValueMap(Word* args, Word& result,
int message, Word& local, Supplier s) {
#ifdef DEBUGHEAD
cout << "CreateValueMap" << endl;
#endif
result = qp->ResultStorage(s);
Collection* resultColl = static_cast<Collection*>(result.addr);
int sons = qp->GetNoSons(s);
resultColl->Clear();
resultColl->SetDefined(true);
int i = 0;
while(i < sons) {
Attribute* elem = static_cast<Attribute*>(args[i].addr);
resultColl->Insert(elem, 1);
i++;
}
resultColl->Finish();
return 0;
}
struct CreateVectorInfo : OperatorInfo {
CreateVectorInfo()
{
name = "create_" + Vector::BasicType();
signature = "t+ -> " + Vector::BasicType() + "(t)";
syntax = "create_" + Vector::BasicType() + "(_, _)";
meaning = "Creates a " + Vector::BasicType() + " of t.";
}
};
struct CreateSetInfo : OperatorInfo {
CreateSetInfo()
{
name = "create_" + Set::BasicType();
signature = "t+ -> " + Set::BasicType() + "(t)";
syntax = "create_" + Set::BasicType() + "(_, _)";
meaning = "Creates a " + Set::BasicType() + " of t.";
}
};
struct CreateMultisetInfo : OperatorInfo {
CreateMultisetInfo()
{
name = "create_" + Multiset::BasicType();
signature = "t+ -> " + Multiset::BasicType() + "(t)";
syntax = "create_" + Multiset::BasicType() + "(_, _)";
meaning = "Creates a " + Multiset::BasicType() + " of t.";
}
};
/*
4.4 Implementation of function collect
*/
template<CollectionType targetType> ListExpr CollectTypeMap(ListExpr args) {
#ifdef DEBUGHEAD
cout << "CollectTypeMap: " << nl->ToString(args) << endl;
#endif
string operatorName;
string resultType;
switch(targetType){
case collection::vector:
operatorName = "collect_vector";
resultType = Vector::BasicType();
break;
case collection::set:
operatorName = "collect_set";
resultType = Set::BasicType();
break;
case collection::multiset:
operatorName = "collect_multiset";
resultType = Multiset::BasicType();
break;
default:
operatorName = "";
}
const string errMsg = "Operator " + operatorName
+ " expects (stream DATA)";
ListExpr argStream;
ListExpr argType;
ListExpr errorInfo = nl->OneElemList(nl->SymbolAtom("ERROR"));
if ( nl->ListLength(args) == 1 )
{
argStream = nl->First(args);
if ( !nl->IsAtom(argStream) && nl->ListLength(argStream) == 2)
{
argType = nl->Second(argStream);
if ( nl->IsEqual(nl->First(argStream), Symbol::STREAM())
&& am->CheckKind(Kind::DATA(), argType, errorInfo) ){
return nl->TwoElemList(
nl->SymbolAtom(resultType),
argType);
}
}
}
ErrorReporter::ReportError(errMsg);
return nl->TypeError();
}
template<CollectionType targetType> int CollectValueMap(
Word* args, Word& result,
int message, Word& local, Supplier s) {
#ifdef DEBUGHEAD
cout << "CollectValueMap" << endl;
#endif
result = qp->ResultStorage(s);
Collection* resColl = static_cast<Collection*>(result.addr);
resColl->Clear();
resColl->SetDefined(true);
Attribute* elemToInsert;
Word elem = SetWord(Address(0));
qp->Open(args[0].addr);
qp->Request(args[0].addr, elem);
while ( qp->Received(args[0].addr) )
{
elemToInsert = static_cast<Attribute*>(elem.addr);
resColl->Insert(elemToInsert, 1);
elemToInsert->DeleteIfAllowed();
qp->Request(args[0].addr, elem);
}
resColl->Finish();
qp->Close(args[0].addr);
return 0;
}
struct collectSetInfo : OperatorInfo {
collectSetInfo()
{
name = "collect_set";
signature = Symbol::STREAM() + "(t) -> " + Set::BasicType() + "(t)";
syntax = "_ collect_set";
meaning = "Collects the stream elements into a new set";
}
};
struct collectMultisetInfo : OperatorInfo {
collectMultisetInfo()
{
name = "collect_multiset";
signature = Symbol::STREAM() + "(t) -> " + Multiset::BasicType() + "(t)";
syntax = "_ collect_multiset";
meaning = "Collects the stream elements into a new multiset";
}
};
struct collectVectorInfo : OperatorInfo {
collectVectorInfo()
{
name = "collect_vector";
signature = Symbol::STREAM() + "(t) -> " + Vector::BasicType() + "(t)";
syntax = "_ collect_vector";
meaning = "Collects the stream elements into a new vector";
}
};
/*
4.5 Implementation of operator components
*/
ListExpr ComponentsTypeMap(ListExpr args) {
#ifdef DEBUGHEAD
cout << "ComponentsTypeMap" << endl;
#endif
const string errMsg = "Operator components expects (vector DATA)"
" or (set DATA)"
" or (multiset DATA)";
ListExpr argCollection;
ListExpr argType;
ListExpr errorInfo = nl->OneElemList(nl->SymbolAtom("ERROR"));
if ( nl->ListLength(args) == 1 )
{
argCollection = nl->First(args);
if ( !nl->IsAtom(argCollection) && nl->ListLength(argCollection) == 2)
{
argType = nl->Second(argCollection);
if (
(nl->IsEqual(nl->First(argCollection), Vector::BasicType()) ||
nl->IsEqual(nl->First(argCollection), Set::BasicType()) ||
nl->IsEqual(nl->First(argCollection), Multiset::BasicType()))
&& am->CheckKind(Kind::DATA(), argType, errorInfo) ){
return nl->TwoElemList(
nl->SymbolAtom(Symbol::STREAM()),
argType);
}
}
}
ErrorReporter::ReportError(errMsg);
return nl->TypeError();
}
struct ComponentsLocalInfo
{
int componentIndex;
int componentCount;
};
int ComponentsValueMap( Word* args, Word& result,
int message, Word& local, Supplier s) {
#ifdef DEBUGHEAD
cout << "ComponentsValueMap" << endl;
#endif
ComponentsLocalInfo *linfo;
Collection* coll = (Collection*)args[0].addr;
switch( message )
{
case OPEN:
linfo = new ComponentsLocalInfo;
linfo->componentIndex = 0;
if(coll->GetNoUniqueComponents()>0) {
linfo->componentCount = coll->GetComponentCount(0);
} else {
linfo->componentCount = 0;
}
local = SetWord(linfo);
return 0;
case REQUEST:
if ( local.addr == 0 ){
result.addr = 0;
return CANCEL;
}
linfo = (ComponentsLocalInfo*)local.addr;
if (linfo->componentCount <= 0){
if(linfo->componentIndex + 1 >= coll->GetNoUniqueComponents()){
result.addr = 0;
return CANCEL;
}else{
linfo->componentIndex++;
linfo->componentCount =
coll->GetComponentCount(linfo->componentIndex);
}
}
result = SetWord(coll->GetComponent(linfo->componentIndex));
linfo->componentCount--;
return YIELD;
case CLOSE:
if ( local.addr != 0 )
{
linfo = ( ComponentsLocalInfo*) local.addr;
delete linfo;
local = SetWord(Address(0));
}
return 0;
}
return -1; // should not be reached
}
struct componentsInfo : OperatorInfo {
componentsInfo()
{
name = "components";
signature = Vector::BasicType() + "(t) -> " + Symbol::STREAM() + "(t)";
appendSignature(Set::BasicType() + "(t) -> " + Symbol::STREAM() + "(t)");
appendSignature(Multiset::BasicType() + "(t) -> "
+ Symbol::STREAM() + "(t)");
syntax = "components(_)";
meaning = "Takes the elements from the Collection into a stream";
}
};
namespace collection {
/*
4.6 Implementation of operator get
*/
ListExpr GetTypeMap(ListExpr args) {
#ifdef DEBUGHEAD
cout << "GetTypeMap" << endl;
#endif
const string errMsg = "Operator get expects (vector DATA) x int";
ListExpr argCollection;
ListExpr argIndex;
ListExpr argType;
ListExpr errorInfo = nl->OneElemList(nl->SymbolAtom("ERROR"));
if ( nl->ListLength(args) == 2 )
{
argCollection = nl->First(args);
argIndex = nl->Second(args);
if(!(nl->IsAtom(argIndex) && nl->IsEqual(argIndex, CcInt::BasicType())))
{
ErrorReporter::ReportError(errMsg);
return nl->TypeError();
}
if ( !nl->IsAtom(argCollection) && nl->ListLength(argCollection) == 2)
{
argType = nl->Second(argCollection);
if (
(nl->IsEqual(nl->First(argCollection), Vector::BasicType()))
&& am->CheckKind(Kind::DATA(), argType, errorInfo) ){
return argType;
}
}
}
ErrorReporter::ReportError(errMsg);
return nl->TypeError();
}
int GetValueMap( Word* args, Word& result,
int message, Word& local, Supplier s) {
#ifdef DEBUGHEAD
cout << "GetValueMap" << endl;
#endif
Collection* sourceColl = static_cast<Collection*>(args[0].addr);
CcInt* index = static_cast<CcInt*>( args[1].addr );
int indexVal = index->GetIntval();
result = qp->ResultStorage(s);
Attribute* resAttribute = static_cast<Attribute*>(result.addr);
if(sourceColl->GetNoComponents() <= indexVal || indexVal < 0){
((Attribute*)result.addr)->SetDefined(false);
}else{
Attribute* elem = sourceColl->GetComponent(indexVal);
resAttribute->CopyFrom(elem);
elem->DeleteIfAllowed(true);
}
return 0;
}
struct getInfo : OperatorInfo {
getInfo()
{
name = "get";
signature = Vector::BasicType() + "(t) x int -> t";
syntax = "get( _, _ )";
meaning = "Gets a component from the vector and index or undefined"
" if the index is invalid";
}
};
/*
4.7 Implementation of operator delete
*/
ListExpr DeleteTypeMap(ListExpr args) {
#ifdef DEBUGHEAD
cout << "DeleteTypeMap" << endl;
#endif
const string errMsg = "Operator 'deleteelem' "
" expects (set DATA) x DATA"
" or (multiset DATA) x DATA";
ListExpr argCollection;
ListExpr argCollectionType;
ListExpr argDeleteType;
ListExpr errorInfo = nl->OneElemList(nl->SymbolAtom("ERROR"));
if ( nl->ListLength(args) == 2 )
{
argCollection = nl->First(args);
argDeleteType = nl->Second(args);
if (!nl->IsAtom(argCollection) &&
nl->ListLength(argCollection) == 2)
{
argCollectionType = nl->Second(argCollection);
if (
(nl->IsEqual(nl->First(argCollection), Set::BasicType()) ||
nl->IsEqual(nl->First(argCollection), Multiset::BasicType()))
&& am->CheckKind(Kind::DATA(), argCollectionType, errorInfo)
&& nl->Equal(argCollectionType, argDeleteType)){
return argCollection;
}
}
}
ErrorReporter::ReportError(errMsg);
return nl->TypeError();
}
int DeleteValueMap( Word* args, Word& result,
int message, Word& local, Supplier s) {
#ifdef DEBUGHEAD
cout << "DeleteValueMap" << endl;
#endif
Collection* sourceColl = static_cast<Collection*>(args[0].addr);
Attribute* elemToDelete = static_cast<Attribute*>( args[1].addr );
result = qp->ResultStorage( s );
Collection* resColl = static_cast<Collection*>(result.addr);
resColl->Clear();
if(!sourceColl->IsDefined()){
resColl->SetDefined(false);
}else{
for(int i = 0; i < sourceColl->GetNoUniqueComponents(); i++){
int componentCount = sourceColl->GetComponentCount(i);
Attribute* elem = sourceColl->GetComponent(i);
if(elem->Compare(elemToDelete) == 0){
componentCount--;
}
if(componentCount > 0){
resColl->Insert(elem, componentCount);
}
if(elem) {
elem->DeleteIfAllowed(true);
}
}
resColl->Finish();
}
return 0;
}
struct deleteInfo : OperatorInfo {
deleteInfo()
{
name = "deleteelem";
signature = Set::BasicType() + "(t) x t -> " + Set::BasicType() + "(t)";
appendSignature(Multiset::BasicType() + "(t) x t -> "
+ Multiset::BasicType() + "(t)");
syntax = "deleteelem( _, _ )";
meaning = "Deletes a component one time from the set or multiset"
" if it is present in the collection";
}
};
/*
4.8 Implementation of operator concat
*/
ListExpr ConcatTypeMap(ListExpr args) {
#ifdef DEBUGHEAD
cout << "ConcatTypeMap" << endl;
#endif
const string errMsg = "Operator concat expects (vector DATA)"
" x (vector DATA)";
ListExpr argCollection1;
ListExpr argCollection2;
ListExpr argCollectionType;
ListExpr errorInfo = nl->OneElemList(nl->SymbolAtom("ERROR"));
if ( nl->ListLength(args) == 2 )
{
argCollection1 = nl->First(args);
argCollection2 = nl->Second(args);
if (!nl->IsAtom(argCollection1) &&
nl->ListLength(argCollection1) == 2)
{
argCollectionType = nl->Second(argCollection1);
if (
nl->IsEqual(nl->First(argCollection1), Vector::BasicType())
&& am->CheckKind(Kind::DATA(), argCollectionType, errorInfo)
&& nl->ToString(argCollection1)
== nl->ToString(argCollection2)){
return argCollection1;
}
}
}
ErrorReporter::ReportError(errMsg);
return nl->TypeError();
}
int ConcatValueMap( Word* args, Word& result,
int message, Word& local, Supplier s) {
#ifdef DEBUGHEAD
cout << "ConcatValueMap" << endl;
#endif
Collection* vector1 = static_cast<Collection*>(args[0].addr);
Collection* vector2 = static_cast<Collection*>(args[1].addr);
result = qp->ResultStorage( s );
Collection *resVector = static_cast<Collection*>(result.addr);
resVector->CopyFrom(static_cast<Attribute*>(vector1));
for(int eCnt = 0; eCnt < vector2->GetNoUniqueComponents(); eCnt++){
Attribute* elem = vector2->GetComponent(eCnt);
resVector->Insert(elem, 1);
elem->DeleteIfAllowed(true);
}
resVector->Finish();
return 0;
}
struct concatInfo : OperatorInfo {
concatInfo()
{
name = "concat";
signature = Vector::BasicType() + "(t) x "
+ Vector::BasicType() + "(t) -> " + Vector::BasicType() + "(t)";
syntax = "_ _ concat";
meaning = "Concatenates two vectors to a new one";
}
};
/*
4.9 Implementation of operators union, intersection and difference
*/
enum MathSetOperationType {unionOp, intersectionOp, differenceOp};
template<MathSetOperationType opType>
ListExpr MathSetOperationTypeMap(ListExpr args) {
string opName;
#ifdef DEBUGHEAD
cout << "MathSetTypeMap" << endl;
#endif
switch(opType){
case unionOp:
opName = "union";
break;
case intersectionOp:
opName = "intersection";
break;
case differenceOp:
opName = "difference";
break;
default:
break;
}
const string errMsg = "Operator " + opName + " expects (set DATA)"
" x (set DATA) or"
" (multiset DATA) x (multiset DATA)";
ListExpr argCollection1;
ListExpr argCollection2;
ListExpr argCollectionType;
ListExpr errorInfo = nl->OneElemList(nl->SymbolAtom("ERROR"));
if ( nl->ListLength(args) == 2 )
{
argCollection1 = nl->First(args);
argCollection2 = nl->Second(args);
if (!nl->IsAtom(argCollection1) &&
nl->ListLength(argCollection1) == 2)
{
argCollectionType = nl->Second(argCollection1);
if (
(nl->IsEqual(nl->First(argCollection1), Set::BasicType())
|| nl->IsEqual(nl->First(argCollection1),
Multiset::BasicType()))
&& am->CheckKind(Kind::DATA(), argCollectionType, errorInfo)
&& nl->ToString(argCollection1)
== nl->ToString(argCollection2)){
return argCollection1;
}
}
}
ErrorReporter::ReportError(errMsg);
return nl->TypeError();
}
template<MathSetOperationType opType>
int MathSetOperationValueMap( Word* args, Word& result,
int message, Word& local, Supplier s) {
#ifdef DEBUGHEAD
cout << "MathSetValueMap" << endl;
#endif
Collection* coll1 = static_cast<Collection*>(args[0].addr);
Collection* coll2 = static_cast<Collection*>(args[1].addr);
result = qp->ResultStorage( s );
Collection* resColl = static_cast<Collection*>(result.addr);
resColl->Clear();
if( !coll1->IsDefined() || !coll2->IsDefined() ){
resColl->SetDefined( false );
return 0;
}
int insertCnt;
int noColl1Components = coll1->GetNoUniqueComponents();
int noColl2Components = coll2->GetNoUniqueComponents();
int elementIdx1 = 0;
int elementIdx2 = 0;
bool coll1Ended = (noColl1Components <= elementIdx1);
bool coll2Ended = (noColl2Components <= elementIdx2);
bool restore1 = !coll1Ended;
bool restore2 = !coll2Ended;
Attribute* elem1 = 0;
Attribute* elem2 = 0;
while(!coll1Ended && !coll2Ended){
if(restore1) {
elem1 = coll1->GetComponent(elementIdx1);
restore1 = false;
}
if(restore2) {
elem2 = coll2->GetComponent(elementIdx2);
restore2 = false;
}
int compareRes = elem1->Compare(elem2);
switch(compareRes){
case -1:
switch(opType){
case unionOp:
resColl->Insert(elem1,coll1->GetComponentCount(elementIdx1));
elem1->Print(cout) << endl;
break;
case differenceOp:
resColl->Insert(elem1,coll1->GetComponentCount(elementIdx1));
break;
default:
break;
}
elementIdx1++; restore1 = true;
break;
case 0:
switch(opType){
case unionOp:
resColl->Insert(elem1, coll1->GetComponentCount(elementIdx1)
+ coll2->GetComponentCount(elementIdx2));
elem1->Print(cout) << endl;
break;
case intersectionOp:
insertCnt =
coll1->GetComponentCount(elementIdx1) >
coll2->GetComponentCount(elementIdx2) ?
coll2->GetComponentCount(elementIdx2) :
coll1->GetComponentCount(elementIdx1);
resColl->Insert(elem1, insertCnt);
break;
case differenceOp:
insertCnt = coll1->GetComponentCount(elementIdx1) -
coll2->GetComponentCount(elementIdx2);
if(insertCnt > 0){
resColl->Insert(elem1, insertCnt);
}
break;
default:
break;
}
elementIdx1++; restore1 = true;
elementIdx2++; restore2 = true;
break;
case 1:
switch(opType){
case unionOp:
resColl->Insert(elem2, coll2->GetComponentCount(elementIdx2));
elem2->Print(cout) << endl;
break;
default:
break;
}
elementIdx2++;
restore2 = true;
break;
default:
break;
}
coll1Ended = (noColl1Components <= elementIdx1);
coll2Ended = (noColl2Components <= elementIdx2);
if(elem1 && restore1) {
elem1->DeleteIfAllowed(true);
elem1 = 0;
}
if(elem2 && restore2) {
elem2->DeleteIfAllowed(true);
elem2 = 0;
}
}
if(elem1) {
elem1->DeleteIfAllowed(true);
}
if(elem2) {
elem2->DeleteIfAllowed(true);
}
for(int iCnt1 = elementIdx1;
iCnt1 < coll1->GetNoUniqueComponents(); iCnt1++){
elem1 = coll1->GetComponent(iCnt1);
switch(opType){
case unionOp:
case differenceOp:
resColl->Insert(elem1, coll1->GetComponentCount(iCnt1));
elem1->Print(cout) << endl;
break;
default:
break;
}
elem1->DeleteIfAllowed(true);
}
for(int iCnt2 = elementIdx2;
iCnt2 < coll2->GetNoUniqueComponents(); iCnt2++){
elem2 = coll2->GetComponent(iCnt2);
switch(opType){
case unionOp:
resColl->Insert(elem2, coll2->GetComponentCount(iCnt2));
elem2->Print(cout) << endl;
break;
default:
break;
}
elem2->DeleteIfAllowed(true);
}
resColl->Finish();
return 0;
}
struct unionInfo : OperatorInfo {
unionInfo()
{
name = "union";
signature = Set::BasicType() + "(t) x " + Set::BasicType() + "(t) -> "
+ Set::BasicType() + "(t)";
appendSignature(Multiset::BasicType() + "(t) x "
+ Multiset::BasicType() + "(t) -> "
+ Multiset::BasicType() + "(t)");
syntax = "_ union _";
meaning = "assigns the union-operation on two sets or multisets";
}
};
struct intersectionInfo : OperatorInfo {
intersectionInfo()
{
name = "intersection";
signature = Set::BasicType() + "(t) x " + Set::BasicType() + "(t) -> "
+ Set::BasicType() + "(t)";
appendSignature(Multiset::BasicType() + "(t) x " + Multiset::BasicType()
+ "(t) -> "
+ Multiset::BasicType() + "(t)");
syntax = "intersection( _, _)";
meaning = "assigns the intersection-operation on two sets or multisets";
}
};
struct differenceInfo : OperatorInfo {
differenceInfo()
{
name = "difference";
signature = Set::BasicType() + "(t) x " + Set::BasicType() + "(t) -> "
+ Set::BasicType() + "(t)";
appendSignature(Multiset::BasicType() + "(t) x " + Multiset::BasicType() +
"(t) -> " + Multiset::BasicType() + "(t)");
syntax = "difference( _, _)";
meaning = "assigns the difference-operation on two sets or multisets";
}
};
/*
4.10 Implementation of operation size
*/
int sizeFun(Word* args, Word& result, int message, Word& local, Supplier s){
Collection* co = (Collection*)args[0].addr;
result = qp->ResultStorage(s);
((CcInt*)result.addr)->Set(co->IsDefined(), co->GetNoComponents());
return 0;
}
ListExpr sizeTypeMap(ListExpr args){
if( nl->ListLength(args) > 0)
{
ListExpr arg1 = nl->First(args);
if (!nl->IsAtom(arg1) && (nl->IsEqual(nl->First(arg1),
Set::BasicType()) || nl->IsEqual(nl->First(arg1), Multiset::BasicType())
|| nl->IsEqual(nl->First(arg1), Vector::BasicType()))) {
return nl->SymbolAtom(CcInt::BasicType());
}
}
return nl->SymbolAtom(Symbol::TYPEERROR());
}
struct sizeInfo : OperatorInfo {
sizeInfo() : OperatorInfo()
{
name = "size";
signature = Set::BasicType() + " -> " + CcInt::BasicType();
appendSignature(Multiset::BasicType() + " -> " + CcInt::BasicType());
appendSignature(Vector::BasicType() + " -> " + CcInt::BasicType());
syntax = "size( _ )";
meaning = "Number of contained objects";
}
};
/*
4.11 Implementation of operators <, <=, >, >= and =
*/
int ltFun(Word* args, Word& result, int message, Word& local, Supplier s){
bool r = true;
int tmp;
Collection* co = (Collection*)args[0].addr;
Collection* cl = (Collection*)args[1].addr;
result = qp->ResultStorage(s);
tmp = co->Compare(cl);
if(tmp == 0){
r = false;
}
else if(tmp == 1)
r = false;
else
r = true;
((CcBool*)result.addr)->Set(true, r);
return 0;
}
ListExpr compareTypeMap(ListExpr args){
if (nl->IsAtom(args) || nl->ListLength(args) != 2){
return nl->SymbolAtom(Symbol::TYPEERROR());
}
ListExpr arg1 = nl->First(args);
ListExpr arg2 = nl->Second(args);
if ( !nl->IsAtom(arg1)
&& ( nl->IsEqual(nl->First(arg1), Set::BasicType())
|| nl->IsEqual(nl->First(arg1), Multiset::BasicType())
|| nl->IsEqual(nl->First(arg1), Vector::BasicType())
)
&& nl->Equal(arg1, arg2)
) {
return nl->SymbolAtom(CcBool::BasicType());
}
return nl->SymbolAtom(Symbol::TYPEERROR());
}
struct ltInfo : OperatorInfo {
ltInfo() : OperatorInfo()
{
name = "<";
signature = Set::BasicType() + " x " + Set::BasicType() + " -> "
+ CcBool::BasicType();
appendSignature(Multiset::BasicType() + " x " + Multiset::BasicType()
+ " -> " + CcBool::BasicType());
appendSignature(Vector::BasicType() + " x " + Vector::BasicType() + " -> "
+ CcBool::BasicType());
syntax = " _ < _ ";
meaning = "Object 1 Smaller Than Object 2";
}
};
int eqFun(Word* args, Word& result, int message, Word& local, Supplier s){
bool r = true;
int tmp;
Collection* co = (Collection*)args[0].addr;
Collection* cl = (Collection*)args[1].addr;
result = qp->ResultStorage(s);
tmp = co->Compare(cl);
if(tmp == 0){
r = true;
}
else if(tmp == 1)
r = false;
else
r = false;
((CcBool*)result.addr)->Set(true, r);
return 0;
}
struct eqInfo : OperatorInfo {
eqInfo() : OperatorInfo()
{
name = "=";
signature = Set::BasicType() + " x " + Set::BasicType() + " -> "
+ CcBool::BasicType();
appendSignature(Multiset::BasicType() + " x " + Multiset::BasicType()
+ " -> " + CcBool::BasicType());
appendSignature(Vector::BasicType() + " x " + Vector::BasicType()
+ " -> " + CcBool::BasicType());
syntax = " _ = _ ";
meaning = "Object 1 equals Object 2";
}
};
int neFun(Word* args, Word& result, int message, Word& local, Supplier s){
bool r = true;
int tmp;
Collection* co = (Collection*)args[0].addr;
Collection* cl = (Collection*)args[1].addr;
result = qp->ResultStorage(s);
tmp = co->Compare(cl);
if(tmp == 0){
r = false;
}
else
r = true;
((CcBool*)result.addr)->Set(true, r);
return 0;
}
struct neInfo : OperatorInfo {
neInfo() : OperatorInfo()
{
name = "#";
signature = Set::BasicType() + " x " + Set::BasicType() + " -> "
+ CcBool::BasicType();
appendSignature(Multiset::BasicType() + " x " + Multiset::BasicType()
+ " -> " + CcBool::BasicType());
appendSignature(Vector::BasicType() + " x " + Vector::BasicType() + " -> "
+ CcBool::BasicType());
syntax = " _ # _ ";
meaning = "Object 1 does not equal Object 2";
}
};
int gtFun(Word* args, Word& result, int message, Word& local, Supplier s){
bool r = true;
int tmp;
Collection* co = (Collection*)args[0].addr;
Collection* cl = (Collection*)args[1].addr;
result = qp->ResultStorage(s);
tmp = co->Compare(cl);
if(tmp == 0){
r = false;
}
else if(tmp == 1)
r = true;
else
r = false;
((CcBool*)result.addr)->Set(true, r);
return 0;
}
struct gtInfo : OperatorInfo {
gtInfo() : OperatorInfo()
{
name = ">";
signature = Set::BasicType() + " x " + Set::BasicType() +
" -> " + CcBool::BasicType();
appendSignature(Multiset::BasicType() + " x " + Multiset::BasicType() +
" -> " + CcBool::BasicType());
appendSignature(Vector::BasicType() + " x " + Vector::BasicType() +
" -> " + CcBool::BasicType());
syntax = " _ > _ ";
meaning = "Object 1 Greater Than Object 2";
}
};
int leFun(Word* args, Word& result, int message, Word& local, Supplier s){
bool r = true;
int tmp;
Collection* co = (Collection*)args[0].addr;
Collection* cl = (Collection*)args[1].addr;
result = qp->ResultStorage(s);
tmp = co->Compare(cl);
if(tmp == 0){
r = true;
}
else if(tmp == 1)
r = false;
else
r = true;
((CcBool*)result.addr)->Set(true, r);
return 0;
}
struct leInfo : OperatorInfo {
leInfo() : OperatorInfo()
{
name = "<=";
signature = Set::BasicType() + " x " + Set::BasicType() + " -> "
+ CcBool::BasicType();
appendSignature(Multiset::BasicType() + " x " + Multiset::BasicType()
+ " -> " + CcBool::BasicType());
appendSignature(Vector::BasicType() + " x " + Vector::BasicType()
+ " -> " + CcBool::BasicType());
syntax = " _ <= _ ";
meaning = "Object 1 Smaller equal Object 2";
}
};
int geFun(Word* args, Word& result, int message, Word& local, Supplier s){
//cout << "Wir sind in der ge Funktion 0" << endl;
bool r = true;
int tmp;
Collection* co = (Collection*)args[0].addr;
Collection* cl = (Collection*)args[1].addr;
result = qp->ResultStorage(s);
tmp = co->Compare(cl);
if(tmp == 0){
r = true;
}
else if(tmp == 1)
r = true;
else
r = false;
((CcBool*)result.addr)->Set(true, r);
return 0;
}
struct geInfo : OperatorInfo {
geInfo() : OperatorInfo()
{
name = ">=";
signature = Set::BasicType() + " x " + Set::BasicType() + " -> "
+ CcBool::BasicType();
appendSignature(Multiset::BasicType() + " x " + Multiset::BasicType()
+ " -> " + CcBool::BasicType());
appendSignature(Vector::BasicType() + " x " + Vector::BasicType() + " -> "
+ CcBool::BasicType());
syntax = " _ >= _ ";
meaning = "Object 1 Greater equal Object 2";
}
};
/*
Operators over intset
*/
ListExpr collect_intsetTM(ListExpr args){
if(!nl->HasLength(args,2)){
return listutils::typeError("2 arguments required");
}
if(!Stream<CcInt>::checkType(nl->First(args))){
return listutils::typeError("first argument is not a stream(int)");
}
if(!CcBool::checkType(nl->Second(args))){
return listutils::typeError("second argument is not a bool");
}
return listutils::basicSymbol<IntSet>();
}
int collect_intsetVM(Word* args, Word& result, int message,
Word& local, Supplier s){
CcBool* IgnoreUndef = (CcBool*) args[1].addr;
bool ig = IgnoreUndef->IsDefined() && IgnoreUndef->GetValue();
result = qp->ResultStorage(s);
IntSet* res = (IntSet*) result.addr;
Stream<CcInt> stream(args[0]);
std::set<int> v;
CcInt* elem;
stream.open();
while( (elem = stream.request()) != nullptr ){
if(!elem->IsDefined()){
if(!ig){
res->clear();
res->SetDefined(false);
}
elem->DeleteIfAllowed();
stream.close();
return 0;
} else {
v.insert(elem->GetValue());
}
elem->DeleteIfAllowed();
}
stream.close();
res->setTo(v);
return 0;
}
OperatorSpec collect_intsetSpec(
"stream(int) x bool -> intset",
" _ collect_intset[_] ",
"Collects all incoming integers into an intset. "
"If the second arguemnt is true, undefined values "
"inside the stream are ignored. If it is false, "
"the result will be undefined in case of undefined "
" stream elements",
"query intstream(1,877) collect_intset[TRUE]"
);
Operator collect_intsetOp(
"collect_intset",
collect_intsetSpec.getStr(),
collect_intsetVM,
Operator::SimpleSelect,
collect_intsetTM
);
ListExpr sizeTM(ListExpr args){
if(!nl->HasLength(args,1)){
return listutils::typeError("1 arg expected");
}
if(!IntSet::checkType(nl->First(args))){
return listutils::typeError("intset expected");
}
return listutils::basicSymbol<CcInt>();
}
int sizeVM(Word* args, Word& result, int message,
Word& local, Supplier s){
result = qp->ResultStorage(s);
CcInt* res = (CcInt*) result.addr;
IntSet* arg = (IntSet*) args[0].addr;
if(!arg->IsDefined()){
res->SetDefined(false);
} else {
res->Set(true, arg->getSize());
}
return 0;
}
OperatorSpec sizeSpec(
"intset -> int",
"size(_)",
"Returns the number of elements of an intset.",
"query size(is1)"
);
Operator sizeOp(
"size",
sizeSpec.getStr(),
sizeVM,
Operator::SimpleSelect,
sizeTM
);
ListExpr containsTM(ListExpr args){
if(!nl->HasLength(args,2)){
return listutils::typeError("2 args expected");
}
if(!IntSet::checkType(nl->First(args)) ||
!CcInt::checkType(nl->Second(args))){
return listutils::typeError("intset x int expected");
}
return listutils::basicSymbol<CcBool>();
}
int containsVM(Word* args, Word& result, int message,
Word& local, Supplier s){
result = qp->ResultStorage(s);
CcBool* res = (CcBool*) result.addr;
IntSet* is = (IntSet*) args[0].addr;
CcInt* a = (CcInt*) args[1].addr;
if(!is->IsDefined() || !a->IsDefined()){
res->SetDefined(false);
} else {
res->Set(true, is->contains(a->GetValue()));
}
return 0;
}
OperatorSpec containsSpec(
"intset x int -> bool ",
" _ contains _ ",
"Checkes whether an intset contains a given value ",
"query is1 contains 23"
);
Operator containsOp(
"contains",
containsSpec.getStr(),
containsVM,
Operator::SimpleSelect,
containsTM
);
ListExpr feedISTM(ListExpr args){
if(!nl->HasLength(args,1)){
return listutils::typeError("1 arg expected");
}
if(!IntSet::checkType(nl->First(args))){
return listutils::typeError("intset expecetd");
}
return Stream<CcInt>::wrap(listutils::basicSymbol<CcInt>());
}
class feedISInfo{
public:
feedISInfo(IntSet* _is): is(_is), pos(0){
end = is->IsDefined()?is->getSize():0;
}
CcInt* next(){
if(pos>=end){
return nullptr;
}
return new CcInt(true, is->get(pos++));
}
private:
IntSet* is;
size_t pos;
size_t end;
};
int feedISVM(Word* args, Word& result, int message,
Word& local, Supplier s){
feedISInfo* li = (feedISInfo*) local.addr;
switch(message) {
case OPEN: if(li) delete li;
local.addr = new feedISInfo( (IntSet*) args[0].addr);
return 0;
case REQUEST: result.addr = li?li->next():0;
return result.addr?YIELD:CANCEL;
case CLOSE : if(li){
delete li;
local.addr = 0;
}
return 0;
}
return -1;
}
OperatorSpec feedISSpec(
"intset -> stream(int)",
" _ feed ",
"feedIS the content of an intset into a stream",
"query is1 feed count"
);
Operator feedISOp(
"feedIS",
feedISSpec.getStr(),
feedISVM,
Operator::SimpleSelect,
feedISTM
);
/*
General Type mapping for all set operations.
*/
ListExpr setOpsTM(ListExpr args){
if(!nl->HasLength(args,2)){
return listutils::typeError("2 args expected");
}
if(!IntSet::checkType(nl->First(args))
||!IntSet::checkType(nl->Second(args))){
return listutils::typeError("intset x intset expected");
}
return listutils::basicSymbol<IntSet>();
}
/*
Classes for different operators
*/
class UnionIS{
public:
static void compute(const IntSet& s1, const IntSet& s2,
IntSet& result){
result = s1.add(s2);
}
};
class MinusIS{
public:
static void compute(const IntSet& s1, const IntSet& s2,
IntSet& result){
result = s1.minus(s2);
}
};
class IntersectionIS{
public:
static void compute(const IntSet& s1, const IntSet& s2,
IntSet& result){
result = s1.intersection(s2);
}
};
class SDiffIS{
public:
static void compute(const IntSet& s1, const IntSet& s2,
IntSet& result){
result = s1.sdiff(s2);
}
};
/*
General value mapping for set operations.
*/
template<class OP>
int setOpsVM(Word* args, Word& result, int message,
Word& local, Supplier s){
result = qp->ResultStorage(s);
IntSet* a1 = (IntSet*) args[0].addr;
IntSet* a2 = (IntSet*) args[1].addr;
IntSet* res = (IntSet*) result.addr;
OP::compute(*a1,*a2,*res);
return 0;
}
OperatorSpec getSetOpSpec(const std::string& opname, bool infix){
std::string syntax = infix ? "_ " + opname + " _" : opname + "(_ , _)";
std::string ex = infix ? "query is1 " + opname + " is2"
: "query " + opname +"(is1, is2)";
OperatorSpec res( "intset x intset -> intset",
syntax,
"computes the " + opname + " of two intsets ",
ex);
return res;
}
Operator unionOp2(
"union",
getSetOpSpec("union",true).getStr(),
setOpsVM<UnionIS>,
Operator::SimpleSelect,
setOpsTM
);
Operator minusOp(
"minus",
getSetOpSpec("minus",true).getStr(),
setOpsVM<MinusIS>,
Operator::SimpleSelect,
setOpsTM
);
Operator intersectionOp2(
"intersection",
getSetOpSpec("intersection", false).getStr(),
setOpsVM<IntersectionIS>,
Operator::SimpleSelect,
setOpsTM
);
Operator sdiffOp(
"sdiff",
getSetOpSpec("sdiff", true).getStr(),
setOpsVM<SDiffIS>,
Operator::SimpleSelect,
setOpsTM
);
/*
~minCommon~
*/
ListExpr minCommonTM(ListExpr args){
if(!nl->HasLength(args,2)){
return listutils::typeError("2 arguments expected");
}
if( !IntSet::checkType(nl->First(args))
|| !IntSet::checkType(nl->Second(args))) {
return listutils::typeError("intset x intset expected");
}
return listutils::basicSymbol<CcInt>();
}
int minCommonVM(Word* args, Word& result, int message,
Word& local, Supplier s){
result = qp->ResultStorage(s);
IntSet* a1 = (IntSet*) args[0].addr;
IntSet* a2 = (IntSet*) args[1].addr;
CcInt* res = (CcInt*) result.addr;
int value;
bool intersects = a1->minCommon(*a2,value);
res->Set(intersects,value);
return 0;
}
OperatorSpec minCommonSpec(
"intset x intset -> int",
"minCommon(_,_)",
"Computes the minimum common element of both sets. "
"If such an element does not exist, an undefined value "
"is returned.",
"query minCommon(is1,is2)"
);
Operator minCommonOp(
"minCommon",
minCommonSpec.getStr(),
minCommonVM,
Operator::SimpleSelect,
minCommonTM
);
/*
5 Implementation of class CollectionAlgebra, registration of TypeConstructors
and operators
*/
class CollectionAlgebra : public Algebra {
public:
CollectionAlgebra() : Algebra() {
AddTypeConstructor(&vectorTC);
AddTypeConstructor(&setTC);
AddTypeConstructor(&multisetTC);
AddTypeConstructor(&IntSetTC);
vectorTC.AssociateKind(Kind::DATA());
setTC.AssociateKind(Kind::DATA());
multisetTC.AssociateKind(Kind::DATA());
IntSetTC.AssociateKind(Kind::DATA());
AddOperator(containsInfo(), ContainsInValueMap<true>,
ContainsInTypeMap<true>);
AddOperator(inInfo(), ContainsInValueMap<false>,
ContainsInTypeMap<false>);
AddOperator(insertInfo(), InsertValueMap<true>, InsertTypeMap<true>);
AddOperator(addInfo(), InsertValueMap<false>, InsertTypeMap<false>);
AddOperator(CreateVectorInfo(), CreateValueMap,
CreateTypeMap<collection::vector>);
AddOperator(CreateSetInfo(), CreateValueMap,
CreateTypeMap<collection::set>);
AddOperator(CreateMultisetInfo(), CreateValueMap,
CreateTypeMap<collection::multiset>);
AddOperator(collectSetInfo(), CollectValueMap<collection::set>,
CollectTypeMap<collection::set>);
AddOperator(collectMultisetInfo(), CollectValueMap<collection::multiset>,
CollectTypeMap<collection::multiset>);
AddOperator(collectVectorInfo(), CollectValueMap<collection::vector>,
CollectTypeMap<collection::vector>);
AddOperator(componentsInfo(), ComponentsValueMap,
ComponentsTypeMap);
AddOperator(getInfo(), GetValueMap,
GetTypeMap);
AddOperator(deleteInfo(), DeleteValueMap,
DeleteTypeMap);
AddOperator(concatInfo(), ConcatValueMap,
ConcatTypeMap);
AddOperator(unionInfo(), MathSetOperationValueMap<unionOp>,
MathSetOperationTypeMap<unionOp>);
AddOperator(intersectionInfo(), MathSetOperationValueMap<intersectionOp>,
MathSetOperationTypeMap<intersectionOp>);
AddOperator(differenceInfo(), MathSetOperationValueMap<differenceOp>,
MathSetOperationTypeMap<differenceOp>);
AddOperator( sizeInfo(), sizeFun, sizeTypeMap );
AddOperator( eqInfo(), eqFun, compareTypeMap );
AddOperator( gtInfo(), gtFun, compareTypeMap );
AddOperator( ltInfo(), ltFun, compareTypeMap );
AddOperator( geInfo(), geFun, compareTypeMap );
AddOperator( leInfo(), leFun, compareTypeMap );
AddOperator( neInfo(), neFun, compareTypeMap );
AddOperator(&collect_intsetOp);
AddOperator(&sizeOp);
AddOperator(&containsOp);
AddOperator(&feedISOp);
AddOperator(&unionOp2);
AddOperator(&minusOp);
AddOperator(&intersectionOp2);
AddOperator(&sdiffOp);
AddOperator(&minCommonOp);
}
~CollectionAlgebra() {};
};
} // end namespace collection
/*
6 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 (if it is built as a dynamic link library). The name
of the initialization function defines the name of the algebra module. By
convention it must start with "Initialize<AlgebraName>".
*/
extern "C"
Algebra* InitializeCollectionAlgebra(NestedList* nlRef, QueryProcessor* qpRef) {
return new (collection::CollectionAlgebra);
}
namespace Vector{
const string BasicType() {return "vector"; };
const bool checkType(ListExpr list){
return collection::Collection::checkType(list, BasicType());
}
}
namespace Set{
const string BasicType() {return "set"; };
const bool checkType(ListExpr list){
return collection::Collection::checkType(list, BasicType());
}
}
namespace Multiset{
const string BasicType() {return "multiset"; };
const bool checkType(ListExpr list){
return collection::Collection::checkType(list, BasicType());
}
}