diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-06-21 22:57:07 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-06-26 10:04:04 +0000 |
commit | 5faf2e9a693d10e1e689c42deec911083a35ddb2 (patch) | |
tree | 58d56608b05274c89139175b6664d7157437aa7e /src/qml | |
parent | b797006c4491127f5c34f8eca49c6d1d576941db (diff) |
Properly distinguish between class expressions and declarations
Introduce both types in the AST, and handle them properly
in the code generator.
Change-Id: I754ac0976de69009bdb8b203d890e4ec0ad03b30
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 9 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 1 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilerscanfunctions.cpp | 17 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilerscanfunctions_p.h | 3 | ||||
-rw-r--r-- | src/qml/parser/qqmljs.g | 23 | ||||
-rw-r--r-- | src/qml/parser/qqmljsast.cpp | 10 | ||||
-rw-r--r-- | src/qml/parser/qqmljsast_p.h | 14 | ||||
-rw-r--r-- | src/qml/parser/qqmljsastfwd_p.h | 1 | ||||
-rw-r--r-- | src/qml/parser/qqmljsastvisitor_p.h | 3 |
9 files changed, 77 insertions, 4 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 3e7fcbf77b..a7517fcde9 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -916,12 +916,19 @@ bool Codegen::visit(ClassExpression *ast) Reference ctor = referenceForName(ast->name.toString(), true); (void) ctor.storeRetainAccumulator(); - (void) outerVar.storeRetainAccumulator(); _expr.setResult(Reference::fromAccumulator(this)); return false; } +bool Codegen::visit(ClassDeclaration *ast) +{ + Reference outerVar = referenceForName(ast->name.toString(), true); + visit(static_cast<ClassExpression *>(ast)); + (void) outerVar.storeRetainAccumulator(); + return false; +} + bool Codegen::visit(Expression *ast) { if (hasError) diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index 5ddb762c8b..5232624f0f 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -600,6 +600,7 @@ protected: bool visit(AST::FunctionDeclaration *ast) override; bool visit(AST::YieldExpression *ast) override; bool visit(AST::ClassExpression *ast) override; + bool visit(AST::ClassDeclaration *ast) override; // statements bool visit(AST::Block *ast) override; diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp index eda0102844..8b8c385b84 100644 --- a/src/qml/compiler/qv4compilerscanfunctions.cpp +++ b/src/qml/compiler/qv4compilerscanfunctions.cpp @@ -226,6 +226,21 @@ bool ScanFunctions::visit(FunctionExpression *ast) bool ScanFunctions::visit(ClassExpression *ast) { + enterEnvironment(ast, ContextType::Block, QStringLiteral("%Class")); + _context->isStrict = true; + _context->hasNestedFunctions = true; + if (!ast->name.isEmpty()) + _context->addLocalVar(ast->name.toString(), Context::VariableDeclaration, AST::VariableScope::Let); + return true; +} + +void ScanFunctions::endVisit(ClassExpression *) +{ + leaveEnvironment(); +} + +bool ScanFunctions::visit(ClassDeclaration *ast) +{ if (!ast->name.isEmpty()) _context->addLocalVar(ast->name.toString(), Context::VariableDeclaration, AST::VariableScope::Let); @@ -237,7 +252,7 @@ bool ScanFunctions::visit(ClassExpression *ast) return true; } -void ScanFunctions::endVisit(ClassExpression *) +void ScanFunctions::endVisit(ClassDeclaration *) { leaveEnvironment(); } diff --git a/src/qml/compiler/qv4compilerscanfunctions_p.h b/src/qml/compiler/qv4compilerscanfunctions_p.h index ffa1409da9..f2d8c2988d 100644 --- a/src/qml/compiler/qv4compilerscanfunctions_p.h +++ b/src/qml/compiler/qv4compilerscanfunctions_p.h @@ -124,6 +124,9 @@ protected: bool visit(AST::ClassExpression *ast) override; void endVisit(AST::ClassExpression *) override; + bool visit(AST::ClassDeclaration *ast) override; + void endVisit(AST::ClassDeclaration *) override; + bool visit(AST::DoWhileStatement *ast) override; bool visit(AST::ForStatement *ast) override; void endVisit(AST::ForStatement *) override; diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index 510baef352..9231001f17 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -3863,7 +3863,17 @@ YieldExpression_In: T_YIELD AssignmentExpression_In; ClassDeclaration: T_CLASS BindingIdentifier ClassHeritageOpt ClassLBrace ClassBodyOpt ClassRBrace; -/. case $rule_number: Q_FALLTHROUGH(); ./ +/. + case $rule_number: { + AST::ClassDeclaration *node = new (pool) AST::ClassDeclaration(stringRef(2), sym(3).Expression, sym(5).ClassElementList); + node->classToken = loc(1); + node->identifierToken = loc(2); + node->lbraceToken = loc(4); + node->rbraceToken = loc(6); + sym(1).Node = node; + } break; +./ + ClassExpression: T_CLASS BindingIdentifier ClassHeritageOpt ClassLBrace ClassBodyOpt ClassRBrace; /. case $rule_number: { @@ -3877,7 +3887,16 @@ ClassExpression: T_CLASS BindingIdentifier ClassHeritageOpt ClassLBrace ClassBod ./ ClassDeclaration_Default: T_CLASS ClassHeritageOpt ClassLBrace ClassBodyOpt ClassRBrace; -/. case $rule_number: Q_FALLTHROUGH(); ./ +/. + case $rule_number: { + AST::ClassDeclaration *node = new (pool) AST::ClassDeclaration(QStringRef(), sym(2).Expression, sym(4).ClassElementList); + node->classToken = loc(1); + node->lbraceToken = loc(3); + node->rbraceToken = loc(5); + sym(1).Node = node; + } break; +./ + ClassExpression: T_CLASS ClassHeritageOpt ClassLBrace ClassBodyOpt ClassRBrace; /. case $rule_number: { diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp index 1c997e1de7..89ef861c85 100644 --- a/src/qml/parser/qqmljsast.cpp +++ b/src/qml/parser/qqmljsast.cpp @@ -1296,6 +1296,16 @@ void ClassExpression::accept0(Visitor *visitor) visitor->endVisit(this); } +void ClassDeclaration::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(heritage, visitor); + accept(elements, visitor); + } + + visitor->endVisit(this); +} + void ClassElementList::accept0(Visitor *visitor) { if (visitor->visit(this)) { diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h index 67abbbf88a..6a4e1e6ea1 100644 --- a/src/qml/parser/qqmljsast_p.h +++ b/src/qml/parser/qqmljsast_p.h @@ -169,6 +169,7 @@ public: Kind_FunctionDeclaration, Kind_FunctionExpression, Kind_ClassExpression, + Kind_ClassDeclaration, Kind_IdentifierExpression, Kind_IdentifierPropertyName, Kind_ComputedPropertyName, @@ -2246,6 +2247,19 @@ public: SourceLocation rbraceToken; }; +class QML_PARSER_EXPORT ClassDeclaration: public ClassExpression +{ +public: + QQMLJS_DECLARE_AST_NODE(ClassDeclaration) + + ClassDeclaration(const QStringRef &n, ExpressionNode *heritage, ClassElementList *elements) + : ClassExpression(n, heritage, elements) + { kind = K; } + + void accept0(Visitor *visitor) override; +}; + + class QML_PARSER_EXPORT ClassElementList : public Node { public: diff --git a/src/qml/parser/qqmljsastfwd_p.h b/src/qml/parser/qqmljsastfwd_p.h index 196d23a9c4..406a06c6db 100644 --- a/src/qml/parser/qqmljsastfwd_p.h +++ b/src/qml/parser/qqmljsastfwd_p.h @@ -162,6 +162,7 @@ class Program; class DebuggerStatement; class NestedExpression; class ClassExpression; +class ClassDeclaration; class ClassElementList; // ui elements diff --git a/src/qml/parser/qqmljsastvisitor_p.h b/src/qml/parser/qqmljsastvisitor_p.h index 5fbdf4adff..6e1fed9dbb 100644 --- a/src/qml/parser/qqmljsastvisitor_p.h +++ b/src/qml/parser/qqmljsastvisitor_p.h @@ -326,6 +326,9 @@ public: virtual bool visit(ClassExpression *) { return true; } virtual void endVisit(ClassExpression *) {} + virtual bool visit(ClassDeclaration *) { return true; } + virtual void endVisit(ClassDeclaration *) {} + virtual bool visit(ClassElementList *) { return true; } virtual void endVisit(ClassElementList *) {} |