Docs - add missing images and code, clean up sections
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlcompiler_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QQMLCOMPILER_P_H
43 #define QQMLCOMPILER_P_H
44
45 //
46 //  W A R N I N G
47 //  -------------
48 //
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.
52 //
53 // We mean it.
54 //
55
56 #include "qqml.h"
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"
67
68 #include <QtCore/qbytearray.h>
69 #include <QtCore/qset.h>
70 #include <QtCore/QCoreApplication>
71
72 QT_BEGIN_NAMESPACE
73
74 class QQmlEngine;
75 class QQmlComponent;
76 class QQmlContext;
77 class QQmlContextData;
78
79 class Q_AUTOTEST_EXPORT QQmlCompiledData : public QQmlRefCount, public QQmlCleanup
80 {
81 public:
82     QQmlCompiledData(QQmlEngine *engine);
83     virtual ~QQmlCompiledData();
84
85     QQmlEngine *engine;
86
87     QString name;
88     QUrl url;
89     QQmlTypeNameCache *importCache;
90
91     int metaTypeId;
92     int listMetaTypeId;
93     bool isRegisteredWithEngine;
94
95     struct TypeReference 
96     {
97         TypeReference()
98         : type(0), typePropertyCache(0), component(0) {}
99
100         QQmlType *type;
101         QQmlPropertyCache *typePropertyCache;
102         QQmlCompiledData *component;
103
104         QQmlPropertyCache *propertyCache() const;
105         QQmlPropertyCache *createPropertyCache(QQmlEngine *);
106     };
107     QList<TypeReference> types;
108
109     struct V8Program {
110         V8Program(const QByteArray &p, QQmlCompiledData *c)
111         : program(p), cdata(c) {}
112
113         QByteArray program;
114         v8::Persistent<v8::Array> bindings;
115         QQmlCompiledData *cdata;
116     };
117
118     QList<V8Program> programs;
119
120     QQmlPropertyCache *rootPropertyCache;
121     QList<QString> primitives;
122     QList<QByteArray> datas;
123     QByteArray bytecode;
124     QList<QQmlPropertyCache *> propertyCaches;
125     QList<QQmlIntegerCache *> contextCaches;
126     QList<QQmlScriptData *> scripts;
127     QList<QUrl> urls;
128
129     struct Instruction {
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
133     private:
134         Instruction();
135     };
136
137     void dumpInstructions();
138
139     template <int Instr>
140     int addInstruction(const QQmlInstructionData<Instr> &data)
141     {
142         QQmlInstruction genericInstr;
143         QQmlInstructionMeta<Instr>::setData(genericInstr, data);
144         return addInstructionHelper(static_cast<QQmlInstruction::Type>(Instr), genericInstr);
145     }
146     int nextInstructionIndex();
147     QQmlInstruction *instruction(int index);
148     QQmlInstruction::Type instructionType(const QQmlInstruction *instr);
149
150     bool isInitialized() const { return hasEngine(); }
151     void initialize(QQmlEngine *);
152
153 protected:
154     virtual void destroy(); // From QQmlRefCount
155     virtual void clear(); // From QQmlCleanup
156
157 private:
158     friend class QQmlCompiler;
159
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);
164
165     int indexForString(const QString &);
166     int indexForByteArray(const QByteArray &);
167     int indexForUrl(const QUrl &);
168 };
169
170 namespace QQmlCompilerTypes {
171     struct BindingContext 
172     {
173         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;
180             return rv;
181         }
182         bool isSubContext() const { return stack != 0; }
183         int stack;
184         int owner;
185         QQmlScript::Object *object;
186     };
187
188     struct BindingReference
189     {
190         enum DataType { QtScript, V4, V8,
191                         Tr, TrId };
192         DataType dataType;
193     };
194
195     struct JSBindingReference : public QQmlPool::Class,
196                                 public BindingReference
197     {
198         JSBindingReference() : nextReference(0) {}
199
200         QQmlScript::Variant expression;
201         QQmlScript::Property *property;
202         QQmlScript::Value *value;
203
204         int compiledIndex:15;
205         int sharedIndex:15;
206
207         QString rewrittenExpression;
208         BindingContext bindingContext;
209
210         JSBindingReference *nextReference;
211     };
212
213     struct TrBindingReference : public QQmlPool::POD,
214                                 public BindingReference
215     {
216         QStringRef text;
217         QStringRef comment;
218         int n;
219     };
220
221     struct IdList : public QFieldList<QQmlScript::Object, 
222                                       &QQmlScript::Object::nextIdObject>
223     {
224         QQmlScript::Object *value(const QString &id) const {
225             for (QQmlScript::Object *o = first(); o; o = next(o)) {
226                 if (o->id == id)
227                     return o;
228             }
229             return 0;
230         }
231     };
232
233     struct DepthStack {
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; }
237
238         int depth() const { return _depth; }
239         int maxDepth() const { return _maxDepth; }
240
241         void push() { ++_depth; _maxDepth = qMax(_depth, _maxDepth); }
242         void pop() { --_depth; Q_ASSERT(_depth >= 0); Q_ASSERT(_maxDepth > _depth); }
243
244         void pushPop(int count) { _maxDepth = qMax(_depth + count, _maxDepth); }
245     private:
246         int _depth;
247         int _maxDepth;
248     };
249
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
254     {
255         ComponentCompileState() 
256         : parserStatusCount(0), totalBindingsCount(0), pushedProperties(0), nested(false), 
257           v8BindingProgramLine(-1), root(0) {}
258
259         IdList ids;
260         int parserStatusCount;
261         int totalBindingsCount;
262         int pushedProperties;
263         bool nested;
264
265         QByteArray compiledBindingData;
266         QByteArray v8BindingProgram;
267         int v8BindingProgramLine;
268
269         DepthStack objectDepth;
270         DepthStack listDepth;
271
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;
279     };
280 };
281
282 class QMetaObjectBuilder;
283 class Q_AUTOTEST_EXPORT QQmlCompiler
284 {
285     Q_DECLARE_TR_FUNCTIONS(QQmlCompiler)
286 public:
287     QQmlCompiler(QQmlPool *);
288
289     bool compile(QQmlEngine *, QQmlTypeData *, QQmlCompiledData *);
290
291     bool isError() const;
292     QList<QQmlError> errors() const;
293
294     static bool isAttachedPropertyName(const QString &);
295     static bool isSignalPropertyName(const QString &);
296     static bool isAttachedPropertyName(const QHashedStringRef &);
297     static bool isSignalPropertyName(const QHashedStringRef &);
298
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
303
304 private:
305     typedef QQmlCompiledData::Instruction Instruction;
306
307     static void reset(QQmlCompiledData *);
308
309     void compileTree(QQmlScript::Object *tree);
310
311
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,
362                                      bool *isAssignment);
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 &);
375
376
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();
393
394     QQmlPropertyData genValueTypeData(QQmlScript::Property *prop,
395                                               QQmlScript::Property *valueTypeProp);
396
397     int componentTypeRef();
398     int translationContextIndex();
399
400     QQmlType *toQmlType(QQmlScript::Object *from);
401     bool canCoerce(int to, QQmlScript::Object *from);
402
403     QString elementName(QQmlScript::Object *);
404
405     QStringList deferredProperties(QQmlScript::Object *);
406
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);
416
417     void addId(const QString &, QQmlScript::Object *);
418
419     void dumpStats();
420
421     void addBindingReference(QQmlCompilerTypes::JSBindingReference *);
422
423     QQmlCompilerTypes::ComponentCompileState *compileState;
424
425     QQmlPool *pool;
426
427     QQmlCompilerTypes::ComponentCompileState *componentState(QQmlScript::Object *);
428     void saveComponentState();
429
430     QList<QQmlError> exceptions;
431     QQmlCompiledData *output;
432     QQmlEngine *engine;
433     QQmlEnginePrivate *enginePrivate;
434     QQmlScript::Object *unitRoot;
435     QQmlTypeData *unit;
436     int cachedComponentTypeRef;
437     int cachedTranslationContextIndex;
438
439     // Compiler component statistics.  Only collected if QML_COMPILER_STATS=1
440     struct ComponentStat
441     {
442         ComponentStat() : lineNumber(0), ids(0), objects(0) {}
443
444         quint16 lineNumber;
445
446         int ids;
447         QList<QQmlScript::LocationSpan> scriptBindings;
448         QList<QQmlScript::LocationSpan> sharedBindings;
449         QList<QQmlScript::LocationSpan> optimizedBindings;
450         int objects;
451     };
452     struct ComponentStats : public QQmlPool::Class
453     {
454         ComponentStat componentStat;
455         QList<ComponentStat> savedComponentStats;
456     };
457     ComponentStats *componentStats;
458 };
459
460 QT_END_NAMESPACE
461
462 #endif // QQMLCOMPILER_P_H