Improve documentation.
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlcompiler_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** 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.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
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() : isSafe(false), 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         bool isSafe:1;
207
208         QString rewrittenExpression;
209         BindingContext bindingContext;
210
211         JSBindingReference *nextReference;
212     };
213
214     struct TrBindingReference : public QQmlPool::POD,
215                                 public BindingReference
216     {
217         QStringRef text;
218         QStringRef comment;
219         int n;
220     };
221
222     struct IdList : public QFieldList<QQmlScript::Object, 
223                                       &QQmlScript::Object::nextIdObject>
224     {
225         QQmlScript::Object *value(const QString &id) const {
226             for (QQmlScript::Object *o = first(); o; o = next(o)) {
227                 if (o->id == id)
228                     return o;
229             }
230             return 0;
231         }
232     };
233
234     struct DepthStack {
235         DepthStack() : _depth(0), _maxDepth(0) {}
236         DepthStack(const DepthStack &o) : _depth(o._depth), _maxDepth(o._maxDepth) {}
237         DepthStack &operator=(const DepthStack &o) { _depth = o._depth; _maxDepth = o._maxDepth; return *this; }
238
239         int depth() const { return _depth; }
240         int maxDepth() const { return _maxDepth; }
241
242         void push() { ++_depth; _maxDepth = qMax(_depth, _maxDepth); }
243         void pop() { --_depth; Q_ASSERT(_depth >= 0); Q_ASSERT(_maxDepth > _depth); }
244
245         void pushPop(int count) { _maxDepth = qMax(_depth + count, _maxDepth); }
246     private:
247         int _depth;
248         int _maxDepth;
249     };
250
251     // Contains all the incremental compiler state about a component.  As
252     // a single QML file can have multiple components defined, there may be
253     // more than one of these for each compile
254     struct ComponentCompileState : public QQmlPool::Class
255     {
256         ComponentCompileState() 
257         : parserStatusCount(0), totalBindingsCount(0), pushedProperties(0), nested(false), 
258           v8BindingProgramLine(-1), root(0) {}
259
260         IdList ids;
261         int parserStatusCount;
262         int totalBindingsCount;
263         int pushedProperties;
264         bool nested;
265
266         QByteArray compiledBindingData;
267         QByteArray v8BindingProgram;
268         int v8BindingProgramLine;
269
270         DepthStack objectDepth;
271         DepthStack listDepth;
272
273         typedef QQmlCompilerTypes::JSBindingReference B;
274         typedef QFieldList<B, &B::nextReference> JSBindingReferenceList;
275         JSBindingReferenceList bindings;
276         typedef QQmlScript::Object O;
277         typedef QFieldList<O, &O::nextAliasingObject> AliasingObjectsList;
278         AliasingObjectsList aliasingObjects;
279         QQmlScript::Object *root;
280     };
281 };
282
283 class QMetaObjectBuilder;
284 class Q_AUTOTEST_EXPORT QQmlCompiler
285 {
286     Q_DECLARE_TR_FUNCTIONS(QQmlCompiler)
287 public:
288     QQmlCompiler(QQmlPool *);
289
290     bool compile(QQmlEngine *, QQmlTypeData *, QQmlCompiledData *);
291
292     bool isError() const;
293     QList<QQmlError> errors() const;
294
295     static bool isAttachedPropertyName(const QString &);
296     static bool isSignalPropertyName(const QString &);
297     static bool isAttachedPropertyName(const QHashedStringRef &);
298     static bool isSignalPropertyName(const QHashedStringRef &);
299
300     int evaluateEnum(const QHashedStringRef &scope, const QByteArray& enumValue, bool *ok) const; // for QQmlCustomParser::evaluateEnum
301     const QMetaObject *resolveType(const QString& name) const; // for QQmlCustomParser::resolveType
302     int rewriteBinding(const QQmlScript::Variant& value, const QString& name); // for QQmlCustomParser::rewriteBinding
303     QString rewriteSignalHandler(const QQmlScript::Variant& value, const QString &name);  // for QQmlCustomParser::rewriteSignalHandler
304
305 private:
306     typedef QQmlCompiledData::Instruction Instruction;
307
308     static void reset(QQmlCompiledData *);
309
310     void compileTree(QQmlScript::Object *tree);
311
312
313     bool buildObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
314     bool buildComponent(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
315     bool buildSubObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
316     bool buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj, 
317                      const QQmlCompilerTypes::BindingContext &);
318     bool buildProperty(QQmlScript::Property *prop, QQmlScript::Object *obj, 
319                        const QQmlCompilerTypes::BindingContext &);
320     bool buildPropertyInNamespace(QQmlImportNamespace *ns,
321                                   QQmlScript::Property *prop, 
322                                   QQmlScript::Object *obj, 
323                                   const QQmlCompilerTypes::BindingContext &);
324     bool buildIdProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
325     bool buildAttachedProperty(QQmlScript::Property *prop, 
326                                QQmlScript::Object *obj,
327                                const QQmlCompilerTypes::BindingContext &ctxt);
328     bool buildGroupedProperty(QQmlScript::Property *prop,
329                               QQmlScript::Object *obj,
330                               const QQmlCompilerTypes::BindingContext &ctxt);
331     bool buildValueTypeProperty(QObject *type, 
332                                 QQmlScript::Object *obj, 
333                                 QQmlScript::Object *baseObj,
334                                 const QQmlCompilerTypes::BindingContext &ctxt);
335     bool buildListProperty(QQmlScript::Property *prop,
336                            QQmlScript::Object *obj,
337                            const QQmlCompilerTypes::BindingContext &ctxt);
338     bool buildScriptStringProperty(QQmlScript::Property *prop,
339                                    QQmlScript::Object *obj,
340                                    const QQmlCompilerTypes::BindingContext &ctxt);
341     bool buildPropertyAssignment(QQmlScript::Property *prop,
342                                  QQmlScript::Object *obj,
343                                  const QQmlCompilerTypes::BindingContext &ctxt);
344     bool buildPropertyObjectAssignment(QQmlScript::Property *prop,
345                                        QQmlScript::Object *obj,
346                                        QQmlScript::Value *value,
347                                        const QQmlCompilerTypes::BindingContext &ctxt);
348     bool buildPropertyOnAssignment(QQmlScript::Property *prop,
349                                    QQmlScript::Object *obj,
350                                    QQmlScript::Object *baseObj,
351                                    QQmlScript::Value *value,
352                                    const QQmlCompilerTypes::BindingContext &ctxt);
353     bool buildPropertyLiteralAssignment(QQmlScript::Property *prop,
354                                         QQmlScript::Object *obj,
355                                         QQmlScript::Value *value,
356                                         const QQmlCompilerTypes::BindingContext &ctxt);
357     bool doesPropertyExist(QQmlScript::Property *prop, QQmlScript::Object *obj);
358     bool testLiteralAssignment(QQmlScript::Property *prop,
359                                QQmlScript::Value *value);
360     bool testQualifiedEnumAssignment(QQmlScript::Property *prop,
361                                      QQmlScript::Object *obj,
362                                      QQmlScript::Value *value,
363                                      bool *isAssignment);
364     enum DynamicMetaMode { Normal, ForceCreation };
365     bool mergeDynamicMetaProperties(QQmlScript::Object *obj);
366     bool buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mode);
367     bool buildDynamicMetaAliases(QQmlScript::Object *obj);
368     bool checkDynamicMeta(QQmlScript::Object *obj);
369     bool buildBinding(QQmlScript::Value *, QQmlScript::Property *prop,
370                       const QQmlCompilerTypes::BindingContext &ctxt);
371     bool buildLiteralBinding(QQmlScript::Value *, QQmlScript::Property *prop,
372                              const QQmlCompilerTypes::BindingContext &ctxt);
373     bool buildComponentFromRoot(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
374     bool completeComponentBuild();
375     bool checkValidId(QQmlScript::Value *, const QString &);
376
377
378     void genObject(QQmlScript::Object *obj, bool parentToSuper = false);
379     void genObjectBody(QQmlScript::Object *obj);
380     void genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Property *);
381     void genComponent(QQmlScript::Object *obj);
382     void genValueProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
383     void genListProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
384     void genPropertyAssignment(QQmlScript::Property *prop, 
385                                QQmlScript::Object *obj,
386                                QQmlScript::Property *valueTypeProperty = 0);
387     void genLiteralAssignment(QQmlScript::Property *prop,
388                               QQmlScript::Value *value);
389     void genBindingAssignment(QQmlScript::Value *binding, 
390                               QQmlScript::Property *prop, 
391                               QQmlScript::Object *obj,
392                               QQmlScript::Property *valueTypeProperty = 0);
393     int genContextCache();
394
395     QQmlPropertyData genValueTypeData(QQmlScript::Property *prop,
396                                               QQmlScript::Property *valueTypeProp);
397
398     int componentTypeRef();
399     int translationContextIndex();
400
401     QQmlType *toQmlType(QQmlScript::Object *from);
402     bool canCoerce(int to, QQmlScript::Object *from);
403
404     QString elementName(QQmlScript::Object *);
405
406     QStringList deferredProperties(QQmlScript::Object *);
407
408     QQmlPropertyCache *propertyCacheForObject(QQmlScript::Object *);
409     QQmlPropertyData *property(QQmlScript::Object *, int);
410     QQmlPropertyData *property(QQmlScript::Object *, const QHashedStringRef &,
411                                        bool *notInRevision = 0);
412     QQmlPropertyData *signal(QQmlScript::Object *, const QHashedStringRef &,
413                                      bool *notInRevision = 0);
414     int indexOfProperty(QQmlScript::Object *, const QHashedStringRef &, bool *notInRevision = 0);
415     int indexOfProperty(QQmlScript::Object *, const QString &, bool *notInRevision = 0);
416     int indexOfSignal(QQmlScript::Object *, const QString &, bool *notInRevision = 0);
417
418     void addId(const QString &, QQmlScript::Object *);
419
420     void dumpStats();
421
422     void addBindingReference(QQmlCompilerTypes::JSBindingReference *);
423
424     QQmlCompilerTypes::ComponentCompileState *compileState;
425
426     QQmlPool *pool;
427
428     QQmlCompilerTypes::ComponentCompileState *componentState(QQmlScript::Object *);
429     void saveComponentState();
430
431     QList<QQmlError> exceptions;
432     QQmlCompiledData *output;
433     QQmlEngine *engine;
434     QQmlEnginePrivate *enginePrivate;
435     QQmlScript::Object *unitRoot;
436     QQmlTypeData *unit;
437     int cachedComponentTypeRef;
438     int cachedTranslationContextIndex;
439
440     // Compiler component statistics.  Only collected if QML_COMPILER_STATS=1
441     struct ComponentStat
442     {
443         ComponentStat() : lineNumber(0), ids(0), objects(0) {}
444
445         quint16 lineNumber;
446
447         int ids;
448         QList<QQmlScript::LocationSpan> scriptBindings;
449         QList<QQmlScript::LocationSpan> sharedBindings;
450         QList<QQmlScript::LocationSpan> optimizedBindings;
451         int objects;
452     };
453     struct ComponentStats : public QQmlPool::Class
454     {
455         ComponentStat componentStat;
456         QList<ComponentStat> savedComponentStats;
457     };
458     ComponentStats *componentStats;
459 };
460
461 QT_END_NAMESPACE
462
463 #endif // QQMLCOMPILER_P_H