452cb43150a2e18f4be88c9eb9273d9b87b09989
[profile/ivi/qtdeclarative.git] / src / declarative / qml / v4 / qv4irbuilder.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
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/qdeclarativemetatype_p.h>
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 == QDeclarativeMetaType::QQuickAnchorLineMetaTypeId())
76             return IR::SGAnchorLineType;
77         else if (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
318 // JS
319 bool QV4IRBuilder::visit(AST::Program *)
320 {
321     Q_ASSERT(!"unreachable");
322     return false;
323 }
324
325 bool QV4IRBuilder::visit(AST::SourceElements *)
326 {
327     Q_ASSERT(!"unreachable");
328     return false;
329 }
330
331 bool QV4IRBuilder::visit(AST::FunctionSourceElement *)
332 {
333     Q_ASSERT(!"unreachable");
334     return false;
335 }
336
337 bool QV4IRBuilder::visit(AST::StatementSourceElement *)
338 {
339     Q_ASSERT(!"unreachable");
340     return false;
341 }
342
343 // object literals
344 bool QV4IRBuilder::visit(AST::PropertyNameAndValueList *)
345 {
346     Q_ASSERT(!"unreachable");
347     return false;
348 }
349
350 bool QV4IRBuilder::visit(AST::IdentifierPropertyName *)
351 {
352     Q_ASSERT(!"unreachable");
353     return false;
354 }
355
356 bool QV4IRBuilder::visit(AST::StringLiteralPropertyName *)
357 {
358     Q_ASSERT(!"unreachable");
359     return false;
360 }
361
362 bool QV4IRBuilder::visit(AST::NumericLiteralPropertyName *)
363 {
364     Q_ASSERT(!"unreachable");
365     return false;
366 }
367
368
369 // array literals
370 bool QV4IRBuilder::visit(AST::ElementList *)
371 {
372     Q_ASSERT(!"unreachable");
373     return false;
374 }
375
376 bool QV4IRBuilder::visit(AST::Elision *)
377 {
378     Q_ASSERT(!"unreachable");
379     return false;
380 }
381
382
383 // function calls
384 bool QV4IRBuilder::visit(AST::ArgumentList *)
385 {
386     Q_ASSERT(!"unreachable");
387     return false;
388 }
389
390 // expressions
391 bool QV4IRBuilder::visit(AST::ObjectLiteral *)
392 {
393     return false;
394 }
395
396 bool QV4IRBuilder::visit(AST::ArrayLiteral *)
397 {
398     return false;
399 }
400
401 bool QV4IRBuilder::visit(AST::ThisExpression *)
402 {
403     return false;
404 }
405
406 bool QV4IRBuilder::visit(AST::IdentifierExpression *ast)
407 {
408     const quint32 line = ast->identifierToken.startLine;
409     const quint32 column = ast->identifierToken.startColumn;
410
411     const QString name = ast->name.toString();
412
413     if (name.at(0) == QLatin1Char('u') && name.length() == 9 && name == QLatin1String("undefined")) {
414         _expr.code = _block->CONST(IR::UndefinedType, 0); // ### undefined value
415     } else if (m_engine->v8engine()->illegalNames().contains(name) ) {
416         if (qmlVerboseCompiler()) qWarning() << "*** illegal symbol:" << name;
417         return false;
418     } else if (const QDeclarativeScript::Object *obj = m_expression->ids->value(name)) {
419         IR::Name *code = _block->ID_OBJECT(name, obj, line, column);
420         if (obj == m_expression->component)
421             code->storage = IR::Name::RootStorage;
422         _expr.code = code;
423     } else {
424
425         QDeclarativeTypeNameCache::Result r = m_expression->importCache->query(name);
426         if (r.isValid()) {
427             if (r.type) {
428                 _expr.code = _block->ATTACH_TYPE(name, r.type, IR::Name::ScopeStorage, line, column);
429             }
430             // We don't support anything else
431         } else {
432             bool found = false;
433
434             if (m_expression->context != m_expression->component) {
435                 // RootStorage is more efficient than ScopeStorage, so prefer that if they are the same
436                 QDeclarativePropertyCache *cache = m_expression->context->synthCache;
437                 const QMetaObject *metaObject = m_expression->context->metaObject();
438                 if (!cache) cache = m_engine->cache(metaObject);
439
440                 QDeclarativePropertyData *data = cache->property(name);
441
442                 if (data && data->revision != 0) {
443                     if (qmlVerboseCompiler()) 
444                         qWarning() << "*** versioned symbol:" << name;
445                     discard();
446                     return false;
447                 }
448
449                 if (data && !data->isFunction()) {
450                     IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
451                     _expr.code = _block->SYMBOL(irType, name, metaObject, data, IR::Name::ScopeStorage, line, column);
452                     found = true;
453                 } 
454             }
455
456             if (!found) {
457                 QDeclarativePropertyCache *cache = m_expression->component->synthCache;
458                 const QMetaObject *metaObject = m_expression->component->metaObject();
459                 if (!cache) cache = m_engine->cache(metaObject);
460
461                 QDeclarativePropertyData *data = cache->property(name);
462
463                 if (data && data->revision != 0) {
464                     if (qmlVerboseCompiler()) 
465                         qWarning() << "*** versioned symbol:" << name;
466                     discard();
467                     return false;
468                 }
469
470                 if (data && !data->isFunction()) {
471                     IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
472                     _expr.code = _block->SYMBOL(irType, name, metaObject, data, IR::Name::RootStorage, line, column);
473                     found = true;
474                 } 
475             }
476
477             if (!found && qmlVerboseCompiler())
478                 qWarning() << "*** unknown symbol:" << name;
479         }
480     }
481
482     if (_expr.code && _expr.hint == ExprResult::cx) {
483         _expr.format = ExprResult::cx;
484
485         if (_expr.type() != IR::BoolType) {
486             IR::Temp *t = _block->TEMP(IR::BoolType);
487             _block->MOVE(t, _expr);
488             _expr.code = t;
489         }
490
491         _block->CJUMP(_expr.code, _expr.iftrue, _expr.iffalse);
492         _expr.code = 0;
493     }
494
495     return false;
496 }
497
498 bool QV4IRBuilder::visit(AST::NullExpression *)
499 {
500     // ### TODO: cx format
501     _expr.code = _block->CONST(IR::NullType, 0);
502     return false;
503 }
504
505 bool QV4IRBuilder::visit(AST::TrueLiteral *)
506 {
507     // ### TODO: cx format
508     _expr.code = _block->CONST(IR::BoolType, 1);
509     return false;
510 }
511
512 bool QV4IRBuilder::visit(AST::FalseLiteral *)
513 {
514     // ### TODO: cx format
515     _expr.code = _block->CONST(IR::BoolType, 0);
516     return false;
517 }
518
519 bool QV4IRBuilder::visit(AST::StringLiteral *ast)
520 {
521     // ### TODO: cx format
522     _expr.code = _block->STRING(ast->value);
523     return false;
524 }
525
526 bool QV4IRBuilder::visit(AST::NumericLiteral *ast)
527 {
528     if (_expr.hint == ExprResult::cx) {
529         _expr.format = ExprResult::cx;
530         _block->JUMP(ast->value ? _expr.iftrue : _expr.iffalse);
531     } else {
532         _expr.code = _block->CONST(ast->value);
533     }
534     return false;
535 }
536
537 bool QV4IRBuilder::visit(AST::RegExpLiteral *)
538 {
539     return false;
540 }
541
542 bool QV4IRBuilder::visit(AST::NestedExpression *)
543 {
544     return true; // the value of the nested expression
545 }
546
547 bool QV4IRBuilder::visit(AST::ArrayMemberExpression *)
548 {
549     return false;
550 }
551
552 bool QV4IRBuilder::visit(AST::FieldMemberExpression *ast)
553 {
554     if (IR::Expr *left = expression(ast->base)) {
555         if (IR::Name *baseName = left->asName()) {
556             const quint32 line = ast->identifierToken.startLine;
557             const quint32 column = ast->identifierToken.startColumn;
558
559             QString name = ast->name.toString();
560
561             switch(baseName->symbol) {
562             case IR::Name::Unbound:
563                 break;
564
565             case IR::Name::AttachType:
566                 if (name.at(0).isUpper()) {
567                     QByteArray utf8Name = name.toUtf8();
568                     const char *enumName = utf8Name.constData();
569
570                     const QMetaObject *meta = baseName->declarativeType->metaObject();
571                     bool found = false;
572                     for (int ii = 0; !found && ii < meta->enumeratorCount(); ++ii) {
573                         QMetaEnum e = meta->enumerator(ii);
574                         for (int jj = 0; !found && jj < e.keyCount(); ++jj) {
575                             if (0 == strcmp(e.key(jj), enumName)) {
576                                 found = true;
577                                 _expr.code = _block->CONST(IR::IntType, e.value(jj));
578                             }
579                         }
580                     }
581
582                     if (!found && qmlVerboseCompiler())
583                         qWarning() << "*** unresolved enum:" 
584                                    << (*baseName->id + QLatin1String(".") + ast->name.toString());
585                 } else if(const QMetaObject *attachedMeta = baseName->declarativeType->attachedPropertiesType()) {
586                     QDeclarativePropertyCache *cache = m_engine->cache(attachedMeta);
587                     QDeclarativePropertyData *data = cache->property(name);
588
589                     if (!data || data->isFunction())
590                         return false; // Don't support methods (or non-existing properties ;)
591
592                     if(!data->isFinal()) {
593                         if (qmlVerboseCompiler())
594                             qWarning() << "*** non-final attached property:"
595                                        << (*baseName->id + QLatin1String(".") + ast->name.toString());
596                         return false; // We don't know enough about this property
597                     }
598
599                     IR::Type irType = irTypeFromVariantType(data->propType, m_engine, attachedMeta);
600                     _expr.code = _block->SYMBOL(baseName, irType, name, attachedMeta, data, line, column);
601                 }
602                 break;
603
604             case IR::Name::IdObject: {
605                 const QDeclarativeScript::Object *idObject = baseName->idObject;
606                 QDeclarativePropertyCache *cache = 
607                     idObject->synthCache?idObject->synthCache:m_engine->cache(idObject->metaObject());
608
609                 QDeclarativePropertyData *data = cache->property(name);
610
611                 if (!data || data->isFunction())
612                     return false; // Don't support methods (or non-existing properties ;)
613
614                 if (data->revision != 0) {
615                     if (qmlVerboseCompiler()) 
616                         qWarning() << "*** versioned symbol:" << name;
617                     discard();
618                     return false;
619                 }
620
621                 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, idObject->metaObject());
622                 _expr.code = _block->SYMBOL(baseName, irType, name,
623                                             idObject->metaObject(), data, line, column);
624                 }
625                 break;
626
627             case IR::Name::Property: 
628                 if (baseName->type == IR::ObjectType && baseName->meta && baseName->property->isFinal()) {
629                     QDeclarativePropertyCache *cache = m_engine->cache(baseName->meta);
630                     if (!cache)
631                         return false;
632
633                     if (QDeclarativePropertyData *data = cache->property(name)) {
634                         if (!data->isFinal()) {
635                             if (qmlVerboseCompiler())
636                                 qWarning() << "*** non-final property access:"
637                                            << (*baseName->id + QLatin1String(".") + ast->name.toString());
638                             return false; // We don't know enough about this property
639                         }
640
641                         IR::Type irType = irTypeFromVariantType(data->propType, m_engine, baseName->meta);
642                         _expr.code = _block->SYMBOL(baseName, irType, name,
643                                                     baseName->meta, data, line, column);
644                     }
645                 }
646                 break;
647
648             case IR::Name::Object: 
649             case IR::Name::Slot:
650                 break;
651             }
652         }
653     }
654
655     return false;
656 }
657
658 bool QV4IRBuilder::preVisit(AST::Node *)
659 {
660     return ! _discard;
661 }
662
663 bool QV4IRBuilder::visit(AST::NewMemberExpression *)
664 {
665     return false;
666 }
667
668 bool QV4IRBuilder::visit(AST::NewExpression *)
669 {
670     return false;
671 }
672
673 bool QV4IRBuilder::visit(AST::CallExpression *ast)
674 {
675     QList<QStringRef> names;
676     QList<AST::ExpressionNode *> nameNodes;
677
678     names.reserve(4);
679     nameNodes.reserve(4);
680
681     if (buildName(names, ast->base, &nameNodes)) {
682         //ExprResult base = expression(ast->base);
683         QString id;
684         for (int i = 0; i < names.size(); ++i) {
685             if (! i)
686                 id += QLatin1Char('.');
687             id += names.at(i);
688         }
689         const AST::SourceLocation loc = nameNodes.last()->firstSourceLocation();
690         IR::Expr *base = _block->NAME(id, loc.startLine, loc.startColumn);
691
692         IR::ExprList *args = 0, **argsInserter = &args;
693         for (AST::ArgumentList *it = ast->arguments; it; it = it->next) {
694             IR::Expr *arg = expression(it->expression);
695             *argsInserter = _function->pool->New<IR::ExprList>();
696             (*argsInserter)->init(arg);
697             argsInserter = &(*argsInserter)->next;
698         }
699
700         IR::Temp *r = _block->TEMP(IR::InvalidType);
701         IR::Expr *call = _block->CALL(base, args);
702         _block->MOVE(r, call);
703         r->type = call->type;
704         _expr.code = r;
705     }
706
707     return false;
708 }
709
710 bool QV4IRBuilder::visit(AST::PostIncrementExpression *)
711 {
712     return false;
713 }
714
715 bool QV4IRBuilder::visit(AST::PostDecrementExpression *)
716 {
717     return false;
718 }
719
720 bool QV4IRBuilder::visit(AST::DeleteExpression *)
721 {
722     return false;
723 }
724
725 bool QV4IRBuilder::visit(AST::VoidExpression *)
726 {
727     return false;
728 }
729
730 bool QV4IRBuilder::visit(AST::TypeOfExpression *)
731 {
732     return false;
733 }
734
735 bool QV4IRBuilder::visit(AST::PreIncrementExpression *)
736 {
737     return false;
738 }
739
740 bool QV4IRBuilder::visit(AST::PreDecrementExpression *)
741 {
742     return false;
743 }
744
745 bool QV4IRBuilder::visit(AST::UnaryPlusExpression *ast)
746 {
747     ExprResult expr = expression(ast->expression);
748     if (expr.isNot(IR::InvalidType)) {
749         if (expr.code->asConst() != 0) {
750             _expr = expr;
751             return false;
752         }
753
754         IR::Expr *code = _block->UNOP(IR::OpUPlus, expr);
755         _expr.code = _block->TEMP(code->type);
756         _block->MOVE(_expr, code);
757     }
758
759     return false;
760 }
761
762 bool QV4IRBuilder::visit(AST::UnaryMinusExpression *ast)
763 {
764     ExprResult expr = expression(ast->expression);
765     if (expr.isNot(IR::InvalidType)) {
766         if (IR::Const *c = expr.code->asConst()) {
767             _expr = expr;
768             _expr.code = _block->CONST(-c->value);
769             return false;
770         }
771
772         IR::Expr *code = _block->UNOP(IR::OpUMinus, expr);
773         _expr.code = _block->TEMP(code->type);
774         _block->MOVE(_expr, code);
775     }
776
777     return false;
778 }
779
780 bool QV4IRBuilder::visit(AST::TildeExpression *ast)
781 {
782     ExprResult expr = expression(ast->expression);
783     if (expr.isNot(IR::InvalidType)) {
784         if (IR::Const *c = expr.code->asConst()) {
785             _expr = expr;
786             _expr.code = _block->CONST(~int(c->value));
787             return false;
788         }
789         IR::Expr *code = _block->UNOP(IR::OpCompl, expr);
790         _expr.code = _block->TEMP(code->type);
791         _block->MOVE(_expr, code);
792     }
793
794     return false;
795 }
796
797 bool QV4IRBuilder::visit(AST::NotExpression *ast)
798 {
799     ExprResult expr = expression(ast->expression);
800
801     if (expr.isNot(IR::InvalidType)) {
802         if (IR::Const *c = expr.code->asConst()) {
803             _expr = expr;
804             _expr.code = _block->CONST(!c->value);
805             return false;
806         }
807
808         IR::Expr *code = _block->UNOP(IR::OpNot, expr);
809         _expr.code = _block->TEMP(code->type);
810         _block->MOVE(_expr, code);
811
812     } else if (expr.hint == ExprResult::cx) {
813         expr.format = ExprResult::cx;
814         _block->CJUMP(_block->UNOP(IR::OpNot, expr), _expr.iftrue, _expr.iffalse);
815         return false;
816     }
817
818     return false;
819 }
820
821 void QV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult right)
822 {
823     if (IR::Type t = maxType(left.type(), right.type())) {
824         implicitCvt(left, t);
825         implicitCvt(right, t);
826
827         if (_expr.hint == ExprResult::cx) {
828             _expr.format = ExprResult::cx;
829             _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse);
830         } else {
831             IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
832             _expr.code = _block->TEMP(code->type);
833             _block->MOVE(_expr.code, code);
834         }
835     }
836 }
837
838 bool QV4IRBuilder::visit(AST::BinaryExpression *ast)
839 {
840     switch (ast->op) {
841     case QSOperator::And: {
842         if (_expr.hint == ExprResult::cx) {
843             _expr.format = ExprResult::cx;
844
845             Q_ASSERT(_expr.iffalse != 0);
846             Q_ASSERT(_expr.iftrue != 0);
847
848             IR::BasicBlock *iftrue = _function->newBasicBlock();
849             condition(ast->left, iftrue, _expr.iffalse);
850
851             _block = iftrue;
852             condition(ast->right, _expr.iftrue, _expr.iffalse);
853         } else {
854             IR::BasicBlock *iftrue = _function->newBasicBlock();
855             IR::BasicBlock *iffalse = _function->newBasicBlock();
856             IR::BasicBlock *endif = _function->newBasicBlock();
857
858             condition(ast->left, iftrue, iffalse);
859
860             IR::Temp *r = _block->TEMP(IR::InvalidType);
861
862             _block = iffalse;
863             _block->MOVE(r, _block->CONST(0)); // ### use the right null value
864             _block->JUMP(endif);
865
866             _block = iftrue;
867             ExprResult right = expression(ast->right);
868             _block->MOVE(r, right);
869             _block->JUMP(endif);
870
871             _block = endif;
872
873             r->type = right.type(); // ### not exactly, it can be IR::BoolType.
874             _expr.code = r;
875         }
876     } break;
877
878     case QSOperator::Or: {
879         IR::BasicBlock *iftrue = _function->newBasicBlock();
880         IR::BasicBlock *endif = _function->newBasicBlock();
881
882         ExprResult left = expression(ast->left);
883         IR::Temp *r = _block->TEMP(left.type());
884         _block->MOVE(r, left);
885
886         IR::Expr *cond = r;
887         if (r->type != IR::BoolType) {
888             cond = _block->TEMP(IR::BoolType);
889             _block->MOVE(cond, r);
890         }
891
892         _block->CJUMP(_block->UNOP(IR::OpNot, cond), iftrue, endif);
893
894         _block = iftrue;
895         ExprResult right = expression(ast->right);
896         _block->MOVE(r, right);
897
898         if (left.type() != right.type())
899             discard();
900
901         _expr.code = r;
902
903         _block = endif;
904     } break;
905
906     case QSOperator::Lt:
907     case QSOperator::Gt:
908     case QSOperator::Le:
909     case QSOperator::Ge: {
910         ExprResult left = expression(ast->left);
911         ExprResult right = expression(ast->right);
912         if (left.type() == IR::StringType && right.type() == IR::StringType) {
913             binop(ast, left, right);
914         } else if (left.isValid() && right.isValid()) {
915             implicitCvt(left, IR::RealType);
916             implicitCvt(right, IR::RealType);
917             binop(ast, left, right);
918         }
919     } break;
920
921     case QSOperator::NotEqual:
922     case QSOperator::Equal: {
923         ExprResult left = expression(ast->left);
924         ExprResult right = expression(ast->right);
925         if ((left.type() == IR::NullType || left.type() == IR::UndefinedType) &&
926                 (right.type() == IR::NullType || right.type() == IR::UndefinedType)) {
927             const bool isEq = ast->op == QSOperator::Equal;
928             if (_expr.hint == ExprResult::cx) {
929                 _expr.format = ExprResult::cx;
930                 _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse);
931             } else {
932                 _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0);
933             }
934         } else if ((left.type() == IR::StringType && right.type() >= IR::FirstNumberType) ||
935                    (left.type() >= IR::FirstNumberType && right.type() == IR::StringType)) {
936             implicitCvt(left, IR::RealType);
937             implicitCvt(right, IR::RealType);
938             binop(ast, left, right);
939         } else if (left.type() == IR::BoolType || right.type() == IR::BoolType) {
940             implicitCvt(left, IR::BoolType);
941             implicitCvt(right, IR::BoolType);
942         } else if (left.isValid() && right.isValid()) {
943             binop(ast, left, right);
944         }
945     } break;
946
947     case QSOperator::StrictEqual:
948     case QSOperator::StrictNotEqual: {
949         ExprResult left = expression(ast->left);
950         ExprResult right = expression(ast->right);
951         if (left.type() == right.type()) {
952             binop(ast, left, right);
953         } else if (left.type() >= IR::BoolType && right.type() >= IR::BoolType) {
954             // left and right have numeric type (int or real)
955             binop(ast, left, right);
956         } else if (left.isValid() && right.isValid()) {
957             const bool isEq = ast->op == QSOperator::StrictEqual;
958             if (_expr.hint == ExprResult::cx) {
959                 _expr.format = ExprResult::cx;
960                 _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse);
961             } else {
962                 _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0);
963             }
964         }
965     } break;
966
967     case QSOperator::BitAnd:
968     case QSOperator::BitOr:
969     case QSOperator::BitXor:
970     case QSOperator::LShift:
971     case QSOperator::RShift:
972     case QSOperator::URShift: {
973         ExprResult left = expression(ast->left);
974         if (left.is(IR::InvalidType))
975             return false;
976
977         ExprResult right = expression(ast->right);
978         if (right.is(IR::InvalidType))
979             return false;
980
981         implicitCvt(left, IR::IntType);
982         implicitCvt(right, IR::IntType);
983
984         IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
985         _expr.code = _block->TEMP(code->type);
986         _block->MOVE(_expr.code, code);
987
988     } break;
989
990     case QSOperator::Add: {
991         ExprResult left = expression(ast->left);
992         if (left.is(IR::InvalidType))
993             return false;
994
995         ExprResult right = expression(ast->right);
996         if (right.is(IR::InvalidType))
997             return false;
998
999         if (left.isPrimitive() && right.isPrimitive()) {
1000             if (left.type() == IR::StringType || right.type() == IR::StringType) {
1001                 implicitCvt(left, IR::StringType);
1002                 implicitCvt(right, IR::StringType);
1003             }
1004             binop(ast, left, right);
1005         }
1006     } break;
1007
1008     case QSOperator::Div:
1009     case QSOperator::Mod:
1010     case QSOperator::Mul:
1011     case QSOperator::Sub: {
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         IR::Type t = maxType(left.type(), right.type());
1021         if (t >= IR::FirstNumberType) {
1022             implicitCvt(left, IR::RealType);
1023             implicitCvt(right, IR::RealType);
1024
1025             IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
1026             _expr.code = _block->TEMP(code->type);
1027             _block->MOVE(_expr.code, code);
1028         }
1029     } break;
1030
1031     case QSOperator::In:
1032     case QSOperator::InstanceOf:
1033     case QSOperator::Assign:
1034     case QSOperator::InplaceAnd:
1035     case QSOperator::InplaceSub:
1036     case QSOperator::InplaceDiv:
1037     case QSOperator::InplaceAdd:
1038     case QSOperator::InplaceLeftShift:
1039     case QSOperator::InplaceMod:
1040     case QSOperator::InplaceMul:
1041     case QSOperator::InplaceOr:
1042     case QSOperator::InplaceRightShift:
1043     case QSOperator::InplaceURightShift:
1044     case QSOperator::InplaceXor:
1045         // yup, we don't do those.
1046         break;
1047     } // switch
1048
1049     return false;
1050 }
1051
1052 bool QV4IRBuilder::visit(AST::ConditionalExpression *ast)
1053 {
1054     IR::BasicBlock *iftrue = _function->newBasicBlock();
1055     IR::BasicBlock *iffalse = _function->newBasicBlock();
1056     IR::BasicBlock *endif = _function->newBasicBlock();
1057
1058     condition(ast->expression, iftrue, iffalse);
1059
1060     IR::Temp *r = _block->TEMP(IR::InvalidType);
1061
1062     qSwap(_block, iftrue);
1063     ExprResult ok = expression(ast->ok);
1064     _block->MOVE(r, ok);
1065     _block->JUMP(endif);
1066     qSwap(_block, iftrue);
1067
1068     qSwap(_block, iffalse);
1069     ExprResult ko = expression(ast->ko);
1070     _block->MOVE(r, ko);
1071     _block->JUMP(endif);
1072     qSwap(_block, iffalse);
1073
1074     r->type = maxType(ok.type(), ko.type());
1075     _expr.code = r;
1076
1077     _block = endif;
1078
1079     return false;
1080 }
1081
1082 bool QV4IRBuilder::visit(AST::Expression *ast)
1083 {
1084     _block->EXP(expression(ast->left));
1085     _expr = expression(ast->right);
1086
1087     return false;
1088 }
1089
1090
1091 // statements
1092 bool QV4IRBuilder::visit(AST::Block *ast)
1093 {
1094     if (ast->statements && ! ast->statements->next) {
1095         // we have one and only one statement
1096         accept(ast->statements->statement);
1097     }
1098
1099     return false;
1100 }
1101
1102 bool QV4IRBuilder::visit(AST::StatementList *)
1103 {
1104     return false;
1105 }
1106
1107 bool QV4IRBuilder::visit(AST::VariableStatement *)
1108 {
1109     return false;
1110 }
1111
1112 bool QV4IRBuilder::visit(AST::VariableDeclarationList *)
1113 {
1114     return false;
1115 }
1116
1117 bool QV4IRBuilder::visit(AST::VariableDeclaration *)
1118 {
1119     return false;
1120 }
1121
1122 bool QV4IRBuilder::visit(AST::EmptyStatement *)
1123 {
1124     return false;
1125 }
1126
1127 bool QV4IRBuilder::visit(AST::ExpressionStatement *ast)
1128 {
1129     if (ast->expression) {
1130          // return the value of this expression
1131         return true;
1132     }
1133
1134     return false;
1135 }
1136
1137 bool QV4IRBuilder::visit(AST::IfStatement *ast)
1138 {
1139     if (! ast->ko) {
1140         // This is an if statement without an else branch.
1141         discard();
1142     } else {
1143         IR::BasicBlock *iftrue = _function->newBasicBlock();
1144         IR::BasicBlock *iffalse = _function->newBasicBlock();
1145         IR::BasicBlock *endif = _function->newBasicBlock();
1146
1147         condition(ast->expression, iftrue, iffalse);
1148
1149         IR::Temp *r = _block->TEMP(IR::InvalidType);
1150
1151         qSwap(_block, iftrue);
1152         ExprResult ok = statement(ast->ok);
1153         _block->MOVE(r, ok);
1154         _block->JUMP(endif);
1155         qSwap(_block, iftrue);
1156
1157         qSwap(_block, iffalse);
1158         ExprResult ko = statement(ast->ko);
1159         _block->MOVE(r, ko);
1160         _block->JUMP(endif);
1161         qSwap(_block, iffalse);
1162
1163         r->type = maxType(ok.type(), ko.type());
1164         _expr.code = r;
1165
1166         _block = endif;
1167     }
1168
1169     return false;
1170 }
1171
1172 bool QV4IRBuilder::visit(AST::DoWhileStatement *)
1173 {
1174     return false;
1175 }
1176
1177 bool QV4IRBuilder::visit(AST::WhileStatement *)
1178 {
1179     return false;
1180 }
1181
1182 bool QV4IRBuilder::visit(AST::ForStatement *)
1183 {
1184     return false;
1185 }
1186
1187 bool QV4IRBuilder::visit(AST::LocalForStatement *)
1188 {
1189     return false;
1190 }
1191
1192 bool QV4IRBuilder::visit(AST::ForEachStatement *)
1193 {
1194     return false;
1195 }
1196
1197 bool QV4IRBuilder::visit(AST::LocalForEachStatement *)
1198 {
1199     discard();
1200     return false;
1201 }
1202
1203 bool QV4IRBuilder::visit(AST::ContinueStatement *)
1204 {
1205     return false;
1206 }
1207
1208 bool QV4IRBuilder::visit(AST::BreakStatement *)
1209 {
1210     return false;
1211 }
1212
1213 bool QV4IRBuilder::visit(AST::ReturnStatement *ast)
1214 {
1215     if (ast->expression) {
1216         // return the value of the expression
1217         return true;
1218     }
1219
1220     return false;
1221 }
1222
1223 bool QV4IRBuilder::visit(AST::WithStatement *)
1224 {
1225     return false;
1226 }
1227
1228 bool QV4IRBuilder::visit(AST::SwitchStatement *)
1229 {
1230     return false;
1231 }
1232
1233 bool QV4IRBuilder::visit(AST::CaseBlock *)
1234 {
1235     return false;
1236 }
1237
1238 bool QV4IRBuilder::visit(AST::CaseClauses *)
1239 {
1240     return false;
1241 }
1242
1243 bool QV4IRBuilder::visit(AST::CaseClause *)
1244 {
1245     return false;
1246 }
1247
1248 bool QV4IRBuilder::visit(AST::DefaultClause *)
1249 {
1250     return false;
1251 }
1252
1253 bool QV4IRBuilder::visit(AST::LabelledStatement *)
1254 {
1255     return false;
1256 }
1257
1258 bool QV4IRBuilder::visit(AST::ThrowStatement *)
1259 {
1260     return false;
1261 }
1262
1263 bool QV4IRBuilder::visit(AST::TryStatement *)
1264 {
1265     return false;
1266 }
1267
1268 bool QV4IRBuilder::visit(AST::Catch *)
1269 {
1270     return false;
1271 }
1272
1273 bool QV4IRBuilder::visit(AST::Finally *)
1274 {
1275     return false;
1276 }
1277
1278 bool QV4IRBuilder::visit(AST::FunctionDeclaration *)
1279 {
1280     return false;
1281 }
1282
1283 bool QV4IRBuilder::visit(AST::FunctionExpression *)
1284 {
1285     return false;
1286 }
1287
1288 bool QV4IRBuilder::visit(AST::FormalParameterList *)
1289 {
1290     return false;
1291 }
1292
1293 bool QV4IRBuilder::visit(AST::FunctionBody *)
1294 {
1295     return false;
1296 }
1297
1298 bool QV4IRBuilder::visit(AST::DebuggerStatement *)
1299 {
1300     return false;
1301 }
1302
1303 QT_END_NAMESPACE