aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs
diff options
context:
space:
mode:
authorChristian Kamm <[email protected]>2010-02-03 10:59:52 +0100
committerChristian Kamm <[email protected]>2010-02-03 10:59:52 +0100
commit49c43aaab152ba4e885f53e2b38720c3704a135d (patch)
tree91aa2acba74579f7e088a28beaf260ea3efe9606 /src/libs
parentba18e7003421562b698d064998b8eecf1f92c4a1 (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.cpp22
-rw-r--r--src/libs/qmljs/qmljscheck.h8
-rw-r--r--src/libs/qmljs/qmljsinterpreter.cpp51
-rw-r--r--src/libs/qmljs/qmljsinterpreter.h22
-rw-r--r--src/libs/qmljs/qmljslink.cpp70
-rw-r--r--src/libs/qmljs/qmljslink.h10
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