103d5ba0df7861684300b1d824b41434ad167c93
[profile/ivi/qtdeclarative.git] / src / declarative / qml / v4 / qdeclarativev4irbuilder.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdeclarativev4irbuilder_p.h"
43
44 #include <private/qdeclarativeglobalscriptclass_p.h> // For illegalNames
45 #include <private/qdeclarativeanchors_p_p.h> // For AnchorLine
46 #include <private/qsganchors_p_p.h> // For AnchorLine
47 #include <private/qdeclarativetypenamecache_p.h>
48
49 DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER)
50
51 QT_BEGIN_NAMESPACE
52
53 using namespace QDeclarativeJS;
54
55 static IR::Type irTypeFromVariantType(int t, QDeclarativeEnginePrivate *engine, const QMetaObject *meta)
56 {
57     switch (t) {
58     case QMetaType::Bool:
59         return IR::BoolType;
60
61     case QMetaType::Int:
62         return IR::IntType;
63
64     case QMetaType::QReal:
65         return IR::RealType;
66
67     case QMetaType::QString:
68         return IR::StringType;
69
70     case QMetaType::QUrl:
71         return IR::UrlType;
72
73     default:
74         if (t == qMetaTypeId<QDeclarativeAnchorLine>())
75             return IR::AnchorLineType;
76         else if (t == qMetaTypeId<QSGAnchorLine>())
77             return IR::SGAnchorLineType;
78         else if (const QMetaObject *m = engine->metaObjectForType(t)) {
79             meta = m;
80             return IR::ObjectType;
81         }
82
83         return IR::InvalidType;
84     }
85 }
86
87 QDeclarativeV4IRBuilder::QDeclarativeV4IRBuilder(const QDeclarativeV4Compiler::Expression *expr, 
88                                                              QDeclarativeEnginePrivate *engine)
89 : m_expression(expr), m_engine(engine), _module(0), _function(0), _block(0), _discard(false)
90 {
91 }
92
93 QDeclarativeJS::IR::Function *
94 QDeclarativeV4IRBuilder::operator()(QDeclarativeJS::IR::Module *module, 
95                                          QDeclarativeJS::AST::Node *ast)
96 {
97     bool discarded = false;
98
99     qSwap(_module, module);
100
101     IR::Function *function = _module->newFunction();
102     IR::BasicBlock *block = function->newBasicBlock();
103
104     qSwap(_discard, discarded);
105     qSwap(_function, function);
106     qSwap(_block, block);
107
108     ExprResult r;
109     AST::SourceLocation location;
110     if (AST::ExpressionNode *asExpr = ast->expressionCast()) {
111         r = expression(asExpr);
112         location = asExpr->firstSourceLocation();
113     } else if (AST::Statement *asStmt = ast->statementCast()) {
114         r = statement(asStmt);
115         location = asStmt->firstSourceLocation();
116     }
117
118     //_block->MOVE(_block->TEMP(IR::InvalidType), r.code);
119     if (r.code) {
120         const QMetaObject *m = 0;
121         const IR::Type targetType = irTypeFromVariantType(m_expression->property->type, m_engine, m);
122         if (targetType != r.type()) {
123             IR::Expr *x = _block->TEMP(targetType);
124             _block->MOVE(x, r, true);
125             r.code = x;
126         }
127         _block->RET(r.code, targetType, location.startLine, location.startColumn);
128     }
129
130     qSwap(_block, block);
131     qSwap(_function, function);
132     qSwap(_discard, discarded);
133
134     qSwap(_module, module);
135
136     return discarded?0:function;
137 }
138
139 bool QDeclarativeV4IRBuilder::buildName(QStringList &name,
140                                               AST::Node *node,
141                                               QList<AST::ExpressionNode *> *nodes)
142 {
143     if (node->kind == AST::Node::Kind_IdentifierExpression) {
144         name << static_cast<AST::IdentifierExpression*>(node)->name->asString();
145         if (nodes) *nodes << static_cast<AST::IdentifierExpression*>(node);
146     } else if (node->kind == AST::Node::Kind_FieldMemberExpression) {
147         AST::FieldMemberExpression *expr =
148             static_cast<AST::FieldMemberExpression *>(node);
149
150         if (!buildName(name, expr->base, nodes))
151             return false;
152
153         name << expr->name->asString();
154         if (nodes) *nodes << expr;
155     } else {
156         return false;
157     }
158
159     return true;
160 }
161
162 void QDeclarativeV4IRBuilder::discard() 
163
164     _discard = true; 
165 }
166
167 QDeclarativeV4IRBuilder::ExprResult 
168 QDeclarativeV4IRBuilder::expression(AST::ExpressionNode *ast)
169 {
170     ExprResult r;
171     if (ast) {
172         qSwap(_expr, r);
173         accept(ast);
174         qSwap(_expr, r);
175
176         if (r.is(IR::InvalidType))
177             discard();
178         else {
179             Q_ASSERT(r.hint == r.format);
180         }
181     }
182
183     return r;
184 }
185
186 void QDeclarativeV4IRBuilder::condition(AST::ExpressionNode *ast, IR::BasicBlock *iftrue, IR::BasicBlock *iffalse)
187 {
188     if (! ast)
189         return;
190     ExprResult r(iftrue, iffalse);
191     qSwap(_expr, r);
192     accept(ast);
193     qSwap(_expr, r);
194
195     if (r.format != ExprResult::cx) {
196         if (! r.code)
197             discard();
198
199         Q_ASSERT(r.hint == ExprResult::cx);
200         Q_ASSERT(r.format == ExprResult::ex);
201
202         if (r.type() != IR::BoolType) {
203             IR::Temp *t = _block->TEMP(IR::BoolType);
204             _block->MOVE(t, r);
205             r = t;
206         }
207
208         _block->CJUMP(_block->UNOP(IR::OpIfTrue, r), iftrue, iffalse);
209     }
210 }
211
212 QDeclarativeV4IRBuilder::ExprResult
213 QDeclarativeV4IRBuilder::statement(AST::Statement *ast)
214 {
215     ExprResult r;
216     if (ast) {
217         qSwap(_expr, r);
218         accept(ast);
219         qSwap(_expr, r);
220
221         if (r.is(IR::InvalidType))
222             discard();
223         else {
224             Q_ASSERT(r.hint == r.format);
225         }
226     }
227
228     return r;
229 }
230
231 void QDeclarativeV4IRBuilder::sourceElement(AST::SourceElement *ast)
232 {
233     accept(ast);
234 }
235
236 void QDeclarativeV4IRBuilder::implicitCvt(ExprResult &expr, IR::Type type)
237 {
238     if (expr.type() == type)
239         return; // nothing to do
240
241     IR::Expr *x = _block->TEMP(type);
242     _block->MOVE(x, expr.code);
243     expr.code = x;
244 }
245
246 // QML
247 bool QDeclarativeV4IRBuilder::visit(AST::UiProgram *)
248 {
249     Q_ASSERT(!"unreachable");
250     return false;
251 }
252
253 bool QDeclarativeV4IRBuilder::visit(AST::UiImportList *)
254 {
255     Q_ASSERT(!"unreachable");
256     return false;
257 }
258
259 bool QDeclarativeV4IRBuilder::visit(AST::UiImport *)
260 {
261     Q_ASSERT(!"unreachable");
262     return false;
263 }
264
265 bool QDeclarativeV4IRBuilder::visit(AST::UiPublicMember *)
266 {
267     Q_ASSERT(!"unreachable");
268     return false;
269 }
270
271 bool QDeclarativeV4IRBuilder::visit(AST::UiSourceElement *)
272 {
273     Q_ASSERT(!"unreachable");
274     return false;
275 }
276
277 bool QDeclarativeV4IRBuilder::visit(AST::UiObjectDefinition *)
278 {
279     Q_ASSERT(!"unreachable");
280     return false;
281 }
282
283 bool QDeclarativeV4IRBuilder::visit(AST::UiObjectInitializer *)
284 {
285     Q_ASSERT(!"unreachable");
286     return false;
287 }
288
289 bool QDeclarativeV4IRBuilder::visit(AST::UiObjectBinding *)
290 {
291     Q_ASSERT(!"unreachable");
292     return false;
293 }
294
295 bool QDeclarativeV4IRBuilder::visit(AST::UiScriptBinding *)
296 {
297     Q_ASSERT(!"unreachable");
298     return false;
299 }
300
301 bool QDeclarativeV4IRBuilder::visit(AST::UiArrayBinding *)
302 {
303     Q_ASSERT(!"unreachable");
304     return false;
305 }
306
307 bool QDeclarativeV4IRBuilder::visit(AST::UiObjectMemberList *)
308 {
309     Q_ASSERT(!"unreachable");
310     return false;
311 }
312
313 bool QDeclarativeV4IRBuilder::visit(AST::UiArrayMemberList *)
314 {
315     Q_ASSERT(!"unreachable");
316     return false;
317 }
318
319 bool QDeclarativeV4IRBuilder::visit(AST::UiQualifiedId *)
320 {
321     Q_ASSERT(!"unreachable");
322     return false;
323 }
324
325 bool QDeclarativeV4IRBuilder::visit(AST::UiSignature *)
326 {
327     Q_ASSERT(!"unreachable");
328     return false;
329 }
330
331 bool QDeclarativeV4IRBuilder::visit(AST::UiFormalList *)
332 {
333     Q_ASSERT(!"unreachable");
334     return false;
335 }
336
337 bool QDeclarativeV4IRBuilder::visit(AST::UiFormal *)
338 {
339     Q_ASSERT(!"unreachable");
340     return false;
341 }
342
343
344 // JS
345 bool QDeclarativeV4IRBuilder::visit(AST::Program *ast)
346 {
347     _function = _module->newFunction();
348     _block = _function->newBasicBlock();
349     accept(ast->elements);
350     return false;
351 }
352
353 bool QDeclarativeV4IRBuilder::visit(AST::SourceElements *)
354 {
355     return false;
356 }
357
358 bool QDeclarativeV4IRBuilder::visit(AST::FunctionSourceElement *)
359 {
360     return true; // look inside
361 }
362
363 bool QDeclarativeV4IRBuilder::visit(AST::StatementSourceElement *)
364 {
365     return true; // look inside
366 }
367
368 // object literals
369 bool QDeclarativeV4IRBuilder::visit(AST::PropertyNameAndValueList *)
370 {
371     Q_ASSERT(!"unreachable");
372     return false;
373 }
374
375 bool QDeclarativeV4IRBuilder::visit(AST::IdentifierPropertyName *)
376 {
377     Q_ASSERT(!"unreachable");
378     return false;
379 }
380
381 bool QDeclarativeV4IRBuilder::visit(AST::StringLiteralPropertyName *)
382 {
383     Q_ASSERT(!"unreachable");
384     return false;
385 }
386
387 bool QDeclarativeV4IRBuilder::visit(AST::NumericLiteralPropertyName *)
388 {
389     Q_ASSERT(!"unreachable");
390     return false;
391 }
392
393
394 // array literals
395 bool QDeclarativeV4IRBuilder::visit(AST::ElementList *)
396 {
397     Q_ASSERT(!"unreachable");
398     return false;
399 }
400
401 bool QDeclarativeV4IRBuilder::visit(AST::Elision *)
402 {
403     Q_ASSERT(!"unreachable");
404     return false;
405 }
406
407
408 // function calls
409 bool QDeclarativeV4IRBuilder::visit(AST::ArgumentList *)
410 {
411     Q_ASSERT(!"unreachable");
412     return false;
413 }
414
415 // expressions
416 bool QDeclarativeV4IRBuilder::visit(AST::ObjectLiteral *)
417 {
418     return false;
419 }
420
421 bool QDeclarativeV4IRBuilder::visit(AST::ArrayLiteral *)
422 {
423     return false;
424 }
425
426 bool QDeclarativeV4IRBuilder::visit(AST::ThisExpression *)
427 {
428     return false;
429 }
430
431 bool QDeclarativeV4IRBuilder::visit(AST::IdentifierExpression *ast)
432 {
433     const quint32 line = ast->identifierToken.startLine;
434     const quint32 column = ast->identifierToken.startColumn;
435
436     const QString name = ast->name->asString();
437
438     if (name.at(0) == QLatin1Char('u') && name.length() == 9 && name == QLatin1String("undefined")) {
439         _expr.code = _block->CONST(IR::UndefinedType, 0); // ### undefined value
440     } else if(m_engine->globalClass->illegalNames().contains(name) ) {
441         if (qmlVerboseCompiler()) qWarning() << "*** illegal symbol:" << name;
442         return false;
443     } else if (const QDeclarativeParser::Object *obj = m_expression->ids.value(name)) {
444         IR::Name *code = _block->ID_OBJECT(name, obj, line, column);
445         if (obj == m_expression->component)
446             code->storage = IR::Name::RootStorage;
447         _expr.code = code;
448     } else if (QDeclarativeTypeNameCache::Data *typeNameData = m_expression->importCache->data(name)) {
449         if (typeNameData->importedScriptIndex != -1) {
450             // We don't support invoking imported scripts
451         } else if (typeNameData->type) {
452             _expr.code = _block->ATTACH_TYPE(name, typeNameData->type, IR::Name::ScopeStorage, line, column);
453         } else if (typeNameData->typeNamespace) {
454             // We don't support namespaces
455         } else {
456             Q_ASSERT(!"Unreachable");
457         }
458     } else {
459         bool found = false;
460
461         if (m_expression->context != m_expression->component) {
462             // RootStorage is more efficient than ScopeStorage, so prefer that if they are the same
463             QDeclarativePropertyCache *cache = m_expression->context->synthCache;
464             const QMetaObject *metaObject = m_expression->context->metaObject();
465             if (!cache) cache = m_engine->cache(metaObject);
466
467             QDeclarativePropertyCache::Data *data = cache->property(name);
468
469             if (data && data->revision != 0) {
470                 if (qmlVerboseCompiler()) 
471                     qWarning() << "*** versioned symbol:" << name;
472                 discard();
473                 return false;
474             }
475
476             if (data && !(data->flags & QDeclarativePropertyCache::Data::IsFunction)) {
477                 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
478                 _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::ScopeStorage, line, column);
479                 found = true;
480             } 
481         }
482
483         if (!found) {
484             QDeclarativePropertyCache *cache = m_expression->component->synthCache;
485             const QMetaObject *metaObject = m_expression->component->metaObject();
486             if (!cache) cache = m_engine->cache(metaObject);
487
488             QDeclarativePropertyCache::Data *data = cache->property(name);
489
490             if (data && data->revision != 0) {
491                 if (qmlVerboseCompiler()) 
492                     qWarning() << "*** versioned symbol:" << name;
493                 discard();
494                 return false;
495             }
496
497             if (data && !(data->flags & QDeclarativePropertyCache::Data::IsFunction)) {
498                 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
499                 _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::RootStorage, line, column);
500                 found = true;
501             } 
502         }
503
504         if (!found && qmlVerboseCompiler())
505             qWarning() << "*** unknown symbol:" << name;
506     }
507
508     if (_expr.code && _expr.hint == ExprResult::cx) {
509         _expr.format = ExprResult::cx;
510
511         if (_expr.type() != IR::BoolType) {
512             IR::Temp *t = _block->TEMP(IR::BoolType);
513             _block->MOVE(t, _expr);
514             _expr.code = t;
515         }
516
517         _block->CJUMP(_expr.code, _expr.iftrue, _expr.iffalse);
518         _expr.code = 0;
519     }
520
521     return false;
522 }
523
524 bool QDeclarativeV4IRBuilder::visit(AST::NullExpression *)
525 {
526     // ### TODO: cx format
527     _expr.code = _block->CONST(IR::NullType, 0);
528     return false;
529 }
530
531 bool QDeclarativeV4IRBuilder::visit(AST::TrueLiteral *)
532 {
533     // ### TODO: cx format
534     _expr.code = _block->CONST(IR::BoolType, 1);
535     return false;
536 }
537
538 bool QDeclarativeV4IRBuilder::visit(AST::FalseLiteral *)
539 {
540     // ### TODO: cx format
541     _expr.code = _block->CONST(IR::BoolType, 0);
542     return false;
543 }
544
545 bool QDeclarativeV4IRBuilder::visit(AST::StringLiteral *ast)
546 {
547     // ### TODO: cx format
548     _expr.code = _block->STRING(ast->value->asString());
549     return false;
550 }
551
552 bool QDeclarativeV4IRBuilder::visit(AST::NumericLiteral *ast)
553 {
554     if (_expr.hint == ExprResult::cx) {
555         _expr.format = ExprResult::cx;
556         _block->JUMP(ast->value ? _expr.iftrue : _expr.iffalse);
557     } else {
558         _expr.code = _block->CONST(ast->value);
559     }
560     return false;
561 }
562
563 bool QDeclarativeV4IRBuilder::visit(AST::RegExpLiteral *)
564 {
565     return false;
566 }
567
568 bool QDeclarativeV4IRBuilder::visit(AST::NestedExpression *)
569 {
570     return true; // the value of the nested expression
571 }
572
573 bool QDeclarativeV4IRBuilder::visit(AST::ArrayMemberExpression *)
574 {
575     return false;
576 }
577
578 bool QDeclarativeV4IRBuilder::visit(AST::FieldMemberExpression *ast)
579 {
580     if (IR::Expr *left = expression(ast->base)) {
581         if (IR::Name *baseName = left->asName()) {
582             const quint32 line = ast->identifierToken.startLine;
583             const quint32 column = ast->identifierToken.startColumn;
584
585             QString name = ast->name->asString();
586
587             switch(baseName->symbol) {
588             case IR::Name::Unbound:
589                 break;
590
591             case IR::Name::AttachType:
592                 if (name.at(0).isUpper()) {
593                     QByteArray utf8Name = name.toUtf8();
594                     const char *enumName = utf8Name.constData();
595
596                     const QMetaObject *meta = baseName->declarativeType->metaObject();
597                     bool found = false;
598                     for (int ii = 0; !found && ii < meta->enumeratorCount(); ++ii) {
599                         QMetaEnum e = meta->enumerator(ii);
600                         for (int jj = 0; !found && jj < e.keyCount(); ++jj) {
601                             if (0 == strcmp(e.key(jj), enumName)) {
602                                 found = true;
603                                 _expr.code = _block->CONST(IR::IntType, e.value(jj));
604                             }
605                         }
606                     }
607
608                     if (!found && qmlVerboseCompiler())
609                         qWarning() << "*** unresolved enum:" 
610                                    << (baseName->id + QLatin1String(".") + ast->name->asString());
611                 } else if(const QMetaObject *attachedMeta = baseName->declarativeType->attachedPropertiesType()) {
612                     QDeclarativePropertyCache *cache = m_engine->cache(attachedMeta);
613                     QDeclarativePropertyCache::Data *data = cache->property(name);
614
615                     if (!data || data->flags & QDeclarativePropertyCache::Data::IsFunction)
616                         return false; // Don't support methods (or non-existing properties ;)
617
618                     if(!(data->flags & QDeclarativePropertyCache::Data::IsFinal)) {
619                         if (qmlVerboseCompiler())
620                             qWarning() << "*** non-final attached property:"
621                                        << (baseName->id + QLatin1String(".") + ast->name->asString());
622                         return false; // We don't know enough about this property
623                     }
624
625                     IR::Type irType = irTypeFromVariantType(data->propType, m_engine, attachedMeta);
626                     _expr.code = _block->SYMBOL(baseName, irType, name, attachedMeta, data->coreIndex, line, column);
627                 }
628                 break;
629
630             case IR::Name::IdObject: {
631                 const QDeclarativeParser::Object *idObject = baseName->idObject;
632                 QDeclarativePropertyCache *cache = 
633                     idObject->synthCache?idObject->synthCache:m_engine->cache(idObject->metaObject());
634
635                 QDeclarativePropertyCache::Data *data = cache->property(name);
636
637                 if (!data || data->flags & QDeclarativePropertyCache::Data::IsFunction)
638                     return false; // Don't support methods (or non-existing properties ;)
639
640                 if (data->revision != 0) {
641                     if (qmlVerboseCompiler()) 
642                         qWarning() << "*** versioned symbol:" << name;
643                     discard();
644                     return false;
645                 }
646
647                 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, idObject->metaObject());
648                 _expr.code = _block->SYMBOL(baseName, irType, name,
649                                             idObject->metaObject(), data->coreIndex, line, column);
650                 }
651                 break;
652
653             case IR::Name::Property: 
654                 if (baseName->type == IR::ObjectType) {
655                     const QMetaObject *m = 
656                         m_engine->metaObjectForType(baseName->meta->property(baseName->index).userType());
657                     QDeclarativePropertyCache *cache = m_engine->cache(m);
658
659                     QDeclarativePropertyCache::Data *data = cache->property(name);
660
661                     if (!data || data->flags & QDeclarativePropertyCache::Data::IsFunction)
662                         return false; // Don't support methods (or non-existing properties ;)
663
664                     if(!(data->flags & QDeclarativePropertyCache::Data::IsFinal)) {
665                         if (qmlVerboseCompiler())
666                             qWarning() << "*** non-final property access:"
667                                 << (baseName->id + QLatin1String(".") + ast->name->asString());
668                         return false; // We don't know enough about this property
669                     }
670
671                     IR::Type irType = irTypeFromVariantType(data->propType, m_engine, baseName->meta);
672                     _expr.code = _block->SYMBOL(baseName, irType, name,
673                                                 baseName->meta, data->coreIndex, line, column);
674                 }
675                 break;
676
677             case IR::Name::Object: 
678             case IR::Name::Slot:
679                 break;
680             }
681         }
682     }
683
684     return false;
685 }
686
687 bool QDeclarativeV4IRBuilder::visit(AST::NewMemberExpression *)
688 {
689     return false;
690 }
691
692 bool QDeclarativeV4IRBuilder::visit(AST::NewExpression *)
693 {
694     return false;
695 }
696
697 bool QDeclarativeV4IRBuilder::visit(AST::CallExpression *ast)
698 {
699     QStringList names;
700     QList<AST::ExpressionNode *> nameNodes;
701     if (buildName(names, ast->base, &nameNodes)) {
702         //ExprResult base = expression(ast->base);
703         const QString id = names.join(QLatin1String("."));
704         const quint32 line = nameNodes.last()->firstSourceLocation().startLine;
705         const quint32 column = nameNodes.last()->firstSourceLocation().startColumn;
706         IR::Expr *base = _block->NAME(id, line, column);
707
708         QVector<IR::Expr *> args;
709         for (AST::ArgumentList *it = ast->arguments; it; it = it->next)
710             args.append(expression(it->expression));
711
712         IR::Temp *r = _block->TEMP(IR::InvalidType);
713         IR::Expr *call = _block->CALL(base, args);
714         _block->MOVE(r, call);
715         r->type = call->type;
716         _expr.code = r;
717     }
718
719     return false;
720 }
721
722 bool QDeclarativeV4IRBuilder::visit(AST::PostIncrementExpression *)
723 {
724     return false;
725 }
726
727 bool QDeclarativeV4IRBuilder::visit(AST::PostDecrementExpression *)
728 {
729     return false;
730 }
731
732 bool QDeclarativeV4IRBuilder::visit(AST::DeleteExpression *)
733 {
734     return false;
735 }
736
737 bool QDeclarativeV4IRBuilder::visit(AST::VoidExpression *)
738 {
739     return false;
740 }
741
742 bool QDeclarativeV4IRBuilder::visit(AST::TypeOfExpression *)
743 {
744     return false;
745 }
746
747 bool QDeclarativeV4IRBuilder::visit(AST::PreIncrementExpression *)
748 {
749     return false;
750 }
751
752 bool QDeclarativeV4IRBuilder::visit(AST::PreDecrementExpression *)
753 {
754     return false;
755 }
756
757 bool QDeclarativeV4IRBuilder::visit(AST::UnaryPlusExpression *ast)
758 {
759     ExprResult expr = expression(ast->expression);
760     if (expr.isNot(IR::InvalidType)) {
761         if (expr.code->asConst() != 0) {
762             _expr = expr;
763             return false;
764         }
765
766         IR::Expr *code = _block->UNOP(IR::OpUPlus, expr);
767         _expr.code = _block->TEMP(code->type);
768         _block->MOVE(_expr, code);
769     }
770
771     return false;
772 }
773
774 bool QDeclarativeV4IRBuilder::visit(AST::UnaryMinusExpression *ast)
775 {
776     ExprResult expr = expression(ast->expression);
777     if (expr.isNot(IR::InvalidType)) {
778         if (IR::Const *c = expr.code->asConst()) {
779             _expr = expr;
780             _expr.code = _block->CONST(-c->value);
781             return false;
782         }
783
784         IR::Expr *code = _block->UNOP(IR::OpUMinus, expr);
785         _expr.code = _block->TEMP(code->type);
786         _block->MOVE(_expr, code);
787     }
788
789     return false;
790 }
791
792 bool QDeclarativeV4IRBuilder::visit(AST::TildeExpression *ast)
793 {
794     ExprResult expr = expression(ast->expression);
795     if (expr.isNot(IR::InvalidType)) {
796         if (IR::Const *c = expr.code->asConst()) {
797             _expr = expr;
798             _expr.code = _block->CONST(~int(c->value));
799             return false;
800         }
801         IR::Expr *code = _block->UNOP(IR::OpCompl, expr);
802         _expr.code = _block->TEMP(code->type);
803         _block->MOVE(_expr, code);
804     }
805
806     return false;
807 }
808
809 bool QDeclarativeV4IRBuilder::visit(AST::NotExpression *ast)
810 {
811     ExprResult expr = expression(ast->expression);
812
813     if (expr.isNot(IR::InvalidType)) {
814         if (IR::Const *c = expr.code->asConst()) {
815             _expr = expr;
816             _expr.code = _block->CONST(!c->value);
817             return false;
818         }
819
820         IR::Expr *code = _block->UNOP(IR::OpNot, expr);
821         _expr.code = _block->TEMP(code->type);
822         _block->MOVE(_expr, code);
823
824     } else if (expr.hint == ExprResult::cx) {
825         expr.format = ExprResult::cx;
826         _block->CJUMP(_block->UNOP(IR::OpNot, expr), _expr.iftrue, _expr.iffalse);
827         return false;
828     }
829
830     return false;
831 }
832
833 void QDeclarativeV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult right)
834 {
835     if (IR::Type t = maxType(left.type(), right.type())) {
836         implicitCvt(left, t);
837         implicitCvt(right, t);
838
839         if (_expr.hint == ExprResult::cx) {
840             _expr.format = ExprResult::cx;
841             _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse);
842         } else {
843             IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
844             _expr.code = _block->TEMP(code->type);
845             _block->MOVE(_expr.code, code);
846         }
847     }
848 }
849
850 bool QDeclarativeV4IRBuilder::visit(AST::BinaryExpression *ast)
851 {
852     switch (ast->op) {
853     case QSOperator::And: {
854         if (_expr.hint == ExprResult::cx) {
855             _expr.format = ExprResult::cx;
856
857             Q_ASSERT(_expr.iffalse != 0);
858             Q_ASSERT(_expr.iftrue != 0);
859
860             IR::BasicBlock *iftrue = _function->newBasicBlock();
861             condition(ast->left, iftrue, _expr.iffalse);
862
863             _block = iftrue;
864             condition(ast->right, _expr.iftrue, _expr.iffalse);
865         } else {
866             IR::BasicBlock *iftrue = _function->newBasicBlock();
867             IR::BasicBlock *iffalse = _function->newBasicBlock();
868             IR::BasicBlock *endif = _function->newBasicBlock();
869
870             condition(ast->left, iftrue, iffalse);
871
872             IR::Temp *r = _block->TEMP(IR::InvalidType);
873
874             _block = iffalse;
875             _block->MOVE(r, _block->CONST(0)); // ### use the right null value
876             _block->JUMP(endif);
877
878             _block = iftrue;
879             ExprResult right = expression(ast->right);
880             _block->MOVE(r, right);
881             _block->JUMP(endif);
882
883             _block = endif;
884
885             r->type = right.type(); // ### not exactly, it can be IR::BoolType.
886             _expr.code = r;
887         }
888     } break;
889
890     case QSOperator::Or: {
891         IR::BasicBlock *iftrue = _function->newBasicBlock();
892         IR::BasicBlock *endif = _function->newBasicBlock();
893
894         ExprResult left = expression(ast->left);
895         IR::Temp *r = _block->TEMP(left.type());
896         _block->MOVE(r, left);
897
898         IR::Expr *cond = r;
899         if (r->type != IR::BoolType) {
900             cond = _block->TEMP(IR::BoolType);
901             _block->MOVE(cond, r);
902         }
903
904         _block->CJUMP(_block->UNOP(IR::OpNot, cond), iftrue, endif);
905
906         _block = iftrue;
907         ExprResult right = expression(ast->right);
908         _block->MOVE(r, right);
909
910         if (left.type() != right.type())
911             discard();
912
913         _expr.code = r;
914
915         _block = endif;
916     } break;
917
918     case QSOperator::Lt:
919     case QSOperator::Gt:
920     case QSOperator::Le:
921     case QSOperator::Ge: {
922         ExprResult left = expression(ast->left);
923         ExprResult right = expression(ast->right);
924         if (left.type() == IR::StringType && right.type() == IR::StringType) {
925             binop(ast, left, right);
926         } else if (left.isValid() && right.isValid()) {
927             implicitCvt(left, IR::RealType);
928             implicitCvt(right, IR::RealType);
929             binop(ast, left, right);
930         }
931     } break;
932
933     case QSOperator::NotEqual:
934     case QSOperator::Equal: {
935         ExprResult left = expression(ast->left);
936         ExprResult right = expression(ast->right);
937         if ((left.type() == IR::NullType || left.type() == IR::UndefinedType) &&
938                 (right.type() == IR::NullType || right.type() == IR::UndefinedType)) {
939             const bool isEq = ast->op == QSOperator::Equal;
940             if (_expr.hint == ExprResult::cx) {
941                 _expr.format = ExprResult::cx;
942                 _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse);
943             } else {
944                 _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0);
945             }
946         } else if ((left.type() == IR::StringType && right.type() >= IR::FirstNumberType) ||
947                    (left.type() >= IR::FirstNumberType && right.type() == IR::StringType)) {
948             implicitCvt(left, IR::RealType);
949             implicitCvt(right, IR::RealType);
950             binop(ast, left, right);
951         } else if (left.type() == IR::BoolType || right.type() == IR::BoolType) {
952             implicitCvt(left, IR::BoolType);
953             implicitCvt(right, IR::BoolType);
954         } else if (left.isValid() && right.isValid()) {
955             binop(ast, left, right);
956         }
957     } break;
958
959     case QSOperator::StrictEqual:
960     case QSOperator::StrictNotEqual: {
961         ExprResult left = expression(ast->left);
962         ExprResult right = expression(ast->right);
963         if (left.type() == right.type()) {
964             binop(ast, left, right);
965         } else if (left.type() >= IR::BoolType && right.type() >= IR::BoolType) {
966             // left and right have numeric type (int or real)
967             binop(ast, left, right);
968         } else if (left.isValid() && right.isValid()) {
969             const bool isEq = ast->op == QSOperator::StrictEqual;
970             if (_expr.hint == ExprResult::cx) {
971                 _expr.format = ExprResult::cx;
972                 _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse);
973             } else {
974                 _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0);
975             }
976         }
977     } break;
978
979     case QSOperator::BitAnd:
980     case QSOperator::BitOr:
981     case QSOperator::BitXor:
982     case QSOperator::LShift:
983     case QSOperator::RShift:
984     case QSOperator::URShift: {
985         ExprResult left = expression(ast->left);
986         if (left.is(IR::InvalidType))
987             return false;
988
989         ExprResult right = expression(ast->right);
990         if (right.is(IR::InvalidType))
991             return false;
992
993         implicitCvt(left, IR::IntType);
994         implicitCvt(right, IR::IntType);
995
996         IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
997         _expr.code = _block->TEMP(code->type);
998         _block->MOVE(_expr.code, code);
999
1000     } break;
1001
1002     case QSOperator::Add: {
1003         ExprResult left = expression(ast->left);
1004         if (left.is(IR::InvalidType))
1005             return false;
1006
1007         ExprResult right = expression(ast->right);
1008         if (right.is(IR::InvalidType))
1009             return false;
1010
1011         if (left.isPrimitive() && right.isPrimitive()) {
1012             if (left.type() == IR::StringType || right.type() == IR::StringType) {
1013                 implicitCvt(left, IR::StringType);
1014                 implicitCvt(right, IR::StringType);
1015             }
1016             binop(ast, left, right);
1017         }
1018     } break;
1019
1020     case QSOperator::Div:
1021     case QSOperator::Mod:
1022     case QSOperator::Mul:
1023     case QSOperator::Sub: {
1024         ExprResult left = expression(ast->left);
1025         if (left.is(IR::InvalidType))
1026             return false;
1027
1028         ExprResult right = expression(ast->right);
1029         if (right.is(IR::InvalidType))
1030             return false;
1031
1032         IR::Type t = maxType(left.type(), right.type());
1033         if (t >= IR::FirstNumberType) {
1034             implicitCvt(left, IR::RealType);
1035             implicitCvt(right, IR::RealType);
1036
1037             IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
1038             _expr.code = _block->TEMP(code->type);
1039             _block->MOVE(_expr.code, code);
1040         }
1041     } break;
1042
1043     case QSOperator::In:
1044     case QSOperator::InstanceOf:
1045     case QSOperator::Assign:
1046     case QSOperator::InplaceAnd:
1047     case QSOperator::InplaceSub:
1048     case QSOperator::InplaceDiv:
1049     case QSOperator::InplaceAdd:
1050     case QSOperator::InplaceLeftShift:
1051     case QSOperator::InplaceMod:
1052     case QSOperator::InplaceMul:
1053     case QSOperator::InplaceOr:
1054     case QSOperator::InplaceRightShift:
1055     case QSOperator::InplaceURightShift:
1056     case QSOperator::InplaceXor:
1057         // yup, we don't do those.
1058         break;
1059     } // switch
1060
1061     return false;
1062 }
1063
1064 bool QDeclarativeV4IRBuilder::visit(AST::ConditionalExpression *ast)
1065 {
1066     IR::BasicBlock *iftrue = _function->newBasicBlock();
1067     IR::BasicBlock *iffalse = _function->newBasicBlock();
1068     IR::BasicBlock *endif = _function->newBasicBlock();
1069
1070     condition(ast->expression, iftrue, iffalse);
1071
1072     IR::Temp *r = _block->TEMP(IR::InvalidType);
1073
1074     qSwap(_block, iftrue);
1075     ExprResult ok = expression(ast->ok);
1076     _block->MOVE(r, ok);
1077     _block->JUMP(endif);
1078     qSwap(_block, iftrue);
1079
1080     qSwap(_block, iffalse);
1081     ExprResult ko = expression(ast->ko);
1082     _block->MOVE(r, ko);
1083     _block->JUMP(endif);
1084     qSwap(_block, iffalse);
1085
1086     r->type = maxType(ok.type(), ko.type());
1087     _expr.code = r;
1088
1089     _block = endif;
1090
1091     return false;
1092 }
1093
1094 bool QDeclarativeV4IRBuilder::visit(AST::Expression *ast)
1095 {
1096     _block->EXP(expression(ast->left));
1097     _expr = expression(ast->right);
1098
1099     return false;
1100 }
1101
1102
1103 // statements
1104 bool QDeclarativeV4IRBuilder::visit(AST::Block *ast)
1105 {
1106     if (ast->statements && ! ast->statements->next) {
1107         // we have one and only one statement
1108         accept(ast->statements->statement);
1109     }
1110
1111     return false;
1112 }
1113
1114 bool QDeclarativeV4IRBuilder::visit(AST::StatementList *)
1115 {
1116     return false;
1117 }
1118
1119 bool QDeclarativeV4IRBuilder::visit(AST::VariableStatement *)
1120 {
1121     return false;
1122 }
1123
1124 bool QDeclarativeV4IRBuilder::visit(AST::VariableDeclarationList *)
1125 {
1126     return false;
1127 }
1128
1129 bool QDeclarativeV4IRBuilder::visit(AST::VariableDeclaration *)
1130 {
1131     return false;
1132 }
1133
1134 bool QDeclarativeV4IRBuilder::visit(AST::EmptyStatement *)
1135 {
1136     return false;
1137 }
1138
1139 bool QDeclarativeV4IRBuilder::visit(AST::ExpressionStatement *ast)
1140 {
1141     if (ast->expression) {
1142          // return the value of this expression
1143         return true;
1144     }
1145
1146     return false;
1147 }
1148
1149 bool QDeclarativeV4IRBuilder::visit(AST::IfStatement *ast)
1150 {
1151     if (! ast->ko) {
1152         // This is an if statement without an else branch.
1153         discard();
1154     } else {
1155         IR::BasicBlock *iftrue = _function->newBasicBlock();
1156         IR::BasicBlock *iffalse = _function->newBasicBlock();
1157         IR::BasicBlock *endif = _function->newBasicBlock();
1158
1159         condition(ast->expression, iftrue, iffalse);
1160
1161         IR::Temp *r = _block->TEMP(IR::InvalidType);
1162
1163         qSwap(_block, iftrue);
1164         ExprResult ok = statement(ast->ok);
1165         _block->MOVE(r, ok);
1166         _block->JUMP(endif);
1167         qSwap(_block, iftrue);
1168
1169         qSwap(_block, iffalse);
1170         ExprResult ko = statement(ast->ko);
1171         _block->MOVE(r, ko);
1172         _block->JUMP(endif);
1173         qSwap(_block, iffalse);
1174
1175         r->type = maxType(ok.type(), ko.type());
1176         _expr.code = r;
1177
1178         _block = endif;
1179     }
1180
1181     return false;
1182 }
1183
1184 bool QDeclarativeV4IRBuilder::visit(AST::DoWhileStatement *)
1185 {
1186     return false;
1187 }
1188
1189 bool QDeclarativeV4IRBuilder::visit(AST::WhileStatement *)
1190 {
1191     return false;
1192 }
1193
1194 bool QDeclarativeV4IRBuilder::visit(AST::ForStatement *)
1195 {
1196     return false;
1197 }
1198
1199 bool QDeclarativeV4IRBuilder::visit(AST::LocalForStatement *)
1200 {
1201     return false;
1202 }
1203
1204 bool QDeclarativeV4IRBuilder::visit(AST::ForEachStatement *)
1205 {
1206     return false;
1207 }
1208
1209 bool QDeclarativeV4IRBuilder::visit(AST::LocalForEachStatement *)
1210 {
1211     discard();
1212     return false;
1213 }
1214
1215 bool QDeclarativeV4IRBuilder::visit(AST::ContinueStatement *)
1216 {
1217     return false;
1218 }
1219
1220 bool QDeclarativeV4IRBuilder::visit(AST::BreakStatement *)
1221 {
1222     return false;
1223 }
1224
1225 bool QDeclarativeV4IRBuilder::visit(AST::ReturnStatement *ast)
1226 {
1227     if (ast->expression) {
1228         // return the value of the expression
1229         return true;
1230     }
1231
1232     return false;
1233 }
1234
1235 bool QDeclarativeV4IRBuilder::visit(AST::WithStatement *)
1236 {
1237     return false;
1238 }
1239
1240 bool QDeclarativeV4IRBuilder::visit(AST::SwitchStatement *)
1241 {
1242     return false;
1243 }
1244
1245 bool QDeclarativeV4IRBuilder::visit(AST::CaseBlock *)
1246 {
1247     return false;
1248 }
1249
1250 bool QDeclarativeV4IRBuilder::visit(AST::CaseClauses *)
1251 {
1252     return false;
1253 }
1254
1255 bool QDeclarativeV4IRBuilder::visit(AST::CaseClause *)
1256 {
1257     return false;
1258 }
1259
1260 bool QDeclarativeV4IRBuilder::visit(AST::DefaultClause *)
1261 {
1262     return false;
1263 }
1264
1265 bool QDeclarativeV4IRBuilder::visit(AST::LabelledStatement *)
1266 {
1267     return false;
1268 }
1269
1270 bool QDeclarativeV4IRBuilder::visit(AST::ThrowStatement *)
1271 {
1272     return false;
1273 }
1274
1275 bool QDeclarativeV4IRBuilder::visit(AST::TryStatement *)
1276 {
1277     return false;
1278 }
1279
1280 bool QDeclarativeV4IRBuilder::visit(AST::Catch *)
1281 {
1282     return false;
1283 }
1284
1285 bool QDeclarativeV4IRBuilder::visit(AST::Finally *)
1286 {
1287     return false;
1288 }
1289
1290 bool QDeclarativeV4IRBuilder::visit(AST::FunctionDeclaration *)
1291 {
1292     return false;
1293 }
1294
1295 bool QDeclarativeV4IRBuilder::visit(AST::FunctionExpression *)
1296 {
1297     return false;
1298 }
1299
1300 bool QDeclarativeV4IRBuilder::visit(AST::FormalParameterList *)
1301 {
1302     return false;
1303 }
1304
1305 bool QDeclarativeV4IRBuilder::visit(AST::FunctionBody *)
1306 {
1307     return false;
1308 }
1309
1310 bool QDeclarativeV4IRBuilder::visit(AST::DebuggerStatement *)
1311 {
1312     return false;
1313 }
1314
1315 QT_END_NAMESPACE