/**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** ** This file is part of the QtQml module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QQMLCOMPILER_P_H #define QQMLCOMPILER_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "qqml.h" #include "qqmlerror.h" #include #include "qqmlinstruction_p.h" #include "qqmlscript_p.h" #include "qqmlengine_p.h" #include #include "qqmlpropertycache_p.h" #include "qqmlintegercache_p.h" #include "qqmltypenamecache_p.h" #include "qqmltypeloader_p.h" #include #include #include QT_BEGIN_NAMESPACE class QQmlEngine; class QQmlComponent; class QQmlContext; class QQmlContextData; class Q_AUTOTEST_EXPORT QQmlCompiledData : public QQmlRefCount, public QQmlCleanup { public: QQmlCompiledData(QQmlEngine *engine); virtual ~QQmlCompiledData(); QQmlEngine *engine; QString name; QUrl url; QQmlTypeNameCache *importCache; struct TypeReference { TypeReference() : type(0), typePropertyCache(0), component(0) {} QString className; QQmlType *type; QQmlPropertyCache *typePropertyCache; QQmlCompiledData *component; const QMetaObject *metaObject() const; QQmlPropertyCache *propertyCache() const; QQmlPropertyCache *createPropertyCache(QQmlEngine *); }; QList types; struct V8Program { V8Program(const QByteArray &p, QQmlCompiledData *c) : program(p), cdata(c) {} QByteArray program; v8::Persistent bindings; QQmlCompiledData *cdata; }; QList programs; const QMetaObject *root; QAbstractDynamicMetaObject rootData; QQmlPropertyCache *rootPropertyCache; QList primitives; QList datas; QByteArray bytecode; QList propertyCaches; QList contextCaches; QList scripts; QList urls; struct Instruction { #define QML_INSTR_DATA_TYPEDEF(I, FMT) typedef QQmlInstructionData I; FOR_EACH_QML_INSTR(QML_INSTR_DATA_TYPEDEF) #undef QML_INSTR_DATA_TYPEDEF private: Instruction(); }; void dumpInstructions(); template int addInstruction(const QQmlInstructionData &data) { QQmlInstruction genericInstr; QQmlInstructionMeta::setData(genericInstr, data); return addInstructionHelper(static_cast(Instr), genericInstr); } int nextInstructionIndex(); QQmlInstruction *instruction(int index); QQmlInstruction::Type instructionType(const QQmlInstruction *instr); bool isInitialized() const { return hasEngine(); } void initialize(QQmlEngine *); protected: virtual void destroy(); // From QQmlRefCount virtual void clear(); // From QQmlCleanup private: friend class QQmlCompiler; int addInstructionHelper(QQmlInstruction::Type type, QQmlInstruction &instr); void dump(QQmlInstruction *, int idx = -1); QQmlCompiledData(const QQmlCompiledData &other); QQmlCompiledData &operator=(const QQmlCompiledData &other); QByteArray packData; int pack(const char *, size_t); int indexForString(const QString &); int indexForByteArray(const QByteArray &); int indexForUrl(const QUrl &); }; namespace QQmlCompilerTypes { struct BindingContext { BindingContext() : stack(0), owner(0), object(0) {} BindingContext(QQmlScript::Object *o) : stack(0), owner(0), object(o) {} BindingContext incr() const { BindingContext rv(object); rv.stack = stack + 1; return rv; } bool isSubContext() const { return stack != 0; } int stack; int owner; QQmlScript::Object *object; }; struct BindingReference { enum DataType { QtScript, V4, V8, Tr, TrId }; DataType dataType; }; struct JSBindingReference : public QQmlPool::Class, public BindingReference { JSBindingReference() : nextReference(0) {} QQmlScript::Variant expression; QQmlScript::Property *property; QQmlScript::Value *value; int compiledIndex; QString rewrittenExpression; BindingContext bindingContext; JSBindingReference *nextReference; }; struct TrBindingReference : public QQmlPool::POD, public BindingReference { QStringRef text; QStringRef comment; int n; }; struct IdList : public QFieldList { QQmlScript::Object *value(const QString &id) const { for (QQmlScript::Object *o = first(); o; o = next(o)) { if (o->id == id) return o; } return 0; } }; struct DepthStack { DepthStack() : _depth(0), _maxDepth(0) {} DepthStack(const DepthStack &o) : _depth(o._depth), _maxDepth(o._maxDepth) {} DepthStack &operator=(const DepthStack &o) { _depth = o._depth; _maxDepth = o._maxDepth; return *this; } int depth() const { return _depth; } int maxDepth() const { return _maxDepth; } void push() { ++_depth; _maxDepth = qMax(_depth, _maxDepth); } void pop() { --_depth; Q_ASSERT(_depth >= 0); Q_ASSERT(_maxDepth > _depth); } void pushPop(int count) { _maxDepth = qMax(_depth + count, _maxDepth); } private: int _depth; int _maxDepth; }; // Contains all the incremental compiler state about a component. As // a single QML file can have multiple components defined, there may be // more than one of these for each compile struct ComponentCompileState : public QQmlPool::Class { ComponentCompileState() : parserStatusCount(0), totalBindingsCount(0), pushedProperties(0), nested(false), v8BindingProgramLine(-1), root(0) {} IdList ids; int parserStatusCount; int totalBindingsCount; int pushedProperties; bool nested; QByteArray compiledBindingData; QByteArray v8BindingProgram; int v8BindingProgramLine; DepthStack objectDepth; DepthStack listDepth; typedef QQmlCompilerTypes::JSBindingReference B; typedef QFieldList JSBindingReferenceList; JSBindingReferenceList bindings; typedef QQmlScript::Object O; typedef QFieldList AliasingObjectsList; AliasingObjectsList aliasingObjects; QQmlScript::Object *root; }; }; class QMetaObjectBuilder; class Q_AUTOTEST_EXPORT QQmlCompiler { Q_DECLARE_TR_FUNCTIONS(QQmlCompiler) public: QQmlCompiler(QQmlPool *); bool compile(QQmlEngine *, QQmlTypeData *, QQmlCompiledData *); bool isError() const; QList errors() const; static bool isAttachedPropertyName(const QString &); static bool isSignalPropertyName(const QString &); static bool isAttachedPropertyName(const QHashedStringRef &); static bool isSignalPropertyName(const QHashedStringRef &); int evaluateEnum(const QByteArray& script) const; // for QQmlCustomParser::evaluateEnum const QMetaObject *resolveType(const QString& name) const; // for QQmlCustomParser::resolveType int rewriteBinding(const QQmlScript::Variant& value, const QString& name); // for QQmlCustomParser::rewriteBinding QString rewriteSignalHandler(const QQmlScript::Variant& value, const QString &name); // for QQmlCustomParser::rewriteSignalHandler private: typedef QQmlCompiledData::Instruction Instruction; static void reset(QQmlCompiledData *); void compileTree(QQmlScript::Object *tree); bool buildObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); bool buildComponent(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); bool buildSubObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); bool buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); bool buildProperty(QQmlScript::Property *prop, QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); bool buildPropertyInNamespace(QQmlImportedNamespace *ns, QQmlScript::Property *prop, QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); bool buildIdProperty(QQmlScript::Property *prop, QQmlScript::Object *obj); bool buildAttachedProperty(QQmlScript::Property *prop, QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &ctxt); bool buildGroupedProperty(QQmlScript::Property *prop, QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &ctxt); bool buildValueTypeProperty(QObject *type, QQmlScript::Object *obj, QQmlScript::Object *baseObj, const QQmlCompilerTypes::BindingContext &ctxt); bool buildListProperty(QQmlScript::Property *prop, QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &ctxt); bool buildScriptStringProperty(QQmlScript::Property *prop, QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &ctxt); bool buildPropertyAssignment(QQmlScript::Property *prop, QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &ctxt); bool buildPropertyObjectAssignment(QQmlScript::Property *prop, QQmlScript::Object *obj, QQmlScript::Value *value, const QQmlCompilerTypes::BindingContext &ctxt); bool buildPropertyOnAssignment(QQmlScript::Property *prop, QQmlScript::Object *obj, QQmlScript::Object *baseObj, QQmlScript::Value *value, const QQmlCompilerTypes::BindingContext &ctxt); bool buildPropertyLiteralAssignment(QQmlScript::Property *prop, QQmlScript::Object *obj, QQmlScript::Value *value, const QQmlCompilerTypes::BindingContext &ctxt); bool doesPropertyExist(QQmlScript::Property *prop, QQmlScript::Object *obj); bool testLiteralAssignment(QQmlScript::Property *prop, QQmlScript::Value *value); bool testQualifiedEnumAssignment(QQmlScript::Property *prop, QQmlScript::Object *obj, QQmlScript::Value *value, bool *isAssignment); enum DynamicMetaMode { IgnoreAliases, ResolveAliases, ForceCreation }; bool mergeDynamicMetaProperties(QQmlScript::Object *obj); bool buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mode); bool checkDynamicMeta(QQmlScript::Object *obj); bool buildBinding(QQmlScript::Value *, QQmlScript::Property *prop, const QQmlCompilerTypes::BindingContext &ctxt); bool buildLiteralBinding(QQmlScript::Value *, QQmlScript::Property *prop, const QQmlCompilerTypes::BindingContext &ctxt); bool buildComponentFromRoot(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &); bool compileAlias(QFastMetaBuilder &, QByteArray &data, QQmlScript::Object *obj, int propIndex, int aliasIndex, QQmlScript::Object::DynamicProperty &); bool completeComponentBuild(); bool checkValidId(QQmlScript::Value *, const QString &); void genObject(QQmlScript::Object *obj); void genObjectBody(QQmlScript::Object *obj); void genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Property *); void genComponent(QQmlScript::Object *obj); void genValueProperty(QQmlScript::Property *prop, QQmlScript::Object *obj); void genListProperty(QQmlScript::Property *prop, QQmlScript::Object *obj); void genPropertyAssignment(QQmlScript::Property *prop, QQmlScript::Object *obj, QQmlScript::Property *valueTypeProperty = 0); void genLiteralAssignment(QQmlScript::Property *prop, QQmlScript::Value *value); void genBindingAssignment(QQmlScript::Value *binding, QQmlScript::Property *prop, QQmlScript::Object *obj, QQmlScript::Property *valueTypeProperty = 0); int genContextCache(); QQmlPropertyData genValueTypeData(QQmlScript::Property *prop, QQmlScript::Property *valueTypeProp); int componentTypeRef(); int translationContextIndex(); static QQmlType *toQmlType(QQmlScript::Object *from); bool canCoerce(int to, QQmlScript::Object *from); QString elementName(QQmlScript::Object *); QStringList deferredProperties(QQmlScript::Object *); QQmlPropertyData *property(QQmlScript::Object *, int); QQmlPropertyData *property(QQmlScript::Object *, const QHashedStringRef &, bool *notInRevision = 0); QQmlPropertyData *signal(QQmlScript::Object *, const QHashedStringRef &, bool *notInRevision = 0); int indexOfProperty(QQmlScript::Object *, const QHashedStringRef &, bool *notInRevision = 0); int indexOfProperty(QQmlScript::Object *, const QString &, bool *notInRevision = 0); int indexOfSignal(QQmlScript::Object *, const QString &, bool *notInRevision = 0); void addId(const QString &, QQmlScript::Object *); void dumpStats(); void addBindingReference(QQmlCompilerTypes::JSBindingReference *); QQmlCompilerTypes::ComponentCompileState *compileState; QQmlPool *pool; QQmlCompilerTypes::ComponentCompileState *componentState(QQmlScript::Object *); void saveComponentState(); QList exceptions; QQmlCompiledData *output; QQmlEngine *engine; QQmlEnginePrivate *enginePrivate; QQmlScript::Object *unitRoot; QQmlTypeData *unit; int cachedComponentTypeRef; int cachedTranslationContextIndex; // Compiler component statistics. Only collected if QML_COMPILER_STATS=1 struct ComponentStat { ComponentStat() : ids(0), objects(0) {} int lineNumber; int ids; QList scriptBindings; QList optimizedBindings; int objects; }; struct ComponentStats : public QQmlPool::Class { ComponentStat componentStat; QList savedComponentStats; }; ComponentStats *componentStats; }; QT_END_NAMESPACE #endif // QQMLCOMPILER_P_H