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