00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "object_hierarchy.h"
00019
00020 #include "../objects/object_holder.h"
00021 #include "../objects/other_type.h"
00022 #include "../objects/object_imp.h"
00023 #include "../objects/object_imp_factory.h"
00024 #include "../objects/object_type_factory.h"
00025 #include "../objects/bogus_imp.h"
00026 #include "../objects/transform_types.h"
00027 #include "../objects/object_type.h"
00028
00029 #include <kglobal.h>
00030 #include <qdom.h>
00031
00032 class ObjectHierarchy::Node
00033 {
00034 public:
00035 enum { ID_PushStack, ID_ApplyType, ID_FetchProp };
00036 virtual int id() const = 0;
00037
00038 virtual ~Node();
00039 virtual Node* copy() const = 0;
00040
00041 virtual void apply( std::vector<const ObjectImp*>& stack, int loc,
00042 const KigDocument& ) const = 0;
00043
00044 virtual void apply( std::vector<ObjectCalcer*>& stack, int loc ) const = 0;
00045
00046
00047
00048
00049
00050
00051
00052 virtual void checkDependsOnGiven( std::vector<bool>& dependsstack, int loc ) const = 0;
00053
00054
00055
00056
00057
00058 virtual void checkArgumentsUsed( std::vector<bool>& usedstack ) const = 0;
00059 };
00060
00061 ObjectHierarchy::Node::~Node()
00062 {
00063 }
00064
00065 class PushStackNode
00066 : public ObjectHierarchy::Node
00067 {
00068 ObjectImp* mimp;
00069 public:
00070 PushStackNode( ObjectImp* imp ) : mimp( imp ) {}
00071 ~PushStackNode();
00072
00073 const ObjectImp* imp() const { return mimp; }
00074
00075 int id() const;
00076 Node* copy() const;
00077 void apply( std::vector<const ObjectImp*>& stack,
00078 int loc, const KigDocument& ) const;
00079 void apply( std::vector<ObjectCalcer*>& stack, int loc ) const;
00080
00081 void checkDependsOnGiven( std::vector<bool>& dependsstack, int loc ) const;
00082 void checkArgumentsUsed( std::vector<bool>& usedstack ) const;
00083 };
00084
00085 void PushStackNode::checkArgumentsUsed( std::vector<bool>& ) const
00086 {
00087 }
00088
00089 void PushStackNode::apply( std::vector<ObjectCalcer*>& stack, int loc ) const
00090 {
00091 stack[loc] = new ObjectConstCalcer( mimp->copy() );
00092 }
00093
00094 void PushStackNode::checkDependsOnGiven( std::vector<bool>&, int ) const {
00095
00096 return;
00097 }
00098
00099 int PushStackNode::id() const { return ID_PushStack; }
00100
00101 PushStackNode::~PushStackNode()
00102 {
00103 delete mimp;
00104 }
00105
00106 ObjectHierarchy::Node* PushStackNode::copy() const
00107 {
00108 return new PushStackNode( mimp->copy() );
00109 }
00110
00111 void PushStackNode::apply( std::vector<const ObjectImp*>& stack,
00112 int loc, const KigDocument& ) const
00113 {
00114 stack[loc] = mimp->copy();
00115 }
00116
00117 class ApplyTypeNode
00118 : public ObjectHierarchy::Node
00119 {
00120 const ObjectType* mtype;
00121 std::vector<int> mparents;
00122 public:
00123 ApplyTypeNode( const ObjectType* type, const std::vector<int>& parents )
00124 : mtype( type ), mparents( parents ) {}
00125 ~ApplyTypeNode();
00126 Node* copy() const;
00127
00128 const ObjectType* type() const { return mtype; }
00129 const std::vector<int>& parents() const { return mparents; }
00130
00131 int id() const;
00132 void apply( std::vector<const ObjectImp*>& stack,
00133 int loc, const KigDocument& ) const;
00134 void apply( std::vector<ObjectCalcer*>& stack, int loc ) const;
00135
00136 void checkDependsOnGiven( std::vector<bool>& dependsstack, int loc ) const;
00137 void checkArgumentsUsed( std::vector<bool>& usedstack ) const;
00138 };
00139
00140 int ApplyTypeNode::id() const { return ID_ApplyType; }
00141
00142 void ApplyTypeNode::checkArgumentsUsed( std::vector<bool>& usedstack ) const
00143 {
00144 for ( uint i = 0; i < mparents.size(); ++i )
00145 {
00146 usedstack[mparents[i]] = true;
00147 }
00148 }
00149
00150 void ApplyTypeNode::checkDependsOnGiven( std::vector<bool>& dependsstack, int loc ) const
00151 {
00152 bool result = false;
00153 for ( uint i = 0; i < mparents.size(); ++i )
00154 if ( dependsstack[mparents[i]] == true ) result = true;
00155 dependsstack[loc] = result;
00156 }
00157
00158 ApplyTypeNode::~ApplyTypeNode()
00159 {
00160 }
00161
00162 ObjectHierarchy::Node* ApplyTypeNode::copy() const
00163 {
00164 return new ApplyTypeNode( mtype, mparents );
00165 }
00166
00167 void ApplyTypeNode::apply( std::vector<ObjectCalcer*>& stack, int loc ) const
00168 {
00169 std::vector<ObjectCalcer*> parents;
00170 for ( uint i = 0; i < mparents.size(); ++i )
00171 parents.push_back( stack[ mparents[i] ] );
00172 stack[loc] = new ObjectTypeCalcer( mtype, parents );
00173 }
00174
00175 void ApplyTypeNode::apply( std::vector<const ObjectImp*>& stack,
00176 int loc, const KigDocument& doc ) const
00177 {
00178 Args args;
00179 for ( uint i = 0; i < mparents.size(); ++i )
00180 args.push_back( stack[mparents[i]] );
00181 args = mtype->sortArgs( args );
00182 stack[loc] = mtype->calc( args, doc );
00183 }
00184
00185 class FetchPropertyNode
00186 : public ObjectHierarchy::Node
00187 {
00188 mutable int mpropgid;
00189 int mparent;
00190 const QByteArray mname;
00191 public:
00192
00193
00194
00195
00196 FetchPropertyNode( const int parent, const QByteArray& name, const int propgid = -1 )
00197 : mpropgid( propgid ), mparent( parent ), mname( name ) {}
00198 ~FetchPropertyNode();
00199 Node* copy() const;
00200
00201 void checkDependsOnGiven( std::vector<bool>& dependsstack, int loc ) const;
00202 void checkArgumentsUsed( std::vector<bool>& usedstack ) const;
00203 int parent() const { return mparent; }
00204 const QByteArray& propinternalname() const { return mname; }
00205
00206 int id() const;
00207 void apply( std::vector<const ObjectImp*>& stack,
00208 int loc, const KigDocument& ) const;
00209 void apply( std::vector<ObjectCalcer*>& stack, int loc ) const;
00210 };
00211
00212 FetchPropertyNode::~FetchPropertyNode()
00213 {
00214 }
00215
00216 void FetchPropertyNode::checkArgumentsUsed( std::vector<bool>& usedstack ) const
00217 {
00218 usedstack[mparent] = true;
00219 }
00220
00221 void FetchPropertyNode::checkDependsOnGiven( std::vector<bool>& dependsstack, int loc ) const
00222 {
00223 dependsstack[loc] = dependsstack[mparent];
00224 }
00225
00226 ObjectHierarchy::Node* FetchPropertyNode::copy() const
00227 {
00228 return new FetchPropertyNode( mparent, mname, mpropgid );
00229 }
00230
00231 int FetchPropertyNode::id() const
00232 {
00233 return ID_FetchProp;
00234 }
00235
00236 void FetchPropertyNode::apply( std::vector<const ObjectImp*>& stack,
00237 int loc, const KigDocument& d ) const
00238 {
00239 assert( stack[mparent] );
00240 if ( mpropgid == -1 ) mpropgid = stack[mparent]->getPropGid( mname );
00241 if ( mpropgid != -1 )
00242 stack[loc] = stack[mparent]->property(
00243 stack[mparent]->getPropLid( mpropgid ), d );
00244 else
00245 stack[loc] = new InvalidImp();
00246 }
00247
00248 void FetchPropertyNode::apply( std::vector<ObjectCalcer*>& stack, int loc ) const
00249 {
00250 if ( mpropgid == -1 )
00251 mpropgid = stack[mparent]->imp()->getPropGid( mname );
00252 assert( mpropgid != -1 );
00253 stack[loc] = new ObjectPropertyCalcer( stack[mparent], mpropgid, false );
00254 }
00255
00256 std::vector<ObjectImp*> ObjectHierarchy::calc( const Args& a, const KigDocument& doc ) const
00257 {
00258 assert( a.size() == mnumberofargs );
00259 for ( uint i = 0; i < a.size(); ++i )
00260 assert( a[i]->inherits( margrequirements[i] ) );
00261
00262 std::vector<const ObjectImp*> stack;
00263 stack.resize( mnodes.size() + mnumberofargs, 0 );
00264 std::copy( a.begin(), a.end(), stack.begin() );
00265 for( uint i = 0; i < mnodes.size(); ++i )
00266 {
00267 mnodes[i]->apply( stack, mnumberofargs + i, doc );
00268 };
00269 for ( uint i = mnumberofargs; i < stack.size() - mnumberofresults; ++i )
00270 delete stack[i];
00271 if ( stack.size() < mnumberofargs + mnumberofresults )
00272 {
00273 std::vector<ObjectImp*> ret;
00274 ret.push_back( new InvalidImp );
00275 return ret;
00276 }
00277 else
00278 {
00279 std::vector<ObjectImp*> ret;
00280 for ( uint i = stack.size() - mnumberofresults; i < stack.size(); ++i )
00281 ret.push_back( const_cast<ObjectImp*>( stack[i] ) );
00282 return ret;
00283 };
00284 }
00285
00286 int ObjectHierarchy::visit( const ObjectCalcer* o, std::map<const ObjectCalcer*, int>& seenmap,
00287 bool needed, bool neededatend )
00288 {
00289 using namespace std;
00290
00291 std::map<const ObjectCalcer*, int>::iterator smi = seenmap.find( o );
00292 if ( smi != seenmap.end() )
00293 {
00294 if ( neededatend )
00295 {
00296
00297
00298
00299
00300 int ret = mnumberofargs + mnodes.size();
00301 std::vector<int> parents;
00302 parents.push_back( smi->second );
00303 mnodes.push_back( new ApplyTypeNode( CopyObjectType::instance(), parents ) );
00304 return ret;
00305 }
00306 else return smi->second;
00307 }
00308
00309 std::vector<ObjectCalcer*> p( o->parents() );
00310
00311 bool descendsfromgiven = false;
00312 std::vector<int> parents;
00313 parents.resize( p.size(), -1 );
00314 for ( uint i = 0; i < p.size(); ++i )
00315 {
00316 int v = visit( p[i], seenmap, false );
00317 parents[i] = v;
00318 descendsfromgiven |= (v != -1);
00319 };
00320
00321 if ( ! descendsfromgiven && ! ( needed && o->imp()->isCache() ) )
00322 {
00323 if ( needed )
00324 {
00325 assert( ! o->imp()->isCache() );
00326
00327
00328
00329 Node* node = new PushStackNode( o->imp()->copy() );
00330 mnodes.push_back( node );
00331 int ret = mnodes.size() + mnumberofargs - 1;
00332 seenmap[o] = ret;
00333 return ret;
00334 }
00335 else
00336 return -1;
00337 };
00338
00339 return storeObject( o, p, parents, seenmap );
00340 }
00341
00342 ObjectHierarchy::~ObjectHierarchy()
00343 {
00344 for ( uint i = 0; i < mnodes.size(); ++i ) delete mnodes[i];
00345 }
00346
00347 ObjectHierarchy::ObjectHierarchy( const ObjectHierarchy& h )
00348 : mnumberofargs( h.mnumberofargs ), mnumberofresults( h.mnumberofresults ),
00349 msaveinputtags( h.msaveinputtags ),
00350 margrequirements( h.margrequirements ), musetexts( h.musetexts ),
00351 mselectstatements( h.mselectstatements )
00352 {
00353 mnodes.reserve( h.mnodes.size() );
00354 for ( uint i = 0; i < h.mnodes.size(); ++i )
00355 mnodes.push_back( h.mnodes[i]->copy() );
00356 }
00357
00358 ObjectHierarchy ObjectHierarchy::withFixedArgs( const Args& a ) const
00359 {
00360 assert( a.size() <= mnumberofargs );
00361 ObjectHierarchy ret( *this );
00362
00363 ret.mnumberofargs -= a.size();
00364 ret.margrequirements.resize( ret.mnumberofargs );
00365
00366 std::vector<Node*> newnodes( mnodes.size() + a.size() );
00367 std::vector<Node*>::iterator newnodesiter = newnodes.begin();
00368 for ( uint i = 0; i < a.size(); ++i )
00369 {
00370 assert( ! a[i]->isCache() );
00371 *newnodesiter++ = new PushStackNode( a[i]->copy() );
00372 };
00373 std::copy( ret.mnodes.begin(), ret.mnodes.end(), newnodesiter );
00374 ret.mnodes = newnodes;
00375
00376 return ret;
00377 }
00378
00379 void ObjectHierarchy::init( const std::vector<ObjectCalcer*>& from, const std::vector<ObjectCalcer*>& to )
00380 {
00381 msaveinputtags = false;
00382 mnumberofargs = from.size();
00383 mnumberofresults = to.size();
00384 margrequirements.resize( from.size(), ObjectImp::stype() );
00385 musetexts.resize( margrequirements.size(), "" );
00386 std::map<const ObjectCalcer*, int> seenmap;
00387 for ( uint i = 0; i < from.size(); ++i )
00388 seenmap[from[i]] = i;
00389 for ( std::vector<ObjectCalcer*>::const_iterator i = to.begin(); i != to.end(); ++i )
00390 {
00391 std::vector<ObjectCalcer*> parents = (*i)->parents();
00392 for ( std::vector<ObjectCalcer*>::const_iterator j = parents.begin();
00393 j != parents.end(); ++j )
00394 visit( *j, seenmap, true );
00395 }
00396 for ( std::vector<ObjectCalcer*>::const_iterator i = to.begin(); i != to.end(); ++i )
00397 visit( *i, seenmap, true, true );
00398
00399 mselectstatements.resize( margrequirements.size(), "" );
00400 }
00401
00402 ObjectHierarchy::ObjectHierarchy( const std::vector<ObjectCalcer*>& from, const ObjectCalcer* to )
00403 {
00404 std::vector<ObjectCalcer*> tov;
00405 tov.push_back( const_cast<ObjectCalcer*>( to ) );
00406 init( from, tov );
00407 }
00408
00409 ObjectHierarchy::ObjectHierarchy( const std::vector<ObjectCalcer*>& from, const std::vector<ObjectCalcer*>& to )
00410 {
00411 init( from, to );
00412 }
00413
00414 void ObjectHierarchy::serialize( QDomElement& parent, QDomDocument& doc ) const
00415 {
00416 int id = 1;
00417 for ( uint i = 0; i < mnumberofargs; ++i )
00418 {
00419 QDomElement e = doc.createElement( "input" );
00420 e.setAttribute( "id", id++ );
00421 e.setAttribute( "requirement", margrequirements[i]->internalName() );
00422
00423
00424 if ( msaveinputtags )
00425 {
00426 QDomElement ut = doc.createElement( "UseText" );
00427 ut.appendChild( doc.createTextNode( QString::fromLatin1(musetexts[i].c_str() ) ) );
00428 e.appendChild( ut );
00429 QDomElement ss = doc.createElement( "SelectStatement" );
00430 ss.appendChild( doc.createTextNode( QString::fromLatin1(mselectstatements[i].c_str() ) ) );
00431 e.appendChild( ss );
00432 }
00433 parent.appendChild( e );
00434 }
00435
00436 for ( uint i = 0; i < mnodes.size(); ++i )
00437 {
00438 bool result = mnodes.size() - ( id - mnumberofargs - 1 ) <= mnumberofresults;
00439 QDomElement e = doc.createElement( result ? "result" : "intermediate" );
00440 e.setAttribute( "id", id++ );
00441
00442 if ( mnodes[i]->id() == Node::ID_ApplyType )
00443 {
00444 const ApplyTypeNode* node = static_cast<const ApplyTypeNode*>( mnodes[i] );
00445 e.setAttribute( "action", "calc" );
00446 e.setAttribute( "type", QString::fromLatin1( node->type()->fullName() ) );
00447 for ( uint i = 0; i < node->parents().size(); ++i )
00448 {
00449 int parent = node->parents()[i] + 1;
00450 QDomElement arge = doc.createElement( "arg" );
00451 arge.appendChild( doc.createTextNode( QString::number( parent ) ) );
00452 e.appendChild( arge );
00453 };
00454 }
00455 else if ( mnodes[i]->id() == Node::ID_FetchProp )
00456 {
00457 const FetchPropertyNode* node = static_cast<const FetchPropertyNode*>( mnodes[i] );
00458 e.setAttribute( "action", "fetch-property" );
00459 e.setAttribute( "property", QString( node->propinternalname() ) );
00460 QDomElement arge = doc.createElement( "arg" );
00461 arge.appendChild( doc.createTextNode( QString::number( node->parent() + 1 ) ) );
00462 e.appendChild( arge );
00463 }
00464 else
00465 {
00466 assert( mnodes[i]->id() == ObjectHierarchy::Node::ID_PushStack );
00467 const PushStackNode* node = static_cast<const PushStackNode*>( mnodes[i] );
00468 e.setAttribute( "action", "push" );
00469 QString type = ObjectImpFactory::instance()->serialize( *node->imp(), e, doc );
00470 e.setAttribute( "type", type );
00471 };
00472
00473 parent.appendChild( e );
00474 };
00475 }
00476
00477 ObjectHierarchy::ObjectHierarchy()
00478 : mnumberofargs( 0 ), mnumberofresults( 0 ), msaveinputtags( false )
00479 {
00480 }
00481
00482 ObjectHierarchy* ObjectHierarchy::buildSafeObjectHierarchy( const QDomElement& parent, QString& error )
00483 {
00484 #define KIG_GENERIC_PARSE_ERROR \
00485 { \
00486 error = i18n( "An error was encountered at line %1 in file %2.", \
00487 __LINE__, __FILE__ ); \
00488 return 0; \
00489 }
00490
00491 ObjectHierarchy* obhi = new ObjectHierarchy();
00492
00493 bool ok = true;
00494 QString tmp;
00495 QDomElement e = parent.firstChild().toElement();
00496 for (; !e.isNull(); e = e.nextSibling().toElement() )
00497 {
00498 if ( e.tagName() != "input" ) break;
00499
00500 tmp = e.attribute( "id" );
00501 uint id = tmp.toInt( &ok );
00502 if ( !ok ) KIG_GENERIC_PARSE_ERROR;
00503
00504 obhi->mnumberofargs = qMax( id, obhi->mnumberofargs );
00505
00506 tmp = e.attribute( "requirement" );
00507 const ObjectImpType* req = ObjectImpType::typeFromInternalName( tmp.toLatin1() );
00508 if ( req == 0 ) req = ObjectImp::stype();
00509 obhi->margrequirements.resize( obhi->mnumberofargs, ObjectImp::stype() );
00510 obhi->musetexts.resize( obhi->mnumberofargs, "" );
00511 obhi->mselectstatements.resize( obhi->mnumberofargs, "" );
00512 obhi->margrequirements[id - 1] = req;
00513 obhi->musetexts[id - 1] = req->selectStatement();
00514 QDomElement esub = e.firstChild().toElement();
00515 for ( ; !esub.isNull(); esub = esub.nextSibling().toElement() )
00516 {
00517 if ( esub.tagName() == "UseText" )
00518 {
00519 obhi->msaveinputtags = true;
00520 obhi->musetexts[id - 1] = esub.text().toLatin1().data();
00521 }
00522 else if ( esub.tagName() == "SelectStatement" )
00523 {
00524 obhi->msaveinputtags = true;
00525 obhi->mselectstatements[id - 1] = esub.text().toLatin1().data();
00526 }
00527 else
00528 {
00529
00530 }
00531 }
00532 }
00533 for (; !e.isNull(); e = e.nextSibling().toElement() )
00534 {
00535 bool result = e.tagName() == "result";
00536 if ( result ) ++obhi->mnumberofresults;
00537
00538 tmp = e.attribute( "id" );
00539 int id = tmp.toInt( &ok );
00540 if ( !ok ) KIG_GENERIC_PARSE_ERROR;
00541
00542 tmp = e.attribute( "action" );
00543 Node* newnode = 0;
00544 if ( tmp == "calc" )
00545 {
00546
00547 QByteArray typen = e.attribute( "type" ).toLatin1();
00548 const ObjectType* type = ObjectTypeFactory::instance()->find( typen );
00549 if ( ! type )
00550 {
00551 error = i18n( "This Kig file uses an object of type \"%1\", "
00552 "which this Kig version does not support. "
00553 "Perhaps you have compiled Kig without support "
00554 "for this object type, "
00555 "or perhaps you are using an older Kig version.", QString( typen ) );
00556 return 0;
00557 }
00558
00559 std::vector<int> parents;
00560 for ( QDomNode p = e.firstChild(); !p.isNull(); p = p.nextSibling() )
00561 {
00562 QDomElement q = p.toElement();
00563 if ( q.isNull() ) KIG_GENERIC_PARSE_ERROR;
00564 if ( q.tagName() != "arg" ) KIG_GENERIC_PARSE_ERROR;
00565 int pid = q.text().toInt(&ok );
00566 if ( !ok ) KIG_GENERIC_PARSE_ERROR;
00567 parents.push_back( pid - 1 );
00568 };
00569 newnode = new ApplyTypeNode( type, parents );
00570 }
00571 else if ( tmp == "fetch-property" )
00572 {
00573
00574 QByteArray propname = e.attribute( "property" ).toLatin1();
00575 QDomElement arge = e.firstChild().toElement();
00576 int parent = arge.text().toInt( &ok );
00577 if ( !ok ) KIG_GENERIC_PARSE_ERROR;
00578 newnode = new FetchPropertyNode( parent - 1, propname );
00579 }
00580 else
00581 {
00582
00583 if ( e.attribute( "action" ) != "push" ) KIG_GENERIC_PARSE_ERROR;
00584 QString typen = e.attribute( "type" );
00585 if ( typen.isNull() ) KIG_GENERIC_PARSE_ERROR;
00586 ObjectImp* imp = ObjectImpFactory::instance()->deserialize( typen, e, error );
00587 if ( ( ! imp ) && !error.isEmpty() ) return 0;
00588 newnode = new PushStackNode( imp );
00589 };
00590 obhi->mnodes.resize( qMax( size_t(id - obhi->mnumberofargs), obhi->mnodes.size() ) );
00591 obhi->mnodes[id - obhi->mnumberofargs - 1] = newnode;
00592 };
00593
00594
00595 return obhi;
00596 }
00597
00598 ArgsParser ObjectHierarchy::argParser() const
00599 {
00600 std::vector<ArgsParser::spec> specs;
00601 for ( uint i = 0; i < margrequirements.size(); ++i )
00602 {
00603 const ObjectImpType* req = margrequirements[i];
00604 ArgsParser::spec spec;
00605 spec.type = req;
00606 spec.usetext = musetexts[i];
00607 spec.selectstat = mselectstatements[i];
00608 specs.push_back( spec );
00609 };
00610 return ArgsParser( specs );
00611 }
00612
00613 std::vector<ObjectCalcer*> ObjectHierarchy::buildObjects( const std::vector<ObjectCalcer*>& os, const KigDocument& doc ) const
00614 {
00615 assert( os.size() == mnumberofargs );
00616 for ( uint i = 0; i < os.size(); ++i )
00617 assert( os[i]->imp()->inherits( margrequirements[i] ) );
00618
00619 std::vector<ObjectCalcer*> stack;
00620 stack.resize( mnodes.size() + mnumberofargs, 0 );
00621 std::copy( os.begin(), os.end(), stack.begin() );
00622
00623 for( uint i = 0; i < mnodes.size(); ++i )
00624 {
00625 mnodes[i]->apply( stack, mnumberofargs + i );
00626 stack[mnumberofargs + i]->calc( doc );
00627 };
00628
00629 std::vector<ObjectCalcer*> ret( stack.end() - mnumberofresults, stack.end() );
00630
00631 return ret;
00632 }
00633
00634 const ObjectImpType* ObjectHierarchy::idOfLastResult() const
00635 {
00636 const Node* n = mnodes.back();
00637 if ( n->id() == Node::ID_PushStack )
00638 return static_cast<const PushStackNode*>( n )->imp()->type();
00639 else if ( n->id() == Node::ID_FetchProp )
00640 return ObjectImp::stype();
00641 else
00642 return static_cast<const ApplyTypeNode*>( n )->type()->resultId();
00643 }
00644
00645 ObjectHierarchy ObjectHierarchy::transformFinalObject( const Transformation& t ) const
00646 {
00647 assert( mnumberofresults == 1 );
00648 ObjectHierarchy ret( *this );
00649 ret.mnodes.push_back( new PushStackNode( new TransformationImp( t ) ) );
00650
00651 std::vector<int> parents;
00652 parents.push_back( ret.mnodes.size() - 1);
00653 parents.push_back( ret.mnodes.size() );
00654 const ObjectType* type = ApplyTransformationObjectType::instance();
00655 ret.mnodes.push_back( new ApplyTypeNode( type, parents ) );
00656 return ret;
00657 }
00658
00659 bool operator==( const ObjectHierarchy& lhs, const ObjectHierarchy& rhs )
00660 {
00661 if ( ! ( lhs.mnumberofargs == rhs.mnumberofargs &&
00662 lhs.mnumberofresults == rhs.mnumberofresults &&
00663 lhs.margrequirements == rhs.margrequirements &&
00664 lhs.mnodes.size() == rhs.mnodes.size() ) )
00665 return false;
00666
00667
00668
00669
00670 for ( uint i = 0; i < lhs.mnodes.size(); ++i )
00671 if ( lhs.mnodes[i] != lhs.mnodes[i] )
00672 return false;
00673
00674 return true;
00675 }
00676
00677 bool ObjectHierarchy::resultDoesNotDependOnGiven() const
00678 {
00679 std::vector<bool> dependsstack( mnodes.size() + mnumberofargs, false );
00680
00681 for ( uint i = 0; i < mnumberofargs; ++i )
00682 dependsstack[i] = true;
00683 for ( uint i = 0; i < mnodes.size(); ++i )
00684 mnodes[i]->checkDependsOnGiven( dependsstack, i + mnumberofargs );
00685 for ( uint i = dependsstack.size() - mnumberofresults; i < dependsstack.size(); ++i )
00686 if ( !dependsstack[i] )
00687 return true;
00688 return false;
00689 }
00690
00691
00692
00693
00694
00695
00696
00697 const ObjectImpType* lowermost( const ObjectImpType* a, const ObjectImpType* b )
00698 {
00699 if ( a->inherits( b ) ) return a;
00700 assert( b->inherits( a ) );
00701 return b;
00702 }
00703
00704
00705
00706
00707
00708
00709
00710
00711 int ObjectHierarchy::storeObject( const ObjectCalcer* o, const std::vector<ObjectCalcer*>& po, std::vector<int>& pl,
00712 std::map<const ObjectCalcer*, int>& seenmap )
00713 {
00714 for ( uint i = 0; i < po.size(); ++i )
00715 {
00716 if ( pl[i] == -1 )
00717 {
00718
00719 if ( po[i]->imp()->isCache() )
00720 {
00721 pl[i] = visit( po[i], seenmap, true, false );
00722 }
00723 else
00724 {
00725 Node* argnode = new PushStackNode( po[i]->imp()->copy() );
00726 mnodes.push_back( argnode );
00727 int argloc = mnumberofargs + mnodes.size() - 1;
00728 seenmap[po[i]] = argloc;
00729 pl[i] = argloc;
00730 };
00731 }
00732 else if ( (uint) pl[i] < mnumberofargs )
00733 {
00734 ObjectCalcer* parent = o->parents()[i];
00735 std::vector<ObjectCalcer*> opl = o->parents();
00736
00737 margrequirements[pl[i]] =
00738 lowermost( margrequirements[pl[i]],
00739 o->impRequirement( parent, opl ) );
00740 musetexts[pl[i]] = margrequirements[pl[i]]->selectStatement();
00741 };
00742 };
00743 if ( dynamic_cast<const ObjectTypeCalcer*>( o ) )
00744 mnodes.push_back( new ApplyTypeNode( static_cast<const ObjectTypeCalcer*>( o )->type(), pl ) );
00745 else if ( dynamic_cast<const ObjectPropertyCalcer*>( o ) )
00746 {
00747 assert( pl.size() == 1 );
00748 int parent = pl.front();
00749 ObjectCalcer* op = po.front();
00750 assert( op );
00751 int propgid = static_cast<const ObjectPropertyCalcer*>( o )->propGid();
00752
00753
00754 mnodes.push_back( new FetchPropertyNode( parent, op->imp()->getPropName( propgid ), propgid ) );
00755 }
00756 else
00757 assert( false );
00758 seenmap[o] = mnumberofargs + mnodes.size() - 1;
00759 return mnumberofargs + mnodes.size() - 1;
00760 }
00761
00762 ObjectHierarchy::ObjectHierarchy( const ObjectCalcer* from, const ObjectCalcer* to )
00763 {
00764 std::vector<ObjectCalcer*> fromv;
00765 fromv.push_back( const_cast<ObjectCalcer*>( from ) );
00766 std::vector<ObjectCalcer*> tov;
00767 tov.push_back( const_cast<ObjectCalcer*>( to ) );
00768 init( fromv, tov );
00769 }
00770
00771 bool ObjectHierarchy::allGivenObjectsUsed() const
00772 {
00773 std::vector<bool> usedstack( mnodes.size() + mnumberofargs, false );
00774 for ( uint i = mnodes.size() - mnumberofresults; i < mnodes.size(); ++i )
00775 usedstack[i + mnumberofargs] = true;
00776 for ( int i = mnodes.size() - 1; i >= 0; --i )
00777 if ( usedstack[i + mnumberofargs] )
00778 mnodes[i]->checkArgumentsUsed( usedstack );
00779 for ( uint i = 0; i < mnumberofargs; ++i )
00780 if ( ! usedstack[i] ) return false;
00781 return true;
00782 }
00783