1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #ifndef QQMLCOMPILER_P_H
43 #define QQMLCOMPILER_P_H
49 // This file is not part of the Qt API. It exists purely as an
50 // implementation detail. This header file may change from version to
51 // version without notice, or even be removed.
57 #include "qqmlerror.h"
58 #include <private/qv8_p.h>
59 #include "qqmlinstruction_p.h"
60 #include "qqmlscript_p.h"
61 #include "qqmlengine_p.h"
62 #include <private/qbitfield_p.h>
63 #include "qqmlpropertycache_p.h"
64 #include "qqmlintegercache_p.h"
65 #include "qqmltypenamecache_p.h"
66 #include "qqmltypeloader_p.h"
68 #include <QtCore/qbytearray.h>
69 #include <QtCore/qset.h>
70 #include <QtCore/QCoreApplication>
77 class QQmlContextData;
79 class Q_AUTOTEST_EXPORT QQmlCompiledData : public QQmlRefCount, public QQmlCleanup
82 QQmlCompiledData(QQmlEngine *engine);
83 virtual ~QQmlCompiledData();
89 QQmlTypeNameCache *importCache;
93 bool isRegisteredWithEngine;
98 : type(0), typePropertyCache(0), component(0) {}
101 QQmlPropertyCache *typePropertyCache;
102 QQmlCompiledData *component;
104 QQmlPropertyCache *propertyCache() const;
105 QQmlPropertyCache *createPropertyCache(QQmlEngine *);
107 QList<TypeReference> types;
110 V8Program(const QByteArray &p, QQmlCompiledData *c)
111 : program(p), cdata(c) {}
114 v8::Persistent<v8::Array> bindings;
115 QQmlCompiledData *cdata;
118 QList<V8Program> programs;
120 QQmlPropertyCache *rootPropertyCache;
121 QList<QString> primitives;
122 QList<QByteArray> datas;
124 QList<QQmlPropertyCache *> propertyCaches;
125 QList<QQmlIntegerCache *> contextCaches;
126 QList<QQmlScriptData *> scripts;
130 #define QML_INSTR_DATA_TYPEDEF(I, FMT) typedef QQmlInstructionData<QQmlInstruction::I> I;
131 FOR_EACH_QML_INSTR(QML_INSTR_DATA_TYPEDEF)
132 #undef QML_INSTR_DATA_TYPEDEF
137 void dumpInstructions();
140 int addInstruction(const QQmlInstructionData<Instr> &data)
142 QQmlInstruction genericInstr;
143 QQmlInstructionMeta<Instr>::setData(genericInstr, data);
144 return addInstructionHelper(static_cast<QQmlInstruction::Type>(Instr), genericInstr);
146 int nextInstructionIndex();
147 QQmlInstruction *instruction(int index);
148 QQmlInstruction::Type instructionType(const QQmlInstruction *instr);
150 bool isInitialized() const { return hasEngine(); }
151 void initialize(QQmlEngine *);
154 virtual void destroy(); // From QQmlRefCount
155 virtual void clear(); // From QQmlCleanup
158 friend class QQmlCompiler;
160 int addInstructionHelper(QQmlInstruction::Type type, QQmlInstruction &instr);
161 void dump(QQmlInstruction *, int idx = -1);
162 QQmlCompiledData(const QQmlCompiledData &other);
163 QQmlCompiledData &operator=(const QQmlCompiledData &other);
165 int indexForString(const QString &);
166 int indexForByteArray(const QByteArray &);
167 int indexForUrl(const QUrl &);
170 namespace QQmlCompilerTypes {
171 struct BindingContext
174 : stack(0), owner(0), object(0) {}
175 BindingContext(QQmlScript::Object *o)
176 : stack(0), owner(0), object(o) {}
177 BindingContext incr() const {
178 BindingContext rv(object);
179 rv.stack = stack + 1;
182 bool isSubContext() const { return stack != 0; }
185 QQmlScript::Object *object;
188 struct BindingReference
190 enum DataType { QtScript, V4, V8,
195 struct JSBindingReference : public QQmlPool::Class,
196 public BindingReference
198 JSBindingReference() : nextReference(0) {}
200 QQmlScript::Variant expression;
201 QQmlScript::Property *property;
202 QQmlScript::Value *value;
204 int compiledIndex:15;
207 QString rewrittenExpression;
208 BindingContext bindingContext;
210 JSBindingReference *nextReference;
213 struct TrBindingReference : public QQmlPool::POD,
214 public BindingReference
221 struct IdList : public QFieldList<QQmlScript::Object,
222 &QQmlScript::Object::nextIdObject>
224 QQmlScript::Object *value(const QString &id) const {
225 for (QQmlScript::Object *o = first(); o; o = next(o)) {
234 DepthStack() : _depth(0), _maxDepth(0) {}
235 DepthStack(const DepthStack &o) : _depth(o._depth), _maxDepth(o._maxDepth) {}
236 DepthStack &operator=(const DepthStack &o) { _depth = o._depth; _maxDepth = o._maxDepth; return *this; }
238 int depth() const { return _depth; }
239 int maxDepth() const { return _maxDepth; }
241 void push() { ++_depth; _maxDepth = qMax(_depth, _maxDepth); }
242 void pop() { --_depth; Q_ASSERT(_depth >= 0); Q_ASSERT(_maxDepth > _depth); }
244 void pushPop(int count) { _maxDepth = qMax(_depth + count, _maxDepth); }
250 // Contains all the incremental compiler state about a component. As
251 // a single QML file can have multiple components defined, there may be
252 // more than one of these for each compile
253 struct ComponentCompileState : public QQmlPool::Class
255 ComponentCompileState()
256 : parserStatusCount(0), totalBindingsCount(0), pushedProperties(0), nested(false),
257 v8BindingProgramLine(-1), root(0) {}
260 int parserStatusCount;
261 int totalBindingsCount;
262 int pushedProperties;
265 QByteArray compiledBindingData;
266 QByteArray v8BindingProgram;
267 int v8BindingProgramLine;
269 DepthStack objectDepth;
270 DepthStack listDepth;
272 typedef QQmlCompilerTypes::JSBindingReference B;
273 typedef QFieldList<B, &B::nextReference> JSBindingReferenceList;
274 JSBindingReferenceList bindings;
275 typedef QQmlScript::Object O;
276 typedef QFieldList<O, &O::nextAliasingObject> AliasingObjectsList;
277 AliasingObjectsList aliasingObjects;
278 QQmlScript::Object *root;
282 class QMetaObjectBuilder;
283 class Q_AUTOTEST_EXPORT QQmlCompiler
285 Q_DECLARE_TR_FUNCTIONS(QQmlCompiler)
287 QQmlCompiler(QQmlPool *);
289 bool compile(QQmlEngine *, QQmlTypeData *, QQmlCompiledData *);
291 bool isError() const;
292 QList<QQmlError> errors() const;
294 static bool isAttachedPropertyName(const QString &);
295 static bool isSignalPropertyName(const QString &);
296 static bool isAttachedPropertyName(const QHashedStringRef &);
297 static bool isSignalPropertyName(const QHashedStringRef &);
299 int evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue, bool *ok) const; // for QQmlCustomParser::evaluateEnum
300 const QMetaObject *resolveType(const QString& name) const; // for QQmlCustomParser::resolveType
301 int rewriteBinding(const QQmlScript::Variant& value, const QString& name); // for QQmlCustomParser::rewriteBinding
302 QString rewriteSignalHandler(const QQmlScript::Variant& value, const QString &name); // for QQmlCustomParser::rewriteSignalHandler
305 typedef QQmlCompiledData::Instruction Instruction;
307 static void reset(QQmlCompiledData *);
309 void compileTree(QQmlScript::Object *tree);
312 bool buildObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
313 bool buildComponent(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
314 bool buildSubObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
315 bool buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj,
316 const QQmlCompilerTypes::BindingContext &);
317 bool buildProperty(QQmlScript::Property *prop, QQmlScript::Object *obj,
318 const QQmlCompilerTypes::BindingContext &);
319 bool buildPropertyInNamespace(QQmlImportNamespace *ns,
320 QQmlScript::Property *prop,
321 QQmlScript::Object *obj,
322 const QQmlCompilerTypes::BindingContext &);
323 bool buildIdProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
324 bool buildAttachedProperty(QQmlScript::Property *prop,
325 QQmlScript::Object *obj,
326 const QQmlCompilerTypes::BindingContext &ctxt);
327 bool buildGroupedProperty(QQmlScript::Property *prop,
328 QQmlScript::Object *obj,
329 const QQmlCompilerTypes::BindingContext &ctxt);
330 bool buildValueTypeProperty(QObject *type,
331 QQmlScript::Object *obj,
332 QQmlScript::Object *baseObj,
333 const QQmlCompilerTypes::BindingContext &ctxt);
334 bool buildListProperty(QQmlScript::Property *prop,
335 QQmlScript::Object *obj,
336 const QQmlCompilerTypes::BindingContext &ctxt);
337 bool buildScriptStringProperty(QQmlScript::Property *prop,
338 QQmlScript::Object *obj,
339 const QQmlCompilerTypes::BindingContext &ctxt);
340 bool buildPropertyAssignment(QQmlScript::Property *prop,
341 QQmlScript::Object *obj,
342 const QQmlCompilerTypes::BindingContext &ctxt);
343 bool buildPropertyObjectAssignment(QQmlScript::Property *prop,
344 QQmlScript::Object *obj,
345 QQmlScript::Value *value,
346 const QQmlCompilerTypes::BindingContext &ctxt);
347 bool buildPropertyOnAssignment(QQmlScript::Property *prop,
348 QQmlScript::Object *obj,
349 QQmlScript::Object *baseObj,
350 QQmlScript::Value *value,
351 const QQmlCompilerTypes::BindingContext &ctxt);
352 bool buildPropertyLiteralAssignment(QQmlScript::Property *prop,
353 QQmlScript::Object *obj,
354 QQmlScript::Value *value,
355 const QQmlCompilerTypes::BindingContext &ctxt);
356 bool doesPropertyExist(QQmlScript::Property *prop, QQmlScript::Object *obj);
357 bool testLiteralAssignment(QQmlScript::Property *prop,
358 QQmlScript::Value *value);
359 bool testQualifiedEnumAssignment(QQmlScript::Property *prop,
360 QQmlScript::Object *obj,
361 QQmlScript::Value *value,
363 enum DynamicMetaMode { Normal, ForceCreation };
364 bool mergeDynamicMetaProperties(QQmlScript::Object *obj);
365 bool buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mode);
366 bool buildDynamicMetaAliases(QQmlScript::Object *obj);
367 bool checkDynamicMeta(QQmlScript::Object *obj);
368 bool buildBinding(QQmlScript::Value *, QQmlScript::Property *prop,
369 const QQmlCompilerTypes::BindingContext &ctxt);
370 bool buildLiteralBinding(QQmlScript::Value *, QQmlScript::Property *prop,
371 const QQmlCompilerTypes::BindingContext &ctxt);
372 bool buildComponentFromRoot(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
373 bool completeComponentBuild();
374 bool checkValidId(QQmlScript::Value *, const QString &);
377 void genObject(QQmlScript::Object *obj, bool parentToSuper = false);
378 void genObjectBody(QQmlScript::Object *obj);
379 void genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Property *);
380 void genComponent(QQmlScript::Object *obj);
381 void genValueProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
382 void genListProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
383 void genPropertyAssignment(QQmlScript::Property *prop,
384 QQmlScript::Object *obj,
385 QQmlScript::Property *valueTypeProperty = 0);
386 void genLiteralAssignment(QQmlScript::Property *prop,
387 QQmlScript::Value *value);
388 void genBindingAssignment(QQmlScript::Value *binding,
389 QQmlScript::Property *prop,
390 QQmlScript::Object *obj,
391 QQmlScript::Property *valueTypeProperty = 0);
392 int genContextCache();
394 QQmlPropertyData genValueTypeData(QQmlScript::Property *prop,
395 QQmlScript::Property *valueTypeProp);
397 int componentTypeRef();
398 int translationContextIndex();
400 QQmlType *toQmlType(QQmlScript::Object *from);
401 bool canCoerce(int to, QQmlScript::Object *from);
403 QString elementName(QQmlScript::Object *);
405 QStringList deferredProperties(QQmlScript::Object *);
407 QQmlPropertyCache *propertyCacheForObject(QQmlScript::Object *);
408 QQmlPropertyData *property(QQmlScript::Object *, int);
409 QQmlPropertyData *property(QQmlScript::Object *, const QHashedStringRef &,
410 bool *notInRevision = 0);
411 QQmlPropertyData *signal(QQmlScript::Object *, const QHashedStringRef &,
412 bool *notInRevision = 0);
413 int indexOfProperty(QQmlScript::Object *, const QHashedStringRef &, bool *notInRevision = 0);
414 int indexOfProperty(QQmlScript::Object *, const QString &, bool *notInRevision = 0);
415 int indexOfSignal(QQmlScript::Object *, const QString &, bool *notInRevision = 0);
417 void addId(const QString &, QQmlScript::Object *);
421 void addBindingReference(QQmlCompilerTypes::JSBindingReference *);
423 QQmlCompilerTypes::ComponentCompileState *compileState;
427 QQmlCompilerTypes::ComponentCompileState *componentState(QQmlScript::Object *);
428 void saveComponentState();
430 QList<QQmlError> exceptions;
431 QQmlCompiledData *output;
433 QQmlEnginePrivate *enginePrivate;
434 QQmlScript::Object *unitRoot;
436 int cachedComponentTypeRef;
437 int cachedTranslationContextIndex;
439 // Compiler component statistics. Only collected if QML_COMPILER_STATS=1
442 ComponentStat() : lineNumber(0), ids(0), objects(0) {}
447 QList<QQmlScript::LocationSpan> scriptBindings;
448 QList<QQmlScript::LocationSpan> sharedBindings;
449 QList<QQmlScript::LocationSpan> optimizedBindings;
452 struct ComponentStats : public QQmlPool::Class
454 ComponentStat componentStat;
455 QList<ComponentStat> savedComponentStats;
457 ComponentStats *componentStats;
462 #endif // QQMLCOMPILER_P_H