diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2013-08-06 13:59:47 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-08-22 04:24:10 +0200 |
commit | e8cb9ac132dbac4c7373a47469a097e572b818d2 (patch) | |
tree | d2874528fd391ce6fb0ac979df6019f2ba8e11ee /src | |
parent | e04cadca4a6c0b43d29c83d23ac74393694a5ea5 (diff) |
Cleanup: Separate JS environment scanner class declaration from definition
This will allow the use of it from outside.
Change-Id: Ia05a17b4b4f3e772554979e215a6252a75a63273
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 592 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 72 |
2 files changed, 358 insertions, 306 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 6c913a6dc4..e97be71d02 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -67,383 +67,365 @@ using namespace QQmlJS; using namespace AST; -class Codegen::ScanFunctions: Visitor -{ - typedef QV4::TemporaryAssignment<bool> TemporaryBoolAssignment; -public: - ScanFunctions(Codegen *cg, const QString &sourceCode) - : _cg(cg) - , _sourceCode(sourceCode) - , _env(0) - , _inFuncBody(false) - , _allowFuncDecls(true) - { - } - - void operator()(Node *node) - { - if (node) - node->accept(this); - } +Codegen::ScanFunctions::ScanFunctions(Codegen *cg, const QString &sourceCode) + : _cg(cg) + , _sourceCode(sourceCode) + , _env(0) + , _inFuncBody(false) + , _allowFuncDecls(true) +{ +} - inline void enterEnvironment(Node *node) - { - Environment *e = _cg->newEnvironment(node, _env); - if (!e->isStrict) - e->isStrict = _cg->_strictMode; - _envStack.append(e); - _env = e; - } +void Codegen::ScanFunctions::operator()(Node *node) +{ + if (node) + node->accept(this); +} - inline void leaveEnvironment() - { - _envStack.pop(); - _env = _envStack.isEmpty() ? 0 : _envStack.top(); - } +void Codegen::ScanFunctions::enterEnvironment(Node *node) +{ + Environment *e = _cg->newEnvironment(node, _env); + if (!e->isStrict) + e->isStrict = _cg->_strictMode; + _envStack.append(e); + _env = e; +} -protected: - using Visitor::visit; - using Visitor::endVisit; +void Codegen::ScanFunctions::leaveEnvironment() +{ + _envStack.pop(); + _env = _envStack.isEmpty() ? 0 : _envStack.top(); +} - void checkDirectivePrologue(SourceElements *ast) - { - for (SourceElements *it = ast; it; it = it->next) { - if (StatementSourceElement *stmt = cast<StatementSourceElement *>(it->element)) { - if (ExpressionStatement *expr = cast<ExpressionStatement *>(stmt->statement)) { - if (StringLiteral *strLit = cast<StringLiteral *>(expr->expression)) { - // Use the source code, because the StringLiteral's - // value might have escape sequences in it, which is not - // allowed. - if (strLit->literalToken.length < 2) - continue; - QStringRef str = _sourceCode.midRef(strLit->literalToken.offset + 1, strLit->literalToken.length - 2); - if (str == QStringLiteral("use strict")) { - _env->isStrict = true; - } else { - // TODO: give a warning. - } +void Codegen::ScanFunctions::checkDirectivePrologue(SourceElements *ast) +{ + for (SourceElements *it = ast; it; it = it->next) { + if (StatementSourceElement *stmt = cast<StatementSourceElement *>(it->element)) { + if (ExpressionStatement *expr = cast<ExpressionStatement *>(stmt->statement)) { + if (StringLiteral *strLit = cast<StringLiteral *>(expr->expression)) { + // Use the source code, because the StringLiteral's + // value might have escape sequences in it, which is not + // allowed. + if (strLit->literalToken.length < 2) continue; + QStringRef str = _sourceCode.midRef(strLit->literalToken.offset + 1, strLit->literalToken.length - 2); + if (str == QStringLiteral("use strict")) { + _env->isStrict = true; + } else { + // TODO: give a warning. } + continue; } } - - break; } + + break; } +} - void checkName(const QStringRef &name, const SourceLocation &loc) - { - if (_env->isStrict) { - if (name == QLatin1String("implements") - || name == QLatin1String("interface") - || name == QLatin1String("let") - || name == QLatin1String("package") - || name == QLatin1String("private") - || name == QLatin1String("protected") - || name == QLatin1String("public") - || name == QLatin1String("static") - || name == QLatin1String("yield")) { - _cg->throwSyntaxError(loc, QCoreApplication::translate("qv4codegen", "Unexpected strict mode reserved word")); - } +void Codegen::ScanFunctions::checkName(const QStringRef &name, const SourceLocation &loc) +{ + if (_env->isStrict) { + if (name == QLatin1String("implements") + || name == QLatin1String("interface") + || name == QLatin1String("let") + || name == QLatin1String("package") + || name == QLatin1String("private") + || name == QLatin1String("protected") + || name == QLatin1String("public") + || name == QLatin1String("static") + || name == QLatin1String("yield")) { + _cg->throwSyntaxError(loc, QCoreApplication::translate("qv4codegen", "Unexpected strict mode reserved word")); } } - void checkForArguments(AST::FormalParameterList *parameters) - { - while (parameters) { - if (parameters->name == QStringLiteral("arguments")) - _env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed; - parameters = parameters->next; - } +} +void Codegen::ScanFunctions::checkForArguments(AST::FormalParameterList *parameters) +{ + while (parameters) { + if (parameters->name == QStringLiteral("arguments")) + _env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed; + parameters = parameters->next; } +} - virtual bool visit(Program *ast) - { - enterEnvironment(ast); - checkDirectivePrologue(ast->elements); - return true; - } +bool Codegen::ScanFunctions::visit(Program *ast) +{ + enterEnvironment(ast); + checkDirectivePrologue(ast->elements); + return true; +} - virtual void endVisit(Program *) - { - leaveEnvironment(); - } +void Codegen::ScanFunctions::endVisit(Program *) +{ + leaveEnvironment(); +} - virtual bool visit(CallExpression *ast) - { - if (! _env->hasDirectEval) { - if (IdentifierExpression *id = cast<IdentifierExpression *>(ast->base)) { - if (id->name == QStringLiteral("eval")) { - if (_env->usesArgumentsObject == Environment::ArgumentsObjectUnknown) - _env->usesArgumentsObject = Environment::ArgumentsObjectUsed; - _env->hasDirectEval = true; - } +bool Codegen::ScanFunctions::visit(CallExpression *ast) +{ + if (! _env->hasDirectEval) { + if (IdentifierExpression *id = cast<IdentifierExpression *>(ast->base)) { + if (id->name == QStringLiteral("eval")) { + if (_env->usesArgumentsObject == Environment::ArgumentsObjectUnknown) + _env->usesArgumentsObject = Environment::ArgumentsObjectUsed; + _env->hasDirectEval = true; } } - int argc = 0; - for (ArgumentList *it = ast->arguments; it; it = it->next) - ++argc; - _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc); - return true; } + int argc = 0; + for (ArgumentList *it = ast->arguments; it; it = it->next) + ++argc; + _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc); + return true; +} - virtual bool visit(NewMemberExpression *ast) - { - int argc = 0; - for (ArgumentList *it = ast->arguments; it; it = it->next) - ++argc; - _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc); - return true; - } +bool Codegen::ScanFunctions::visit(NewMemberExpression *ast) +{ + int argc = 0; + for (ArgumentList *it = ast->arguments; it; it = it->next) + ++argc; + _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc); + return true; +} - virtual bool visit(ArrayLiteral *ast) - { - int index = 0; - for (ElementList *it = ast->elements; it; it = it->next) { - for (Elision *elision = it->elision; elision; elision = elision->next) - ++index; +bool Codegen::ScanFunctions::visit(ArrayLiteral *ast) +{ + int index = 0; + for (ElementList *it = ast->elements; it; it = it->next) { + for (Elision *elision = it->elision; elision; elision = elision->next) ++index; - } - if (ast->elision) { - for (Elision *elision = ast->elision->next; elision; elision = elision->next) - ++index; - } - _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, index); - return true; - } - - virtual bool visit(VariableDeclaration *ast) - { - if (_env->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments"))) - _cg->throwSyntaxError(ast->identifierToken, QCoreApplication::translate("qv4codegen", "Variable name may not be eval or arguments in strict mode")); - checkName(ast->name, ast->identifierToken); - if (ast->name == QLatin1String("arguments")) - _env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed; - _env->enter(ast->name.toString(), ast->expression ? Environment::VariableDefinition : Environment::VariableDeclaration); - return true; + ++index; } - - virtual bool visit(IdentifierExpression *ast) - { - checkName(ast->name, ast->identifierToken); - if (_env->usesArgumentsObject == Environment::ArgumentsObjectUnknown && ast->name == QLatin1String("arguments")) - _env->usesArgumentsObject = Environment::ArgumentsObjectUsed; - return true; + if (ast->elision) { + for (Elision *elision = ast->elision->next; elision; elision = elision->next) + ++index; } + _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, index); + return true; +} - virtual bool visit(ExpressionStatement *ast) - { - if (FunctionExpression* expr = AST::cast<AST::FunctionExpression*>(ast->expression)) { - if (!_allowFuncDecls) - _cg->throwSyntaxError(expr->functionToken, QCoreApplication::translate("qv4codegen", "conditional function or closure declaration")); - - enterFunction(expr, /*enterName*/ true); - Node::accept(expr->formals, this); - Node::accept(expr->body, this); - leaveEnvironment(); - return false; - } else { - SourceLocation firstToken = ast->firstSourceLocation(); - if (_sourceCode.midRef(firstToken.offset, firstToken.length) == QStringLiteral("function")) { - _cg->throwSyntaxError(firstToken, QCoreApplication::translate("qv4codegen", "unexpected token")); - } - } - return true; - } +bool Codegen::ScanFunctions::visit(VariableDeclaration *ast) +{ + if (_env->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments"))) + _cg->throwSyntaxError(ast->identifierToken, QCoreApplication::translate("qv4codegen", "Variable name may not be eval or arguments in strict mode")); + checkName(ast->name, ast->identifierToken); + if (ast->name == QLatin1String("arguments")) + _env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed; + _env->enter(ast->name.toString(), ast->expression ? Environment::VariableDefinition : Environment::VariableDeclaration); + return true; +} - virtual bool visit(FunctionExpression *ast) - { - enterFunction(ast, /*enterName*/ false); - return true; - } +bool Codegen::ScanFunctions::visit(IdentifierExpression *ast) +{ + checkName(ast->name, ast->identifierToken); + if (_env->usesArgumentsObject == Environment::ArgumentsObjectUnknown && ast->name == QLatin1String("arguments")) + _env->usesArgumentsObject = Environment::ArgumentsObjectUsed; + return true; +} - void enterFunction(FunctionExpression *ast, bool enterName, bool isExpression = true) - { - if (_env->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments"))) - _cg->throwSyntaxError(ast->identifierToken, QCoreApplication::translate("qv4codegen", "Function name may not be eval or arguments in strict mode")); - enterFunction(ast, ast->name.toString(), ast->formals, ast->body, enterName ? ast : 0, isExpression); - } +bool Codegen::ScanFunctions::visit(ExpressionStatement *ast) +{ + if (FunctionExpression* expr = AST::cast<AST::FunctionExpression*>(ast->expression)) { + if (!_allowFuncDecls) + _cg->throwSyntaxError(expr->functionToken, QCoreApplication::translate("qv4codegen", "conditional function or closure declaration")); - virtual void endVisit(FunctionExpression *) - { + enterFunction(expr, /*enterName*/ true); + Node::accept(expr->formals, this); + Node::accept(expr->body, this); leaveEnvironment(); - } - - virtual bool visit(ObjectLiteral *ast) - { - int argc = 0; - for (PropertyAssignmentList *it = ast->properties; it; it = it->next) { - ++argc; - if (AST::cast<AST::PropertyGetterSetter *>(it->assignment)) - ++argc; - } - _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc); - - TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true); - Node::accept(ast->properties, this); return false; + } else { + SourceLocation firstToken = ast->firstSourceLocation(); + if (_sourceCode.midRef(firstToken.offset, firstToken.length) == QStringLiteral("function")) { + _cg->throwSyntaxError(firstToken, QCoreApplication::translate("qv4codegen", "unexpected token")); + } } + return true; +} - virtual bool visit(PropertyGetterSetter *ast) - { - TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true); - enterFunction(ast, QString(), ast->formals, ast->functionBody, /*FunctionExpression*/0, /*isExpression*/false); - return true; - } +bool Codegen::ScanFunctions::visit(FunctionExpression *ast) +{ + enterFunction(ast, /*enterName*/ false); + return true; +} - virtual void endVisit(PropertyGetterSetter *) - { - leaveEnvironment(); - } +void Codegen::ScanFunctions::enterFunction(FunctionExpression *ast, bool enterName, bool isExpression) +{ + if (_env->isStrict && (ast->name == QLatin1String("eval") || ast->name == QLatin1String("arguments"))) + _cg->throwSyntaxError(ast->identifierToken, QCoreApplication::translate("qv4codegen", "Function name may not be eval or arguments in strict mode")); + enterFunction(ast, ast->name.toString(), ast->formals, ast->body, enterName ? ast : 0, isExpression); +} - virtual bool visit(FunctionDeclaration *ast) - { - enterFunction(ast, /*enterName*/ true, /*isExpression */false); - return true; - } +void Codegen::ScanFunctions::endVisit(FunctionExpression *) +{ + leaveEnvironment(); +} - virtual void endVisit(FunctionDeclaration *) - { - leaveEnvironment(); +bool Codegen::ScanFunctions::visit(ObjectLiteral *ast) +{ + int argc = 0; + for (PropertyAssignmentList *it = ast->properties; it; it = it->next) { + ++argc; + if (AST::cast<AST::PropertyGetterSetter *>(it->assignment)) + ++argc; } + _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc); - virtual bool visit(FunctionBody *ast) - { - TemporaryBoolAssignment inFuncBody(_inFuncBody, true); - Node::accept(ast->elements, this); - return false; - } + TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true); + Node::accept(ast->properties, this); + return false; +} - virtual bool visit(WithStatement *ast) - { - if (_env->isStrict) { - _cg->throwSyntaxError(ast->withToken, QCoreApplication::translate("qv4codegen", "'with' statement is not allowed in strict mode")); - return false; - } +bool Codegen::ScanFunctions::visit(PropertyGetterSetter *ast) +{ + TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, true); + enterFunction(ast, QString(), ast->formals, ast->functionBody, /*FunctionExpression*/0, /*isExpression*/false); + return true; +} - return true; - } +void Codegen::ScanFunctions::endVisit(PropertyGetterSetter *) +{ + leaveEnvironment(); +} + +bool Codegen::ScanFunctions::visit(FunctionDeclaration *ast) +{ + enterFunction(ast, /*enterName*/ true, /*isExpression */false); + return true; +} - virtual bool visit(IfStatement *ast) { - Node::accept(ast->expression, this); +void Codegen::ScanFunctions::endVisit(FunctionDeclaration *) +{ + leaveEnvironment(); +} - TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_inFuncBody); - Node::accept(ast->ok, this); - Node::accept(ast->ko, this); +bool Codegen::ScanFunctions::visit(FunctionBody *ast) +{ + TemporaryBoolAssignment inFuncBody(_inFuncBody, true); + Node::accept(ast->elements, this); + return false; +} +bool Codegen::ScanFunctions::visit(WithStatement *ast) +{ + if (_env->isStrict) { + _cg->throwSyntaxError(ast->withToken, QCoreApplication::translate("qv4codegen", "'with' statement is not allowed in strict mode")); return false; } - virtual bool visit(WhileStatement *ast) { - Node::accept(ast->expression, this); + return true; +} - TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_inFuncBody); - Node::accept(ast->statement, this); +bool Codegen::ScanFunctions::visit(IfStatement *ast) { + Node::accept(ast->expression, this); - return false; - } + TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_inFuncBody); + Node::accept(ast->ok, this); + Node::accept(ast->ko, this); - virtual bool visit(DoWhileStatement *ast) { - { - TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict); - Node::accept(ast->statement, this); - } - Node::accept(ast->expression, this); - return false; - } + return false; +} + +bool Codegen::ScanFunctions::visit(WhileStatement *ast) { + Node::accept(ast->expression, this); + + TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_inFuncBody); + Node::accept(ast->statement, this); - virtual bool visit(ForStatement *ast) { - Node::accept(ast->initialiser, this); - Node::accept(ast->condition, this); - Node::accept(ast->expression, this); + return false; +} +bool Codegen::ScanFunctions::visit(DoWhileStatement *ast) { + { TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict); Node::accept(ast->statement, this); - - return false; } + Node::accept(ast->expression, this); + return false; +} - virtual bool visit(LocalForStatement *ast) { - Node::accept(ast->declarations, this); - Node::accept(ast->condition, this); - Node::accept(ast->expression, this); +bool Codegen::ScanFunctions::visit(ForStatement *ast) { + Node::accept(ast->initialiser, this); + Node::accept(ast->condition, this); + Node::accept(ast->expression, this); - TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict); - Node::accept(ast->statement, this); + TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict); + Node::accept(ast->statement, this); - return false; - } + return false; +} - virtual bool visit(ForEachStatement *ast) { - Node::accept(ast->initialiser, this); - Node::accept(ast->expression, this); +bool Codegen::ScanFunctions::visit(LocalForStatement *ast) { + Node::accept(ast->declarations, this); + Node::accept(ast->condition, this); + Node::accept(ast->expression, this); - TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict); - Node::accept(ast->statement, this); + TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict); + Node::accept(ast->statement, this); - return false; - } + return false; +} - virtual bool visit(LocalForEachStatement *ast) { - Node::accept(ast->declaration, this); - Node::accept(ast->expression, this); +bool Codegen::ScanFunctions::visit(ForEachStatement *ast) { + Node::accept(ast->initialiser, this); + Node::accept(ast->expression, this); - TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict); - Node::accept(ast->statement, this); + TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict); + Node::accept(ast->statement, this); - return false; - } + return false; +} - virtual bool visit(Block *ast) { - TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _env->isStrict ? false : _allowFuncDecls); - Node::accept(ast->statements, this); - return false; - } +bool Codegen::ScanFunctions::visit(LocalForEachStatement *ast) { + Node::accept(ast->declaration, this); + Node::accept(ast->expression, this); -private: - void enterFunction(Node *ast, const QString &name, FormalParameterList *formals, FunctionBody *body, FunctionExpression *expr, bool isExpression) - { - bool wasStrict = false; - if (_env) { - _env->hasNestedFunctions = true; - // The identifier of a function expression cannot be referenced from the enclosing environment. - if (expr) - _env->enter(name, Environment::FunctionDefinition, expr); - if (name == QLatin1String("arguments")) - _env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed; - wasStrict = _env->isStrict; - } + TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, !_env->isStrict); + Node::accept(ast->statement, this); - enterEnvironment(ast); - checkForArguments(formals); + return false; +} - _env->isNamedFunctionExpression = isExpression && !name.isEmpty(); - _env->formals = formals; +bool Codegen::ScanFunctions::visit(Block *ast) { + TemporaryBoolAssignment allowFuncDecls(_allowFuncDecls, _env->isStrict ? false : _allowFuncDecls); + Node::accept(ast->statements, this); + return false; +} - if (body) - checkDirectivePrologue(body->elements); +void Codegen::ScanFunctions::enterFunction(Node *ast, const QString &name, FormalParameterList *formals, FunctionBody *body, FunctionExpression *expr, bool isExpression) +{ + bool wasStrict = false; + if (_env) { + _env->hasNestedFunctions = true; + // The identifier of a function expression cannot be referenced from the enclosing environment. + if (expr) + _env->enter(name, Environment::FunctionDefinition, expr); + if (name == QLatin1String("arguments")) + _env->usesArgumentsObject = Environment::ArgumentsObjectNotUsed; + wasStrict = _env->isStrict; + } - if (wasStrict || _env->isStrict) { - QStringList args; - for (FormalParameterList *it = formals; it; it = it->next) { - QString arg = it->name.toString(); - if (args.contains(arg)) - _cg->throwSyntaxError(it->identifierToken, QCoreApplication::translate("qv4codegen", "Duplicate parameter name '%1' is not allowed in strict mode").arg(arg)); - if (arg == QLatin1String("eval") || arg == QLatin1String("arguments")) - _cg->throwSyntaxError(it->identifierToken, QCoreApplication::translate("qv4codegen", "'%1' cannot be used as parameter name in strict mode").arg(arg)); - args += arg; - } + enterEnvironment(ast); + checkForArguments(formals); + + _env->isNamedFunctionExpression = isExpression && !name.isEmpty(); + _env->formals = formals; + + if (body) + checkDirectivePrologue(body->elements); + + if (wasStrict || _env->isStrict) { + QStringList args; + for (FormalParameterList *it = formals; it; it = it->next) { + QString arg = it->name.toString(); + if (args.contains(arg)) + _cg->throwSyntaxError(it->identifierToken, QCoreApplication::translate("qv4codegen", "Duplicate parameter name '%1' is not allowed in strict mode").arg(arg)); + if (arg == QLatin1String("eval") || arg == QLatin1String("arguments")) + _cg->throwSyntaxError(it->identifierToken, QCoreApplication::translate("qv4codegen", "'%1' cannot be used as parameter name in strict mode").arg(arg)); + args += arg; } } +} -private: // fields: - Codegen *_cg; - const QString _sourceCode; - Environment *_env; - QStack<Environment *> _envStack; - - bool _inFuncBody; - bool _allowFuncDecls; -}; Codegen::Codegen(bool strict) : _module(0) diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index 85c38d8d8c..2aa4b42c6a 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -46,8 +46,10 @@ #include <private/qqmljsastvisitor_p.h> #include <private/qqmljsast_p.h> #include <QtCore/QStringList> +#include <QStack> #include <qqmlerror.h> #include <assert.h> +#include <private/qv4util_p.h> QT_BEGIN_NAMESPACE @@ -433,7 +435,75 @@ protected: QList<QQmlError> _errors; - class ScanFunctions; + class ScanFunctions: Visitor + { + typedef QV4::TemporaryAssignment<bool> TemporaryBoolAssignment; + public: + ScanFunctions(Codegen *cg, const QString &sourceCode); + void operator()(AST::Node *node); + + void enterEnvironment(AST::Node *node); + void leaveEnvironment(); + + protected: + using Visitor::visit; + using Visitor::endVisit; + + void checkDirectivePrologue(AST::SourceElements *ast); + + void checkName(const QStringRef &name, const AST::SourceLocation &loc); + void checkForArguments(AST::FormalParameterList *parameters); + + virtual bool visit(AST::Program *ast); + virtual void endVisit(AST::Program *); + + virtual bool visit(AST::CallExpression *ast); + virtual bool visit(AST::NewMemberExpression *ast); + virtual bool visit(AST::ArrayLiteral *ast); + virtual bool visit(AST::VariableDeclaration *ast); + virtual bool visit(AST::IdentifierExpression *ast); + virtual bool visit(AST::ExpressionStatement *ast); + virtual bool visit(AST::FunctionExpression *ast); + + void enterFunction(AST::FunctionExpression *ast, bool enterName, bool isExpression = true); + + virtual void endVisit(AST::FunctionExpression *); + + virtual bool visit(AST::ObjectLiteral *ast); + + virtual bool visit(AST::PropertyGetterSetter *ast); + virtual void endVisit(AST::PropertyGetterSetter *); + + virtual bool visit(AST::FunctionDeclaration *ast); + virtual void endVisit(AST::FunctionDeclaration *); + + virtual bool visit(AST::FunctionBody *ast); + + virtual bool visit(AST::WithStatement *ast); + + virtual bool visit(AST::IfStatement *ast); + virtual bool visit(AST::WhileStatement *ast); + virtual bool visit(AST::DoWhileStatement *ast); + virtual bool visit(AST::ForStatement *ast); + virtual bool visit(AST::LocalForStatement *ast); + virtual bool visit(AST::ForEachStatement *ast); + virtual bool visit(AST::LocalForEachStatement *ast); + + virtual bool visit(AST::Block *ast); + + protected: + void enterFunction(AST::Node *ast, const QString &name, AST::FormalParameterList *formals, AST::FunctionBody *body, AST::FunctionExpression *expr, bool isExpression); + + // fields: + Codegen *_cg; + const QString _sourceCode; + Environment *_env; + QStack<Environment *> _envStack; + + bool _inFuncBody; + bool _allowFuncDecls; + }; + }; class RuntimeCodegen : public Codegen |