diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-02-26 10:08:37 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-04-25 17:49:44 +0000 |
commit | aabf2196016d96bd171a7d632b6e1cc5622d05ae (patch) | |
tree | 6e30bcc5bb6b6fbaa30d31b296e254ad0048e5a3 /src/qml | |
parent | da5fffbd34d8be68f8ee4c649881dbb673c9c0a5 (diff) |
Support for destructuring arrays
add support for destructuring of arrays when passing
arguments to functions.
Change-Id: I19feb39aa3ae520ec7591d49d1b14ceaa78783c6
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml')
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 37 | ||||
-rw-r--r-- | src/qml/parser/qqmljs.g | 44 | ||||
-rw-r--r-- | src/qml/parser/qqmljsast.cpp | 9 | ||||
-rw-r--r-- | src/qml/parser/qqmljsast_p.h | 32 |
4 files changed, 96 insertions, 26 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 973d5cd992..1aceb0f619 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -58,6 +58,8 @@ #include <cmath> #include <iostream> +static const bool disable_lookups = false; + #ifdef CONST #undef CONST #endif @@ -456,9 +458,6 @@ void Codegen::initializeAndDestructureBindingElement(AST::BindingElement *e, con void Codegen::destructurePropertyList(const Codegen::Reference &object, BindingPropertyList *bindingList) { - Q_UNUSED(object); - Q_UNUSED(bindingList); - RegisterScope scope(this); for (BindingPropertyList *p = bindingList; p; p = p->next) { @@ -467,14 +466,28 @@ void Codegen::destructurePropertyList(const Codegen::Reference &object, BindingP Reference property = Reference::fromMember(object, propertyName); initializeAndDestructureBindingElement(p->binding, property); } - } void Codegen::destructureElementList(const Codegen::Reference &array, BindingElementList *bindingList) { - Q_UNUSED(array); - // #### implement me - throwSyntaxError(bindingList->firstSourceLocation(), QString::fromLatin1("Support for binding element lists not implemented!")); + RegisterScope scope(this); + + int index = 0; + for (BindingElementList *p = bindingList; p; p = p->next) { + for (Elision *elision = p->elision; elision; elision = elision->next) + ++index; + + RegisterScope scope(this); + + Reference idx = Reference::fromConst(this, Encode(index)); + Reference property = Reference::fromSubscript(array, idx); + BindingElement *e = p->bindingElement(); + if (e) + initializeAndDestructureBindingElement(e, property); + else { + throwSyntaxError(bindingList->firstSourceLocation(), QString::fromLatin1("Support for rest elements in binding arrays not implemented!")); + } + } } @@ -1354,7 +1367,7 @@ void Codegen::handleCall(Reference &base, Arguments calldata) call.argv = calldata.argv; bytecodeGenerator->addInstruction(call); } else if (base.type == Reference::Member) { - if (useFastLookups) { + if (!disable_lookups && useFastLookups) { Instruction::CallPropertyLookup call; call.base = base.propertyBase.stackSlot(); call.lookupIndex = registerGetterLookup(base.propertyNameIndex); @@ -1382,7 +1395,7 @@ void Codegen::handleCall(Reference &base, Arguments calldata) call.argc = calldata.argc; call.argv = calldata.argv; bytecodeGenerator->addInstruction(call); - } else if (useFastLookups && base.global) { + } else if (!disable_lookups && useFastLookups && base.global) { Instruction::CallGlobalLookup call; call.index = registerGlobalGetterLookup(base.nameAsIndex()); call.argc = calldata.argc; @@ -3528,7 +3541,7 @@ void Codegen::Reference::storeAccumulator() const } } return; case Member: - if (codegen->useFastLookups) { + if (!disable_lookups && codegen->useFastLookups) { Instruction::SetLookup store; store.base = propertyBase.stackSlot(); store.index = codegen->registerSetterLookup(propertyNameIndex); @@ -3644,7 +3657,7 @@ QT_WARNING_POP return; } } - if (codegen->useFastLookups && global) { + if (!disable_lookups && codegen->useFastLookups && global) { Instruction::LoadGlobalLookup load; load.index = codegen->registerGlobalGetterLookup(nameAsIndex()); codegen->bytecodeGenerator->addInstruction(load); @@ -3655,7 +3668,7 @@ QT_WARNING_POP } return; case Member: - if (codegen->useFastLookups) { + if (!disable_lookups && codegen->useFastLookups) { if (propertyBase.isAccumulator()) { Instruction::GetLookupA load; load.index = codegen->registerGetterLookup(propertyNameIndex); diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index 376edb9f85..5b75ba2f8a 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -275,6 +275,7 @@ public: AST::VariableDeclarationList *VariableDeclarationList; AST::BindingElement *BindingElement; AST::BindingPropertyList *BindingPropertyList; + AST::BindingElementList *BindingElementList; AST::UiProgram *UiProgram; AST::UiHeaderItemList *UiHeaderItemList; @@ -1608,6 +1609,11 @@ case $rule_number: { ./ ElisionOpt: Elision ; +/. +case $rule_number: { + sym(1).Node = sym(1).Elision->finish(); +} break; +./ PropertyAssignment: PropertyName T_COLON AssignmentExpression ; /. @@ -3200,13 +3206,6 @@ case $rule_number: { BindingPattern: ObjectBindingPattern ; BindingPattern: ArrayBindingPattern ; -/. -case $rule_number: { - AST::BindingElementList *node = new (pool) AST::BindingElementList(); - node->loc = loc(1); - sym(1).Node = node; -} break; -./ ObjectBindingPattern: T_LBRACE T_RBRACE ; /. @@ -3225,8 +3224,28 @@ case $rule_number: { ./ ArrayBindingPattern: T_LBRACKET ElisionOpt BindingRestElementOpt T_RBRACKET ; +/. +case $rule_number: { + AST::BindingElementList *l = new (pool) AST::BindingElementList(sym(4).Elision, sym(5).Node); + sym(1).Node = l->finish(); +} break; +./ + ArrayBindingPattern: T_LBRACKET BindingElementList T_RBRACKET ; +/. +case $rule_number: { + sym(1).Node = sym(2).BindingElementList->finish(); +} break; +./ + ArrayBindingPattern: T_LBRACKET BindingElementList T_COMMA ElisionOpt BindingRestElementOpt T_RBRACKET ; +/. +case $rule_number: { + AST::BindingElementList *l = new (pool) AST::BindingElementList(sym(4).Elision, sym(5).Node); + l = sym(2).BindingElementList->append(l); + sym(1).Node = l->finish(); +} break; +./ BindingPropertyList: BindingProperty ; @@ -3239,8 +3258,19 @@ case $rule_number: { BindingElementList: BindingElisionElement ; BindingElementList: BindingElementList T_COMMA BindingElisionElement ; +/. +case $rule_number: { + sym(1).BindingElementList->append(sym(3).BindingElementList); +} break; +./ BindingElisionElement: ElisionOpt BindingElement ; +/. +case $rule_number: { + sym(1).Node = new (pool) AST::BindingElementList(sym(1).Elision, sym(2).BindingElement); +} break; +./ + BindingProperty: BindingIdentifier InitializerOpt ; /. diff --git a/src/qml/parser/qqmljsast.cpp b/src/qml/parser/qqmljsast.cpp index 60064319c9..8b253abbef 100644 --- a/src/qml/parser/qqmljsast.cpp +++ b/src/qml/parser/qqmljsast.cpp @@ -1093,9 +1093,12 @@ void BindingElementList::accept0(Visitor *visitor) void BindingElementList::boundNames(QStringList *names) { - // ### - Q_UNUSED(names); - + for (BindingElementList *it = this; it; it = it->next) { + if (BindingElement *e = it->bindingElement()) + e->boundNames(names); + else if (BindingRestElement *r = it->bindingRestElement()) + names->append(r->name.toString()); + } } void BindingPropertyList::accept0(Visitor *visitor) diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h index 6142b00712..52f6aeb1a2 100644 --- a/src/qml/parser/qqmljsast_p.h +++ b/src/qml/parser/qqmljsast_p.h @@ -2128,20 +2128,44 @@ class QML_PARSER_EXPORT BindingElementList : public Node public: QQMLJS_DECLARE_AST_NODE(BindingElementList) - BindingElementList() + BindingElementList(Elision *e, Node *p) + : elision(e), param(p), next(this) { kind = K; } + BindingElementList *append(BindingElementList *n) { + n->next = next; + next = n; + return n; + } + + inline BindingElementList *finish () + { + BindingElementList *front = next; + next = 0; + return front; + } + + BindingRestElement *bindingRestElement() const { + return cast<BindingRestElement *>(param); + } + + BindingElement *bindingElement() const { + return cast<BindingElement *>(param); + } + void accept0(Visitor *visitor) override; void boundNames(QStringList *names); SourceLocation firstSourceLocation() const override - { return loc; } + { return elision ? elision->firstSourceLocation() : param->firstSourceLocation(); } SourceLocation lastSourceLocation() const override - { return loc; } + { return next ? next->lastSourceLocation() : param->lastSourceLocation(); } - SourceLocation loc; + Elision *elision = nullptr; + Node *param = nullptr; + BindingElementList *next; }; class QML_PARSER_EXPORT BindingPropertyList : public Node |