📄 qscriptcompiler.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.**** This file is part of the QtScript module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://trolltech.com/products/qt/licenses/licensing/opensource/**** If you are unsure which license is appropriate for your use, please** review the following information:** http://trolltech.com/products/qt/licenses/licensing/licensingoverview** or contact the sales department at sales@trolltech.com.**** In addition, as a special exception, Trolltech gives you certain** additional rights. These rights are described in the Trolltech GPL** Exception version 1.0, which can be found at** http://www.trolltech.com/products/qt/gplexception/ and in the file** GPL_EXCEPTION.txt in this package.**** In addition, as a special exception, Trolltech, as the sole copyright** holder for Qt Designer, grants users of the Qt/Eclipse Integration** plug-in the right for the Qt/Eclipse Integration to link to** functionality provided by Qt Designer and its related libraries.**** Trolltech reserves all rights not expressly granted herein.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qscriptcompiler_p.h"#ifndef QT_NO_SCRIPT#include "qscriptast_p.h"#include "qscriptengine_p.h"#include "qscriptvalueimpl_p.h"#include "qscriptcontext_p.h"#include "qscriptmember_p.h"#include "qscriptobject_p.h"#include <QtCore/QtDebug>namespace QScript {class Compare : protected AST::Visitor{public: bool operator()(AST::ExpressionNode *e1, AST::ExpressionNode *e2) { if (!e1 || !e2) return (e1 == e2); if (e1->kind != e2->kind) return false; m_e2 = e2; m_equal = false; e1->accept(this); return m_equal; }protected: virtual bool visit(AST::ThisExpression *) { m_equal = true; return false; } virtual bool visit(AST::NullExpression *) { m_equal = true; return false; } virtual bool visit(AST::VoidExpression *) { m_equal = true; return false; } virtual bool visit(AST::FalseLiteral *) { m_equal = true; return false; } virtual bool visit(AST::TrueLiteral *) { m_equal = true; return false; } virtual bool visit(AST::NumericLiteral *e1) { AST::NumericLiteral *e2 = static_cast<AST::NumericLiteral*>(m_e2); m_equal = (e1->value == e2->value); return false; } virtual bool visit(AST::RegExpLiteral *e1) { AST::RegExpLiteral *e2 = static_cast<AST::RegExpLiteral*>(m_e2); m_equal = (e1->pattern == e2->pattern) && (e1->flags == e2->flags); return false; } virtual bool visit(AST::StringLiteral *e1) { AST::StringLiteral *e2 = static_cast<AST::StringLiteral*>(m_e2); m_equal = (e1->value == e2->value); return false; } virtual bool visit(AST::IdentifierExpression *e1) { AST::IdentifierExpression *e2 = static_cast<AST::IdentifierExpression*>(m_e2); m_equal = (e1->name == e2->name); return false; } virtual bool visit(AST::ArrayMemberExpression *e1) { AST::ArrayMemberExpression *e2 = static_cast<AST::ArrayMemberExpression*>(m_e2); m_equal = operator()(e1->base, e2->base) && operator()(e1->expression, e2->expression); return false; } virtual bool visit(AST::FieldMemberExpression *e1) { AST::FieldMemberExpression *e2 = static_cast<AST::FieldMemberExpression*>(m_e2); m_equal = (e1->name == e2->name) && operator()(e1->base, e2->base); return false; } virtual bool visit(AST::BinaryExpression *e1) { AST::BinaryExpression *e2 = static_cast<AST::BinaryExpression*>(m_e2); m_equal = (e1->op == e2->op) && operator()(e1->left, e2->left) && operator()(e1->right, e2->right); return false; } virtual bool visit(AST::ConditionalExpression *e1) { AST::ConditionalExpression *e2 = static_cast<AST::ConditionalExpression*>(m_e2); m_equal = operator()(e1->expression, e2->expression) && operator()(e1->ok, e2->ok) && operator()(e1->ko, e2->ko); return false; } virtual bool visit(AST::TypeOfExpression *e1) { AST::TypeOfExpression *e2 = static_cast<AST::TypeOfExpression*>(m_e2); m_equal = operator()(e1->expression, e2->expression); return false; } virtual bool visit(AST::UnaryPlusExpression *e1) { AST::UnaryPlusExpression *e2 = static_cast<AST::UnaryPlusExpression*>(m_e2); m_equal = operator()(e1->expression, e2->expression); return false; } virtual bool visit(AST::UnaryMinusExpression *e1) { AST::UnaryMinusExpression *e2 = static_cast<AST::UnaryMinusExpression*>(m_e2); m_equal = operator()(e1->expression, e2->expression); return false; } virtual bool visit(AST::TildeExpression *e1) { AST::TildeExpression *e2 = static_cast<AST::TildeExpression*>(m_e2); m_equal = operator()(e1->expression, e2->expression); return false; } virtual bool visit(AST::NotExpression *e1) { AST::NotExpression *e2 = static_cast<AST::NotExpression*>(m_e2); m_equal = operator()(e1->expression, e2->expression); return false; } virtual bool visit(AST::Expression *) { return false; } virtual bool visit(AST::ArrayLiteral *) { return false; } virtual bool visit(AST::ObjectLiteral *) { return false; } virtual bool visit(AST::CallExpression *) { return false; } virtual bool visit(AST::DeleteExpression *) { return false; } virtual bool visit(AST::FunctionExpression *) { return false; } virtual bool visit(AST::NewExpression *) { return false; } virtual bool visit(AST::NewMemberExpression *) { return false; } virtual bool visit(AST::PostDecrementExpression *) { return false; } virtual bool visit(AST::PostIncrementExpression *) { return false; } virtual bool visit(AST::PreDecrementExpression *) { return false; } virtual bool visit(AST::PreIncrementExpression *) { return false; }private: AST::ExpressionNode *m_e2; bool m_equal;};class FetchName: protected AST::Visitor{public: inline FetchName(QScriptEnginePrivate *e): eng(e), name(0) {} QScriptNameIdImpl *operator() (AST::PropertyName *node) { name = 0; node->accept(this); return name; }protected: virtual bool visit(AST::IdentifierPropertyName *node) { name = node->id; return false; } virtual bool visit(AST::StringLiteralPropertyName *node) { name = node->id; return false; } virtual bool visit(AST::NumericLiteralPropertyName *node) { name = eng->nameId(QString::number(node->id), /*persistent=*/false); // ### don't use QString::number name->persistent = true; // ### remove return false; }private: QScriptEnginePrivate *eng; QScriptNameIdImpl *name;};class EmptySourceElements: protected AST::Visitor{public: EmptySourceElements(QScriptEngine *d): driver(d), empty(false) {} inline bool operator () (AST::Node *) { empty = false; return empty; }private: QScriptEngine *driver; bool empty;};class DeclareLocals: protected AST::Visitor{public: DeclareLocals(Compiler *c): compiler(c), eng(c->engine()) { } void operator () (AST::Node *node) { if (node) node->accept(this); }protected: virtual bool visit(AST::FunctionDeclaration *node) { compiler->iDeclareLocal(node->name, /*readOnly=*/false); return false; } virtual bool visit(AST::FunctionExpression *) { return false; } virtual bool visit(AST::VariableDeclaration *node) { compiler->iDeclareLocal(node->name, node->readOnly); return false; }private: Compiler *compiler; QScriptEnginePrivate *eng;};Compiler::Compiler(QScriptEngine *eng): m_eng(QScriptEnginePrivate::get(eng)), m_generateReferences(0), m_iterationStatement(0), m_switchStatement(0), m_withStatement(0), m_generateLeaveWithOnBreak(0), m_generateFastArgumentLookup(0), m_parseStatements(0), m_pad(0), m_topLevelCompiler(false), m_activeLoop(0){}Compiler::~Compiler(){}bool Compiler::topLevelCompiler() const{ return m_topLevelCompiler;}void Compiler::setTopLevelCompiler(bool b){ m_topLevelCompiler = b;} CompilationUnit Compiler::compile(AST::Node *node, const QList<QScriptNameIdImpl *> &formals){ m_formals = formals; m_generateReferences = 0; m_iterationStatement = 0; m_switchStatement = 0; m_withStatement = 0; m_generateLeaveWithOnBreak = 0; m_generateFastArgumentLookup = 0; m_parseStatements = 0; m_pad = 0; m_instructions.clear(); m_exceptionHandlers.clear(); m_generateFastArgumentLookup = false; // ### !formals.isEmpty(); // ### disabled for now.. it's buggy :( m_compilationUnit = CompilationUnit(); if (node) node->accept(this); // add a terminator if (topLevelCompiler()) { iHalt(); } else if (m_instructions.isEmpty() || m_instructions.last().op != QScriptInstruction::OP_Ret) { iLoadUndefined(); iRet(); } m_compilationUnit.setInstructions(m_instructions); m_compilationUnit.setExceptionHandlers(m_exceptionHandlers); return m_compilationUnit;}bool Compiler::preVisit(AST::Node *){ return m_compilationUnit.isValid();}bool Compiler::visit(AST::SourceElements *node){ DeclareLocals declareLocals(this); declareLocals(node); bool was = changeParseStatements(false); for (AST::SourceElements *it = node; it != 0; it = it->next) it->element->accept(this); changeParseStatements(true); for (AST::SourceElements *it = node; it != 0; it = it->next) it->element->accept(this); changeParseStatements(was); return false;}bool Compiler::visit(AST::StatementList *){ return true;}bool Compiler::visit(AST::FunctionSourceElement *){ return m_parseStatements == 0;}bool Compiler::visit(AST::StatementSourceElement *){ return m_parseStatements;}bool Compiler::visit(AST::ThisExpression *){ iLoadThis(); return false;}bool Compiler::visit(AST::NullExpression *){ iLoadNull(); return false;}bool Compiler::visit(AST::RegExpLiteral *node){ Q_ASSERT(node->pattern != 0); if (node->flags) iNewRegExp(node->pattern, node->flags); else iNewRegExp(node->pattern); return false;}bool Compiler::visit(AST::NumericLiteral *node){ iLoadNumber(node->value); return false;}bool Compiler::visit(AST::StringLiteral *node){ iNewString(node->value); return false;}bool Compiler::visit(AST::ObjectLiteral *node){ iNewObject(); FetchName fetchName(m_eng); for (AST::PropertyNameAndValueList *it = node->properties; it != 0; it = it->next) { iDuplicate(); QScriptNameIdImpl *name = fetchName(it->name); Q_ASSERT(name != 0); iLoadString(name); iMakeReference(); it->value->accept(this); iPutField(); } return false;}bool Compiler::visit(AST::IdentifierExpression *node){ Q_ASSERT(node->name != 0); if (m_generateReferences) iResolve(node->name); else if (node->name == m_eng->idTable()->id_arguments) iFetchArguments(); else iFetch(node->name); return false;}bool Compiler::visit(AST::FunctionDeclaration *node){ iResolve(node->name); iNewClosure(node); iPutField(); return false;}bool Compiler::visit(AST::FunctionExpression *node){ if (node->name) { iResolve(node->name); iNewClosure(node); iAssign(); } else { iNewClosure(node); } return false;}bool Compiler::visit(AST::CallExpression *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); iCall(argc); return false;}bool Compiler::visit(AST::NewExpression *node){ bool was = generateReferences(true); node->expression->accept(this); generateReferences(was); iNew(0); return false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -