989 lines
25 KiB
C++
989 lines
25 KiB
C++
/*
|
|
----
|
|
This file is part of SECONDO.
|
|
|
|
Copyright (C) 2004-2009, University in Hagen, Faculty of Mathematics and 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
|
|
----
|
|
|
|
//[&] [\&]
|
|
|
|
*/
|
|
|
|
#include "ListUtils.h"
|
|
#include "NestedList.h"
|
|
#include "SecondoSystem.h"
|
|
|
|
#include "Symbols.h" // Kind::*, Symbol::*
|
|
#include "StandardTypes.h" // int, real, bool, string
|
|
#include "Algebras/OldRelation-C++/OldRelationAlgebra.h" // rel, tuple
|
|
#include "Algebras/Relation-C++/RelationAlgebra.h" // rel, trel, tuple
|
|
#include "Algebras/OrderedRelation/OrderedRelationAlgebra.h" // orel
|
|
#include "Algebras/TupleIdentifier/TupleIdentifier.h" // tid
|
|
#include "Algebras/Rectangle/RectangleAlgebra.h" // rect, rect3, rect4, rect8
|
|
#include "Algebras/RTree/RTreeAlgebra.h" // rtree, rtree3, rtree4, rtee8
|
|
#include "Algebras/BTree/BTreeAlgebra.h" // btree
|
|
#include "Algebras/BTree2/BTree2.h" // btree2
|
|
#include "Algebras/Hash/HashAlgebra.h" // hash
|
|
|
|
|
|
#include <set>
|
|
#include <string>
|
|
#include <stdarg.h>
|
|
|
|
extern NestedList* nl;
|
|
|
|
using namespace std;
|
|
|
|
namespace listutils{
|
|
|
|
/*
|
|
Returns a list containing a symbol "ERROR";
|
|
|
|
*/
|
|
|
|
ListExpr emptyErrorInfo(){
|
|
return nl->OneElemList(nl->SymbolAtom(Symbol::ERROR()));
|
|
}
|
|
|
|
/*
|
|
Checks for a Spatial type.
|
|
|
|
*/
|
|
|
|
bool isSpatialType(ListExpr arg){
|
|
AlgebraManager *algMgr = SecondoSystem::GetAlgebraManager();
|
|
ListExpr errorInfo = emptyErrorInfo();
|
|
return algMgr->CheckKind(Kind::SPATIAL1D(), arg, errorInfo) ||
|
|
algMgr->CheckKind(Kind::SPATIAL2D(), arg, errorInfo) ||
|
|
algMgr->CheckKind(Kind::SPATIAL3D(), arg, errorInfo) ||
|
|
algMgr->CheckKind(Kind::SPATIAL4D(), arg, errorInfo) ||
|
|
algMgr->CheckKind(Kind::SPATIAL8D(), arg, errorInfo);
|
|
}
|
|
|
|
/*
|
|
Checks for a rectangle type
|
|
|
|
*/
|
|
|
|
bool isRectangle(ListExpr arg){
|
|
return nl->IsEqual(arg, Rectangle<1>::BasicType()) ||
|
|
nl->IsEqual(arg, Rectangle<2>::BasicType()) ||
|
|
nl->IsEqual(arg, Rectangle<3>::BasicType()) ||
|
|
nl->IsEqual(arg, Rectangle<4>::BasicType()) ||
|
|
nl->IsEqual(arg, Rectangle<8>::BasicType());
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
Creates a list "typeerror".
|
|
|
|
*/
|
|
ListExpr typeError(){
|
|
return nl->TypeError();
|
|
}
|
|
|
|
/*
|
|
Writes a message to the errorreporter and returns
|
|
"typeerror".
|
|
|
|
*/
|
|
ListExpr typeError(string message){
|
|
ErrorReporter::ReportError(message);
|
|
return nl->TypeError();
|
|
}
|
|
|
|
|
|
/*
|
|
Checks for a valid description of an rtree.
|
|
|
|
|
|
*/
|
|
|
|
bool isRTreeDescription(ListExpr rtree){
|
|
// (rtree tupledescription type bool)
|
|
if(nl->ListLength(rtree)!=4){
|
|
return false;
|
|
}
|
|
ListExpr rtreeSymbol = nl->First(rtree);
|
|
if(nl->AtomType(rtreeSymbol)!=SymbolType){
|
|
return false;
|
|
}
|
|
string rtreestr = nl->SymbolValue(rtreeSymbol);
|
|
|
|
if( (rtreestr != RTree1TID::BasicType()) &&
|
|
(rtreestr != RTree2TID::BasicType()) &&
|
|
(rtreestr != RTree3TID::BasicType()) &&
|
|
(rtreestr != RTree4TID::BasicType()) &&
|
|
(rtreestr != RTree8TID::BasicType()) ){
|
|
return false;
|
|
}
|
|
|
|
if(!isTupleDescription(nl->Second(rtree))){
|
|
return false;
|
|
}
|
|
if(nl->AtomType(nl->Fourth(rtree))!= BoolType){
|
|
return false;
|
|
}
|
|
// check for valid type as third element omitted
|
|
return true;
|
|
}
|
|
|
|
|
|
bool isRTreeDescription(ListExpr rtree, const string& basicType){
|
|
// (rtree tupledescription type bool)
|
|
if(nl->ListLength(rtree)!=4){
|
|
return false;
|
|
}
|
|
ListExpr rtreeSymbol = nl->First(rtree);
|
|
if(nl->AtomType(rtreeSymbol)!=SymbolType){
|
|
return false;
|
|
}
|
|
string rtreestr = nl->SymbolValue(rtreeSymbol);
|
|
|
|
if( rtreestr != basicType) {
|
|
return false;
|
|
}
|
|
|
|
if(!isTupleDescription(nl->Second(rtree))){
|
|
return false;
|
|
}
|
|
if(nl->AtomType(nl->Fourth(rtree))!= BoolType){
|
|
return false;
|
|
}
|
|
// check for valid type as third element omitted
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
Checks for a BTreeDescription
|
|
|
|
*/
|
|
bool isBTreeDescription(ListExpr btree){
|
|
if((nl->ListLength(btree)<3) || (nl->ListLength(btree)>4)){
|
|
return false;
|
|
}
|
|
return nl->IsEqual(nl->First(btree),BTree::BasicType()) &&
|
|
isTupleDescription(nl->Second(btree)) &&
|
|
isDATA(nl->Third(btree)) &&
|
|
((nl->ListLength(btree) == 3) ||
|
|
isKeyDescription(nl->Second(btree), nl->Fourth(btree)));
|
|
}
|
|
|
|
|
|
/*
|
|
Checks wether the list given as argument is a type usuable as
|
|
an key for a Berkeley DB index.
|
|
|
|
*/
|
|
bool isBDBIndexableType(ListExpr key){
|
|
ListExpr errorInfo = emptyErrorInfo();
|
|
AlgebraManager *algMgr = SecondoSystem::GetAlgebraManager();
|
|
bool indexable = algMgr->CheckKind(Kind::INDEXABLE(), key,errorInfo) ||
|
|
(nl->IsAtom(key) &&
|
|
nl->AtomType(key) == SymbolType &&
|
|
(nl->SymbolValue(key) == CcInt::BasicType() ||
|
|
nl->SymbolValue(key) == TupleIdentifier::BasicType() ||
|
|
nl->SymbolValue(key) == CcReal::BasicType() ||
|
|
nl->SymbolValue(key) == CcBool::BasicType() ||
|
|
nl->SymbolValue(key) == CcString::BasicType()));
|
|
return indexable;
|
|
}
|
|
|
|
|
|
/*
|
|
Checks for a BTree2Description
|
|
|
|
*/
|
|
bool isBTree2Description(ListExpr btree2){
|
|
if(nl->ListLength(btree2)!=4){
|
|
return false;
|
|
}
|
|
ListExpr uniq = nl->Fourth(btree2);
|
|
ListExpr key = nl->Second(btree2);
|
|
bool indexable = isBDBIndexableType(key);
|
|
return (nl->IsEqual(nl->First(btree2),BTree2Algebra::BTree2::BasicType()) &&
|
|
indexable &&
|
|
nl->IsAtom(nl->Third(btree2)) &&
|
|
nl->AtomType(uniq) == SymbolType) &&
|
|
(nl->SymbolValue(uniq) == "multiple" ||
|
|
nl->SymbolValue(uniq) == "uniqueKey" ||
|
|
nl->SymbolValue(uniq) == "uniqueKeyMultiData");
|
|
}
|
|
|
|
/*
|
|
Checks for a valid hash table
|
|
|
|
*/
|
|
|
|
bool isHashDescription(ListExpr hash){
|
|
if(nl->ListLength(hash)!=3){
|
|
return false;
|
|
}
|
|
return isSymbol(nl->First(hash),Hash::BasicType()) &&
|
|
isTupleDescription(nl->Second(hash)) &&
|
|
isDATA(nl->Third(hash));
|
|
}
|
|
|
|
|
|
/*
|
|
Checks for valid description of a tuple.
|
|
|
|
*/
|
|
|
|
bool isTupleDescription(ListExpr tuple, const bool ismtuple /*=false*/){
|
|
if(nl->ListLength(tuple)!=2){
|
|
return false;
|
|
}
|
|
string tuplesym = ismtuple
|
|
?oldrelation::CcTuple::BasicType()
|
|
:Tuple::BasicType();
|
|
if(!isSymbol(nl->First(tuple),tuplesym)){
|
|
return false;
|
|
}
|
|
return isAttrList(nl->Second(tuple));
|
|
}
|
|
|
|
/*
|
|
Checks for a valid atribute list
|
|
|
|
*/
|
|
bool isAttrList(ListExpr attrList){
|
|
ListExpr rest = attrList;
|
|
ListExpr current;
|
|
ListExpr errorInfo = emptyErrorInfo();
|
|
|
|
if(nl->AtomType(attrList)!=NoAtom){
|
|
return false;
|
|
}
|
|
if(nl->IsEmpty(attrList)){
|
|
return false;
|
|
}
|
|
set<string> attrnames;
|
|
while(!nl->IsEmpty(rest)) {
|
|
current = nl->First(rest);
|
|
rest = nl->Rest(rest);
|
|
if(nl->ListLength(current)!=2){
|
|
return false;
|
|
}
|
|
ListExpr attrName = nl->First(current);
|
|
ListExpr attrType = nl->Second(current);
|
|
if(nl->AtomType(attrName)!=SymbolType){
|
|
return false;
|
|
}
|
|
string name = nl->SymbolValue(attrName);
|
|
if(attrnames.find(name)!=attrnames.end()){
|
|
return false;
|
|
}
|
|
attrnames.insert(name);
|
|
if(!am->CheckKind(Kind::DATA(), attrType, errorInfo)){
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
Checks an attribute list for naming conventions
|
|
|
|
*/
|
|
bool checkAttrListForNamingConventions(ListExpr attrList){
|
|
// assert(isAttrList(attrList));
|
|
while(!nl->IsEmpty(attrList)){
|
|
if(!checkAttrForNamingConventions(nl->First(nl->First(attrList)))){
|
|
return false;
|
|
}
|
|
attrList = nl->Rest(attrList);
|
|
}
|
|
return true;
|
|
|
|
}
|
|
|
|
/*
|
|
Checks an attribute name for naming conventions.
|
|
|
|
*/
|
|
bool checkAttrForNamingConventions(const ListExpr attr){
|
|
// assert(isSymbol(attr))
|
|
string name = nl->SymbolValue(attr);
|
|
if(name.length()<1){
|
|
return false;
|
|
}
|
|
char f = name[0];
|
|
if(f<'A' || f>'Z'){
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
bool isValidAttributeName(const ListExpr attr, string& error){
|
|
if(!isSymbol(attr)){
|
|
error = "attribute name is not a symbol";
|
|
return false;
|
|
}
|
|
string attrstr = nl->SymbolValue(attr);
|
|
if(!SecondoSystem::GetCatalog()->IsValidIdentifier(attrstr,
|
|
error)){
|
|
error = "attribute name "+ error + ".";
|
|
return false;
|
|
}
|
|
if(!checkAttrForNamingConventions(attr)){
|
|
error = attrstr + " does not fit Secondo's names conventions";
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
Checks for disjoint attribute lists.
|
|
|
|
Precondition isAttrList(l1) [&] isAttrList(l2)
|
|
|
|
*/
|
|
bool disjointAttrNames(ListExpr l1, ListExpr l2){
|
|
assert(isAttrList(l1));
|
|
assert(isAttrList(l2));
|
|
set<string> names;
|
|
ListExpr rest = l1;
|
|
while(!nl->IsEmpty(rest)){
|
|
names.insert(nl->SymbolValue(nl->First(nl->First(rest))));
|
|
rest = nl->Rest(rest);
|
|
}
|
|
rest = l2;
|
|
while(!nl->IsEmpty(rest)){
|
|
string name = nl->SymbolValue(nl->First(nl->First(rest)));
|
|
if(names.find(name)!=names.end()){
|
|
return false;
|
|
}
|
|
rest = nl->Rest(rest);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
Checks whether the list corresponds to a given symbol.
|
|
|
|
*/
|
|
bool isSymbol(const ListExpr list, const string& v){
|
|
if(nl->AtomType(list)!=SymbolType){
|
|
return false;
|
|
}
|
|
return nl->SymbolValue(list) == v;
|
|
}
|
|
|
|
bool isSymbol(const ListExpr list){
|
|
return nl->IsAtom(list) && (nl->AtomType(list)==SymbolType);
|
|
}
|
|
|
|
bool isASymbolIn(const ListExpr list, const set<string>& s){
|
|
if(!isSymbol(list)){
|
|
return false;
|
|
}
|
|
string v = nl->SymbolValue(list);
|
|
return s.find(v)!=s.end();
|
|
}
|
|
|
|
/*
|
|
Concatenates l1 and l2.
|
|
|
|
*/
|
|
ListExpr concat(ListExpr l1, ListExpr l2){
|
|
assert(nl->AtomType(l1) == NoAtom);
|
|
assert(nl->AtomType(l2) == NoAtom);
|
|
if(nl->IsEmpty(l1)){
|
|
return l2;
|
|
}
|
|
ListExpr res = nl->OneElemList(nl->First(l1));
|
|
l1 = nl->Rest(l1);
|
|
ListExpr last = res;
|
|
while(!nl->IsEmpty(l1)){
|
|
last = nl->Append(last, nl->First(l1));
|
|
l1 = nl->Rest(l1);
|
|
}
|
|
while(!nl->IsEmpty(l2)){
|
|
last = nl->Append(last, nl->First(l2));
|
|
l2 = nl->Rest(l2);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
Returns the keytype fo an rtree description.
|
|
|
|
*/
|
|
ListExpr getRTreeType(ListExpr rtree){
|
|
assert(isRTreeDescription(rtree));
|
|
return nl->Third(rtree);
|
|
}
|
|
|
|
/*
|
|
Returns the dimension of an rtree.
|
|
|
|
*/
|
|
int getRTreeDim(ListExpr rtree){
|
|
assert(isRTreeDescription(rtree));
|
|
string t = nl->SymbolValue(nl->First(rtree));
|
|
if(t==RTree1TID::BasicType()) return 1;
|
|
if(t==RTree2TID::BasicType()) return 2;
|
|
if(t==RTree3TID::BasicType()) return 3;
|
|
if(t==RTree4TID::BasicType()) return 4;
|
|
if(t==RTree8TID::BasicType()) return 8;
|
|
assert(false);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
Checks for a valid relation description.
|
|
|
|
*/
|
|
bool isRelDescription(ListExpr rel, const bool trel /*=false*/){
|
|
string relsymb = trel?TempRelation::BasicType():Relation::BasicType();
|
|
return isRelDescription2(rel, relsymb);
|
|
}
|
|
|
|
|
|
bool isRelDescription2(ListExpr rel, const string& relsymb){
|
|
if(nl->ListLength(rel)!=2){
|
|
return false;
|
|
}
|
|
if(!isSymbol(nl->First(rel),relsymb)){
|
|
return false;
|
|
}
|
|
bool mtuple = relsymb==oldrelation::CcRel::BasicType();
|
|
return isTupleDescription(nl->Second(rel),mtuple);
|
|
}
|
|
|
|
bool isOrelDescription(ListExpr orel) {
|
|
if(nl->ListLength(orel)!=3) {
|
|
return false;
|
|
}
|
|
return isSymbol(nl->First(orel),OrderedRelation::BasicType()) &&
|
|
isTupleDescription(nl->Second(orel),false) &&
|
|
isKeyDescription(nl->Second(orel), nl->Third(orel));
|
|
}
|
|
|
|
bool isKeyDescription(ListExpr tupleList, ListExpr keyList) {
|
|
ListExpr attrType;
|
|
int attrIndex;
|
|
if(nl->IsAtom(keyList)) {
|
|
if(nl->AtomType(keyList)!=SymbolType)
|
|
return false;
|
|
attrIndex = findAttribute(nl->Second(tupleList),
|
|
nl->SymbolValue(keyList), attrType);
|
|
return attrIndex > 0 && isBDBIndexableType(attrType);
|
|
}
|
|
while(!nl->IsEmpty(keyList)) {
|
|
ListExpr elem = nl->First(keyList);
|
|
if(nl->AtomType(elem)!=SymbolType) {
|
|
return false;
|
|
}
|
|
keyList = nl->Rest(keyList);
|
|
ListExpr attrType;
|
|
int attrIndex = findAttribute(nl->Second(tupleList),
|
|
nl->SymbolValue(elem), attrType);
|
|
if (attrIndex == 0 || !isBDBIndexableType(attrType)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
Checks for a tuple stream
|
|
|
|
*/
|
|
bool isTupleStream(ListExpr s){
|
|
if(nl->ListLength(s)!=2){
|
|
return false;
|
|
}
|
|
if(!nl->IsEqual(nl->First(s),Symbol::STREAM())){
|
|
return false;
|
|
}
|
|
return isTupleDescription(nl->Second(s));
|
|
}
|
|
|
|
/*
|
|
Checks for Kind DATA
|
|
|
|
*/
|
|
bool isDATA(ListExpr type){
|
|
AlgebraManager *algMgr = SecondoSystem::GetAlgebraManager();
|
|
ListExpr errorInfo = emptyErrorInfo();
|
|
return algMgr->CheckKind(Kind::DATA(), type, errorInfo);
|
|
}
|
|
|
|
|
|
/*
|
|
CHecks whether this list corresponds to a type in given kind
|
|
|
|
*/
|
|
bool isKind(ListExpr type, const string& kind){
|
|
AlgebraManager *algMgr = SecondoSystem::GetAlgebraManager();
|
|
ListExpr errorInfo = emptyErrorInfo();
|
|
return algMgr->CheckKind(kind, type, errorInfo);
|
|
}
|
|
|
|
|
|
/*
|
|
Checks for a numeric type
|
|
|
|
*/
|
|
bool isNumeric(ListExpr num){
|
|
return nl->AtomType(num) == IntType ||
|
|
nl->AtomType(num) == RealType;
|
|
}
|
|
|
|
double getNumValue(ListExpr n){
|
|
if(nl->AtomType(n)==IntType){
|
|
return nl->IntValue(n);
|
|
} if(nl->AtomType(n)==RealType){
|
|
return nl->RealValue(n);
|
|
} else {
|
|
assert(false);
|
|
}
|
|
return 0.0;
|
|
}
|
|
|
|
bool isNumericType(ListExpr n){
|
|
if(nl->AtomType(n)!=SymbolType){
|
|
return false;
|
|
}
|
|
string v = nl->SymbolValue(n);
|
|
return v==CcInt::BasicType() || v==CcReal::BasicType();
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
Checks for a stream of kind DATA
|
|
|
|
*/
|
|
bool isDATAStream(ListExpr s){
|
|
if(nl->ListLength(s)!=2){
|
|
return false;
|
|
}
|
|
if(!nl->IsEqual(nl->First(s),Symbol::STREAM())){
|
|
return false;
|
|
}
|
|
AlgebraManager *algMgr = SecondoSystem::GetAlgebraManager();
|
|
ListExpr errorInfo = emptyErrorInfo();
|
|
return algMgr->CheckKind(Kind::DATA(), nl->Second(s), errorInfo);
|
|
}
|
|
|
|
/*
|
|
Checks whether the list represents a stream.
|
|
|
|
*/
|
|
bool isStream(ListExpr s){
|
|
if(nl->ListLength(s)!=2){
|
|
return false;
|
|
}
|
|
if(!nl->IsEqual(nl->First(s),Symbol::STREAM())){
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int findAttribute(ListExpr attrList, const string& name, ListExpr& type){
|
|
assert(isAttrList(attrList));
|
|
int j = 0;
|
|
ListExpr rest = attrList;
|
|
while(!nl->IsEmpty(rest)){
|
|
ListExpr current = nl->First(rest);
|
|
j++;
|
|
if(nl->IsEqual(nl->First(current),name)){
|
|
type = nl->Second(current);
|
|
return j;
|
|
}
|
|
rest = nl->Rest(rest);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int findType(ListExpr attrList, const ListExpr type,
|
|
string& name, const int start/*=1*/){
|
|
assert(isAttrList(attrList));
|
|
ListExpr rest = attrList;
|
|
int j = 0;
|
|
while(!nl->IsEmpty(rest)){
|
|
ListExpr current = nl->First(rest);
|
|
rest = nl->Rest(rest);
|
|
j++;
|
|
if(j>=start){
|
|
if(nl->Equal(nl->Second(current),type)){
|
|
name = nl->SymbolValue(nl->First(current));
|
|
return j;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
int removeAttributes(ListExpr list, const set<string>& names,
|
|
ListExpr& head, ListExpr& last){
|
|
assert(isAttrList(list));
|
|
bool firstCall = true;
|
|
int count = 0;
|
|
while(!nl->IsEmpty(list)){
|
|
ListExpr pair = nl->First(list);
|
|
list = nl->Rest(list);
|
|
string name = nl->SymbolValue(nl->First(pair));
|
|
if(names.find(name)==names.end()){
|
|
if(firstCall){
|
|
firstCall=false;
|
|
head = nl->OneElemList(pair);
|
|
last = head;
|
|
} else {
|
|
last = nl->Append(last, pair);
|
|
}
|
|
} else {
|
|
count++;
|
|
}
|
|
|
|
}
|
|
if(firstCall){
|
|
head = nl->TheEmptyList();
|
|
last = head;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
|
|
|
|
bool replaceAttributes( ListExpr attrList,
|
|
map<string, string>& renameMap,
|
|
ListExpr& resAttrList, string& errmsg){
|
|
|
|
bool firstCall = true;
|
|
ListExpr last = nl->TheEmptyList();
|
|
map<string, string>::iterator it;
|
|
while(!nl->IsEmpty(attrList)){
|
|
ListExpr attr = nl->First(attrList);
|
|
attrList = nl->Rest(attrList);
|
|
string name = nl->SymbolValue(nl->First(attr));
|
|
it = renameMap.find(name);
|
|
ListExpr newAttr;
|
|
if(it==renameMap.end()){
|
|
newAttr = attr;
|
|
} else {
|
|
newAttr = nl->TwoElemList( nl->SymbolAtom(it->second),
|
|
nl->Second(attr));
|
|
renameMap.erase(it);
|
|
}
|
|
if(firstCall){
|
|
resAttrList = nl->OneElemList(newAttr);
|
|
last = resAttrList;
|
|
firstCall = false;
|
|
} else {
|
|
last = nl->Append(last, newAttr);
|
|
}
|
|
}
|
|
if(firstCall){
|
|
errmsg = "empty attribute list cannot be renamed";
|
|
resAttrList = nl->TheEmptyList();
|
|
return false;
|
|
}
|
|
if(!renameMap.empty()){
|
|
it = renameMap.begin();
|
|
errmsg = "attribute " + it->first + " not found in attrlist";
|
|
resAttrList = nl->TheEmptyList();
|
|
return false;
|
|
}
|
|
|
|
|
|
if(!isAttrList(resAttrList)){
|
|
errmsg = "renamed names are not unique";
|
|
resAttrList = nl->TheEmptyList();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool isSymbolUndefined( const string& s ) {
|
|
return (s == Symbol::UNDEFINED()) ||
|
|
(s == "undef") || (s == "UNDEF") ||
|
|
(s == "undefined") || (s == "UNDEFINED") ||
|
|
(s == "null") || (s == "NULL") ;
|
|
}
|
|
|
|
bool isSymbolUndefined( ListExpr le ){
|
|
if(isSymbol(le)){
|
|
string s = nl->SymbolValue(le);
|
|
return isSymbolUndefined(s);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
ListExpr getUndefined(){
|
|
return nl->SymbolAtom("undefined");
|
|
}
|
|
|
|
string getUndefinedString(){
|
|
return "undefined";
|
|
}
|
|
|
|
ListExpr getPtrList(const void* ptr){
|
|
// ensure that two int atoms can pick up a pointer
|
|
assert(sizeof(void*) <= 8);
|
|
uint32_t v1 = 0;
|
|
uint32_t v2 = 0;
|
|
uint64_t v = (uint64_t) ptr;
|
|
v1 = v; // lower bits
|
|
v2 = (v >> 32); // higher bits
|
|
ListExpr res = nl->TwoElemList(nl->IntAtom(v2), nl->IntAtom(v1));
|
|
return res;
|
|
|
|
}
|
|
|
|
ListExpr getInt64List(const int64_t value){
|
|
int64_t min = numeric_limits<int32_t>::min();
|
|
int64_t max = numeric_limits<int32_t>::max();
|
|
if((min<=value) && (value <= max)){
|
|
return nl->IntAtom(value);
|
|
}
|
|
// ensure that two int atoms can pick up a pointer
|
|
uint32_t v1 = 0;
|
|
uint32_t v2 = 0;
|
|
uint64_t v = (uint64_t) value;
|
|
v1 = v; // lower bits
|
|
v2 = (v >> 32); // higher bits
|
|
ListExpr res = nl->TwoElemList(nl->IntAtom(v2), nl->IntAtom(v1));
|
|
return res;
|
|
}
|
|
|
|
bool decodeInt64(const ListExpr value, int64_t& result){
|
|
if(nl->AtomType(value)==IntType){
|
|
result = nl->IntValue(value);
|
|
return true;
|
|
}
|
|
if(!nl->HasLength(value,2)){
|
|
return false;
|
|
}
|
|
ListExpr hb = nl->First(value);
|
|
ListExpr lb = nl->Second(value);
|
|
if(nl->AtomType(hb)!=IntType || nl->AtomType(lb)!=IntType){
|
|
return false;
|
|
}
|
|
uint64_t v1 = nl->IntValue(hb);
|
|
uint64_t v2 = nl->IntValue(lb);
|
|
uint64_t r = (v1 << 32) | v2;
|
|
result = r; // implicit cast to signed
|
|
return true;
|
|
}
|
|
|
|
|
|
bool isPtrList(const ListExpr list){
|
|
|
|
return nl->HasLength(list,2) &&
|
|
nl->AtomType(nl->First(list)) == IntType &&
|
|
nl->AtomType(nl->Second(list)) == IntType;
|
|
}
|
|
|
|
void* getPtr( const ListExpr ptrList){
|
|
uint64_t v2 = (uint32_t) nl->IntValue(nl->First(ptrList));
|
|
uint64_t v1 = (uint32_t) nl->IntValue(nl->Second(ptrList));
|
|
|
|
uint64_t v = (v2 << 32) | v1;
|
|
return (void*) v;
|
|
}
|
|
|
|
|
|
string stringValue(ListExpr src){
|
|
if(nl->AtomType(src)==StringType){
|
|
return nl->StringValue(src);
|
|
}
|
|
if(nl->AtomType(src)==TextType){
|
|
return nl->Text2String(src);
|
|
}
|
|
return "";
|
|
|
|
}
|
|
|
|
ListExpr xElemList(int count, ...){
|
|
if(count <= 0){
|
|
return nl->TheEmptyList();
|
|
}
|
|
va_list ap;
|
|
va_start(ap,count);
|
|
|
|
ListExpr first = nl->OneElemList(va_arg(ap,ListExpr));
|
|
ListExpr last = first;
|
|
for(int i=1;i<count;i++){
|
|
last = nl->Append(last, va_arg(ap,ListExpr));
|
|
}
|
|
|
|
va_end(ap);
|
|
return first;
|
|
}
|
|
|
|
ListExpr simpleMessage(const string& msg){
|
|
return getMessage("simple",msg);
|
|
}
|
|
ListExpr simpleMessage(const int value){
|
|
return getMessage("simple", value);
|
|
}
|
|
ListExpr getMessage( const string& messageType, const string& message){
|
|
ListExpr l = message.length()>=MAX_STRINGSIZE
|
|
? nl->TextAtom(message)
|
|
: nl->StringAtom(message);
|
|
return nl->TwoElemList( nl->SymbolAtom(messageType),l);
|
|
|
|
}
|
|
ListExpr getMessage( const string& messageType, const int value){
|
|
return nl->TwoElemList( nl->SymbolAtom(messageType),
|
|
nl->IntAtom(value));
|
|
}
|
|
|
|
|
|
bool containsSymbol(ListExpr list, const string& symbol){
|
|
if(nl->AtomType(list)==SymbolType){
|
|
return nl->SymbolValue(list)==symbol;
|
|
}
|
|
if(nl->AtomType(list) != NoAtom){
|
|
return false;
|
|
}
|
|
while(!nl->IsEmpty(list)){
|
|
ListExpr f = nl->First(list);
|
|
list = nl->Rest(list);
|
|
if(containsSymbol(f,symbol)){
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
bool isMapX(int x, ListExpr map){
|
|
int a = x+2; // (map arg1 arg2 .. argx result)
|
|
|
|
|
|
return nl->ListLength(map)==a &&
|
|
nl->AtomType(nl->First(map))==SymbolType &&
|
|
nl->SymbolValue(nl->First(map)) == "map";
|
|
|
|
}
|
|
|
|
|
|
bool isAnyMap(ListExpr map){
|
|
return nl->HasMinLength(map,2)
|
|
&& isSymbol(nl->First(map), "map");
|
|
}
|
|
|
|
|
|
ListExpr replaceSymbol(ListExpr list, const std::string& symb,
|
|
ListExpr replacement, NestedList* nl){
|
|
|
|
int t = nl->AtomType(list);
|
|
switch(t){
|
|
case IntType :
|
|
case RealType :
|
|
case BoolType :
|
|
case StringType :
|
|
case TextType : return list;
|
|
case SymbolType : {
|
|
std::string s = nl->SymbolValue(list);
|
|
return s==symb? replacement: list;
|
|
}
|
|
case NoAtom : {
|
|
if(nl->IsEmpty(list)) return list;
|
|
ListExpr cp = nl->OneElemList(replaceSymbol(nl->First(list),
|
|
symb, replacement, nl));
|
|
ListExpr last = cp;
|
|
ListExpr rest = nl->Rest(list);
|
|
while(!nl->IsEmpty(rest)){
|
|
last = nl->Append(last,
|
|
replaceSymbol(nl->First(rest),symb,
|
|
replacement, nl));
|
|
rest = nl->Rest(rest);
|
|
}
|
|
return cp;
|
|
}
|
|
default: assert(false);
|
|
return nl->TheEmptyList();
|
|
|
|
}
|
|
}
|
|
|
|
bool checkUsesArgsInTypeMapping(ListExpr args){
|
|
if(nl->AtomType(args)!= NoAtom){
|
|
return false;
|
|
}
|
|
while(nl->IsEmpty(args)){
|
|
if(!nl->HasLength(nl->First(args),2)){
|
|
return false;
|
|
}
|
|
args = nl->Rest(args);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
ListExpr replaceSymbols(ListExpr list,
|
|
const map<string,ListExpr>& replacements){
|
|
|
|
if(nl->IsEmpty(list)){
|
|
return nl->TheEmptyList();
|
|
}
|
|
switch(nl->AtomType(list)){
|
|
case SymbolType: {
|
|
string symb = nl->SymbolValue(list);
|
|
map<string,ListExpr>::const_iterator it = replacements.find(symb);
|
|
if(it==replacements.end()){
|
|
return list;
|
|
} else {
|
|
return it->second;
|
|
}
|
|
}
|
|
case NoAtom: {
|
|
ListExpr first = nl->OneElemList( replaceSymbols(nl->First(list),
|
|
replacements));
|
|
ListExpr last = first;
|
|
list = nl->Rest(list);
|
|
while(!nl->IsEmpty(list)){
|
|
last = nl->Append(last, replaceSymbols(nl->First(list),replacements));
|
|
list = nl->Rest(list);
|
|
}
|
|
return first;
|
|
}
|
|
default: return list;
|
|
}
|
|
}
|
|
|
|
} // end of namespace listutils
|