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