1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** Licensees holding valid Qt Commercial licenses may use this file in
12 ** accordance with the Qt Commercial License Agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and Nokia.
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** If you are unsure which license is appropriate for your use, please
26 ** contact the sales department at http://qt.nokia.com/contact.
28 **************************************************************************/
30 #ifndef QMLJS_INTERPRETER_H
31 #define QMLJS_INTERPRETER_H
33 #include <qmljs/qmljsdocument.h>
34 #include <qmljs/qmljs_global.h>
35 #include <qmljs/qmljscomponentversion.h>
36 #include <qmljs/parser/qmljsastfwd_p.h>
38 #include <QtCore/QFileInfoList>
39 #include <QtCore/QList>
40 #include <QtCore/QString>
41 #include <QtCore/QHash>
42 #include <QtCore/QSet>
49 namespace Interpreter {
51 ////////////////////////////////////////////////////////////////////////////////
52 // Forward declarations
53 ////////////////////////////////////////////////////////////////////////////////
65 class AnchorLineValue;
67 typedef QList<const Value *> ValueList;
71 class FakeMetaProperty;
74 ////////////////////////////////////////////////////////////////////////////////
76 ////////////////////////////////////////////////////////////////////////////////
77 class QMLJS_EXPORT ValueVisitor
81 virtual ~ValueVisitor();
83 virtual void visit(const NullValue *);
84 virtual void visit(const UndefinedValue *);
85 virtual void visit(const NumberValue *);
86 virtual void visit(const BooleanValue *);
87 virtual void visit(const StringValue *);
88 virtual void visit(const ObjectValue *);
89 virtual void visit(const FunctionValue *);
90 virtual void visit(const Reference *);
91 virtual void visit(const ColorValue *);
92 virtual void visit(const AnchorLineValue *);
95 ////////////////////////////////////////////////////////////////////////////////
97 ////////////////////////////////////////////////////////////////////////////////
98 class QMLJS_EXPORT Value
100 Value(const Value &other);
101 void operator = (const Value &other);
107 virtual const NullValue *asNullValue() const;
108 virtual const UndefinedValue *asUndefinedValue() const;
109 virtual const NumberValue *asNumberValue() const;
110 virtual const BooleanValue *asBooleanValue() const;
111 virtual const StringValue *asStringValue() const;
112 virtual const ObjectValue *asObjectValue() const;
113 virtual const FunctionValue *asFunctionValue() const;
114 virtual const Reference *asReference() const;
115 virtual const ColorValue *asColorValue() const;
116 virtual const AnchorLineValue *asAnchorLineValue() const;
118 virtual void accept(ValueVisitor *) const = 0;
120 virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
123 template <typename _RetTy> _RetTy value_cast(const Value *v);
125 template <> Q_INLINE_TEMPLATE const NullValue *value_cast(const Value *v)
127 if (v) return v->asNullValue();
131 template <> Q_INLINE_TEMPLATE const UndefinedValue *value_cast(const Value *v)
133 if (v) return v->asUndefinedValue();
137 template <> Q_INLINE_TEMPLATE const NumberValue *value_cast(const Value *v)
139 if (v) return v->asNumberValue();
143 template <> Q_INLINE_TEMPLATE const BooleanValue *value_cast(const Value *v)
145 if (v) return v->asBooleanValue();
149 template <> Q_INLINE_TEMPLATE const StringValue *value_cast(const Value *v)
151 if (v) return v->asStringValue();
155 template <> Q_INLINE_TEMPLATE const ObjectValue *value_cast(const Value *v)
157 if (v) return v->asObjectValue();
161 template <> Q_INLINE_TEMPLATE const FunctionValue *value_cast(const Value *v)
163 if (v) return v->asFunctionValue();
167 template <> Q_INLINE_TEMPLATE const Reference *value_cast(const Value *v)
169 if (v) return v->asReference();
173 template <> Q_INLINE_TEMPLATE const ColorValue *value_cast(const Value *v)
175 if (v) return v->asColorValue();
179 template <> Q_INLINE_TEMPLATE const AnchorLineValue *value_cast(const Value *v)
181 if (v) return v->asAnchorLineValue();
185 ////////////////////////////////////////////////////////////////////////////////
187 ////////////////////////////////////////////////////////////////////////////////
188 class QMLJS_EXPORT NullValue: public Value
191 virtual const NullValue *asNullValue() const;
192 virtual void accept(ValueVisitor *visitor) const;
195 class QMLJS_EXPORT UndefinedValue: public Value
198 virtual const UndefinedValue *asUndefinedValue() const;
199 virtual void accept(ValueVisitor *visitor) const;
202 class QMLJS_EXPORT NumberValue: public Value
205 virtual const NumberValue *asNumberValue() const;
206 virtual void accept(ValueVisitor *visitor) const;
209 class QMLJS_EXPORT BooleanValue: public Value
212 virtual const BooleanValue *asBooleanValue() const;
213 virtual void accept(ValueVisitor *visitor) const;
216 class QMLJS_EXPORT StringValue: public Value
219 virtual const StringValue *asStringValue() const;
220 virtual void accept(ValueVisitor *visitor) const;
223 class QMLJS_EXPORT MemberProcessor
225 MemberProcessor(const MemberProcessor &other);
226 void operator = (const MemberProcessor &other);
230 virtual ~MemberProcessor();
232 // Returns false to stop the processor.
233 virtual bool processProperty(const QString &name, const Value *value);
234 virtual bool processEnumerator(const QString &name, const Value *value);
235 virtual bool processSignal(const QString &name, const Value *value);
236 virtual bool processSlot(const QString &name, const Value *value);
237 virtual bool processGeneratedSlot(const QString &name, const Value *value);
240 class QMLJS_EXPORT ScopeChain
245 struct QmlComponentChain
248 ~QmlComponentChain();
250 QList<QmlComponentChain *> instantiatingComponents;
251 Document::Ptr document;
253 void add(QList<const ObjectValue *> *list) const;
257 const ObjectValue *globalScope;
258 QmlComponentChain qmlComponentScope;
259 QList<const ObjectValue *> qmlScopeObjects;
260 const ObjectValue *qmlTypes;
261 QList<const ObjectValue *> jsScopes;
263 // rebuilds the flat list of all scopes
265 QList<const ObjectValue *> all() const;
268 QList<const ObjectValue *> _all;
271 class QMLJS_EXPORT Context
274 Context(Engine *engine);
277 Engine *engine() const;
278 const ScopeChain &scopeChain() const;
279 ScopeChain &scopeChain();
281 const ObjectValue *typeEnvironment(const Document *doc) const;
282 void setTypeEnvironment(const Document *doc, const ObjectValue *typeEnvironment);
284 const Value *lookup(const QString &name);
285 const ObjectValue *lookupType(const Document *doc, AST::UiQualifiedId *qmlTypeName);
286 const ObjectValue *lookupType(const Document *doc, const QStringList &qmlTypeName);
287 const Value *lookupReference(const Reference *reference);
289 const Value *property(const ObjectValue *object, const QString &name) const;
290 void setProperty(const ObjectValue *object, const QString &name, const Value *value);
292 QString defaultPropertyName(const ObjectValue *object);
294 bool documentImportsPlugins(const Document *doc) const;
295 void setDocumentImportsPlugins(const Document *doc);
298 typedef QHash<QString, const Value *> Properties;
301 QHash<const ObjectValue *, Properties> _properties;
302 QHash<QString, const ObjectValue *> _typeEnvironments;
303 QSet<QString> _documentsImportingPlugins;
304 ScopeChain _scopeChain;
305 int _qmlScopeObjectIndex;
306 bool _qmlScopeObjectSet;
307 QList<const Reference *> _referenceStack;
310 class QMLJS_EXPORT Reference: public Value
313 Reference(Engine *engine);
314 virtual ~Reference();
316 Engine *engine() const;
319 virtual const Reference *asReference() const;
320 virtual void accept(ValueVisitor *) const;
323 virtual const Value *value(Context *context) const;
326 friend class Context;
329 class QMLJS_EXPORT ColorValue: public Value
333 virtual const ColorValue *asColorValue() const;
334 virtual void accept(ValueVisitor *) const;
337 class QMLJS_EXPORT AnchorLineValue: public Value
341 virtual const AnchorLineValue *asAnchorLineValue() const;
342 virtual void accept(ValueVisitor *) const;
345 class QMLJS_EXPORT ObjectValue: public Value
348 ObjectValue(Engine *engine);
349 virtual ~ObjectValue();
351 Engine *engine() const;
353 QString className() const;
354 void setClassName(const QString &className);
356 const ObjectValue *prototype(Context *context) const;
357 void setPrototype(const Value *prototype);
359 virtual void processMembers(MemberProcessor *processor) const;
361 virtual const Value *property(const QString &name, Context *context) const;
362 virtual void setProperty(const QString &name, const Value *value);
363 virtual void removeProperty(const QString &name);
365 virtual const Value *lookupMember(const QString &name, Context *context, bool examinePrototypes = true) const;
368 virtual const ObjectValue *asObjectValue() const;
369 virtual void accept(ValueVisitor *visitor) const;
372 bool checkPrototype(const ObjectValue *prototype, QSet<const ObjectValue *> *processed) const;
376 const Value *_prototype;
377 QHash<QString, const Value *> _members;
381 class QMLJS_EXPORT QmlObjectValue: public ObjectValue
384 QmlObjectValue(const FakeMetaObject *metaObject, Engine *engine);
385 virtual ~QmlObjectValue();
387 virtual void processMembers(MemberProcessor *processor) const;
388 const Value *propertyValue(const FakeMetaProperty &prop) const;
390 QString packageName() const;
391 ComponentVersion version() const;
392 QString defaultPropertyName() const;
393 QString propertyType(const QString &propertyName) const;
394 bool isListProperty(const QString &name) const;
395 bool isEnum(const QString &typeName) const;
396 bool enumContainsKey(const QString &enumName, const QString &enumKeyName) const;
397 bool hasChildInPackage() const;
400 const Value *findOrCreateSignature(int index, const FakeMetaMethod &method, QString *methodName) const;
401 bool isDerivedFrom(const FakeMetaObject *base) const;
404 const FakeMetaObject *_metaObject;
405 mutable QHash<int, const Value *> _metaSignature;
408 class QMLJS_EXPORT QmlEnumValue: public NumberValue
411 QmlEnumValue(const FakeMetaEnum &metaEnum, Engine *engine);
412 virtual ~QmlEnumValue();
414 QString name() const;
415 QStringList keys() const;
418 FakeMetaEnum *_metaEnum;
421 class QMLJS_EXPORT Activation
424 explicit Activation(Context *parentContext = 0);
425 virtual ~Activation();
427 Context *context() const;
428 Context *parentContext() const;
430 bool calledAsConstructor() const;
431 void setCalledAsConstructor(bool calledAsConstructor);
433 bool calledAsFunction() const;
434 void setCalledAsFunction(bool calledAsFunction);
436 ObjectValue *thisObject() const;
437 void setThisObject(ObjectValue *thisObject);
439 ValueList arguments() const;
440 void setArguments(const ValueList &arguments);
443 ObjectValue *_thisObject;
444 ValueList _arguments;
445 bool _calledAsFunction;
446 Context *_parentContext;
450 class QMLJS_EXPORT FunctionValue: public ObjectValue
453 FunctionValue(Engine *engine);
454 virtual ~FunctionValue();
457 const Value *construct(const ValueList &actuals = ValueList()) const;
460 const Value *call(const ValueList &actuals = ValueList()) const;
462 const Value *call(const ObjectValue *thisObject,
463 const ValueList &actuals = ValueList()) const;
466 virtual const Value *returnValue() const;
468 virtual int argumentCount() const;
469 virtual const Value *argument(int index) const;
470 virtual QString argumentName(int index) const;
471 virtual bool isVariadic() const;
473 virtual const Value *invoke(const Activation *activation) const;
476 virtual const FunctionValue *asFunctionValue() const;
477 virtual void accept(ValueVisitor *visitor) const;
480 class QMLJS_EXPORT Function: public FunctionValue
483 Function(Engine *engine);
486 void addArgument(const Value *argument);
487 void setReturnValue(const Value *returnValue);
489 // ObjectValue interface
490 virtual const Value *property(const QString &name, Context *context) const;
492 // FunctionValue interface
493 virtual const Value *returnValue() const;
494 virtual int argumentCount() const;
495 virtual const Value *argument(int index) const;
496 virtual const Value *invoke(const Activation *activation) const;
499 ValueList _arguments;
500 const Value *_returnValue;
504 ////////////////////////////////////////////////////////////////////////////////
505 // typing environment
506 ////////////////////////////////////////////////////////////////////////////////
508 class QMLJS_EXPORT CppQmlTypesLoader
511 /** \return an empty list when successful, error messages otherwise. */
512 static QStringList load(const QFileInfoList &xmlFiles);
513 static QList<const FakeMetaObject *> builtinObjects;
515 // parses the xml string and fills the newObjects map
516 static QString parseQmlTypeXml(const QByteArray &xml, QMap<QString, FakeMetaObject *> *newObjects);
518 static void setSuperClasses(QMap<QString, FakeMetaObject *> *newObjects);
521 class QMLJS_EXPORT CppQmlTypes
524 void load(Interpreter::Engine *interpreter, const QList<const FakeMetaObject *> &objects);
526 QList<Interpreter::QmlObjectValue *> typesForImport(const QString &prefix, ComponentVersion version) const;
527 Interpreter::QmlObjectValue *typeForImport(const QString &qualifiedName) const;
529 bool hasPackage(const QString &package) const;
531 QHash<QString, QmlObjectValue *> types() const
532 { return _typesByFullyQualifiedName; }
535 QHash<QString, QList<QmlObjectValue *> > _typesByPackage;
536 QHash<QString, QmlObjectValue *> _typesByFullyQualifiedName;
539 class ConvertToNumber: protected ValueVisitor // ECMAScript ToInt()
542 ConvertToNumber(Engine *engine);
544 const Value *operator()(const Value *value);
547 const Value *switchResult(const Value *value);
549 virtual void visit(const NullValue *);
550 virtual void visit(const UndefinedValue *);
551 virtual void visit(const NumberValue *);
552 virtual void visit(const BooleanValue *);
553 virtual void visit(const StringValue *);
554 virtual void visit(const ObjectValue *);
555 virtual void visit(const FunctionValue *);
559 const Value *_result;
562 class ConvertToString: protected ValueVisitor // ECMAScript ToString
565 ConvertToString(Engine *engine);
567 const Value *operator()(const Value *value);
570 const Value *switchResult(const Value *value);
572 virtual void visit(const NullValue *);
573 virtual void visit(const UndefinedValue *);
574 virtual void visit(const NumberValue *);
575 virtual void visit(const BooleanValue *);
576 virtual void visit(const StringValue *);
577 virtual void visit(const ObjectValue *);
578 virtual void visit(const FunctionValue *);
582 const Value *_result;
585 class ConvertToObject: protected ValueVisitor // ECMAScript ToObject
588 ConvertToObject(Engine *engine);
590 const Value *operator()(const Value *value);
593 const Value *switchResult(const Value *value);
595 virtual void visit(const NullValue *);
596 virtual void visit(const UndefinedValue *);
597 virtual void visit(const NumberValue *);
598 virtual void visit(const BooleanValue *);
599 virtual void visit(const StringValue *);
600 virtual void visit(const ObjectValue *);
601 virtual void visit(const FunctionValue *);
605 const Value *_result;
608 class TypeId: protected ValueVisitor
613 QString operator()(const Value *value);
616 virtual void visit(const NullValue *);
617 virtual void visit(const UndefinedValue *);
618 virtual void visit(const NumberValue *);
619 virtual void visit(const BooleanValue *);
620 virtual void visit(const StringValue *);
621 virtual void visit(const ObjectValue *object);
622 virtual void visit(const FunctionValue *object);
623 virtual void visit(const ColorValue *);
624 virtual void visit(const AnchorLineValue *);
627 class QMLJS_EXPORT Engine
629 Engine(const Engine &other);
630 void operator = (const Engine &other);
636 const NullValue *nullValue() const;
637 const UndefinedValue *undefinedValue() const;
638 const NumberValue *numberValue() const;
639 const BooleanValue *booleanValue() const;
640 const StringValue *stringValue() const;
641 const ColorValue *colorValue() const;
642 const AnchorLineValue *anchorLineValue() const;
644 ObjectValue *newObject(const ObjectValue *prototype);
645 ObjectValue *newObject();
646 Function *newFunction();
647 const Value *newArray(); // ### remove me
650 const ObjectValue *qmlKeysObject();
651 const Value *defaultValueForBuiltinType(const QString &typeName) const;
654 ObjectValue *globalObject() const;
655 const ObjectValue *mathObject() const;
656 const ObjectValue *qtObject() const;
659 ObjectValue *objectPrototype() const;
660 ObjectValue *functionPrototype() const;
661 ObjectValue *numberPrototype() const;
662 ObjectValue *booleanPrototype() const;
663 ObjectValue *stringPrototype() const;
664 ObjectValue *arrayPrototype() const;
665 ObjectValue *datePrototype() const;
666 ObjectValue *regexpPrototype() const;
669 const FunctionValue *objectCtor() const;
670 const FunctionValue *functionCtor() const;
671 const FunctionValue *arrayCtor() const;
672 const FunctionValue *stringCtor() const;
673 const FunctionValue *booleanCtor() const;
674 const FunctionValue *numberCtor() const;
675 const FunctionValue *dateCtor() const;
676 const FunctionValue *regexpCtor() const;
679 const Value *convertToBoolean(const Value *value);
680 const Value *convertToNumber(const Value *value);
681 const Value *convertToString(const Value *value);
682 const Value *convertToObject(const Value *value);
683 QString typeId(const Value *value);
686 CppQmlTypes &cppQmlTypes()
687 { return _cppQmlTypes; }
688 const CppQmlTypes &cppQmlTypes() const
689 { return _cppQmlTypes; }
691 void registerValue(Value *value); // internal
694 void initializePrototypes();
696 void addFunction(ObjectValue *object, const QString &name, const Value *result, int argumentCount);
697 void addFunction(ObjectValue *object, const QString &name, int argumentCount);
700 ObjectValue *_objectPrototype;
701 ObjectValue *_functionPrototype;
702 ObjectValue *_numberPrototype;
703 ObjectValue *_booleanPrototype;
704 ObjectValue *_stringPrototype;
705 ObjectValue *_arrayPrototype;
706 ObjectValue *_datePrototype;
707 ObjectValue *_regexpPrototype;
709 Function *_objectCtor;
710 Function *_functionCtor;
711 Function *_arrayCtor;
712 Function *_stringCtor;
713 Function *_booleanCtor;
714 Function *_numberCtor;
716 Function *_regexpCtor;
718 ObjectValue *_globalObject;
719 ObjectValue *_mathObject;
720 ObjectValue *_qtObject;
721 ObjectValue *_qmlKeysObject;
723 NullValue _nullValue;
724 UndefinedValue _undefinedValue;
725 NumberValue _numberValue;
726 BooleanValue _booleanValue;
727 StringValue _stringValue;
728 ColorValue _colorValue;
729 AnchorLineValue _anchorLineValue;
730 QList<Value *> _registeredValues;
732 ConvertToNumber _convertToNumber;
733 ConvertToString _convertToString;
734 ConvertToObject _convertToObject;
737 CppQmlTypes _cppQmlTypes;
742 class QMLJS_EXPORT QmlPrototypeReference: public Reference
745 QmlPrototypeReference(AST::UiQualifiedId *qmlTypeName, const Document *doc, Engine *engine);
746 virtual ~QmlPrototypeReference();
748 AST::UiQualifiedId *qmlTypeName() const;
751 virtual const Value *value(Context *context) const;
753 AST::UiQualifiedId *_qmlTypeName;
754 const Document *_doc;
757 class QMLJS_EXPORT ASTVariableReference: public Reference
759 AST::VariableDeclaration *_ast;
762 ASTVariableReference(AST::VariableDeclaration *ast, Engine *engine);
763 virtual ~ASTVariableReference();
766 virtual const Value *value(Context *context) const;
769 class QMLJS_EXPORT ASTFunctionValue: public FunctionValue
771 AST::FunctionDeclaration *_ast;
772 QList<NameId *> _argumentNames;
775 ASTFunctionValue(AST::FunctionDeclaration *ast, Engine *engine);
776 virtual ~ASTFunctionValue();
778 AST::FunctionDeclaration *ast() const;
780 virtual const Value *returnValue() const;
781 virtual int argumentCount() const;
782 virtual const Value *argument(int) const;
783 virtual QString argumentName(int index) const;
784 virtual bool isVariadic() const;
787 class QMLJS_EXPORT ASTPropertyReference: public Reference
789 AST::UiPublicMember *_ast;
790 const Document *_doc;
791 QString _onChangedSlotName;
794 ASTPropertyReference(AST::UiPublicMember *ast, const Document *doc, Engine *engine);
795 virtual ~ASTPropertyReference();
797 AST::UiPublicMember *ast() const { return _ast; }
798 QString onChangedSlotName() const { return _onChangedSlotName; }
800 virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
803 virtual const Value *value(Context *context) const;
806 class QMLJS_EXPORT ASTSignalReference: public Reference
808 AST::UiPublicMember *_ast;
809 const Document *_doc;
813 ASTSignalReference(AST::UiPublicMember *ast, const Document *doc, Engine *engine);
814 virtual ~ASTSignalReference();
816 AST::UiPublicMember *ast() const { return _ast; }
817 QString slotName() const { return _slotName; }
819 virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
822 virtual const Value *value(Context *context) const;
825 class QMLJS_EXPORT ASTObjectValue: public ObjectValue
827 AST::UiQualifiedId *_typeName;
828 AST::UiObjectInitializer *_initializer;
829 const Document *_doc;
830 QList<ASTPropertyReference *> _properties;
831 QList<ASTSignalReference *> _signals;
832 ASTPropertyReference *_defaultPropertyRef;
835 ASTObjectValue(AST::UiQualifiedId *typeName,
836 AST::UiObjectInitializer *initializer,
839 virtual ~ASTObjectValue();
841 bool getSourceLocation(QString *fileName, int *line, int *column) const;
842 virtual void processMembers(MemberProcessor *processor) const;
844 QString defaultPropertyName() const;
847 } } // end of namespace QmlJS::Interpreter
849 #endif // QMLJS_INTERPRETER_H