Introduce methods to get the source location of the AST nodes.
[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/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) {
629                     QDeclarativePropertyData *data = baseName->property;
630                     if (!data || data->isFunction())
631                         return false; // Don't support methods (or non-existing properties ;)
632
633                     if(!data->isFinal()) {
634                         if (qmlVerboseCompiler())
635                             qWarning() << "*** non-final property access:"
636                                 << (*baseName->id + QLatin1String(".") + ast->name.toString());
637                         return false; // We don't know enough about this property
638                     }
639
640                     IR::Type irType = irTypeFromVariantType(data->propType, m_engine, baseName->meta);
641                     _expr.code = _block->SYMBOL(baseName, irType, name,
642                                                 baseName->meta, data, line, column);
643                 }
644                 break;
645
646             case IR::Name::Object: 
647             case IR::Name::Slot:
648                 break;
649             }
650         }
651     }
652
653     return false;
654 }
655
656 bool QV4IRBuilder::preVisit(AST::Node *)
657 {
658     return ! _discard;
659 }
660
661 bool QV4IRBuilder::visit(AST::NewMemberExpression *)
662 {
663     return false;
664 }
665
666 bool QV4IRBuilder::visit(AST::NewExpression *)
667 {
668     return false;
669 }
670
671 bool QV4IRBuilder::visit(AST::CallExpression *ast)
672 {
673     QList<QStringRef> names;
674     QList<AST::ExpressionNode *> nameNodes;
675
676     names.reserve(4);
677     nameNodes.reserve(4);
678
679     if (buildName(names, ast->base, &nameNodes)) {
680         //ExprResult base = expression(ast->base);
681         QString id;
682         for (int i = 0; i < names.size(); ++i) {
683             if (! i)
684                 id += QLatin1Char('.');
685             id += names.at(i);
686         }
687         const AST::SourceLocation loc = nameNodes.last()->firstSourceLocation();
688         IR::Expr *base = _block->NAME(id, loc.startLine, loc.startColumn);
689
690         IR::ExprList *args = 0, **argsInserter = &args;
691         for (AST::ArgumentList *it = ast->arguments; it; it = it->next) {
692             IR::Expr *arg = expression(it->expression);
693             *argsInserter = _function->pool->New<IR::ExprList>();
694             (*argsInserter)->init(arg);
695             argsInserter = &(*argsInserter)->next;
696         }
697
698         IR::Temp *r = _block->TEMP(IR::InvalidType);
699         IR::Expr *call = _block->CALL(base, args);
700         _block->MOVE(r, call);
701         r->type = call->type;
702         _expr.code = r;
703     }
704
705     return false;
706 }
707
708 bool QV4IRBuilder::visit(AST::PostIncrementExpression *)
709 {
710     return false;
711 }
712
713 bool QV4IRBuilder::visit(AST::PostDecrementExpression *)
714 {
715     return false;
716 }
717
718 bool QV4IRBuilder::visit(AST::DeleteExpression *)
719 {
720     return false;
721 }
722
723 bool QV4IRBuilder::visit(AST::VoidExpression *)
724 {
725     return false;
726 }
727
728 bool QV4IRBuilder::visit(AST::TypeOfExpression *)
729 {
730     return false;
731 }
732
733 bool QV4IRBuilder::visit(AST::PreIncrementExpression *)
734 {
735     return false;
736 }
737
738 bool QV4IRBuilder::visit(AST::PreDecrementExpression *)
739 {
740     return false;
741 }
742
743 bool QV4IRBuilder::visit(AST::UnaryPlusExpression *ast)
744 {
745     ExprResult expr = expression(ast->expression);
746     if (expr.isNot(IR::InvalidType)) {
747         if (expr.code->asConst() != 0) {
748             _expr = expr;
749             return false;
750         }
751
752         IR::Expr *code = _block->UNOP(IR::OpUPlus, expr);
753         _expr.code = _block->TEMP(code->type);
754         _block->MOVE(_expr, code);
755     }
756
757     return false;
758 }
759
760 bool QV4IRBuilder::visit(AST::UnaryMinusExpression *ast)
761 {
762     ExprResult expr = expression(ast->expression);
763     if (expr.isNot(IR::InvalidType)) {
764         if (IR::Const *c = expr.code->asConst()) {
765             _expr = expr;
766             _expr.code = _block->CONST(-c->value);
767             return false;
768         }
769
770         IR::Expr *code = _block->UNOP(IR::OpUMinus, expr);
771         _expr.code = _block->TEMP(code->type);
772         _block->MOVE(_expr, code);
773     }
774
775     return false;
776 }
777
778 bool QV4IRBuilder::visit(AST::TildeExpression *ast)
779 {
780     ExprResult expr = expression(ast->expression);
781     if (expr.isNot(IR::InvalidType)) {
782         if (IR::Const *c = expr.code->asConst()) {
783             _expr = expr;
784             _expr.code = _block->CONST(~int(c->value));
785             return false;
786         }
787         IR::Expr *code = _block->UNOP(IR::OpCompl, expr);
788         _expr.code = _block->TEMP(code->type);
789         _block->MOVE(_expr, code);
790     }
791
792     return false;
793 }
794
795 bool QV4IRBuilder::visit(AST::NotExpression *ast)
796 {
797     ExprResult expr = expression(ast->expression);
798
799     if (expr.isNot(IR::InvalidType)) {
800         if (IR::Const *c = expr.code->asConst()) {
801             _expr = expr;
802             _expr.code = _block->CONST(!c->value);
803             return false;
804         }
805
806         IR::Expr *code = _block->UNOP(IR::OpNot, expr);
807         _expr.code = _block->TEMP(code->type);
808         _block->MOVE(_expr, code);
809
810     } else if (expr.hint == ExprResult::cx) {
811         expr.format = ExprResult::cx;
812         _block->CJUMP(_block->UNOP(IR::OpNot, expr), _expr.iftrue, _expr.iffalse);
813         return false;
814     }
815
816     return false;
817 }
818
819 void QV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult right)
820 {
821     if (IR::Type t = maxType(left.type(), right.type())) {
822         implicitCvt(left, t);
823         implicitCvt(right, t);
824
825         if (_expr.hint == ExprResult::cx) {
826             _expr.format = ExprResult::cx;
827             _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse);
828         } else {
829             IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
830             _expr.code = _block->TEMP(code->type);
831             _block->MOVE(_expr.code, code);
832         }
833     }
834 }
835
836 bool QV4IRBuilder::visit(AST::BinaryExpression *ast)
837 {
838     switch (ast->op) {
839     case QSOperator::And: {
840         if (_expr.hint == ExprResult::cx) {
841             _expr.format = ExprResult::cx;
842
843             Q_ASSERT(_expr.iffalse != 0);
844             Q_ASSERT(_expr.iftrue != 0);
845
846             IR::BasicBlock *iftrue = _function->newBasicBlock();
847             condition(ast->left, iftrue, _expr.iffalse);
848
849             _block = iftrue;
850             condition(ast->right, _expr.iftrue, _expr.iffalse);
851         } else {
852             IR::BasicBlock *iftrue = _function->newBasicBlock();
853             IR::BasicBlock *iffalse = _function->newBasicBlock();
854             IR::BasicBlock *endif = _function->newBasicBlock();
855
856             condition(ast->left, iftrue, iffalse);
857
858             IR::Temp *r = _block->TEMP(IR::InvalidType);
859
860             _block = iffalse;
861             _block->MOVE(r, _block->CONST(0)); // ### use the right null value
862             _block->JUMP(endif);
863
864             _block = iftrue;
865             ExprResult right = expression(ast->right);
866             _block->MOVE(r, right);
867             _block->JUMP(endif);
868
869             _block = endif;
870
871             r->type = right.type(); // ### not exactly, it can be IR::BoolType.
872             _expr.code = r;
873         }
874     } break;
875
876     case QSOperator::Or: {
877         IR::BasicBlock *iftrue = _function->newBasicBlock();
878         IR::BasicBlock *endif = _function->newBasicBlock();
879
880         ExprResult left = expression(ast->left);
881         IR::Temp *r = _block->TEMP(left.type());
882         _block->MOVE(r, left);
883
884         IR::Expr *cond = r;
885         if (r->type != IR::BoolType) {
886             cond = _block->TEMP(IR::BoolType);
887             _block->MOVE(cond, r);
888         }
889
890         _block->CJUMP(_block->UNOP(IR::OpNot, cond), iftrue, endif);
891
892         _block = iftrue;
893         ExprResult right = expression(ast->right);
894         _block->MOVE(r, right);
895
896         if (left.type() != right.type())
897             discard();
898
899         _expr.code = r;
900
901         _block = endif;
902     } break;
903
904     case QSOperator::Lt:
905     case QSOperator::Gt:
906     case QSOperator::Le:
907     case QSOperator::Ge: {
908         ExprResult left = expression(ast->left);
909         ExprResult right = expression(ast->right);
910         if (left.type() == IR::StringType && right.type() == IR::StringType) {
911             binop(ast, left, right);
912         } else if (left.isValid() && right.isValid()) {
913             implicitCvt(left, IR::RealType);
914             implicitCvt(right, IR::RealType);
915             binop(ast, left, right);
916         }
917     } break;
918
919     case QSOperator::NotEqual:
920     case QSOperator::Equal: {
921         ExprResult left = expression(ast->left);
922         ExprResult right = expression(ast->right);
923         if ((left.type() == IR::NullType || left.type() == IR::UndefinedType) &&
924                 (right.type() == IR::NullType || right.type() == IR::UndefinedType)) {
925             const bool isEq = ast->op == QSOperator::Equal;
926             if (_expr.hint == ExprResult::cx) {
927                 _expr.format = ExprResult::cx;
928                 _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse);
929             } else {
930                 _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0);
931             }
932         } else if ((left.type() == IR::StringType && right.type() >= IR::FirstNumberType) ||
933                    (left.type() >= IR::FirstNumberType && right.type() == IR::StringType)) {
934             implicitCvt(left, IR::RealType);
935             implicitCvt(right, IR::RealType);
936             binop(ast, left, right);
937         } else if (left.type() == IR::BoolType || right.type() == IR::BoolType) {
938             implicitCvt(left, IR::BoolType);
939             implicitCvt(right, IR::BoolType);
940         } else if (left.isValid() && right.isValid()) {
941             binop(ast, left, right);
942         }
943     } break;
944
945     case QSOperator::StrictEqual:
946     case QSOperator::StrictNotEqual: {
947         ExprResult left = expression(ast->left);
948         ExprResult right = expression(ast->right);
949         if (left.type() == right.type()) {
950             binop(ast, left, right);
951         } else if (left.type() >= IR::BoolType && right.type() >= IR::BoolType) {
952             // left and right have numeric type (int or real)
953             binop(ast, left, right);
954         } else if (left.isValid() && right.isValid()) {
955             const bool isEq = ast->op == QSOperator::StrictEqual;
956             if (_expr.hint == ExprResult::cx) {
957                 _expr.format = ExprResult::cx;
958                 _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse);
959             } else {
960                 _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0);
961             }
962         }
963     } break;
964
965     case QSOperator::BitAnd:
966     case QSOperator::BitOr:
967     case QSOperator::BitXor:
968     case QSOperator::LShift:
969     case QSOperator::RShift:
970     case QSOperator::URShift: {
971         ExprResult left = expression(ast->left);
972         if (left.is(IR::InvalidType))
973             return false;
974
975         ExprResult right = expression(ast->right);
976         if (right.is(IR::InvalidType))
977             return false;
978
979         implicitCvt(left, IR::IntType);
980         implicitCvt(right, IR::IntType);
981
982         IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
983         _expr.code = _block->TEMP(code->type);
984         _block->MOVE(_expr.code, code);
985
986     } break;
987
988     case QSOperator::Add: {
989         ExprResult left = expression(ast->left);
990         if (left.is(IR::InvalidType))
991             return false;
992
993         ExprResult right = expression(ast->right);
994         if (right.is(IR::InvalidType))
995             return false;
996
997         if (left.isPrimitive() && right.isPrimitive()) {
998             if (left.type() == IR::StringType || right.type() == IR::StringType) {
999                 implicitCvt(left, IR::StringType);
1000                 implicitCvt(right, IR::StringType);
1001             }
1002             binop(ast, left, right);
1003         }
1004     } break;
1005
1006     case QSOperator::Div:
1007     case QSOperator::Mod:
1008     case QSOperator::Mul:
1009     case QSOperator::Sub: {
1010         ExprResult left = expression(ast->left);
1011         if (left.is(IR::InvalidType))
1012             return false;
1013
1014         ExprResult right = expression(ast->right);
1015         if (right.is(IR::InvalidType))
1016             return false;
1017
1018         IR::Type t = maxType(left.type(), right.type());
1019         if (t >= IR::FirstNumberType) {
1020             implicitCvt(left, IR::RealType);
1021             implicitCvt(right, IR::RealType);
1022
1023             IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
1024             _expr.code = _block->TEMP(code->type);
1025             _block->MOVE(_expr.code, code);
1026         }
1027     } break;
1028
1029     case QSOperator::In:
1030     case QSOperator::InstanceOf:
1031     case QSOperator::Assign:
1032     case QSOperator::InplaceAnd:
1033     case QSOperator::InplaceSub:
1034     case QSOperator::InplaceDiv:
1035     case QSOperator::InplaceAdd:
1036     case QSOperator::InplaceLeftShift:
1037     case QSOperator::InplaceMod:
1038     case QSOperator::InplaceMul:
1039     case QSOperator::InplaceOr:
1040     case QSOperator::InplaceRightShift:
1041     case QSOperator::InplaceURightShift:
1042     case QSOperator::InplaceXor:
1043         // yup, we don't do those.
1044         break;
1045     } // switch
1046
1047     return false;
1048 }
1049
1050 bool QV4IRBuilder::visit(AST::ConditionalExpression *ast)
1051 {
1052     IR::BasicBlock *iftrue = _function->newBasicBlock();
1053     IR::BasicBlock *iffalse = _function->newBasicBlock();
1054     IR::BasicBlock *endif = _function->newBasicBlock();
1055
1056     condition(ast->expression, iftrue, iffalse);
1057
1058     IR::Temp *r = _block->TEMP(IR::InvalidType);
1059
1060     qSwap(_block, iftrue);
1061     ExprResult ok = expression(ast->ok);
1062     _block->MOVE(r, ok);
1063     _block->JUMP(endif);
1064     qSwap(_block, iftrue);
1065
1066     qSwap(_block, iffalse);
1067     ExprResult ko = expression(ast->ko);
1068     _block->MOVE(r, ko);
1069     _block->JUMP(endif);
1070     qSwap(_block, iffalse);
1071
1072     r->type = maxType(ok.type(), ko.type());
1073     _expr.code = r;
1074
1075     _block = endif;
1076
1077     return false;
1078 }
1079
1080 bool QV4IRBuilder::visit(AST::Expression *ast)
1081 {
1082     _block->EXP(expression(ast->left));
1083     _expr = expression(ast->right);
1084
1085     return false;
1086 }
1087
1088
1089 // statements
1090 bool QV4IRBuilder::visit(AST::Block *ast)
1091 {
1092     if (ast->statements && ! ast->statements->next) {
1093         // we have one and only one statement
1094         accept(ast->statements->statement);
1095     }
1096
1097     return false;
1098 }
1099
1100 bool QV4IRBuilder::visit(AST::StatementList *)
1101 {
1102     return false;
1103 }
1104
1105 bool QV4IRBuilder::visit(AST::VariableStatement *)
1106 {
1107     return false;
1108 }
1109
1110 bool QV4IRBuilder::visit(AST::VariableDeclarationList *)
1111 {
1112     return false;
1113 }
1114
1115 bool QV4IRBuilder::visit(AST::VariableDeclaration *)
1116 {
1117     return false;
1118 }
1119
1120 bool QV4IRBuilder::visit(AST::EmptyStatement *)
1121 {
1122     return false;
1123 }
1124
1125 bool QV4IRBuilder::visit(AST::ExpressionStatement *ast)
1126 {
1127     if (ast->expression) {
1128          // return the value of this expression
1129         return true;
1130     }
1131
1132     return false;
1133 }
1134
1135 bool QV4IRBuilder::visit(AST::IfStatement *ast)
1136 {
1137     if (! ast->ko) {
1138         // This is an if statement without an else branch.
1139         discard();
1140     } else {
1141         IR::BasicBlock *iftrue = _function->newBasicBlock();
1142         IR::BasicBlock *iffalse = _function->newBasicBlock();
1143         IR::BasicBlock *endif = _function->newBasicBlock();
1144
1145         condition(ast->expression, iftrue, iffalse);
1146
1147         IR::Temp *r = _block->TEMP(IR::InvalidType);
1148
1149         qSwap(_block, iftrue);
1150         ExprResult ok = statement(ast->ok);
1151         _block->MOVE(r, ok);
1152         _block->JUMP(endif);
1153         qSwap(_block, iftrue);
1154
1155         qSwap(_block, iffalse);
1156         ExprResult ko = statement(ast->ko);
1157         _block->MOVE(r, ko);
1158         _block->JUMP(endif);
1159         qSwap(_block, iffalse);
1160
1161         r->type = maxType(ok.type(), ko.type());
1162         _expr.code = r;
1163
1164         _block = endif;
1165     }
1166
1167     return false;
1168 }
1169
1170 bool QV4IRBuilder::visit(AST::DoWhileStatement *)
1171 {
1172     return false;
1173 }
1174
1175 bool QV4IRBuilder::visit(AST::WhileStatement *)
1176 {
1177     return false;
1178 }
1179
1180 bool QV4IRBuilder::visit(AST::ForStatement *)
1181 {
1182     return false;
1183 }
1184
1185 bool QV4IRBuilder::visit(AST::LocalForStatement *)
1186 {
1187     return false;
1188 }
1189
1190 bool QV4IRBuilder::visit(AST::ForEachStatement *)
1191 {
1192     return false;
1193 }
1194
1195 bool QV4IRBuilder::visit(AST::LocalForEachStatement *)
1196 {
1197     discard();
1198     return false;
1199 }
1200
1201 bool QV4IRBuilder::visit(AST::ContinueStatement *)
1202 {
1203     return false;
1204 }
1205
1206 bool QV4IRBuilder::visit(AST::BreakStatement *)
1207 {
1208     return false;
1209 }
1210
1211 bool QV4IRBuilder::visit(AST::ReturnStatement *ast)
1212 {
1213     if (ast->expression) {
1214         // return the value of the expression
1215         return true;
1216     }
1217
1218     return false;
1219 }
1220
1221 bool QV4IRBuilder::visit(AST::WithStatement *)
1222 {
1223     return false;
1224 }
1225
1226 bool QV4IRBuilder::visit(AST::SwitchStatement *)
1227 {
1228     return false;
1229 }
1230
1231 bool QV4IRBuilder::visit(AST::CaseBlock *)
1232 {
1233     return false;
1234 }
1235
1236 bool QV4IRBuilder::visit(AST::CaseClauses *)
1237 {
1238     return false;
1239 }
1240
1241 bool QV4IRBuilder::visit(AST::CaseClause *)
1242 {
1243     return false;
1244 }
1245
1246 bool QV4IRBuilder::visit(AST::DefaultClause *)
1247 {
1248     return false;
1249 }
1250
1251 bool QV4IRBuilder::visit(AST::LabelledStatement *)
1252 {
1253     return false;
1254 }
1255
1256 bool QV4IRBuilder::visit(AST::ThrowStatement *)
1257 {
1258     return false;
1259 }
1260
1261 bool QV4IRBuilder::visit(AST::TryStatement *)
1262 {
1263     return false;
1264 }
1265
1266 bool QV4IRBuilder::visit(AST::Catch *)
1267 {
1268     return false;
1269 }
1270
1271 bool QV4IRBuilder::visit(AST::Finally *)
1272 {
1273     return false;
1274 }
1275
1276 bool QV4IRBuilder::visit(AST::FunctionDeclaration *)
1277 {
1278     return false;
1279 }
1280
1281 bool QV4IRBuilder::visit(AST::FunctionExpression *)
1282 {
1283     return false;
1284 }
1285
1286 bool QV4IRBuilder::visit(AST::FormalParameterList *)
1287 {
1288     return false;
1289 }
1290
1291 bool QV4IRBuilder::visit(AST::FunctionBody *)
1292 {
1293     return false;
1294 }
1295
1296 bool QV4IRBuilder::visit(AST::DebuggerStatement *)
1297 {
1298     return false;
1299 }
1300
1301 QT_END_NAMESPACE