aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-02-26 10:08:37 +0100
committerLars Knoll <lars.knoll@qt.io>2018-04-25 17:49:44 +0000
commitaabf2196016d96bd171a7d632b6e1cc5622d05ae (patch)
tree6e30bcc5bb6b6fbaa30d31b296e254ad0048e5a3 /src/qml
parentda5fffbd34d8be68f8ee4c649881dbb673c9c0a5 (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.cpp37
-rw-r--r--src/qml/parser/qqmljs.g44
-rw-r--r--src/qml/parser/qqmljsast.cpp9
-rw-r--r--src/qml/parser/qqmljsast_p.h32
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