Commit ba18e700 authored by Roberto Raggi's avatar Roberto Raggi
Browse files

Introduced QML/JS references.

Done with ckamm
parent 95849cb0
......@@ -36,8 +36,9 @@
using namespace QmlJS;
using namespace QmlJS::Interpreter;
Check::Check(Interpreter::Engine *engine)
Check::Check(Interpreter::Engine *engine, Interpreter::Context *context)
: _engine(engine),
_context(context),
_scope(engine->globalObject()),
_result(0)
{
......@@ -57,11 +58,21 @@ const Interpreter::Value *Check::operator()(AST::Node *ast, const Interpreter::O
const Interpreter::Value *Check::check(AST::Node *ast)
{
// save the result
const Value *previousResult = switchResult(0);
// process the expression
accept(ast);
// restore the previous result
const Value *result = switchResult(previousResult);
if (const Reference *ref = value_cast<const Reference *>(result))
result = ref->value(_context);
if (! result)
result = _engine->undefinedValue();
return result;
}
......
......@@ -37,6 +37,7 @@ namespace QmlJS {
namespace Interpreter {
class Engine;
class Context;
class Value;
class ObjectValue;
class FunctionValue;
......@@ -45,7 +46,7 @@ namespace Interpreter {
class QMLJS_EXPORT Check: protected AST::Visitor
{
public:
Check(Interpreter::Engine *engine);
Check(Interpreter::Engine *engine, Interpreter::Context *context);
virtual ~Check();
const Interpreter::Value *operator()(AST::Node *ast, const Interpreter::ObjectValue *scope);
......@@ -155,6 +156,7 @@ protected:
private:
QmlJS::Document::Ptr _doc;
Interpreter::Engine *_engine;
Interpreter::Context *_context;
const Interpreter::ObjectValue *_scope;
const Interpreter::Value *_result;
};
......
......@@ -567,6 +567,9 @@ void ValueVisitor::visit(const FunctionValue *)
{
}
void ValueVisitor::visit(const Reference *)
{
}
////////////////////////////////////////////////////////////////////////////////
// Value
......@@ -614,6 +617,11 @@ const FunctionValue *Value::asFunctionValue() const
return 0;
}
const Reference *Value::asReference() const
{
return 0;
}
////////////////////////////////////////////////////////////////////////////////
// Environment
////////////////////////////////////////////////////////////////////////////////
......@@ -700,6 +708,51 @@ void StringValue::accept(ValueVisitor *visitor) const
visitor->visit(this);
}
Context::Context(Engine *engine)
: _engine(engine)
{
}
Context::~Context()
{
}
Engine *Context::engine() const
{
return _engine;
}
const Value *Context::property(const ObjectValue *object, const QString &name) const
{
const Properties properties = _properties.value(object);
return properties.value(name, engine()->undefinedValue());
}
void Context::setProperty(const ObjectValue *object, const QString &name, const Value *value)
{
_properties[object].insert(name, value);
}
Reference::Reference()
{
}
Reference::~Reference()
{
}
const Reference *Reference::asReference() const
{
return this;
}
void Reference::accept(ValueVisitor *visitor) const
{
visitor->visit(this);
}
MemberProcessor::MemberProcessor()
{
}
......
......@@ -53,6 +53,7 @@ class BooleanValue;
class StringValue;
class ObjectValue;
class FunctionValue;
class Reference;
typedef QList<const Value *> ValueList;
......@@ -72,6 +73,7 @@ public:
virtual void visit(const StringValue *);
virtual void visit(const ObjectValue *);
virtual void visit(const FunctionValue *);
virtual void visit(const Reference *);
};
////////////////////////////////////////////////////////////////////////////////
......@@ -93,6 +95,7 @@ public:
virtual const StringValue *asStringValue() const;
virtual const ObjectValue *asObjectValue() const;
virtual const FunctionValue *asFunctionValue() const;
virtual const Reference *asReference() const;
virtual void accept(ValueVisitor *) const = 0;
};
......@@ -141,6 +144,12 @@ template <> Q_INLINE_TEMPLATE const FunctionValue *value_cast(const Value *v)
else return 0;
}
template <> Q_INLINE_TEMPLATE const Reference *value_cast(const Value *v)
{
if (v) return v->asReference();
else return 0;
}
////////////////////////////////////////////////////////////////////////////////
// Execution environment
////////////////////////////////////////////////////////////////////////////////
......@@ -210,6 +219,37 @@ public:
virtual bool processGeneratedSlot(const QString &name, const Value *value);
};
class QMLJS_EXPORT Context
{
public:
Context(Engine *engine);
virtual ~Context();
Engine *engine() const;
const Value *property(const ObjectValue *object, const QString &name) const;
void setProperty(const ObjectValue *object, const QString &name, const Value *value);
private:
typedef QHash<QString, const Value *> Properties;
Engine *_engine;
QHash<const ObjectValue *, Properties> _properties;
};
class QMLJS_EXPORT Reference: public Value
{
public:
Reference();
virtual ~Reference();
virtual const Value *value(const Context *context) const = 0;
// Value interface
virtual const Reference *asReference() const;
virtual void accept(ValueVisitor *) const;
};
class QMLJS_EXPORT ObjectValue: public Value, public Environment
{
public:
......
......@@ -15,6 +15,7 @@ using namespace QmlJS::AST;
Link::Link(Document::Ptr currentDoc, const Snapshot &snapshot, Interpreter::Engine *interp)
: _snapshot(snapshot)
, _interp(interp)
, _context(interp)
{
_docs = reachableDocuments(currentDoc, snapshot);
......@@ -47,6 +48,11 @@ static ObjectValue *pushScope(ObjectValue *next, ObjectValue *onto)
return next;
}
Context *Link::context()
{
return &_context;
}
ObjectValue *Link::scopeChainAt(Document::Ptr doc, Node *currentObject)
{
BindPtr bind = doc->bind();
......
......@@ -23,6 +23,8 @@ public:
Link(Document::Ptr doc, const Snapshot &snapshot, Interpreter::Engine *interp);
~Link();
Interpreter::Context *context();
// Get the scope chain for the currentObject inside doc.
Interpreter::ObjectValue *scopeChainAt(Document::Ptr doc, AST::Node *currentObject);
......@@ -43,6 +45,7 @@ private:
private:
Snapshot _snapshot;
Interpreter::Engine *_interp;
Interpreter::Context _context;
QList<Document::Ptr> _docs;
QHash<Document *, Interpreter::ObjectValue *> _typeEnvironments;
};
......
......@@ -670,7 +670,7 @@ int QmlCodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
//qDebug() << "expression:" << expression;
if (expression != 0) {
Check evaluate(&interp);
Check evaluate(&interp, link.context());
// Evaluate the expression under cursor.
const Interpreter::Value *value = interp.convertToObject(evaluate(expression , scope));
......
......@@ -175,7 +175,7 @@ void QmlHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in
Link link(qmlDocument, snapshot, &interp);
const Interpreter::ObjectValue *scope = link.scopeChainAt(qmlDocument, declaringMember);
Check check(&interp);
Check check(&interp, link.context());
const Interpreter::Value *value = check(node, scope);
QStringList baseClasses;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment