aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-06-21 22:57:07 +0200
committerLars Knoll <lars.knoll@qt.io>2018-06-26 10:04:04 +0000
commit5faf2e9a693d10e1e689c42deec911083a35ddb2 (patch)
tree58d56608b05274c89139175b6664d7157437aa7e /src
parentb797006c4491127f5c34f8eca49c6d1d576941db (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')
-rw-r--r--src/qml/compiler/qv4codegen.cpp9
-rw-r--r--src/qml/compiler/qv4codegen_p.h1
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp17
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions_p.h3
-rw-r--r--src/qml/parser/qqmljs.g23
-rw-r--r--src/qml/parser/qqmljsast.cpp10
-rw-r--r--src/qml/parser/qqmljsast_p.h14
-rw-r--r--src/qml/parser/qqmljsastfwd_p.h1
-rw-r--r--src/qml/parser/qqmljsastvisitor_p.h3
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 *) {}