1 /***************************************************************************
2 dstructdesc.cpp - GDL struct descriptor
3 -------------------
4 begin : July 22 2002
5 copyright : (C) 2002 by Marc Schellens
6 email : m_schellens@users.sf.net
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "includefirst.hpp"
19
20 #include <algorithm>
21
22 #include "datatypes.hpp"
23 #include "dstructdesc.hpp"
24 #include "GDLInterpreter.hpp"
25 #include "dstructgdl.hpp"
26
27 using namespace std;
28
29 // store vtable in this obj file
~DStructBase()30 DStructBase::~DStructBase()
31 {
32 SizeT nTags = NTags();
33 for( SizeT i=0; i < nTags; ++i)
34 {
35 delete tags[ i];
36 }
37 }
38
39 // DUStructDesc::~DUStructDesc()
40 // {}
41
~DStructDesc()42 DStructDesc::~DStructDesc()
43 {
44 assert( !isUnnamed || (operatorList == NULL));
45 if( !isUnnamed) // only named structs have members and overloaded operators
46 // (usually they are never deleted only with .RESET_SESSION and .FULL_RESET_SESSION dot commands)
47 {
48 delete operatorList;
49 for(FunListT::iterator i = this->fun.begin(); i != this->fun.end(); ++i)
50 { delete *i;}
51 for(ProListT::iterator i = this->pro.begin(); i != this->pro.end(); ++i)
52 { delete *i;}
53 }
54 }
55
FindInStructList(StructListT v,const string & s)56 DStructDesc* FindInStructList(StructListT v, const string& s)
57 {
58 StructListT::iterator f=find_if(v.begin(),v.end(),DStruct_eq(s));
59 if( f == v.end()) return NULL;
60 return *f;
61 }
FindObjectInStructList(StructListT v,const string & s)62 DStructDesc* FindObjectInStructList(StructListT v, const string& s)
63 {
64 StructListT::iterator f=find_if(v.begin(),v.end(),DStruct_eq(s));
65 if( f == v.end()) return NULL;
66 if (((*f)->FunList().size() + (*f)->ProList().size()) == 0) return NULL;
67 return *f;
68 }
ContainsStringPtrObject()69 bool DStructBase::ContainsStringPtrObject()
70 {
71 for( SizeT t=0; t<tags.size(); ++t)
72 {
73 if( tags[t]->Type() == GDL_STRING) return true;
74 if( tags[t]->Type() == GDL_PTR) return true;
75 if( tags[t]->Type() == GDL_OBJ) return true;
76 if( tags[t]->Type() == GDL_STRUCT)
77 {
78 if( static_cast<DStructGDL*>( tags[t])->Desc()->ContainsStringPtrObject()) return true;
79 }
80 }
81 return false;
82 }
83
AddTag(const string & tagName,const BaseGDL * data)84 void DUStructDesc::AddTag( const string& tagName, const BaseGDL* data)
85 {
86 string TN = StrUpCase( tagName); // prevent non-capitalized chars.
87 for( SizeT i=0; i < tNames.size(); i++)
88 if( tNames[i] == TN)
89 throw GDLException(TN+" is already defined "
90 "with a conflicting definition");
91
92 tNames.push_back( TN);
93 Add( data->GetTag());
94 }
95
AddParent(DStructDesc * p)96 void DStructDesc::AddParent( DStructDesc* p)
97 {
98 SizeT nTags=p->NTags();
99 for( SizeT t=0; t < nTags; t++)
100 AddTag( p->TagName(t), (*p)[t]);
101 parent.push_back(p);
102 OperatorList* parentOperatorList = p->GetOperatorList();
103 if( parentOperatorList != NULL)
104 {
105 assert( this->operatorList == NULL); // GDL_OBJECT can only be inherited once
106 operatorList = new OperatorList(*parentOperatorList);
107 }
108 }
109
AddParentListOnly(DStructDesc * p)110 void DStructDesc::AddParentListOnly( DStructDesc* p)
111 {
112 parent.push_back(p);
113 OperatorList* parentOperatorList = p->GetOperatorList();
114 if( parentOperatorList != NULL)
115 {
116 assert( this->operatorList == NULL); // GDL_OBJECT can only be inherited once
117 operatorList = new OperatorList(*parentOperatorList);
118 }
119 }
120
121 // copy appropriate member subroutines from fun and pro lists
SetupOperators()122 void DStructDesc::SetupOperators()
123 {
124 assert( this->operatorList != NULL);
125 for( FunListT::iterator f = this->fun.begin(); f != this->fun.end(); ++f)
126 {
127 int ix = OverloadOperatorIndexFun( (*f)->Name());
128 if( ix != -1)
129 operatorList->SetOperator(ix,*f);
130 }
131 for( ProListT::iterator p = this->pro.begin(); p != this->pro.end(); ++p)
132 {
133 int ix = OverloadOperatorIndexPro( (*p)->Name());
134 if( ix != -1)
135 operatorList->SetOperator(ix,*p);
136 }
137 }
138
139 // more sophisticated error messages than operator==
AssureIdentical(DStructDesc * d)140 void DStructDesc::AssureIdentical( DStructDesc* d)
141 {
142 // name is the same
143 if( NTags() != d->NTags())
144 {
145 throw GDLException( "STRUCT: "+name+": redefinition with different "
146 "number of tags.");
147 }
148 if( parent.size() != d->parent.size())
149 {
150 throw GDLException( "STRUCT: "+name+": redefinition with different "
151 "number of parents.");
152 }
153 // compare all tag names
154 // compare the tags (type and dim)
155 for( SizeT i=0; i < NTags(); i++)
156 {
157 if( TagName(i) != d->TagName(i))
158 {
159 throw GDLException( "STRUCT: "+name+": "+TagName(i)+
160 " tag name differs in redefinition.");
161 }
162 if( tags[i]->Dim() != d->tags[i]->Dim())
163 {
164 throw GDLException( "STRUCT: "+name+": "+TagName(i)+
165 " tag dimension "
166 "differs in redefinition.");
167 }
168
169 // tag type is converted for convertable types
170 if( (!ConvertableType( tags[i]->Type()) ||
171 !ConvertableType( d->tags[i]->Type())) &&
172 tags[i]->Type() != d->tags[i]->Type())
173 {
174 throw GDLException( "STRUCT: "+name+": "+TagName(i)+
175 " tag type differs in redefinition.");
176 }
177 if( tags[i]->Type() == GDL_STRUCT)
178 {
179 SpDStruct* castLeft=
180 static_cast<SpDStruct*>(tags[i]);
181 SpDStruct* castRight=
182 static_cast<SpDStruct*>(d->tags[i]);
183 DStructDesc* leftD=castLeft->Desc();
184 DStructDesc* rightD=castRight->Desc();
185
186 if( !(*leftD == *rightD))
187 {
188 throw GDLException( "STRUCT: "+name+": "+TagName(i)+
189 " tag struct differs in"
190 " redefinition.");
191 }
192 }
193 }
194 // compare all parents
195 for( SizeT i=0; i < parent.size(); i++)
196 {
197 if( parent[i] != d->parent[i])
198 {
199 throw GDLException( "STRUCT: "+name+": "+parent[i]->Name()+
200 " parent class differs in redefinition.");
201 }
202 }
203 }
204
205 // two structs are equal if the contain the same datatypes in the
206 // same order (although names might differ)
operator ==(const DStructDesc & left,const DStructDesc & right)207 bool operator==(const DStructDesc& left,
208 const DStructDesc& right)
209 {
210 // name is the same
211 if( left.NTags() != right.NTags()) return false;
212 // struct layout can be same with different inheritance
213 // if( left.parent.size() != right.parent.size()) return false;
214 // compare all tag names
215 // compare the tags (type and dim)
216 for( SizeT i=0; i < left.NTags(); i++)
217 {
218 // if( left.TagName(i) != right.TagName(i)) return false;
219 if( left.tags[i]->Dim() != right.tags[i]->Dim()) return false;
220 if( left.tags[i]->Type() != right.tags[i]->Type()) return false;
221 if( left.tags[i]->Type() == GDL_STRUCT)
222 {
223 SpDStruct* castLeft=
224 static_cast<SpDStruct*>(left.tags[i]);
225 SpDStruct* castRight=
226 static_cast<SpDStruct*>(right.tags[i]);
227 DStructDesc* leftD=castLeft->Desc();
228 DStructDesc* rightD=castRight->Desc();
229
230 // recursive call of operator ==
231 if( (leftD != rightD) && !(*leftD == *rightD))
232 return false;
233 }
234 }
235 // compare all parents
236 // for( SizeT i=0; i < left.parent.size(); i++)
237 // {
238 // if( left.parent[i] != right.parent[i]) return false;
239 // }
240 return true;
241 }
242
operator !=(const DStructDesc & left,const DStructDesc & right)243 bool operator!=(const DStructDesc& left,
244 const DStructDesc& right)
245 {
246 return !(left == right);
247 }
248
249 // DStructDesc* DStructDesc::FindEqual( const StructListT& sL)
250 // {
251 // for( SizeT i=0; i<sL.size(); i++)
252 // {
253 // if( *this == *sL[i]) return sL[i];
254 // }
255 // return NULL;
256 // }
257
GetPro(const string & pName)258 DPro* DStructDesc::GetPro( const string& pName)
259 {
260 DPro* p;
261
262 p=FindInProList( pName);
263 if( p != NULL) return p;
264
265 int fInIDList=FindInIDList( noDirectMembers, pName);
266 if( fInIDList == -1)
267 {
268 bool found=GDLInterpreter::SearchCompilePro( name+"__"+pName, true); // true -> search for procedure
269 if( found)
270 {
271 p=FindInProList( pName);
272 if( p != NULL) return p;
273 }
274 else
275 noDirectMembers.push_back(pName);
276 }
277
278 SizeT nParents=parent.size();
279 for( SizeT i=0; i<nParents; i++)
280 {
281 p=parent[i]->GetPro( pName);
282 if( p != NULL) return p;
283 }
284 return NULL;
285 }
286
GetFun(const string & pName)287 DFun* DStructDesc::GetFun( const string& pName)
288 {
289 DFun* p;
290
291 p=FindInFunList( pName);
292 if( p != NULL) return p;
293
294 int fInIDList=FindInIDList( noDirectMembers, pName);
295 if( fInIDList == -1)
296 {
297 bool found=GDLInterpreter::SearchCompilePro( name+"__"+pName, false); // false -> search for function
298 if( found)
299 {
300 p=FindInFunList( pName);
301 if( p != NULL) return p;
302 }
303 else
304 noDirectMembers.push_back(pName);
305 }
306
307 SizeT nParents=parent.size();
308 for( SizeT i=0; i<nParents; i++)
309 {
310 p=parent[i]->GetFun( pName);
311 if( p != NULL) return p;
312 }
313 return NULL;
314 }
315
GetPro(const string & pName,const string & parentName)316 DPro* DStructDesc::GetPro( const string& pName, const string& parentName)
317 {
318 if( !IsParent( parentName))
319 throw GDLException( parentName+" is not a parent of "+name);
320
321 DStructDesc* d=FindInStructList( structList, parentName);
322 if( d == NULL)
323 throw GDLException("Internal error: Struct "+parentName+" not found.");
324
325 return d->GetPro( pName);
326 }
327
GetFun(const string & pName,const string & parentName)328 DFun* DStructDesc::GetFun( const string& pName, const string& parentName)
329 {
330 if( !IsParent( parentName))
331 throw GDLException( parentName+" is not a parent of "+name);
332
333 DStructDesc* d=FindInStructList( structList, parentName);
334 if( d == NULL)
335 throw GDLException("Internal error: Struct "+parentName+" not found.");
336
337 return d->GetFun( pName);
338 }
339
340