📄 qscriptcompiler.cpp
字号:
default: break; } return false;}int Compiler::inplaceAssignmentOperator(int op) const{ switch (op) { case QSOperator::BitAnd: return QSOperator::InplaceAnd; case QSOperator::Sub: return QSOperator::InplaceSub; case QSOperator::Div: return QSOperator::InplaceDiv; case QSOperator::Add: return QSOperator::InplaceAdd; case QSOperator::LShift: return QSOperator::InplaceLeftShift; case QSOperator::Mod: return QSOperator::InplaceMod; case QSOperator::Mul: return QSOperator::InplaceMul; case QSOperator::BitOr: return QSOperator::InplaceOr; case QSOperator::RShift: return QSOperator::InplaceRightShift; case QSOperator::URShift: return QSOperator::InplaceURightShift; case QSOperator::BitXor: return QSOperator::InplaceXor; default: break; } return(-1);}bool Compiler::visit(AST::Expression *node){ node->left->accept(this); iPop(); // ### or iSync? node->right->accept(this); return false;}bool Compiler::visit(AST::BinaryExpression *node){ if (isAssignmentOperator(node->op)) { bool was = generateReferences(true); node->left->accept(this); generateReferences(was); } else { node->left->accept(this); } int address = 0; if (node->op == QSOperator::Or || node->op == QSOperator::And) { iDuplicate(); address = nextInstructionOffset(); if (node->op == QSOperator::Or) iBranchTrue(0); else iBranchFalse(0); iPop(); } int op = node->op; Compare compare; if ((op == QSOperator::Assign) && node->right->binaryExpressionCast() && (inplaceAssignmentOperator(node->right->binaryExpressionCast()->op) != -1) && compare(node->left, node->right->binaryExpressionCast()->left)) { // node->left is equivalent to node->right->left, so we generate // x op= y rather than x = x op y op = inplaceAssignmentOperator(node->right->binaryExpressionCast()->op); node->right->binaryExpressionCast()->right->accept(this); } else { node->right->accept(this); } switch (op) { case QSOperator::Assign: iAssign(); break; case QSOperator::InplaceAnd: iInplaceAnd(); break; case QSOperator::InplaceSub: iInplaceSub(); break; case QSOperator::InplaceDiv: iInplaceDiv(); break; case QSOperator::InplaceAdd: iInplaceAdd(); break; case QSOperator::InplaceLeftShift: iInplaceLeftShift(); break; case QSOperator::InplaceMod: iInplaceMod(); break; case QSOperator::InplaceMul: iInplaceMul(); break; case QSOperator::InplaceOr: iInplaceOr(); break; case QSOperator::InplaceRightShift: iInplaceRightShift(); break; case QSOperator::InplaceURightShift: iInplaceURightShift(); break; case QSOperator::InplaceXor: iInplaceXor(); break; case QSOperator::BitAnd: iBitAnd(); break; case QSOperator::BitOr: iBitOr(); break; case QSOperator::BitXor: iBitXor(); break; case QSOperator::LShift: iLeftShift(); break; case QSOperator::Mod: iMod(); break; case QSOperator::RShift: iRightShift(); break; case QSOperator::URShift: iURightShift(); break; case QSOperator::InstanceOf: iInstanceOf(); break; case QSOperator::Add: iAdd(); break; case QSOperator::And: patchInstruction(address, nextInstructionOffset() - address); break; case QSOperator::Div: iDiv(); break; case QSOperator::Equal: iEqual(); break; case QSOperator::Ge: iGreatOrEqual(); break; case QSOperator::Gt: iGreatThan(); break; case QSOperator::Le: iLessOrEqual(); break; case QSOperator::Lt: iLessThan(); break; case QSOperator::Mul: iMul(); break; case QSOperator::NotEqual: iNotEqual(); break; case QSOperator::Or: patchInstruction(address, nextInstructionOffset() - address); break; case QSOperator::Sub: iSub(); break; case QSOperator::StrictEqual: iStrictEqual(); break; case QSOperator::StrictNotEqual: iStrictNotEqual(); break; case QSOperator::In: iIn(); break; } return false;}bool Compiler::visit(AST::TrueLiteral *){ iLoadTrue(); return false;}bool Compiler::visit(AST::FalseLiteral *){ iLoadFalse(); return false;}bool Compiler::visit(AST::SwitchStatement *node){ iLine(node); Loop *previousLoop = changeActiveLoop(&m_loops[node]); node->expression->accept(this); bool was = switchStatement(true); AST::CaseClauses *clauses; int skipIndex = -1; int fallthroughIndex = -1; // ### make a function for this for (clauses = node->block->clauses; clauses != 0; clauses = clauses->next) { AST::CaseClause *clause = clauses->clause; if (skipIndex != -1) patchInstruction(skipIndex, nextInstructionOffset() - skipIndex); iDuplicate(); // expression clause->expression->accept(this); iStrictEqual(); skipIndex = nextInstructionOffset(); iBranchFalse(0); // next case if (fallthroughIndex != -1) // previous case falls through to here patchInstruction(fallthroughIndex, nextInstructionOffset() - fallthroughIndex); int breaksBefore = m_activeLoop->breakLabel.uses.count(); if (clause->statements) clause->statements->accept(this); int breaksAfter = m_activeLoop->breakLabel.uses.count(); if (breaksAfter == breaksBefore) { // fallthrough fallthroughIndex = nextInstructionOffset(); iBranch(0); } else { // no fallthrough (break) fallthroughIndex = -1; } } if (fallthroughIndex != -1) { patchInstruction(fallthroughIndex, nextInstructionOffset() - fallthroughIndex); fallthroughIndex = -1; } int defaultIndex = -1; if (node->block->defaultClause) { int skipDefaultIndex = -1; if (!node->block->clauses && node->block->moreClauses) { skipDefaultIndex = nextInstructionOffset(); iBranch(0); } defaultIndex = nextInstructionOffset(); int breaksBefore = m_activeLoop->breakLabel.uses.count(); if (node->block->defaultClause->statements) node->block->defaultClause->statements->accept(this); int breaksAfter = m_activeLoop->breakLabel.uses.count(); if (breaksAfter == breaksBefore) { // fallthrough fallthroughIndex = nextInstructionOffset(); iBranch(0); } else { // no fallthrough (break) fallthroughIndex = -1; } if (skipDefaultIndex != -1) patchInstruction(skipDefaultIndex, nextInstructionOffset() - skipDefaultIndex); } for (clauses = node->block->moreClauses; clauses != 0; clauses = clauses->next) { AST::CaseClause *clause = clauses->clause; if (skipIndex != -1) patchInstruction(skipIndex, nextInstructionOffset() - skipIndex); iDuplicate(); // expression clause->expression->accept(this); iStrictEqual(); skipIndex = nextInstructionOffset(); iBranchFalse(0); // next case if (fallthroughIndex != -1) // previous case falls through to here patchInstruction(fallthroughIndex, nextInstructionOffset() - fallthroughIndex); int breaksBefore = m_activeLoop->breakLabel.uses.count(); if (clause->statements) clause->statements->accept(this); int breaksAfter = m_activeLoop->breakLabel.uses.count(); if (breaksAfter == breaksBefore) { // fallthrough fallthroughIndex = nextInstructionOffset(); iBranch(0); } else { // no fallthrough (break) fallthroughIndex = -1; } } if (skipIndex != -1) { patchInstruction(skipIndex, nextInstructionOffset() - skipIndex); if (defaultIndex != -1) iBranch(defaultIndex - nextInstructionOffset()); // goto default } if (fallthroughIndex != -1) patchInstruction(fallthroughIndex, nextInstructionOffset() - fallthroughIndex); // backpatch the breaks int term = nextInstructionOffset(); foreach (int index, m_activeLoop->breakLabel.uses) { patchInstruction(index, term - index); } iPop(); // expression switchStatement(was); changeActiveLoop(previousLoop); m_loops.remove(node); return false;}bool Compiler::visit(AST::LabelledStatement *node){ Loop *loop = findLoop(node->label); if (loop != 0) { m_compilationUnit.setValid(false); QString str = m_eng->toString(node->label); m_compilationUnit.setErrorMessage(QString::fromUtf8("duplicate label `%1'").arg(str)); return false; } m_loops[node->statement].name = node->label; node->statement->accept(this); m_loops.remove(node->statement); return false;}bool Compiler::visit(AST::ExpressionStatement *node){ if (node->expression) iLine(node->expression); return true;}void Compiler::endVisit(AST::ExpressionStatement *){ if (topLevelCompiler()) iSync(); else iPop();}void Compiler::endVisit(AST::UnaryPlusExpression *){ iUnaryPlus();}void Compiler::endVisit(AST::UnaryMinusExpression *){ iUnaryMinus();}bool Compiler::visit(AST::ContinueStatement *node){ iLine(node); return true;}void Compiler::endVisit(AST::ContinueStatement *node){ int offset = nextInstructionOffset(); iBranch(0); Loop *loop = findLoop(node->label); if (! loop) { m_compilationUnit.setErrorMessage(QString::fromUtf8("label not found")); m_compilationUnit.setValid(false); return; } loop->continueLabel.uses.append(offset);}bool Compiler::visit(AST::BreakStatement *node){ iLine(node); return true;}void Compiler::endVisit(AST::BreakStatement *node){ Loop *loop = findLoop(node->label); if (! loop) { m_compilationUnit.setErrorMessage(QString::fromUtf8("label not found")); m_compilationUnit.setValid(false); return; } if (m_generateLeaveWithOnBreak) iLeaveWith(); int offset = nextInstructionOffset(); iBranch(0); loop->breakLabel.uses.append(offset);}void Compiler::patchInstruction(int index, int offset){ QScriptInstruction &i = m_instructions[index]; switch (i.op) { case QScriptInstruction::OP_Branch: case QScriptInstruction::OP_BranchFalse: case QScriptInstruction::OP_BranchTrue: m_eng->newInteger(&i.operand[0], offset); break; default: Q_ASSERT_X(0, "Compiler::patchInstruction()", "expected a branch instruction"); break; }}bool Compiler::visit(AST::WithStatement *node){ iLine(node); node->expression->accept(this); iEnterWith(); bool was = withStatement(true); bool was2 = generateLeaveOnBreak(m_iterationStatement); node->statement->accept(this); generateLeaveOnBreak(was2); withStatement(was); iLeaveWith(); return false;}bool Compiler::visit(AST::ArrayLiteral *node){ iNewArray(); int length = 0; for (AST::ElementList *it = node->elements; it != 0; it = it->next) { for (AST::Elision *eit = it->elision; eit != 0; eit = eit->next) { iDuplicate(); iLoadNumber(length); iMakeReference(); iLoadUndefined(); iAssign(); iPop(); ++length; } if (it->expression) { iDuplicate(); iLoadNumber(length); iMakeReference(); it->expression->accept(this); iAssign(); iPop(); ++length; } } for (AST::Elision *eit = node->elision; eit != 0; eit = eit->next) { iDuplicate(); iLoadNumber(length); iMakeReference(); iLoadUndefined(); iAssign(); iPop(); ++length; } return false;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -