diff options
author | Christian Kamm <[email protected]> | 2010-02-03 10:59:52 +0100 |
---|---|---|
committer | Christian Kamm <[email protected]> | 2010-02-03 10:59:52 +0100 |
commit | 49c43aaab152ba4e885f53e2b38720c3704a135d (patch) | |
tree | 91aa2acba74579f7e088a28beaf260ea3efe9606 /src/libs | |
parent | ba18e7003421562b698d064998b8eecf1f92c4a1 (diff) |
Get rid of Environment, introduce external ScopeChain in Link.
Done-with: Roberto
Diffstat (limited to 'src/libs')
-rw-r--r-- | src/libs/qmljs/qmljscheck.cpp | 22 | ||||
-rw-r--r-- | src/libs/qmljs/qmljscheck.h | 8 | ||||
-rw-r--r-- | src/libs/qmljs/qmljsinterpreter.cpp | 51 | ||||
-rw-r--r-- | src/libs/qmljs/qmljsinterpreter.h | 22 | ||||
-rw-r--r-- | src/libs/qmljs/qmljslink.cpp | 70 | ||||
-rw-r--r-- | src/libs/qmljs/qmljslink.h | 10 |
6 files changed, 67 insertions, 116 deletions
diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp index 7532f48de37..3d24f79054d 100644 --- a/src/libs/qmljs/qmljscheck.cpp +++ b/src/libs/qmljs/qmljscheck.cpp @@ -29,6 +29,7 @@ #include "qmljscheck.h" #include "qmljsinterpreter.h" +#include "qmljslink.h" #include "parser/qmljsparser_p.h" #include "parser/qmljsast_p.h" #include <QtCore/QDebug> @@ -36,10 +37,10 @@ using namespace QmlJS; using namespace QmlJS::Interpreter; -Check::Check(Interpreter::Engine *engine, Interpreter::Context *context) - : _engine(engine), - _context(context), - _scope(engine->globalObject()), +Check::Check(Link *link) + : _engine(link->engine()), + _link(link), + _scope(_engine->globalObject()), _result(0) { } @@ -48,12 +49,9 @@ Check::~Check() { } -const Interpreter::Value *Check::operator()(AST::Node *ast, const Interpreter::ObjectValue *scope) +const Interpreter::Value *Check::operator()(AST::Node *ast) { - const Interpreter::ObjectValue *previousScope = switchScope(scope); - const Interpreter::Value *result = check(ast); - (void) switchScope(previousScope); - return result; + return check(ast); } const Interpreter::Value *Check::check(AST::Node *ast) @@ -68,7 +66,7 @@ const Interpreter::Value *Check::check(AST::Node *ast) const Value *result = switchResult(previousResult); if (const Reference *ref = value_cast<const Reference *>(result)) - result = ref->value(_context); + result = ref->value(_link->context()); if (! result) result = _engine->undefinedValue(); @@ -167,7 +165,7 @@ bool Check::visit(AST::UiQualifiedId *ast) if (! ast->name) return false; - const Value *value = _scope->lookup(ast->name->asString()); + const Value *value = _link->lookup(ast->name->asString()); if (! ast->next) { _result = value; @@ -215,7 +213,7 @@ bool Check::visit(AST::IdentifierExpression *ast) if (! ast->name) return false; - _result = _scope->lookup(ast->name->asString()); + _result = _link->lookup(ast->name->asString()); return false; } diff --git a/src/libs/qmljs/qmljscheck.h b/src/libs/qmljs/qmljscheck.h index b37375ea7b1..95fef91b3ff 100644 --- a/src/libs/qmljs/qmljscheck.h +++ b/src/libs/qmljs/qmljscheck.h @@ -35,6 +35,8 @@ namespace QmlJS { +class Link; + namespace Interpreter { class Engine; class Context; @@ -46,10 +48,10 @@ namespace Interpreter { class QMLJS_EXPORT Check: protected AST::Visitor { public: - Check(Interpreter::Engine *engine, Interpreter::Context *context); + Check(Link *link); virtual ~Check(); - const Interpreter::Value *operator()(AST::Node *ast, const Interpreter::ObjectValue *scope); + const Interpreter::Value *operator()(AST::Node *ast); protected: void accept(AST::Node *node); @@ -156,7 +158,7 @@ protected: private: QmlJS::Document::Ptr _doc; Interpreter::Engine *_engine; - Interpreter::Context *_context; + Link *_link; const Interpreter::ObjectValue *_scope; const Interpreter::Value *_result; }; diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp index b248fd2f94d..6d293ac5e37 100644 --- a/src/libs/qmljs/qmljsinterpreter.cpp +++ b/src/libs/qmljs/qmljsinterpreter.cpp @@ -623,39 +623,6 @@ const Reference *Value::asReference() const } //////////////////////////////////////////////////////////////////////////////// -// Environment -//////////////////////////////////////////////////////////////////////////////// -Environment::Environment() -{ -} - -Environment::~Environment() -{ -} - -const Environment *Environment::parent() const -{ - return 0; -} - -const Value *Environment::lookup(const QString &name) const -{ - if (const Value *member = lookupMember(name)) - return member; - - else if (const Environment *p = parent()) - return p->lookup(name); - - else - return 0; -} - -const Value *Environment::lookupMember(const QString &) const -{ - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// // Values //////////////////////////////////////////////////////////////////////////////// const NullValue *NullValue::asNullValue() const @@ -788,8 +755,7 @@ bool MemberProcessor::processGeneratedSlot(const QString &, const Value *) ObjectValue::ObjectValue(Engine *engine) : _engine(engine), - _prototype(0), - _scope(0) + _prototype(0) { engine->registerObject(this); } @@ -818,16 +784,6 @@ const ObjectValue *ObjectValue::prototype() const return _prototype; } -const ObjectValue *ObjectValue::scope() const -{ - return _scope; -} - -void ObjectValue::setScope(const ObjectValue *scope) -{ - _scope = scope; -} - void ObjectValue::setProperty(const QString &name, const Value *value) { _members[name] = value; @@ -893,11 +849,6 @@ void ObjectValue::processMembers(MemberProcessor *processor) const } } -const Environment *ObjectValue::parent() const -{ - return _scope; -} - const Value *ObjectValue::lookupMember(const QString &name) const { if (const Value *m = _members.value(name)) diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h index 623d56821c9..f6cc9dc5201 100644 --- a/src/libs/qmljs/qmljsinterpreter.h +++ b/src/libs/qmljs/qmljsinterpreter.h @@ -151,20 +151,6 @@ template <> Q_INLINE_TEMPLATE const Reference *value_cast(const Value *v) } //////////////////////////////////////////////////////////////////////////////// -// Execution environment -//////////////////////////////////////////////////////////////////////////////// -class QMLJS_EXPORT Environment -{ -public: - Environment(); - virtual ~Environment(); - - virtual const Environment *parent() const; - virtual const Value *lookup(const QString &name) const; - virtual const Value *lookupMember(const QString &name) const; -}; - -//////////////////////////////////////////////////////////////////////////////// // Value nodes //////////////////////////////////////////////////////////////////////////////// class QMLJS_EXPORT NullValue: public Value @@ -250,7 +236,7 @@ public: virtual void accept(ValueVisitor *) const; }; -class QMLJS_EXPORT ObjectValue: public Value, public Environment +class QMLJS_EXPORT ObjectValue: public Value { public: ObjectValue(Engine *engine); @@ -264,17 +250,12 @@ public: const ObjectValue *prototype() const; void setPrototype(const ObjectValue *prototype); - const ObjectValue *scope() const; - void setScope(const ObjectValue *scope); - virtual void processMembers(MemberProcessor *processor) const; virtual const Value *property(const QString &name) const; virtual void setProperty(const QString &name, const Value *value); virtual void removeProperty(const QString &name); - // Environment interface - virtual const Environment *parent() const; virtual const Value *lookupMember(const QString &name) const; // Value interface @@ -287,7 +268,6 @@ private: private: Engine *_engine; const ObjectValue *_prototype; - const ObjectValue *_scope; QHash<QString, const Value *> _members; QString _className; }; diff --git a/src/libs/qmljs/qmljslink.cpp b/src/libs/qmljs/qmljslink.cpp index 55871970563..5af7edf8308 100644 --- a/src/libs/qmljs/qmljslink.cpp +++ b/src/libs/qmljs/qmljslink.cpp @@ -24,69 +24,81 @@ Link::Link(Document::Ptr currentDoc, const Snapshot &snapshot, Interpreter::Engi Link::~Link() { - // unset all prototypes and scopes + // unset all prototypes foreach (Document::Ptr doc, _docs) { BindPtr bind = doc->bind(); if (doc->qmlProgram()) { - bind->_idEnvironment->setScope(0); - bind->_functionEnvironment->setScope(0); - foreach (ObjectValue *object, bind->_qmlObjects) { object->setPrototype(0); - object->setScope(0); } - } else if (doc->jsProgram()) { - bind->_rootObjectValue->setScope(0); } } } -static ObjectValue *pushScope(ObjectValue *next, ObjectValue *onto) +Context *Link::context() { - onto->setScope(next); - return next; + return &_context; } -Context *Link::context() +Link::ScopeChain Link::scopeChain() const { - return &_context; + return _scopeChain; } -ObjectValue *Link::scopeChainAt(Document::Ptr doc, Node *currentObject) +Interpreter::Engine *Link::engine() { - BindPtr bind = doc->bind(); + return _interp; +} - ObjectValue *scopeObject = 0; - if (UiObjectDefinition *definition = cast<UiObjectDefinition *>(currentObject)) - scopeObject = bind->_qmlObjects.value(definition); +void Link::scopeChainAt(Document::Ptr doc, Node *currentObject) +{ + _scopeChain.clear(); + + if (! doc) { + _scopeChain.append(_interp->globalObject()); + return; + } - if (!scopeObject) - return bind->_interp.globalObject(); + BindPtr bind = doc->bind(); // Build the scope chain. - ObjectValue *scopeStart = _typeEnvironments.value(doc.data()); - ObjectValue *scope = scopeStart; - scope = pushScope(bind->_idEnvironment, scope); - scope = pushScope(bind->_functionEnvironment, scope); + _scopeChain.append(_typeEnvironments.value(doc.data())); + _scopeChain.append(bind->_idEnvironment); + _scopeChain.append(bind->_functionEnvironment); foreach (const QString &scriptFile, doc->bind()->includedScripts()) { if (Document::Ptr scriptDoc = _snapshot.document(scriptFile)) { if (scriptDoc->jsProgram()) { - scope = pushScope(scriptDoc->bind()->_rootObjectValue, scope); + _scopeChain.append(scriptDoc->bind()->_rootObjectValue); } } } - scope = pushScope(scopeObject, scope); - if (scopeObject != bind->_rootObjectValue) - scope = pushScope(bind->_rootObjectValue, scope); - scope = pushScope(bind->_interp.globalObject(), scope); + if (UiObjectDefinition *definition = cast<UiObjectDefinition *>(currentObject)) { + ObjectValue *scopeObject = bind->_qmlObjects.value(definition); + _scopeChain.append(scopeObject); + + // ### FIXME: should add the root regardless + if (scopeObject != bind->_rootObjectValue) + _scopeChain.append(bind->_rootObjectValue); + } + + _scopeChain.append(bind->_interp.globalObject()); // May want to link to instantiating components from here. +} + +const Value *Link::lookup(const QString &name) const +{ + foreach (const ObjectValue *scope, _scopeChain) { + if (const Value *member = scope->lookupMember(name)) { + return member; + } + } - return scopeStart; + return _interp->undefinedValue(); } void Link::linkImports() diff --git a/src/libs/qmljs/qmljslink.h b/src/libs/qmljs/qmljslink.h index 1233412848f..8b622140ed0 100644 --- a/src/libs/qmljs/qmljslink.h +++ b/src/libs/qmljs/qmljslink.h @@ -19,14 +19,21 @@ namespace QmlJS { class QMLJS_EXPORT Link { public: + typedef QList<const Interpreter::ObjectValue *> ScopeChain; + +public: // Link all documents in snapshot reachable from doc. Link(Document::Ptr doc, const Snapshot &snapshot, Interpreter::Engine *interp); ~Link(); Interpreter::Context *context(); + ScopeChain scopeChain() const; + Interpreter::Engine *engine(); // Get the scope chain for the currentObject inside doc. - Interpreter::ObjectValue *scopeChainAt(Document::Ptr doc, AST::Node *currentObject); + void scopeChainAt(Document::Ptr doc, AST::Node *currentObject); + + const Interpreter::Value *lookup(const QString &name) const; private: static QList<Document::Ptr> reachableDocuments(Document::Ptr startDoc, const Snapshot &snapshot); @@ -48,6 +55,7 @@ private: Interpreter::Context _context; QList<Document::Ptr> _docs; QHash<Document *, Interpreter::ObjectValue *> _typeEnvironments; + ScopeChain _scopeChain; }; } // namespace QmlJS |