source: branches/4.5.1/src/script/qscriptcompiler.cpp@ 921

Last change on this file since 921 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 48.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtScript module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qscriptcompiler_p.h"
43
44#ifndef QT_NO_SCRIPT
45
46#include "qscriptast_p.h"
47#include "qscriptengine_p.h"
48#include "qscriptvalueimpl_p.h"
49#include "qscriptcontext_p.h"
50#include "qscriptmember_p.h"
51#include "qscriptobject_p.h"
52
53#include <QtCore/QtDebug>
54
55QT_BEGIN_NAMESPACE
56
57namespace QScript {
58
59class Compare : protected AST::Visitor
60{
61public:
62 bool operator()(AST::ExpressionNode *e1, AST::ExpressionNode *e2)
63 {
64 if (!e1 || !e2)
65 return (e1 == e2);
66
67 if (e1->kind != e2->kind)
68 return false;
69
70 m_e2 = e2;
71 m_equal = false;
72 e1->accept(this);
73 return m_equal;
74 }
75
76protected:
77 virtual bool visit(AST::ThisExpression *)
78 {
79 m_equal = true;
80 return false;
81 }
82 virtual bool visit(AST::NullExpression *)
83 {
84 m_equal = true;
85 return false;
86 }
87 virtual bool visit(AST::VoidExpression *)
88 {
89 m_equal = true;
90 return false;
91 }
92 virtual bool visit(AST::FalseLiteral *)
93 {
94 m_equal = true;
95 return false;
96 }
97 virtual bool visit(AST::TrueLiteral *)
98 {
99 m_equal = true;
100 return false;
101 }
102 virtual bool visit(AST::NumericLiteral *e1)
103 {
104 AST::NumericLiteral *e2 = static_cast<AST::NumericLiteral*>(m_e2);
105 m_equal = (e1->value == e2->value);
106 return false;
107 }
108 virtual bool visit(AST::RegExpLiteral *e1)
109 {
110 AST::RegExpLiteral *e2 = static_cast<AST::RegExpLiteral*>(m_e2);
111 m_equal = (e1->pattern == e2->pattern)
112 && (e1->flags == e2->flags);
113 return false;
114 }
115 virtual bool visit(AST::StringLiteral *e1)
116 {
117 AST::StringLiteral *e2 = static_cast<AST::StringLiteral*>(m_e2);
118 m_equal = (e1->value == e2->value);
119 return false;
120 }
121 virtual bool visit(AST::IdentifierExpression *e1)
122 {
123 AST::IdentifierExpression *e2 = static_cast<AST::IdentifierExpression*>(m_e2);
124 m_equal = (e1->name == e2->name);
125 return false;
126 }
127 virtual bool visit(AST::ArrayMemberExpression *e1)
128 {
129 AST::ArrayMemberExpression *e2 = static_cast<AST::ArrayMemberExpression*>(m_e2);
130 m_equal = operator()(e1->base, e2->base)
131 && operator()(e1->expression, e2->expression);
132 return false;
133 }
134 virtual bool visit(AST::FieldMemberExpression *e1)
135 {
136 AST::FieldMemberExpression *e2 = static_cast<AST::FieldMemberExpression*>(m_e2);
137 m_equal = (e1->name == e2->name) && operator()(e1->base, e2->base);
138 return false;
139 }
140 virtual bool visit(AST::BinaryExpression *e1)
141 {
142 AST::BinaryExpression *e2 = static_cast<AST::BinaryExpression*>(m_e2);
143 m_equal = (e1->op == e2->op) && operator()(e1->left, e2->left)
144 && operator()(e1->right, e2->right);
145 return false;
146 }
147 virtual bool visit(AST::ConditionalExpression *e1)
148 {
149 AST::ConditionalExpression *e2 = static_cast<AST::ConditionalExpression*>(m_e2);
150 m_equal = operator()(e1->expression, e2->expression)
151 && operator()(e1->ok, e2->ok)
152 && operator()(e1->ko, e2->ko);
153 return false;
154 }
155 virtual bool visit(AST::TypeOfExpression *e1)
156 {
157 AST::TypeOfExpression *e2 = static_cast<AST::TypeOfExpression*>(m_e2);
158 m_equal = operator()(e1->expression, e2->expression);
159 return false;
160 }
161 virtual bool visit(AST::UnaryPlusExpression *e1)
162 {
163 AST::UnaryPlusExpression *e2 = static_cast<AST::UnaryPlusExpression*>(m_e2);
164 m_equal = operator()(e1->expression, e2->expression);
165 return false;
166 }
167 virtual bool visit(AST::UnaryMinusExpression *e1)
168 {
169 AST::UnaryMinusExpression *e2 = static_cast<AST::UnaryMinusExpression*>(m_e2);
170 m_equal = operator()(e1->expression, e2->expression);
171 return false;
172 }
173 virtual bool visit(AST::TildeExpression *e1)
174 {
175 AST::TildeExpression *e2 = static_cast<AST::TildeExpression*>(m_e2);
176 m_equal = operator()(e1->expression, e2->expression);
177 return false;
178 }
179 virtual bool visit(AST::NotExpression *e1)
180 {
181 AST::NotExpression *e2 = static_cast<AST::NotExpression*>(m_e2);
182 m_equal = operator()(e1->expression, e2->expression);
183 return false;
184 }
185 virtual bool visit(AST::Expression *)
186 { return false; }
187 virtual bool visit(AST::ArrayLiteral *)
188 { return false; }
189 virtual bool visit(AST::ObjectLiteral *)
190 { return false; }
191 virtual bool visit(AST::CallExpression *)
192 { return false; }
193 virtual bool visit(AST::DeleteExpression *)
194 { return false; }
195 virtual bool visit(AST::FunctionExpression *)
196 { return false; }
197 virtual bool visit(AST::NewExpression *)
198 { return false; }
199 virtual bool visit(AST::NewMemberExpression *)
200 { return false; }
201 virtual bool visit(AST::PostDecrementExpression *)
202 { return false; }
203 virtual bool visit(AST::PostIncrementExpression *)
204 { return false; }
205 virtual bool visit(AST::PreDecrementExpression *)
206 { return false; }
207 virtual bool visit(AST::PreIncrementExpression *)
208 { return false; }
209
210private:
211 AST::ExpressionNode *m_e2;
212 bool m_equal;
213};
214
215class FetchName: protected AST::Visitor
216{
217public:
218 inline FetchName(QScriptEnginePrivate *e):
219 eng(e), name(0) {}
220
221 QScriptNameIdImpl *operator() (AST::PropertyName *node)
222 {
223 name = 0;
224 node->accept(this);
225 return name;
226 }
227
228protected:
229 virtual bool visit(AST::IdentifierPropertyName *node)
230 {
231 name = node->id;
232 return false;
233 }
234
235 virtual bool visit(AST::StringLiteralPropertyName *node)
236 {
237 name = node->id;
238 return false;
239 }
240
241 virtual bool visit(AST::NumericLiteralPropertyName *node)
242 {
243 name = eng->nameId(QString::number(node->id), /*persistent=*/false); // ### don't use QString::number
244 name->persistent = true; // ### remove
245 return false;
246 }
247
248private:
249 QScriptEnginePrivate *eng;
250 QScriptNameIdImpl *name;
251};
252
253class EmptySourceElements: protected AST::Visitor
254{
255public:
256 EmptySourceElements(QScriptEngine *d):
257 driver(d), empty(false) {}
258
259 inline bool operator () (AST::Node *)
260 {
261 empty = false;
262 return empty;
263 }
264
265private:
266 QScriptEngine *driver;
267 bool empty;
268};
269
270class DeclareLocals: protected AST::Visitor
271{
272public:
273 DeclareLocals(Compiler *c):
274 compiler(c),
275 eng(c->engine())
276 {
277 }
278
279 void operator () (AST::Node *node)
280 {
281 if (node)
282 node->accept(this);
283 }
284
285protected:
286 virtual bool visit(AST::FunctionDeclaration *node)
287 {
288 compiler->iDeclareLocal(node->name, /*readOnly=*/false);
289 return false;
290 }
291
292 virtual bool visit(AST::FunctionExpression *)
293 { return false; }
294
295 virtual bool visit(AST::VariableDeclaration *node)
296 {
297 compiler->iDeclareLocal(node->name, node->readOnly);
298 return false;
299 }
300
301private:
302 Compiler *compiler;
303 QScriptEnginePrivate *eng;
304};
305
306Compiler::Compiler(QScriptEnginePrivate *eng):
307 m_eng(eng),
308 m_generateReferences(0), m_iterationStatement(0),
309 m_switchStatement(0), m_withStatement(0),
310 m_generateLeaveWithOnBreak(0), m_generateFastArgumentLookup(0),
311 m_parseStatements(0), m_pad(0),
312 m_topLevelCompiler(false),
313 m_activeLoop(0)
314{
315}
316
317Compiler::~Compiler()
318{
319}
320
321bool Compiler::topLevelCompiler() const
322{
323 return m_topLevelCompiler;
324}
325
326void Compiler::setTopLevelCompiler(bool b)
327{
328 m_topLevelCompiler = b;
329}
330
331 CompilationUnit Compiler::compile(AST::Node *node, const QList<QScriptNameIdImpl *> &formals)
332{
333 m_formals = formals;
334 m_generateReferences = 0;
335 m_iterationStatement = 0;
336 m_switchStatement = 0;
337 m_withStatement = 0;
338 m_generateLeaveWithOnBreak = 0;
339 m_generateFastArgumentLookup = 0;
340 m_parseStatements = 0;
341 m_pad = 0;
342 m_instructions.clear();
343 m_exceptionHandlers.clear();
344 m_generateFastArgumentLookup = false; // ### !formals.isEmpty(); // ### disabled for now.. it's buggy :(
345
346 m_compilationUnit = CompilationUnit();
347
348 if (node)
349 node->accept(this);
350
351 // add a terminator
352 if (topLevelCompiler()) {
353 iHalt();
354 } else if (m_instructions.isEmpty() || m_instructions.last().op != QScriptInstruction::OP_Ret) {
355 iLoadUndefined();
356 iRet();
357 }
358
359 m_compilationUnit.setInstructions(m_instructions);
360 m_compilationUnit.setExceptionHandlers(m_exceptionHandlers);
361 return m_compilationUnit;
362}
363
364bool Compiler::preVisit(AST::Node *)
365{
366 return m_compilationUnit.isValid();
367}
368
369bool Compiler::visit(AST::SourceElements *node)
370{
371 DeclareLocals declareLocals(this);
372 declareLocals(node);
373
374 bool was = changeParseStatements(false);
375
376 for (AST::SourceElements *it = node; it != 0; it = it->next)
377 it->element->accept(this);
378
379 changeParseStatements(true);
380
381 for (AST::SourceElements *it = node; it != 0; it = it->next)
382 it->element->accept(this);
383
384 changeParseStatements(was);
385
386 return false;
387}
388
389bool Compiler::visit(AST::StatementList *)
390{
391 return true;
392}
393
394bool Compiler::visit(AST::FunctionSourceElement *)
395{
396 return m_parseStatements == 0;
397}
398
399bool Compiler::visit(AST::StatementSourceElement *)
400{
401 return m_parseStatements;
402}
403
404bool Compiler::visit(AST::ThisExpression *)
405{
406 iLoadThis();
407 return false;
408}
409
410bool Compiler::visit(AST::NullExpression *)
411{
412 iLoadNull();
413 return false;
414}
415
416bool Compiler::visit(AST::RegExpLiteral *node)
417{
418 Q_ASSERT(node->pattern != 0);
419
420 if (node->flags)
421 iNewRegExp(node->pattern, node->flags);
422 else
423 iNewRegExp(node->pattern);
424
425 return false;
426}
427
428bool Compiler::visit(AST::NumericLiteral *node)
429{
430 iLoadNumber(node->value);
431 return false;
432}
433
434bool Compiler::visit(AST::StringLiteral *node)
435{
436 iNewString(node->value);
437
438 return false;
439}
440
441bool Compiler::visit(AST::ObjectLiteral *node)
442{
443 iNewObject();
444
445 FetchName fetchName(m_eng);
446 bool was = generateReferences(false);
447 for (AST::PropertyNameAndValueList *it = node->properties; it != 0; it = it->next) {
448 iLine(it->value);
449 iDuplicate();
450
451 QScriptNameIdImpl *name = fetchName(it->name);
452 Q_ASSERT(name != 0);
453 iLoadString(name);
454 iMakeReference();
455
456 it->value->accept(this);
457 iPutField();
458 }
459 generateReferences(was);
460
461 return false;
462}
463
464bool Compiler::visit(AST::IdentifierExpression *node)
465{
466 Q_ASSERT(node->name != 0);
467
468 if (node->name == m_eng->idTable()->id_arguments)
469 iLazyArguments();
470 if (m_generateReferences)
471 iResolve(node->name);
472 else
473 iFetch(node->name);
474
475 return false;
476}
477
478bool Compiler::visit(AST::FunctionDeclaration *node)
479{
480 iLoadActivation();
481 iLoadString(node->name);
482 iMakeReference();
483 iNewClosure(node);
484 iPutField();
485 return false;
486}
487
488bool Compiler::visit(AST::FunctionExpression *node)
489{
490 iNewClosure(node);
491 if (node->name) {
492 iDuplicate();
493 iLoadActivation();
494 iSwap();
495 iLoadString(node->name);
496 iSwap();
497 iMakeReference();
498 iSwap();
499 iPutField();
500 }
501 return false;
502}
503
504bool Compiler::visit(AST::CallExpression *node)
505{
506 bool was = generateReferences(true);
507 node->base->accept(this);
508 generateReferences(false);
509
510 int argc = 0;
511 for (AST::ArgumentList *it = node->arguments; it != 0; it = it->next) {
512 it->expression->accept(this);
513 ++argc;
514 }
515
516 generateReferences(was);
517
518 iCall(argc);
519 return false;
520}
521
522bool Compiler::visit(AST::NewExpression *node)
523{
524 bool was = generateReferences(true);
525 node->expression->accept(this);
526 generateReferences(was);
527 iNew(0);
528 return false;
529}
530
531bool Compiler::visit(AST::NewMemberExpression *node)
532{
533 bool was = generateReferences(true);
534 node->base->accept(this);
535 generateReferences(false);
536
537 int argc = 0;
538 for (AST::ArgumentList *it = node->arguments; it != 0; it = it->next) {
539 it->expression->accept(this);
540 ++argc;
541 }
542
543 generateReferences(was);
544
545 iNew(argc);
546 return false;
547}
548
549bool Compiler::visit(AST::FieldMemberExpression *node)
550{
551 bool was = generateReferences(false);
552 node->base->accept(this);
553 generateReferences(was);
554
555 iLoadString(node->name);
556
557 if (! was)
558 iFetchField();
559 else
560 iMakeReference();
561
562 return false;
563}
564
565bool Compiler::visit(AST::ArrayMemberExpression *node)
566{
567 bool was = generateReferences(false);
568 node->base->accept(this);
569 node->expression->accept(this);
570 generateReferences(was);
571
572 if (! was)
573 iFetchField();
574 else
575 iMakeReference();
576
577 return false;
578}
579
580bool Compiler::visit(AST::PostIncrementExpression *node)
581{
582 bool was = generateReferences(true);
583 node->base->accept(this);
584 generateReferences(was);
585 iPostIncr();
586
587 return false;
588}
589
590bool Compiler::visit(AST::PostDecrementExpression *node)
591{
592 bool was = generateReferences(true);
593 node->base->accept(this);
594 generateReferences(was);
595 iPostDecr();
596
597 return false;
598}
599
600bool Compiler::visit(AST::PreIncrementExpression *node)
601{
602 bool was = generateReferences(true);
603 node->expression->accept(this);
604 generateReferences(was);
605 iIncr();
606 return false;
607}
608
609bool Compiler::visit(AST::PreDecrementExpression *node)
610{
611 bool was = generateReferences(true);
612 node->expression->accept(this);
613 generateReferences(was);
614 iDecr();
615 return false;
616}
617
618void Compiler::endVisit(AST::NotExpression *)
619{
620 iNot();
621}
622
623void Compiler::endVisit(AST::TildeExpression *)
624{
625 iBitNot();
626}
627
628bool Compiler::visit(AST::ThrowStatement *node)
629{
630 iLine(node);
631 return true;
632}
633
634bool Compiler::visit(AST::TryStatement *node)
635{
636 int start = nextInstructionOffset();
637 if (node->statement)
638 node->statement->accept(this);
639 int end = nextInstructionOffset();
640 if (node->catchExpression) {
641 iBranch(0); // skip the catch if no exception
642 ExceptionHandlerDescriptor ehd(start, end, nextInstructionOffset());
643 m_exceptionHandlers.append(ehd);
644 iBeginCatch(node->catchExpression->name);
645 node->catchExpression->statement->accept(this);
646 iEndCatch();
647 patchInstruction(end, nextInstructionOffset() - end);
648 }
649 if (node->finallyExpression) {
650 if (!node->catchExpression) {
651 ExceptionHandlerDescriptor ehd(start, end, nextInstructionOffset());
652 m_exceptionHandlers.prepend(ehd);
653 }
654 node->finallyExpression->statement->accept(this);
655 }
656 return false;
657}
658
659void Compiler::endVisit(AST::ThrowStatement *node)
660{
661 if (! node->expression)
662 iLoadUndefined();
663
664 iThrow();
665}
666
667void Compiler::endVisit(AST::VoidExpression *)
668{
669 iPop();
670 iLoadUndefined();
671}
672
673bool Compiler::visit(AST::TypeOfExpression *node)
674{
675 bool was = generateReferences(true);
676 node->expression->accept(this);
677 generateReferences(was);
678 iTypeOf();
679 return false;
680}
681
682bool Compiler::visit(AST::DeleteExpression *node)
683{
684 bool was = generateReferences(true);
685 node->expression->accept(this);
686 generateReferences(was);
687 iDelete();
688 return false;
689}
690
691bool Compiler::visit(AST::ReturnStatement *node)
692{
693 if (topLevelCompiler()) {
694 m_compilationUnit.setError(QString::fromUtf8("return outside function body"),
695 node->startLine);
696 return false;
697 }
698 iLine(node);
699 return true;
700}
701
702void Compiler::endVisit(AST::ReturnStatement *node)
703{
704 if (! node->expression)
705 iLoadUndefined();
706
707 iRet();
708}
709
710bool Compiler::visit(AST::VariableStatement *node)
711{
712 AST::VariableDeclarationList *lst = node->declarations;
713 while (lst) {
714 if (lst->declaration->expression) {
715 iLine(node);
716 break;
717 }
718 lst = lst->next;
719 }
720 return true;
721}
722
723bool Compiler::visit(AST::VariableDeclaration *node)
724{
725 if (node->expression != 0) {
726 iResolve(node->name);
727 node->expression->accept(this);
728 iAssign();
729 iPop();
730 }
731
732 return false;
733}
734
735bool Compiler::visit(AST::ConditionalExpression *node)
736{
737 node->expression->accept(this);
738
739 int cond = nextInstructionOffset();
740 iBranchFalse(0);
741
742 node->ok->accept(this);
743
744 if (! node->ko) {
745 patchInstruction(cond, nextInstructionOffset() - cond);
746 } else {
747 int terminator = nextInstructionOffset();
748 iBranch(0);
749 node->ko->accept(this);
750
751 patchInstruction(cond, terminator + 1 - cond);
752 patchInstruction(terminator, nextInstructionOffset() - terminator);
753 }
754
755 return false;
756}
757
758bool Compiler::visit(AST::IfStatement *node)
759{
760 iLine(node);
761 node->expression->accept(this);
762
763 int cond = nextInstructionOffset();
764 iBranchFalse(0);
765
766 node->ok->accept(this);
767
768 if (! node->ko) {
769 patchInstruction(cond, nextInstructionOffset() - cond);
770 } else {
771 int terminator = nextInstructionOffset();
772 iBranch(0);
773 node->ko->accept(this);
774
775 patchInstruction(cond, terminator + 1 - cond);
776 patchInstruction(terminator, nextInstructionOffset() - terminator);
777 }
778 if (!m_instructions.isEmpty() && m_instructions.last().op == QScriptInstruction::OP_Ret)
779 iNop();
780
781 return false;
782}
783
784bool Compiler::visit(AST::Block *node)
785{
786 if (node->statements && m_loops.contains(node)) {
787 Loop &loop = m_loops[node];
788
789 node->statements->accept(this);
790
791 loop.breakLabel.offset = nextInstructionOffset();
792
793 foreach (int index, loop.breakLabel.uses) {
794 patchInstruction(index, loop.breakLabel.offset - index);
795 }
796
797 return false;
798 }
799
800 return true;
801}
802
803bool Compiler::visit(AST::WhileStatement *node)
804{
805 Loop *previousLoop = changeActiveLoop(&m_loops[node]);
806 m_activeLoop->continueLabel.offset = nextInstructionOffset();
807
808 iLine(node);
809 int again = nextInstructionOffset();
810 node->expression->accept(this);
811
812 int cond = nextInstructionOffset();
813 iBranchFalse(0);
814
815 bool was = iterationStatement(true);
816 bool was2 = generateLeaveOnBreak(false);
817 node->statement->accept(this);
818 generateLeaveOnBreak(was2);
819 iterationStatement(was);
820
821 iBranch(again - nextInstructionOffset());
822 patchInstruction(cond, nextInstructionOffset() - cond);
823
824 m_activeLoop->breakLabel.offset = nextInstructionOffset();
825
826 foreach (int index, m_activeLoop->breakLabel.uses) {
827 patchInstruction(index, m_activeLoop->breakLabel.offset - index);
828 }
829
830 foreach (int index, m_activeLoop->continueLabel.uses) {
831 patchInstruction(index, m_activeLoop->continueLabel.offset - index);
832 }
833
834 changeActiveLoop(previousLoop);
835 m_loops.remove(node);
836
837 return false;
838}
839
840bool Compiler::visit(AST::DoWhileStatement *node)
841{
842 Loop *previousLoop = changeActiveLoop(&m_loops[node]);
843 int again = nextInstructionOffset();
844 iLine(node);
845 bool was = iterationStatement(true);
846 node->statement->accept(this);
847 iterationStatement(was);
848
849 m_activeLoop->continueLabel.offset = nextInstructionOffset();
850
851 node->expression->accept(this);
852
853 iBranchTrue(again - nextInstructionOffset());
854 m_activeLoop->breakLabel.offset = nextInstructionOffset();
855
856 foreach (int index, m_activeLoop->breakLabel.uses) {
857 patchInstruction(index, m_activeLoop->breakLabel.offset - index);
858 }
859
860 foreach (int index, m_activeLoop->continueLabel.uses) {
861 patchInstruction(index, m_activeLoop->continueLabel.offset - index);
862 }
863
864 changeActiveLoop(previousLoop);
865 m_loops.remove(node);
866
867 return false;
868}
869
870bool Compiler::visit(AST::ForEachStatement *node)
871{
872 Loop *previousLoop = changeActiveLoop(&m_loops[node]);
873
874 iLine(node);
875 node->expression->accept(this);
876 iNewEnumeration();
877 iDuplicate();
878 iToFirstElement();
879
880 int again = nextInstructionOffset();
881 m_activeLoop->continueLabel.offset = again;
882 iDuplicate();
883 iHasNextElement();
884 int cond = nextInstructionOffset();
885 iBranchFalse(0);
886 bool was = generateReferences(true);
887 node->initialiser->accept(this);
888 generateReferences(was);
889 iNextElement();
890 iAssign();
891 iPop();
892 was = iterationStatement(true);
893 node->statement->accept(this);
894 iterationStatement(was);
895 iBranch(again - nextInstructionOffset());
896 patchInstruction(cond, nextInstructionOffset() - cond);
897
898 m_activeLoop->breakLabel.offset = nextInstructionOffset();
899 iPop(); // pop the Enumeration
900
901 foreach (int index, m_activeLoop->breakLabel.uses) {
902 patchInstruction(index, m_activeLoop->breakLabel.offset - index);
903 }
904
905 foreach (int index, m_activeLoop->continueLabel.uses) {
906 patchInstruction(index, m_activeLoop->continueLabel.offset - index);
907 }
908
909 changeActiveLoop(previousLoop);
910 m_loops.remove(node);
911
912 return false;
913}
914
915bool Compiler::visit(AST::LocalForEachStatement *node)
916{
917 Loop *previousLoop = changeActiveLoop(&m_loops[node]);
918
919 iLine(node);
920 node->declaration->accept(this);
921 node->expression->accept(this);
922 iNewEnumeration();
923 iDuplicate();
924 iToFirstElement();
925
926 int again = nextInstructionOffset();
927 m_activeLoop->continueLabel.offset = again;
928 iDuplicate();
929 iHasNextElement();
930 int cond = nextInstructionOffset();
931 iBranchFalse(0);
932 iResolve(node->declaration->name);
933 iNextElement();
934 iAssign();
935 iPop();
936 bool was = iterationStatement(true);
937 node->statement->accept(this);
938 iterationStatement(was);
939 iBranch(again - nextInstructionOffset());
940 patchInstruction(cond, nextInstructionOffset() - cond);
941
942 m_activeLoop->breakLabel.offset = nextInstructionOffset();
943 iPop(); // pop the Enumeration
944
945 foreach (int index, m_activeLoop->breakLabel.uses) {
946 patchInstruction(index, m_activeLoop->breakLabel.offset - index);
947 }
948
949 foreach (int index, m_activeLoop->continueLabel.uses) {
950 patchInstruction(index, m_activeLoop->continueLabel.offset - index);
951 }
952
953 changeActiveLoop(previousLoop);
954 m_loops.remove(node);
955
956 return false;
957}
958
959void Compiler::visitForInternal(AST::Statement *node, AST::ExpressionNode *condition, AST::Statement *statement, AST::ExpressionNode *expression)
960{
961 Q_ASSERT(statement != 0);
962
963 int again = nextInstructionOffset();
964 if (condition != 0) {
965// iLine(condition);
966 condition->accept(this);
967 } else {
968// iLine(node);
969 iLoadNumber(1);
970 }
971
972 int cond = nextInstructionOffset();
973 iBranchFalse(0);
974
975 Loop *previousLoop = changeActiveLoop(&m_loops[node]);
976
977 bool was = iterationStatement(true);
978 statement->accept(this);
979 iterationStatement(was);
980
981 m_activeLoop->continueLabel.offset = nextInstructionOffset();
982
983 if (expression != 0) {
984 expression->accept(this);
985 iPop();
986 }
987
988 iBranch(again - nextInstructionOffset());
989 patchInstruction(cond, nextInstructionOffset() - cond);
990
991 m_activeLoop->breakLabel.offset = nextInstructionOffset();
992
993 foreach (int index, m_activeLoop->breakLabel.uses) {
994 patchInstruction(index, m_activeLoop->breakLabel.offset - index);
995 }
996
997 foreach (int index, m_activeLoop->continueLabel.uses) {
998 patchInstruction(index, m_activeLoop->continueLabel.offset - index);
999 }
1000
1001 changeActiveLoop(previousLoop);
1002 m_loops.remove(node);
1003}
1004
1005bool Compiler::visit(AST::ForStatement *node)
1006{
1007 iLine(node);
1008
1009 if (node->initialiser != 0) {
1010 node->initialiser->accept(this);
1011 iPop();
1012 }
1013
1014 visitForInternal(node, node->condition, node->statement, node->expression);
1015 return false;
1016}
1017
1018bool Compiler::visit(AST::LocalForStatement *node)
1019{
1020 iLine(node);
1021
1022 if (node->declarations)
1023 node->declarations->accept(this);
1024
1025 visitForInternal(node, node->condition, node->statement, node->expression);
1026 return false;
1027}
1028
1029bool Compiler::isAssignmentOperator(int op) const
1030{
1031 switch (op) {
1032
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 return true;
1046
1047 default:
1048 break;
1049
1050 }
1051
1052 return false;
1053}
1054
1055int Compiler::inplaceAssignmentOperator(int op) const
1056{
1057 switch (op) {
1058 case QSOperator::BitAnd:
1059 return QSOperator::InplaceAnd;
1060 case QSOperator::Sub:
1061 return QSOperator::InplaceSub;
1062 case QSOperator::Div:
1063 return QSOperator::InplaceDiv;
1064 case QSOperator::Add:
1065 return QSOperator::InplaceAdd;
1066 case QSOperator::LShift:
1067 return QSOperator::InplaceLeftShift;
1068 case QSOperator::Mod:
1069 return QSOperator::InplaceMod;
1070 case QSOperator::Mul:
1071 return QSOperator::InplaceMul;
1072 case QSOperator::BitOr:
1073 return QSOperator::InplaceOr;
1074 case QSOperator::RShift:
1075 return QSOperator::InplaceRightShift;
1076 case QSOperator::URShift:
1077 return QSOperator::InplaceURightShift;
1078 case QSOperator::BitXor:
1079 return QSOperator::InplaceXor;
1080
1081 default:
1082 break;
1083
1084 }
1085
1086 return(-1);
1087}
1088
1089bool Compiler::visit(AST::Expression *node)
1090{
1091 node->left->accept(this);
1092 iPop(); // ### or iSync?
1093 node->right->accept(this);
1094 return false;
1095}
1096
1097bool Compiler::visit(AST::BinaryExpression *node)
1098{
1099 if (isAssignmentOperator(node->op)) {
1100 bool was = generateReferences(true);
1101 node->left->accept(this);
1102 generateReferences(was);
1103 } else {
1104 node->left->accept(this);
1105 }
1106
1107 int address = 0;
1108 if (node->op == QSOperator::Or || node->op == QSOperator::And) {
1109 iDuplicate();
1110 address = nextInstructionOffset();
1111 if (node->op == QSOperator::Or)
1112 iBranchTrue(0);
1113 else
1114 iBranchFalse(0);
1115 iPop();
1116 }
1117
1118 int op = node->op;
1119 Compare compare;
1120 if ((op == QSOperator::Assign) && node->right->binaryExpressionCast()
1121 && (inplaceAssignmentOperator(node->right->binaryExpressionCast()->op) != -1)
1122 && compare(node->left, node->right->binaryExpressionCast()->left)) {
1123 // node->left is equivalent to node->right->left, so we generate
1124 // x op= y rather than x = x op y
1125 op = inplaceAssignmentOperator(node->right->binaryExpressionCast()->op);
1126 node->right->binaryExpressionCast()->right->accept(this);
1127 } else {
1128 node->right->accept(this);
1129 }
1130
1131 switch (op) {
1132
1133 case QSOperator::Assign:
1134 iAssign();
1135 break;
1136
1137 case QSOperator::InplaceAnd:
1138 iInplaceAnd();
1139 break;
1140
1141 case QSOperator::InplaceSub:
1142 iInplaceSub();
1143 break;
1144
1145 case QSOperator::InplaceDiv:
1146 iInplaceDiv();
1147 break;
1148
1149 case QSOperator::InplaceAdd:
1150 iInplaceAdd();
1151 break;
1152
1153 case QSOperator::InplaceLeftShift:
1154 iInplaceLeftShift();
1155 break;
1156
1157 case QSOperator::InplaceMod:
1158 iInplaceMod();
1159 break;
1160
1161 case QSOperator::InplaceMul:
1162 iInplaceMul();
1163 break;
1164
1165 case QSOperator::InplaceOr:
1166 iInplaceOr();
1167 break;
1168
1169 case QSOperator::InplaceRightShift:
1170 iInplaceRightShift();
1171 break;
1172
1173 case QSOperator::InplaceURightShift:
1174 iInplaceURightShift();
1175 break;
1176
1177 case QSOperator::InplaceXor:
1178 iInplaceXor();
1179 break;
1180
1181 case QSOperator::BitAnd:
1182 iBitAnd();
1183 break;
1184
1185 case QSOperator::BitOr:
1186 iBitOr();
1187 break;
1188
1189 case QSOperator::BitXor:
1190 iBitXor();
1191 break;
1192
1193 case QSOperator::LShift:
1194 iLeftShift();
1195 break;
1196
1197 case QSOperator::Mod:
1198 iMod();
1199 break;
1200
1201 case QSOperator::RShift:
1202 iRightShift();
1203 break;
1204
1205 case QSOperator::URShift:
1206 iURightShift();
1207 break;
1208
1209 case QSOperator::InstanceOf:
1210 iInstanceOf();
1211 break;
1212
1213 case QSOperator::Add:
1214 iAdd();
1215 break;
1216
1217 case QSOperator::And:
1218 patchInstruction(address, nextInstructionOffset() - address);
1219 break;
1220
1221 case QSOperator::Div:
1222 iDiv();
1223 break;
1224
1225 case QSOperator::Equal:
1226 iEqual();
1227 break;
1228
1229 case QSOperator::Ge:
1230 iGreatOrEqual();
1231 break;
1232
1233 case QSOperator::Gt:
1234 iGreatThan();
1235 break;
1236
1237 case QSOperator::Le:
1238 iLessOrEqual();
1239 break;
1240
1241 case QSOperator::Lt:
1242 iLessThan();
1243 break;
1244
1245 case QSOperator::Mul:
1246 iMul();
1247 break;
1248
1249 case QSOperator::NotEqual:
1250 iNotEqual();
1251 break;
1252
1253 case QSOperator::Or:
1254 patchInstruction(address, nextInstructionOffset() - address);
1255 break;
1256
1257 case QSOperator::Sub:
1258 iSub();
1259 break;
1260
1261 case QSOperator::StrictEqual:
1262 iStrictEqual();
1263 break;
1264
1265 case QSOperator::StrictNotEqual:
1266 iStrictNotEqual();
1267 break;
1268
1269 case QSOperator::In:
1270 iIn();
1271 break;
1272 }
1273
1274 return false;
1275}
1276
1277bool Compiler::visit(AST::TrueLiteral *)
1278{
1279 iLoadTrue();
1280 return false;
1281}
1282
1283bool Compiler::visit(AST::FalseLiteral *)
1284{
1285 iLoadFalse();
1286 return false;
1287}
1288
1289bool Compiler::visit(AST::SwitchStatement *node)
1290{
1291 iLine(node);
1292 Loop *previousLoop = changeActiveLoop(&m_loops[node]);
1293
1294 node->expression->accept(this);
1295
1296 bool was = switchStatement(true);
1297
1298 AST::CaseClauses *clauses;
1299 int skipIndex = -1;
1300 int fallthroughIndex = -1;
1301 // ### make a function for this
1302 for (clauses = node->block->clauses; clauses != 0; clauses = clauses->next) {
1303 AST::CaseClause *clause = clauses->clause;
1304 if (skipIndex != -1)
1305 patchInstruction(skipIndex, nextInstructionOffset() - skipIndex);
1306
1307 iDuplicate(); // expression
1308 clause->expression->accept(this);
1309 iStrictEqual();
1310 skipIndex = nextInstructionOffset();
1311 iBranchFalse(0); // next case
1312
1313 if (fallthroughIndex != -1) // previous case falls through to here
1314 patchInstruction(fallthroughIndex, nextInstructionOffset() - fallthroughIndex);
1315
1316 int breaksBefore = m_activeLoop->breakLabel.uses.count();
1317 if (clause->statements)
1318 clause->statements->accept(this);
1319 int breaksAfter = m_activeLoop->breakLabel.uses.count();
1320 if (breaksAfter == breaksBefore) { // fallthrough
1321 fallthroughIndex = nextInstructionOffset();
1322 iBranch(0);
1323 } else { // no fallthrough (break)
1324 fallthroughIndex = -1;
1325 }
1326 }
1327
1328 if (fallthroughIndex != -1) {
1329 patchInstruction(fallthroughIndex, nextInstructionOffset() - fallthroughIndex);
1330 fallthroughIndex = -1;
1331 }
1332
1333 int defaultIndex = -1;
1334 if (node->block->defaultClause) {
1335 int skipDefaultIndex = -1;
1336 if (!node->block->clauses && node->block->moreClauses) {
1337 skipDefaultIndex = nextInstructionOffset();
1338 iBranch(0);
1339 }
1340 defaultIndex = nextInstructionOffset();
1341 int breaksBefore = m_activeLoop->breakLabel.uses.count();
1342 if (node->block->defaultClause->statements)
1343 node->block->defaultClause->statements->accept(this);
1344 int breaksAfter = m_activeLoop->breakLabel.uses.count();
1345 if (breaksAfter == breaksBefore) { // fallthrough
1346 fallthroughIndex = nextInstructionOffset();
1347 iBranch(0);
1348 } else { // no fallthrough (break)
1349 fallthroughIndex = -1;
1350 }
1351 if (skipDefaultIndex != -1)
1352 patchInstruction(skipDefaultIndex, nextInstructionOffset() - skipDefaultIndex);
1353 }
1354
1355 for (clauses = node->block->moreClauses; clauses != 0; clauses = clauses->next) {
1356 AST::CaseClause *clause = clauses->clause;
1357 if (skipIndex != -1)
1358 patchInstruction(skipIndex, nextInstructionOffset() - skipIndex);
1359
1360 iDuplicate(); // expression
1361 clause->expression->accept(this);
1362 iStrictEqual();
1363 skipIndex = nextInstructionOffset();
1364 iBranchFalse(0); // next case
1365
1366 if (fallthroughIndex != -1) // previous case falls through to here
1367 patchInstruction(fallthroughIndex, nextInstructionOffset() - fallthroughIndex);
1368
1369 int breaksBefore = m_activeLoop->breakLabel.uses.count();
1370 if (clause->statements)
1371 clause->statements->accept(this);
1372 int breaksAfter = m_activeLoop->breakLabel.uses.count();
1373 if (breaksAfter == breaksBefore) { // fallthrough
1374 fallthroughIndex = nextInstructionOffset();
1375 iBranch(0);
1376 } else { // no fallthrough (break)
1377 fallthroughIndex = -1;
1378 }
1379 }
1380
1381 if (skipIndex != -1) {
1382 patchInstruction(skipIndex, nextInstructionOffset() - skipIndex);
1383 if (defaultIndex != -1)
1384 iBranch(defaultIndex - nextInstructionOffset()); // goto default
1385 }
1386
1387 if (fallthroughIndex != -1)
1388 patchInstruction(fallthroughIndex, nextInstructionOffset() - fallthroughIndex);
1389
1390 // backpatch the breaks
1391 int term = nextInstructionOffset();
1392 foreach (int index, m_activeLoop->breakLabel.uses) {
1393 patchInstruction(index, term - index);
1394 }
1395
1396 iPop(); // expression
1397
1398 if (previousLoop && !m_activeLoop->continueLabel.uses.isEmpty()) {
1399 // join the continues and add to outer loop
1400 iBranch(3);
1401 foreach (int index, m_activeLoop->continueLabel.uses) {
1402 patchInstruction(index, nextInstructionOffset() - index);
1403 }
1404 iPop();
1405 iBranch(0);
1406 previousLoop->continueLabel.uses.append(nextInstructionOffset() - 1);
1407 }
1408
1409 switchStatement(was);
1410 changeActiveLoop(previousLoop);
1411 m_loops.remove(node);
1412 return false;
1413}
1414
1415bool Compiler::visit(AST::LabelledStatement *node)
1416{
1417 Loop *loop = findLoop(node->label);
1418 if (loop != 0) {
1419 QString str = m_eng->toString(node->label);
1420 m_compilationUnit.setError(QString::fromUtf8("duplicate label `%1'").arg(str),
1421 node->startLine);
1422 return false;
1423 }
1424
1425 loop = &m_loops[node->statement];
1426 loop->name = node->label;
1427 node->statement->accept(this);
1428 if (m_loops.contains(node->statement)) {
1429 loop->breakLabel.offset = nextInstructionOffset();
1430 foreach (int index, loop->breakLabel.uses) {
1431 patchInstruction(index, loop->breakLabel.offset - index);
1432 }
1433 m_loops.remove(node->statement);
1434 }
1435 return false;
1436}
1437
1438bool Compiler::visit(AST::ExpressionStatement *node)
1439{
1440 if (node->expression)
1441 iLine(node->expression);
1442 return true;
1443}
1444
1445void Compiler::endVisit(AST::ExpressionStatement *)
1446{
1447 if (topLevelCompiler())
1448 iSync();
1449 else
1450 iPop();
1451}
1452
1453void Compiler::endVisit(AST::UnaryPlusExpression *)
1454{
1455 iUnaryPlus();
1456}
1457
1458void Compiler::endVisit(AST::UnaryMinusExpression *)
1459{
1460 iUnaryMinus();
1461}
1462
1463bool Compiler::visit(AST::ContinueStatement *node)
1464{
1465 iLine(node);
1466 return true;
1467}
1468
1469void Compiler::endVisit(AST::ContinueStatement *node)
1470{
1471 int offset = nextInstructionOffset();
1472 iBranch(0);
1473
1474 Loop *loop = findLoop(node->label);
1475 if (!loop || !m_iterationStatement) {
1476 m_compilationUnit.setError(QString::fromUtf8("label not found"),
1477 node->startLine);
1478 return;
1479 }
1480
1481 loop->continueLabel.uses.append(offset);
1482}
1483
1484bool Compiler::visit(AST::BreakStatement *node)
1485{
1486 iLine(node);
1487 return true;
1488}
1489
1490void Compiler::endVisit(AST::BreakStatement *node)
1491{
1492 Loop *loop = findLoop(node->label);
1493 if (! loop) {
1494 m_compilationUnit.setError(QString::fromUtf8("label not found"),
1495 node->startLine);
1496 return;
1497 }
1498
1499 if (m_generateLeaveWithOnBreak)
1500 iLeaveWith();
1501 int offset = nextInstructionOffset();
1502 iBranch(0);
1503 loop->breakLabel.uses.append(offset);
1504}
1505
1506void Compiler::endVisit(AST::EmptyStatement *node)
1507{
1508 iLine(node);
1509}
1510
1511bool Compiler::visit(AST::DebuggerStatement *node)
1512{
1513 iLine(node);
1514 iDebugger();
1515 return false;
1516}
1517
1518void Compiler::patchInstruction(int index, int offset)
1519{
1520 QScriptInstruction &i = m_instructions[index];
1521
1522 switch (i.op) {
1523 case QScriptInstruction::OP_Branch:
1524 case QScriptInstruction::OP_BranchFalse:
1525 case QScriptInstruction::OP_BranchTrue:
1526 m_eng->newInteger(&i.operand[0], offset);
1527 break;
1528
1529 default:
1530 Q_ASSERT_X(0, "Compiler::patchInstruction()", "expected a branch instruction");
1531 break;
1532 }
1533}
1534
1535bool Compiler::visit(AST::WithStatement *node)
1536{
1537 iLine(node);
1538 node->expression->accept(this);
1539 iEnterWith();
1540 bool was = withStatement(true);
1541 bool was2 = generateLeaveOnBreak(true);
1542 node->statement->accept(this);
1543 generateLeaveOnBreak(was2);
1544 withStatement(was);
1545 iLeaveWith();
1546 return false;
1547}
1548
1549bool Compiler::visit(AST::ArrayLiteral *node)
1550{
1551 iNewArray();
1552
1553 int length = 0;
1554
1555 for (AST::ElementList *it = node->elements; it != 0; it = it->next) {
1556 for (AST::Elision *eit = it->elision; eit != 0; eit = eit->next) {
1557 iDuplicate();
1558 iLoadNumber(length);
1559 iMakeReference();
1560 iLoadUndefined();
1561 iAssign();
1562 iPop();
1563 ++length;
1564 }
1565
1566 if (it->expression) {
1567 iDuplicate();
1568 iLoadNumber(length);
1569 iMakeReference();
1570 it->expression->accept(this);
1571 iAssign();
1572 iPop();
1573 ++length;
1574 }
1575 }
1576
1577 for (AST::Elision *eit = node->elision; eit != 0; eit = eit->next) {
1578 iDuplicate();
1579 iLoadNumber(length);
1580 iMakeReference();
1581 iLoadUndefined();
1582 iAssign();
1583 iPop();
1584 ++length;
1585 }
1586
1587 return false;
1588}
1589
1590void Compiler::iLoadUndefined()
1591{
1592 pushInstruction(QScriptInstruction::OP_LoadUndefined);
1593}
1594
1595void Compiler::iLoadThis()
1596{
1597 pushInstruction(QScriptInstruction::OP_LoadThis);
1598}
1599
1600void Compiler::iLoadActivation()
1601{
1602 pushInstruction(QScriptInstruction::OP_LoadActivation);
1603}
1604
1605void Compiler::iLoadNull()
1606{
1607 pushInstruction(QScriptInstruction::OP_LoadNull);
1608}
1609
1610void Compiler::iLoadNumber(double number)
1611{
1612 QScriptValueImpl arg0(number);
1613 pushInstruction(QScriptInstruction::OP_LoadNumber, arg0);
1614}
1615
1616void Compiler::iLoadString(QScriptNameIdImpl *id)
1617{
1618 QScriptValueImpl arg0;
1619 id->persistent = true;
1620 m_eng->newNameId(&arg0, id);
1621 pushInstruction(QScriptInstruction::OP_LoadString, arg0);
1622}
1623
1624void Compiler::iDuplicate()
1625{
1626 pushInstruction(QScriptInstruction::OP_Duplicate);
1627}
1628
1629void Compiler::iSwap()
1630{
1631 pushInstruction(QScriptInstruction::OP_Swap);
1632}
1633
1634void Compiler::iResolve(QScriptNameIdImpl *id)
1635{
1636 QScriptValueImpl arg0;
1637 id->persistent = true;
1638 m_eng->newNameId(&arg0, id);
1639 pushInstruction(QScriptInstruction::OP_Resolve, arg0);
1640}
1641
1642void Compiler::iPutField()
1643{
1644 pushInstruction(QScriptInstruction::OP_PutField);
1645}
1646
1647void Compiler::iCall(int argc)
1648{
1649 QScriptValueImpl arg0;
1650 m_eng->newInteger(&arg0, argc);
1651 pushInstruction(QScriptInstruction::OP_Call, arg0);
1652}
1653
1654void Compiler::iNew(int argc)
1655{
1656 QScriptValueImpl arg0;
1657 m_eng->newInteger(&arg0, argc);
1658 pushInstruction(QScriptInstruction::OP_New, arg0);
1659}
1660
1661void Compiler::iFetchField()
1662{
1663 pushInstruction(QScriptInstruction::OP_FetchField);
1664}
1665
1666void Compiler::iLazyArguments()
1667{
1668 pushInstruction(QScriptInstruction::OP_LazyArguments);
1669}
1670
1671void Compiler::iRet()
1672{
1673 pushInstruction(QScriptInstruction::OP_Ret);
1674}
1675
1676void Compiler::iDeclareLocal(QScriptNameIdImpl *id, bool readOnly)
1677{
1678 QScriptValueImpl arg0;
1679 id->persistent = true;
1680 m_eng->newNameId(&arg0, id);
1681 QScriptValueImpl arg1;
1682 m_eng->newInteger(&arg1, readOnly);
1683 pushInstruction(QScriptInstruction::OP_DeclareLocal, arg0, arg1);
1684}
1685
1686void Compiler::iAssign()
1687{
1688 pushInstruction(QScriptInstruction::OP_Assign);
1689}
1690
1691void Compiler::iBitAnd()
1692{
1693 pushInstruction(QScriptInstruction::OP_BitAnd);
1694}
1695
1696void Compiler::iBitOr()
1697{
1698 pushInstruction(QScriptInstruction::OP_BitOr);
1699}
1700
1701void Compiler::iBitXor()
1702{
1703 pushInstruction(QScriptInstruction::OP_BitXor);
1704}
1705
1706void Compiler::iLeftShift()
1707{
1708 pushInstruction(QScriptInstruction::OP_LeftShift);
1709}
1710
1711void Compiler::iMod()
1712{
1713 pushInstruction(QScriptInstruction::OP_Mod);
1714}
1715
1716void Compiler::iRightShift()
1717{
1718 pushInstruction(QScriptInstruction::OP_RightShift);
1719}
1720
1721void Compiler::iURightShift()
1722{
1723 pushInstruction(QScriptInstruction::OP_URightShift);
1724}
1725
1726void Compiler::iAdd()
1727{
1728 pushInstruction(QScriptInstruction::OP_Add);
1729}
1730
1731void Compiler::iDiv()
1732{
1733 pushInstruction(QScriptInstruction::OP_Div);
1734}
1735
1736void Compiler::iEqual()
1737{
1738 pushInstruction(QScriptInstruction::OP_Equal);
1739}
1740
1741void Compiler::iGreatOrEqual()
1742{
1743 pushInstruction(QScriptInstruction::OP_GreatOrEqual);
1744}
1745
1746void Compiler::iGreatThan()
1747{
1748 pushInstruction(QScriptInstruction::OP_GreatThan);
1749}
1750
1751void Compiler::iLessOrEqual()
1752{
1753 pushInstruction(QScriptInstruction::OP_LessOrEqual);
1754}
1755
1756void Compiler::iLessThan()
1757{
1758 pushInstruction(QScriptInstruction::OP_LessThan);
1759}
1760
1761void Compiler::iMul()
1762{
1763 pushInstruction(QScriptInstruction::OP_Mul);
1764}
1765
1766void Compiler::iNotEqual()
1767{
1768 pushInstruction(QScriptInstruction::OP_NotEqual);
1769}
1770
1771void Compiler::iSub()
1772{
1773 pushInstruction(QScriptInstruction::OP_Sub);
1774}
1775
1776void Compiler::iStrictEqual()
1777{
1778 pushInstruction(QScriptInstruction::OP_StrictEqual);
1779}
1780
1781void Compiler::iStrictNotEqual()
1782{
1783 pushInstruction(QScriptInstruction::OP_StrictNotEqual);
1784}
1785
1786void Compiler::iBranch(int index)
1787{
1788 QScriptValueImpl arg0;
1789 m_eng->newInteger(&arg0, index);
1790 pushInstruction(QScriptInstruction::OP_Branch, arg0);
1791}
1792
1793void Compiler::iBranchFalse(int index)
1794{
1795 QScriptValueImpl arg0;
1796 m_eng->newInteger(&arg0, index);
1797 pushInstruction(QScriptInstruction::OP_BranchFalse, arg0);
1798}
1799
1800void Compiler::iBranchTrue(int index)
1801{
1802 QScriptValueImpl arg0;
1803 m_eng->newInteger(&arg0, index);
1804 pushInstruction(QScriptInstruction::OP_BranchTrue, arg0);
1805}
1806
1807void Compiler::iNewClosure(AST::FunctionExpression *expr)
1808{
1809 QScriptValueImpl arg0;
1810 m_eng->newPointer(&arg0, expr);
1811
1812 pushInstruction(QScriptInstruction::OP_NewClosure, arg0);
1813}
1814
1815void Compiler::iIncr()
1816{
1817 pushInstruction(QScriptInstruction::OP_Incr);
1818}
1819
1820void Compiler::iDecr()
1821{
1822 pushInstruction(QScriptInstruction::OP_Decr);
1823}
1824
1825void Compiler::iPop()
1826{
1827 pushInstruction(QScriptInstruction::OP_Pop);
1828}
1829
1830void Compiler::iFetch(QScriptNameIdImpl *id)
1831{
1832 if (m_generateFastArgumentLookup) {
1833 int index = m_formals.indexOf(id);
1834
1835 if (index != -1) {
1836 QScriptValueImpl arg0;
1837 m_eng->newInteger(&arg0, index);
1838 pushInstruction(QScriptInstruction::OP_Receive, arg0);
1839 return;
1840 }
1841 }
1842
1843 QScriptValueImpl arg0;
1844 id->persistent = true;
1845 m_eng->newNameId(&arg0, id);
1846 pushInstruction(QScriptInstruction::OP_Fetch, arg0);
1847}
1848
1849void Compiler::iLoadTrue()
1850{
1851 pushInstruction(QScriptInstruction::OP_LoadTrue);
1852}
1853
1854void Compiler::iLoadFalse()
1855{
1856 pushInstruction(QScriptInstruction::OP_LoadFalse);
1857}
1858
1859void Compiler::iUnaryMinus()
1860{
1861 pushInstruction(QScriptInstruction::OP_UnaryMinus);
1862}
1863
1864void Compiler::iUnaryPlus()
1865{
1866 pushInstruction(QScriptInstruction::OP_UnaryPlus);
1867}
1868
1869void Compiler::iPostIncr()
1870{
1871 pushInstruction(QScriptInstruction::OP_PostIncr);
1872}
1873
1874void Compiler::iPostDecr()
1875{
1876 pushInstruction(QScriptInstruction::OP_PostDecr);
1877}
1878
1879void Compiler::iNewArray()
1880{
1881 pushInstruction(QScriptInstruction::OP_NewArray);
1882}
1883
1884void Compiler::iNewObject()
1885{
1886 pushInstruction(QScriptInstruction::OP_NewObject);
1887}
1888
1889void Compiler::iTypeOf()
1890{
1891 pushInstruction(QScriptInstruction::OP_TypeOf);
1892}
1893
1894void Compiler::iDelete()
1895{
1896 pushInstruction(QScriptInstruction::OP_Delete);
1897}
1898
1899void Compiler::iInstanceOf()
1900{
1901 pushInstruction(QScriptInstruction::OP_InstanceOf);
1902}
1903
1904void Compiler::iInplaceAnd()
1905{
1906 pushInstruction(QScriptInstruction::OP_InplaceAnd);
1907}
1908
1909void Compiler::iInplaceSub()
1910{
1911 pushInstruction(QScriptInstruction::OP_InplaceSub);
1912}
1913
1914void Compiler::iInplaceDiv()
1915{
1916 pushInstruction(QScriptInstruction::OP_InplaceDiv);
1917}
1918
1919void Compiler::iInplaceAdd()
1920{
1921 pushInstruction(QScriptInstruction::OP_InplaceAdd);
1922}
1923
1924void Compiler::iInplaceLeftShift()
1925{
1926 pushInstruction(QScriptInstruction::OP_InplaceLeftShift);
1927}
1928
1929void Compiler::iInplaceMod()
1930{
1931 pushInstruction(QScriptInstruction::OP_InplaceMod);
1932}
1933
1934void Compiler::iInplaceMul()
1935{
1936 pushInstruction(QScriptInstruction::OP_InplaceMul);
1937}
1938
1939void Compiler::iInplaceOr()
1940{
1941 pushInstruction(QScriptInstruction::OP_InplaceOr);
1942}
1943
1944void Compiler::iInplaceRightShift()
1945{
1946 pushInstruction(QScriptInstruction::OP_InplaceRightShift);
1947}
1948
1949void Compiler::iInplaceURightShift()
1950{
1951 pushInstruction(QScriptInstruction::OP_InplaceURightShift);
1952}
1953
1954void Compiler::iInplaceXor()
1955{
1956 pushInstruction(QScriptInstruction::OP_InplaceXor);
1957}
1958
1959void Compiler::iThrow()
1960{
1961 pushInstruction(QScriptInstruction::OP_Throw);
1962}
1963
1964void Compiler::iLine(AST::Node *node)
1965{
1966 if (! node)
1967 return;
1968
1969 QScriptValueImpl arg0;
1970 m_eng->newInteger(&arg0, node->startLine);
1971
1972 QScriptValueImpl arg1;
1973 m_eng->newInteger(&arg1, node->startColumn);
1974
1975 pushInstruction(QScriptInstruction::OP_Line, arg0, arg1);
1976}
1977
1978void Compiler::iBitNot()
1979{
1980 pushInstruction(QScriptInstruction::OP_BitNot);
1981}
1982
1983void Compiler::iNot()
1984{
1985 pushInstruction(QScriptInstruction::OP_Not);
1986}
1987
1988void Compiler::iNewRegExp(QScriptNameIdImpl *pattern)
1989{
1990 QScriptValueImpl arg0;
1991 pattern->persistent = true;
1992 m_eng->newNameId(&arg0, pattern);
1993 pushInstruction(QScriptInstruction::OP_NewRegExp, arg0);
1994}
1995
1996void Compiler::iNewRegExp(QScriptNameIdImpl *pattern, int flags)
1997{
1998 QScriptValueImpl arg0;
1999 pattern->persistent = true;
2000 m_eng->newNameId(&arg0, pattern);
2001
2002 QScriptValueImpl arg1;
2003 m_eng->newInteger(&arg1, flags);
2004
2005 pushInstruction(QScriptInstruction::OP_NewRegExp, arg0, arg1);
2006}
2007
2008void Compiler::iNewEnumeration()
2009{
2010 pushInstruction(QScriptInstruction::OP_NewEnumeration);
2011}
2012
2013void Compiler::iToFirstElement()
2014{
2015 pushInstruction(QScriptInstruction::OP_ToFirstElement);
2016}
2017
2018void Compiler::iHasNextElement()
2019{
2020 pushInstruction(QScriptInstruction::OP_HasNextElement);
2021}
2022
2023void Compiler::iNextElement()
2024{
2025 pushInstruction(QScriptInstruction::OP_NextElement);
2026}
2027
2028void Compiler::iEnterWith()
2029{
2030 pushInstruction(QScriptInstruction::OP_EnterWith);
2031}
2032
2033void Compiler::iLeaveWith()
2034{
2035 pushInstruction(QScriptInstruction::OP_LeaveWith);
2036}
2037
2038void Compiler::iBeginCatch(QScriptNameIdImpl *id)
2039{
2040 QScriptValueImpl arg0;
2041 id->persistent = true;
2042 m_eng->newNameId(&arg0, id);
2043 pushInstruction(QScriptInstruction::OP_BeginCatch, arg0);
2044}
2045
2046void Compiler::iEndCatch()
2047{
2048 pushInstruction(QScriptInstruction::OP_EndCatch);
2049}
2050
2051void Compiler::iSync()
2052{
2053 pushInstruction(QScriptInstruction::OP_Sync);
2054}
2055
2056void Compiler::iHalt()
2057{
2058 pushInstruction(QScriptInstruction::OP_Halt);
2059}
2060
2061void Compiler::iMakeReference()
2062{
2063 pushInstruction(QScriptInstruction::OP_MakeReference);
2064}
2065
2066void Compiler::iIn()
2067{
2068 pushInstruction(QScriptInstruction::OP_In);
2069}
2070
2071void Compiler::iNop()
2072{
2073 pushInstruction(QScriptInstruction::OP_Nop);
2074}
2075
2076void Compiler::iNewString(QScriptNameIdImpl *id)
2077{
2078 QScriptValueImpl arg0;
2079 id->persistent = true;
2080 m_eng->newNameId(&arg0, id);
2081 pushInstruction(QScriptInstruction::OP_NewString, arg0);
2082}
2083
2084void Compiler::iDebugger()
2085{
2086 pushInstruction(QScriptInstruction::OP_Debugger);
2087}
2088
2089Compiler::Loop *Compiler::findLoop(QScriptNameIdImpl *name)
2090{
2091 if (! name)
2092 return m_activeLoop;
2093
2094 QMap<AST::Statement*, Loop>::iterator it = m_loops.begin();
2095
2096 for (; it != m_loops.end(); ++it) {
2097 Loop &loop = *it;
2098
2099 if (loop.name == name)
2100 return &loop;
2101 }
2102
2103 return 0;
2104}
2105
2106
2107} // namespace QScript
2108
2109QT_END_NAMESPACE
2110
2111#endif // QT_NO_SCRIPT
Note: See TracBrowser for help on using the repository browser.