Merge branch 'master' of git://gitorious.org/qt/qtdeclarative into api_changes
[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,
80                                                    public QQmlCleanup
81 {
82 public:
83     QQmlCompiledData(QQmlEngine *engine);
84     virtual ~QQmlCompiledData();
85
86     QQmlEngine *engine;
87
88     QString name;
89     QUrl url;
90     QQmlTypeNameCache *importCache;
91
92     struct TypeReference 
93     {
94         TypeReference()
95         : type(0), typePropertyCache(0), component(0) {}
96
97         QString className;
98         QQmlType *type;
99         QQmlPropertyCache *typePropertyCache;
100         QQmlCompiledData *component;
101
102         const QMetaObject *metaObject() const;
103         QQmlPropertyCache *propertyCache() const;
104         QQmlPropertyCache *createPropertyCache(QQmlEngine *);
105     };
106     QList<TypeReference> types;
107
108     struct V8Program {
109         V8Program(const QByteArray &p, QQmlCompiledData *c)
110         : program(p), cdata(c) {}
111
112         QByteArray program;
113         v8::Persistent<v8::Array> bindings;
114         QQmlCompiledData *cdata;
115     };
116
117     QList<V8Program> programs;
118
119     const QMetaObject *root;
120     QAbstractDynamicMetaObject rootData;
121     QQmlPropertyCache *rootPropertyCache;
122     QList<QString> primitives;
123     QList<QByteArray> datas;
124     QByteArray bytecode;
125     QList<QQmlPropertyCache *> propertyCaches;
126     QList<QQmlIntegerCache *> contextCaches;
127     QList<QQmlScriptData *> scripts;
128     QList<QUrl> urls;
129
130     struct Instruction {
131 #define QML_INSTR_DATA_TYPEDEF(I, FMT) typedef QQmlInstructionData<QQmlInstruction::I> I;
132     FOR_EACH_QML_INSTR(QML_INSTR_DATA_TYPEDEF)
133 #undef QML_INSTR_DATA_TYPEDEF
134     private:
135         Instruction();
136     };
137
138     void dumpInstructions();
139
140     template <int Instr>
141     int addInstruction(const QQmlInstructionData<Instr> &data)
142     {
143         QQmlInstruction genericInstr;
144         QQmlInstructionMeta<Instr>::setData(genericInstr, data);
145         return addInstructionHelper(static_cast<QQmlInstruction::Type>(Instr), genericInstr);
146     }
147     int nextInstructionIndex();
148     QQmlInstruction *instruction(int index);
149     QQmlInstruction::Type instructionType(const QQmlInstruction *instr);
150
151     bool isInitialized() const { return hasEngine(); }
152     void initialize(QQmlEngine *);
153
154 protected:
155     virtual void destroy(); // From QQmlRefCount
156     virtual void clear(); // From QQmlCleanup
157
158 private:
159     friend class QQmlCompiler;
160
161     int addInstructionHelper(QQmlInstruction::Type type, QQmlInstruction &instr);
162     void dump(QQmlInstruction *, int idx = -1);
163     QQmlCompiledData(const QQmlCompiledData &other);
164     QQmlCompiledData &operator=(const QQmlCompiledData &other);
165     QByteArray packData;
166     int pack(const char *, size_t);
167
168     int indexForString(const QString &);
169     int indexForByteArray(const QByteArray &);
170     int indexForUrl(const QUrl &);
171 };
172
173 namespace QQmlCompilerTypes {
174     struct BindingContext 
175     {
176         BindingContext()
177             : stack(0), owner(0), object(0) {}
178         BindingContext(QQmlScript::Object *o)
179             : stack(0), owner(0), object(o) {}
180         BindingContext incr() const {
181             BindingContext rv(object);
182             rv.stack = stack + 1;
183             return rv;
184         }
185         bool isSubContext() const { return stack != 0; }
186         int stack;
187         int owner;
188         QQmlScript::Object *object;
189     };
190
191     struct BindingReference
192     {
193         enum DataType { QtScript, V4, V8,
194                         Tr, TrId };
195         DataType dataType;
196     };
197
198     struct JSBindingReference : public QQmlPool::Class,
199                                 public BindingReference
200     {
201         JSBindingReference() : nextReference(0) {}
202
203         QQmlScript::Variant expression;
204         QQmlScript::Property *property;
205         QQmlScript::Value *value;
206
207         int compiledIndex;
208
209         QString rewrittenExpression;
210         BindingContext bindingContext;
211
212         JSBindingReference *nextReference;
213     };
214
215     struct TrBindingReference : public QQmlPool::POD,
216                                 public BindingReference
217     {
218         QStringRef text;
219         QStringRef comment;
220         int n;
221     };
222
223     struct IdList : public QFieldList<QQmlScript::Object, 
224                                       &QQmlScript::Object::nextIdObject>
225     {
226         QQmlScript::Object *value(const QString &id) const {
227             for (QQmlScript::Object *o = first(); o; o = next(o)) {
228                 if (o->id == id)
229                     return o;
230             }
231             return 0;
232         }
233     };
234
235     struct DepthStack {
236         DepthStack() : _depth(0), _maxDepth(0) {}
237         DepthStack(const DepthStack &o) : _depth(o._depth), _maxDepth(o._maxDepth) {}
238         DepthStack &operator=(const DepthStack &o) { _depth = o._depth; _maxDepth = o._maxDepth; return *this; }
239
240         int depth() const { return _depth; }
241         int maxDepth() const { return _maxDepth; }
242
243         void push() { ++_depth; _maxDepth = qMax(_depth, _maxDepth); }
244         void pop() { --_depth; Q_ASSERT(_depth >= 0); Q_ASSERT(_maxDepth > _depth); }
245
246         void pushPop(int count) { _maxDepth = qMax(_depth + count, _maxDepth); }
247     private:
248         int _depth;
249         int _maxDepth;
250     };
251
252     // Contains all the incremental compiler state about a component.  As
253     // a single QML file can have multiple components defined, there may be
254     // more than one of these for each compile
255     struct ComponentCompileState : public QQmlPool::Class
256     {
257         ComponentCompileState() 
258         : parserStatusCount(0), totalBindingsCount(0), pushedProperties(0), nested(false), 
259           v8BindingProgramLine(-1), root(0) {}
260
261         IdList ids;
262         int parserStatusCount;
263         int totalBindingsCount;
264         int pushedProperties;
265         bool nested;
266
267         QByteArray compiledBindingData;
268         QByteArray v8BindingProgram;
269         int v8BindingProgramLine;
270
271         DepthStack objectDepth;
272         DepthStack listDepth;
273
274         typedef QQmlCompilerTypes::JSBindingReference B;
275         typedef QFieldList<B, &B::nextReference> JSBindingReferenceList;
276         JSBindingReferenceList bindings;
277         typedef QQmlScript::Object O;
278         typedef QFieldList<O, &O::nextAliasingObject> AliasingObjectsList;
279         AliasingObjectsList aliasingObjects;
280         QQmlScript::Object *root;
281     };
282 };
283
284 class QMetaObjectBuilder;
285 class Q_AUTOTEST_EXPORT QQmlCompiler
286 {
287     Q_DECLARE_TR_FUNCTIONS(QQmlCompiler)
288 public:
289     QQmlCompiler(QQmlPool *);
290
291     bool compile(QQmlEngine *, QQmlTypeData *, QQmlCompiledData *);
292
293     bool isError() const;
294     QList<QQmlError> errors() const;
295
296     static bool isAttachedPropertyName(const QString &);
297     static bool isSignalPropertyName(const QString &);
298     static bool isAttachedPropertyName(const QHashedStringRef &);
299     static bool isSignalPropertyName(const QHashedStringRef &);
300
301     int evaluateEnum(const QByteArray& script) const; // for QQmlCustomParser::evaluateEnum
302     const QMetaObject *resolveType(const QString& name) const; // for QQmlCustomParser::resolveType
303     int rewriteBinding(const QQmlScript::Variant& value, const QString& name); // for QQmlCustomParser::rewriteBinding
304     QString rewriteSignalHandler(const QQmlScript::Variant& value, const QString &name);  // for QQmlCustomParser::rewriteSignalHandler
305
306 private:
307     typedef QQmlCompiledData::Instruction Instruction;
308
309     static void reset(QQmlCompiledData *);
310
311     void compileTree(QQmlScript::Object *tree);
312
313
314     bool buildObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
315     bool buildComponent(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
316     bool buildSubObject(QQmlScript::Object *obj, const QQmlCompilerTypes::BindingContext &);
317     bool buildSignal(QQmlScript::Property *prop, QQmlScript::Object *obj, 
318                      const QQmlCompilerTypes::BindingContext &);
319     bool buildProperty(QQmlScript::Property *prop, QQmlScript::Object *obj, 
320                        const QQmlCompilerTypes::BindingContext &);
321     bool buildPropertyInNamespace(QQmlImportedNamespace *ns,
322                                   QQmlScript::Property *prop, 
323                                   QQmlScript::Object *obj, 
324                                   const QQmlCompilerTypes::BindingContext &);
325     bool buildIdProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
326     bool buildAttachedProperty(QQmlScript::Property *prop, 
327                                QQmlScript::Object *obj,
328                                const QQmlCompilerTypes::BindingContext &ctxt);
329     bool buildGroupedProperty(QQmlScript::Property *prop,
330                               QQmlScript::Object *obj,
331                               const QQmlCompilerTypes::BindingContext &ctxt);
332     bool buildValueTypeProperty(QObject *type, 
333                                 QQmlScript::Object *obj, 
334                                 QQmlScript::Object *baseObj,
335                                 const QQmlCompilerTypes::BindingContext &ctxt);
336     bool buildListProperty(QQmlScript::Property *prop,
337                            QQmlScript::Object *obj,
338                            const QQmlCompilerTypes::BindingContext &ctxt);
339     bool buildScriptStringProperty(QQmlScript::Property *prop,
340                                    QQmlScript::Object *obj,
341                                    const QQmlCompilerTypes::BindingContext &ctxt);
342     bool buildPropertyAssignment(QQmlScript::Property *prop,
343                                  QQmlScript::Object *obj,
344                                  const QQmlCompilerTypes::BindingContext &ctxt);
345     bool buildPropertyObjectAssignment(QQmlScript::Property *prop,
346                                        QQmlScript::Object *obj,
347                                        QQmlScript::Value *value,
348                                        const QQmlCompilerTypes::BindingContext &ctxt);
349     bool buildPropertyOnAssignment(QQmlScript::Property *prop,
350                                    QQmlScript::Object *obj,
351                                    QQmlScript::Object *baseObj,
352                                    QQmlScript::Value *value,
353                                    const QQmlCompilerTypes::BindingContext &ctxt);
354     bool buildPropertyLiteralAssignment(QQmlScript::Property *prop,
355                                         QQmlScript::Object *obj,
356                                         QQmlScript::Value *value,
357                                         const QQmlCompilerTypes::BindingContext &ctxt);
358     bool doesPropertyExist(QQmlScript::Property *prop, QQmlScript::Object *obj);
359     bool testLiteralAssignment(QQmlScript::Property *prop,
360                                QQmlScript::Value *value);
361     bool testQualifiedEnumAssignment(QQmlScript::Property *prop,
362                                      QQmlScript::Object *obj,
363                                      QQmlScript::Value *value,
364                                      bool *isAssignment);
365     enum DynamicMetaMode { IgnoreAliases, ResolveAliases, ForceCreation };
366     bool mergeDynamicMetaProperties(QQmlScript::Object *obj);
367     bool buildDynamicMeta(QQmlScript::Object *obj, DynamicMetaMode mode);
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 compileAlias(QFastMetaBuilder &, 
375                       QByteArray &data,
376                       QQmlScript::Object *obj, 
377                       int propIndex, int aliasIndex,
378                       QQmlScript::Object::DynamicProperty &);
379     bool completeComponentBuild();
380     bool checkValidId(QQmlScript::Value *, const QString &);
381
382
383     void genObject(QQmlScript::Object *obj);
384     void genObjectBody(QQmlScript::Object *obj);
385     void genValueTypeProperty(QQmlScript::Object *obj,QQmlScript::Property *);
386     void genComponent(QQmlScript::Object *obj);
387     void genValueProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
388     void genListProperty(QQmlScript::Property *prop, QQmlScript::Object *obj);
389     void genPropertyAssignment(QQmlScript::Property *prop, 
390                                QQmlScript::Object *obj,
391                                QQmlScript::Property *valueTypeProperty = 0);
392     void genLiteralAssignment(QQmlScript::Property *prop,
393                               QQmlScript::Value *value);
394     void genBindingAssignment(QQmlScript::Value *binding, 
395                               QQmlScript::Property *prop, 
396                               QQmlScript::Object *obj,
397                               QQmlScript::Property *valueTypeProperty = 0);
398     int genContextCache();
399
400     QQmlPropertyData genValueTypeData(QQmlScript::Property *prop,
401                                               QQmlScript::Property *valueTypeProp);
402
403     int componentTypeRef();
404     int translationContextIndex();
405
406     static QQmlType *toQmlType(QQmlScript::Object *from);
407     bool canCoerce(int to, QQmlScript::Object *from);
408
409     QString elementName(QQmlScript::Object *);
410
411     QStringList deferredProperties(QQmlScript::Object *);
412
413     QQmlPropertyData *property(QQmlScript::Object *, int);
414     QQmlPropertyData *property(QQmlScript::Object *, const QHashedStringRef &,
415                                        bool *notInRevision = 0);
416     QQmlPropertyData *signal(QQmlScript::Object *, const QHashedStringRef &,
417                                      bool *notInRevision = 0);
418     int indexOfProperty(QQmlScript::Object *, const QHashedStringRef &, bool *notInRevision = 0);
419     int indexOfProperty(QQmlScript::Object *, const QString &, bool *notInRevision = 0);
420     int indexOfSignal(QQmlScript::Object *, const QString &, bool *notInRevision = 0);
421
422     void addId(const QString &, QQmlScript::Object *);
423
424     void dumpStats();
425
426     void addBindingReference(QQmlCompilerTypes::JSBindingReference *);
427
428     QQmlCompilerTypes::ComponentCompileState *compileState;
429
430     QQmlPool *pool;
431
432     QQmlCompilerTypes::ComponentCompileState *componentState(QQmlScript::Object *);
433     void saveComponentState();
434
435     QList<QQmlError> exceptions;
436     QQmlCompiledData *output;
437     QQmlEngine *engine;
438     QQmlEnginePrivate *enginePrivate;
439     QQmlScript::Object *unitRoot;
440     QQmlTypeData *unit;
441     int cachedComponentTypeRef;
442     int cachedTranslationContextIndex;
443
444     // Compiler component statistics.  Only collected if QML_COMPILER_STATS=1
445     struct ComponentStat
446     {
447         ComponentStat() : ids(0), objects(0) {}
448
449         int lineNumber;
450
451         int ids;
452         QList<QQmlScript::LocationSpan> scriptBindings;
453         QList<QQmlScript::LocationSpan> sharedBindings;
454         QList<QQmlScript::LocationSpan> optimizedBindings;
455         int objects;
456     };
457     struct ComponentStats : public QQmlPool::Class
458     {
459         ComponentStat componentStat;
460         QList<ComponentStat> savedComponentStats;
461     };
462     ComponentStats *componentStats;
463 };
464
465 QT_END_NAMESPACE
466
467 #endif // QQMLCOMPILER_P_H