📄 qscriptcompiler.cpp
字号:
}bool Compiler::visit(AST::NewMemberExpression *node){ bool was = generateReferences(true); node->base->accept(this); generateReferences(false); int argc = 0; for (AST::ArgumentList *it = node->arguments; it != 0; it = it->next) { it->expression->accept(this); ++argc; } generateReferences(was); iNew(argc); return false;}bool Compiler::visit(AST::FieldMemberExpression *node){ bool was = generateReferences(false); node->base->accept(this); generateReferences(was); iLoadString(node->name); if (! was) iFetchField(); else iMakeReference(); return false;}bool Compiler::visit(AST::ArrayMemberExpression *node){ bool was = generateReferences(false); node->base->accept(this); node->expression->accept(this); generateReferences(was); if (! was) iFetchField(); else iMakeReference(); return false;}bool Compiler::visit(AST::PostIncrementExpression *node){ bool was = generateReferences(true); node->base->accept(this); generateReferences(was); iPostIncr(); return false;}bool Compiler::visit(AST::PostDecrementExpression *node){ bool was = generateReferences(true); node->base->accept(this); generateReferences(was); iPostDecr(); return false;}bool Compiler::visit(AST::PreIncrementExpression *node){ bool was = generateReferences(true); node->expression->accept(this); generateReferences(was); iIncr(); return false;}bool Compiler::visit(AST::PreDecrementExpression *node){ bool was = generateReferences(true); node->expression->accept(this); generateReferences(was); iDecr(); return false;}void Compiler::endVisit(AST::NotExpression *){ iNot();}void Compiler::endVisit(AST::TildeExpression *){ iBitNot();}bool Compiler::visit(AST::ThrowStatement *node){ iLine(node); return true;}bool Compiler::visit(AST::TryStatement *node){ int start = nextInstructionOffset(); if (node->statement) node->statement->accept(this); int end = nextInstructionOffset(); if (node->catchExpression) { iBranch(0); // skip the catch if no exception ExceptionHandlerDescriptor ehd(start, end, nextInstructionOffset()); m_exceptionHandlers.append(ehd); iBeginCatch(node->catchExpression->name); node->catchExpression->statement->accept(this); iEndCatch(); patchInstruction(end, nextInstructionOffset() - end); } if (node->finallyExpression) { if (!node->catchExpression) { ExceptionHandlerDescriptor ehd(start, end, nextInstructionOffset()); m_exceptionHandlers.prepend(ehd); } node->finallyExpression->statement->accept(this); } return false;}void Compiler::endVisit(AST::ThrowStatement *node){ if (! node->expression) iLoadUndefined(); iThrow();}void Compiler::endVisit(AST::VoidExpression *){ iPop(); iLoadUndefined();}bool Compiler::visit(AST::TypeOfExpression *node){ bool was = generateReferences(true); node->expression->accept(this); generateReferences(was); iTypeOf(); return false;}bool Compiler::visit(AST::DeleteExpression *node){ bool was = generateReferences(true); node->expression->accept(this); generateReferences(was); iDelete(); return false;}bool Compiler::visit(AST::ReturnStatement *node){ iLine(node); return true;}void Compiler::endVisit(AST::ReturnStatement *node){ if (! node->expression) iLoadUndefined(); iRet();}bool Compiler::visit(AST::VariableStatement *node){ AST::VariableDeclarationList *lst = node->declarations; while (lst) { if (lst->declaration->expression) { iLine(node); break; } lst = lst->next; } return true;}bool Compiler::visit(AST::VariableDeclaration *node){ if (node->expression != 0) { iResolve(node->name); node->expression->accept(this); iAssign(); iPop(); } return false;}bool Compiler::visit(AST::ConditionalExpression *node){ node->expression->accept(this); int cond = nextInstructionOffset(); iBranchFalse(0); node->ok->accept(this); if (! node->ko) { patchInstruction(cond, nextInstructionOffset() - cond); } else { int terminator = nextInstructionOffset(); iBranch(0); node->ko->accept(this); patchInstruction(cond, terminator + 1 - cond); patchInstruction(terminator, nextInstructionOffset() - terminator); } return false;}bool Compiler::visit(AST::IfStatement *node){ iLine(node); node->expression->accept(this); int cond = nextInstructionOffset(); iBranchFalse(0); node->ok->accept(this); if (! node->ko) { patchInstruction(cond, nextInstructionOffset() - cond); if (!m_instructions.isEmpty() && m_instructions.last().op == QScriptInstruction::OP_Ret) iNop(); } else { int terminator = nextInstructionOffset(); iBranch(0); node->ko->accept(this); patchInstruction(cond, terminator + 1 - cond); patchInstruction(terminator, nextInstructionOffset() - terminator); } return false;}bool Compiler::visit(AST::Block *node){ if (node->statements && m_loops.contains(node)) { Loop &loop = m_loops[node]; node->statements->accept(this); loop.breakLabel.offset = nextInstructionOffset(); foreach (int index, loop.breakLabel.uses) { patchInstruction(index, loop.breakLabel.offset - index); } return false; } return true;}bool Compiler::visit(AST::WhileStatement *node){ Loop *previousLoop = changeActiveLoop(&m_loops[node]); m_activeLoop->continueLabel.offset = nextInstructionOffset(); int again = nextInstructionOffset(); iLine(node); node->expression->accept(this); int cond = nextInstructionOffset(); iBranchFalse(0); bool was = iterationStatement(true); bool was2 = generateLeaveOnBreak(false); node->statement->accept(this); generateLeaveOnBreak(was2); iterationStatement(was); iBranch(again - nextInstructionOffset()); patchInstruction(cond, nextInstructionOffset() - cond); m_activeLoop->breakLabel.offset = nextInstructionOffset(); foreach (int index, m_activeLoop->breakLabel.uses) { patchInstruction(index, m_activeLoop->breakLabel.offset - index); } foreach (int index, m_activeLoop->continueLabel.uses) { patchInstruction(index, m_activeLoop->continueLabel.offset - index); } changeActiveLoop(previousLoop); m_loops.remove(node); return false;}bool Compiler::visit(AST::DoWhileStatement *node){ Loop *previousLoop = changeActiveLoop(&m_loops[node]); int again = nextInstructionOffset(); bool was = iterationStatement(true); node->statement->accept(this); iterationStatement(was); m_activeLoop->continueLabel.offset = nextInstructionOffset(); iLine(node->expression); node->expression->accept(this); iBranchTrue(again - nextInstructionOffset()); m_activeLoop->breakLabel.offset = nextInstructionOffset(); foreach (int index, m_activeLoop->breakLabel.uses) { patchInstruction(index, m_activeLoop->breakLabel.offset - index); } foreach (int index, m_activeLoop->continueLabel.uses) { patchInstruction(index, m_activeLoop->continueLabel.offset - index); } changeActiveLoop(previousLoop); m_loops.remove(node); return false;}bool Compiler::visit(AST::ForEachStatement *node){ Loop *previousLoop = changeActiveLoop(&m_loops[node]); node->expression->accept(this); iNewEnumeration(); iDuplicate(); iToFirstElement(); int again = nextInstructionOffset(); m_activeLoop->continueLabel.offset = again; iLine(node); iDuplicate(); iHasNextElement(); int cond = nextInstructionOffset(); iBranchFalse(0); bool was = generateReferences(true); node->initialiser->accept(this); generateReferences(was); iNextElement(); iAssign(); iPop(); was = iterationStatement(true); node->statement->accept(this); iterationStatement(was); iBranch(again - nextInstructionOffset()); patchInstruction(cond, nextInstructionOffset() - cond); m_activeLoop->breakLabel.offset = nextInstructionOffset(); iPop(); // pop the Enumeration foreach (int index, m_activeLoop->breakLabel.uses) { patchInstruction(index, m_activeLoop->breakLabel.offset - index); } foreach (int index, m_activeLoop->continueLabel.uses) { patchInstruction(index, m_activeLoop->continueLabel.offset - index); } changeActiveLoop(previousLoop); m_loops.remove(node); return false;}bool Compiler::visit(AST::LocalForEachStatement *node){ Loop *previousLoop = changeActiveLoop(&m_loops[node]); node->declaration->accept(this); node->expression->accept(this); iNewEnumeration(); iDuplicate(); iToFirstElement(); int again = nextInstructionOffset(); m_activeLoop->continueLabel.offset = again; iLine(node); iDuplicate(); iHasNextElement(); int cond = nextInstructionOffset(); iBranchFalse(0); iResolve(node->declaration->name); iNextElement(); iAssign(); iPop(); bool was = iterationStatement(true); node->statement->accept(this); iterationStatement(was); iBranch(again - nextInstructionOffset()); patchInstruction(cond, nextInstructionOffset() - cond); m_activeLoop->breakLabel.offset = nextInstructionOffset(); iPop(); // pop the Enumeration foreach (int index, m_activeLoop->breakLabel.uses) { patchInstruction(index, m_activeLoop->breakLabel.offset - index); } foreach (int index, m_activeLoop->continueLabel.uses) { patchInstruction(index, m_activeLoop->continueLabel.offset - index); } changeActiveLoop(previousLoop); m_loops.remove(node); return false;}void Compiler::visitForInternal(AST::Statement *node, AST::ExpressionNode *condition, AST::Statement *statement, AST::ExpressionNode *expression){ Q_ASSERT(statement != 0); int again = nextInstructionOffset(); if (condition != 0) { iLine(condition); condition->accept(this); } else { iLine(node); iLoadNumber(1); } int cond = nextInstructionOffset(); iBranchFalse(0); Loop *previousLoop = changeActiveLoop(&m_loops[node]); bool was = iterationStatement(true); statement->accept(this); iterationStatement(was); m_activeLoop->continueLabel.offset = nextInstructionOffset(); if (expression != 0) { expression->accept(this); iPop(); } iBranch(again - nextInstructionOffset()); patchInstruction(cond, nextInstructionOffset() - cond); m_activeLoop->breakLabel.offset = nextInstructionOffset(); foreach (int index, m_activeLoop->breakLabel.uses) { patchInstruction(index, m_activeLoop->breakLabel.offset - index); } foreach (int index, m_activeLoop->continueLabel.uses) { patchInstruction(index, m_activeLoop->continueLabel.offset - index); } changeActiveLoop(previousLoop); m_loops.remove(node);}bool Compiler::visit(AST::ForStatement *node){ iLine(node); if (node->initialiser != 0) { node->initialiser->accept(this); iPop(); } visitForInternal(node, node->condition, node->statement, node->expression); return false;}bool Compiler::visit(AST::LocalForStatement *node){ iLine(node); if (node->declarations) node->declarations->accept(this); visitForInternal(node, node->condition, node->statement, node->expression); return false;}bool Compiler::isAssignmentOperator(int op) const{ switch (op) { case QSOperator::Assign: case QSOperator::InplaceAnd: case QSOperator::InplaceSub: case QSOperator::InplaceDiv: case QSOperator::InplaceAdd: case QSOperator::InplaceLeftShift: case QSOperator::InplaceMod: case QSOperator::InplaceMul: case QSOperator::InplaceOr: case QSOperator::InplaceRightShift: case QSOperator::InplaceURightShift: case QSOperator::InplaceXor: return true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -