aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-05-31 16:06:34 +0200
committerLars Knoll <lars.knoll@qt.io>2018-09-07 10:32:01 +0000
commitff5bc526b4868aef9fb3a551afc5636b308a3d83 (patch)
tree692e956d6fcfd5fc4f064dce7275abeb51429c3a /src/qml/compiler
parentbd4064eabf79a6166805c877ee622931df6fb172 (diff)
Add support for yield*
Change-Id: I5b054b59519ed825459a5b0b0a7cd2c6fc8a3797 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qv4bytecodehandler.cpp6
-rw-r--r--src/qml/compiler/qv4codegen.cpp55
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp7
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h4
4 files changed, 64 insertions, 8 deletions
diff --git a/src/qml/compiler/qv4bytecodehandler.cpp b/src/qml/compiler/qv4bytecodehandler.cpp
index 5b836c2e9c..65293becfd 100644
--- a/src/qml/compiler/qv4bytecodehandler.cpp
+++ b/src/qml/compiler/qv4bytecodehandler.cpp
@@ -240,6 +240,9 @@ std::vector<int> ByteCodeHandler::collectLabelsInBytecode(const char *code, uint
COLLECTOR_BEGIN_INSTR(Yield)
COLLECTOR_END_INSTR(Yield)
+ COLLECTOR_BEGIN_INSTR(YieldStar)
+ COLLECTOR_END_INSTR(YieldStar)
+
COLLECTOR_BEGIN_INSTR(Resume)
COLLECTOR_END_INSTR(Resume)
@@ -335,6 +338,9 @@ std::vector<int> ByteCodeHandler::collectLabelsInBytecode(const char *code, uint
COLLECTOR_BEGIN_INSTR(IteratorNext)
COLLECTOR_END_INSTR(IteratorNext)
+ COLLECTOR_BEGIN_INSTR(IteratorNextForYieldStar)
+ COLLECTOR_END_INSTR(IteratorNextForYieldStar)
+
COLLECTOR_BEGIN_INSTR(IteratorClose)
COLLECTOR_END_INSTR(IteratorClose)
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 2415142df4..09f08e8bf2 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -2826,25 +2826,64 @@ bool Codegen::visit(FunctionDeclaration * ast)
bool Codegen::visit(YieldExpression *ast)
{
- if (ast->isYieldStar) {
- throwSyntaxError(ast->firstSourceLocation(), QLatin1String("yield* is not currently supported"));
- return false;
- }
if (inFormalParameterList) {
throwSyntaxError(ast->firstSourceLocation(), QLatin1String("yield is not allowed inside parameter lists"));
return false;
}
-
- Reference result = ast->expression ? expression(ast->expression) : Reference::fromConst(this, Encode::undefined());
+ RegisterScope scope(this);
+ Reference expr = ast->expression ? expression(ast->expression) : Reference::fromConst(this, Encode::undefined());
if (hasError)
return false;
- result.loadInAccumulator();
+
+ Reference acc = Reference::fromAccumulator(this);
+
+ if (ast->isYieldStar) {
+ Reference iterator = Reference::fromStackSlot(this);
+ Reference lhsValue = Reference::fromConst(this, Encode::undefined()).storeOnStack();
+
+ expr.loadInAccumulator();
+ Instruction::GetIterator getIterator;
+ getIterator.iterator = /*ForEachType::Of*/ 1;
+ bytecodeGenerator->addInstruction(getIterator);
+ iterator.storeConsumeAccumulator();
+ Instruction::LoadUndefined load;
+ bytecodeGenerator->addInstruction(load);
+
+ BytecodeGenerator::Label in = bytecodeGenerator->newLabel();
+ bytecodeGenerator->jump().link(in);
+
+ BytecodeGenerator::Label loop = bytecodeGenerator->label();
+
+ lhsValue.loadInAccumulator();
+ Instruction::YieldStar yield;
+ bytecodeGenerator->addInstruction(yield);
+
+ in.link();
+
+ Instruction::IteratorNextForYieldStar next;
+ next.object = lhsValue.stackSlot();
+ next.iterator = iterator.stackSlot();
+ bytecodeGenerator->addInstruction(next);
+
+ BytecodeGenerator::Jump done = bytecodeGenerator->jumpTrue();
+ bytecodeGenerator->jumpNotUndefined().link(loop);
+ lhsValue.loadInAccumulator();
+ emitReturn(acc);
+
+
+ done.link();
+
+ lhsValue.loadInAccumulator();
+ _expr.setResult(acc);
+ return false;
+ }
+
+ expr.loadInAccumulator();
Instruction::Yield yield;
bytecodeGenerator->addInstruction(yield);
Instruction::Resume resume;
BytecodeGenerator::Jump jump = bytecodeGenerator->addJumpInstruction(resume);
- Reference acc = Reference::fromAccumulator(this);
emitReturn(acc);
jump.link();
_expr.setResult(acc);
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index 00a1e8470b..a125f0ce28 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -349,6 +349,9 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
MOTH_BEGIN_INSTR(Yield)
MOTH_END_INSTR(Yield)
+ MOTH_BEGIN_INSTR(YieldStar)
+ MOTH_END_INSTR(YieldStar)
+
MOTH_BEGIN_INSTR(Resume)
d << ABSOLUTE_OFFSET();
MOTH_END_INSTR(Resume)
@@ -467,6 +470,10 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st
d << dumpRegister(value, nFormals) << ", " << dumpRegister(done, nFormals);
MOTH_END_INSTR(IteratorNext)
+ MOTH_BEGIN_INSTR(IteratorNextForYieldStar)
+ d << dumpRegister(iterator, nFormals) << ", " << dumpRegister(object, nFormals);
+ MOTH_END_INSTR(IteratorNextForYieldStar)
+
MOTH_BEGIN_INSTR(IteratorClose)
d << dumpRegister(done, nFormals);
MOTH_END_INSTR(IteratorClose)
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 34c80db0e8..f9bd3cdd4a 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -94,7 +94,9 @@ QT_BEGIN_NAMESPACE
#define INSTR_LoadContextObjectProperty(op) INSTRUCTION(op, LoadContextObjectProperty, 3, propertyIndex, base, captureRequired)
#define INSTR_LoadIdObject(op) INSTRUCTION(op, LoadIdObject, 2, index, base)
#define INSTR_Yield(op) INSTRUCTION(op, Yield, 0)
+#define INSTR_YieldStar(op) INSTRUCTION(op, YieldStar, 0)
#define INSTR_Resume(op) INSTRUCTION(op, Resume, 1, offset)
+#define INSTR_IteratorNextForYieldStar(op) INSTRUCTION(op, IteratorNextForYieldStar, 2, iterator, object)
#define INSTR_StoreProperty(op) INSTRUCTION(op, StoreProperty, 2, name, base)
#define INSTR_SetLookup(op) INSTRUCTION(op, SetLookup, 2, index, base)
#define INSTR_LoadSuperProperty(op) INSTRUCTION(op, LoadSuperProperty, 1, property)
@@ -327,7 +329,9 @@ QT_BEGIN_NAMESPACE
F(LoadQmlContext) \
F(LoadQmlImportedScripts) \
F(Yield) \
+ F(YieldStar) \
F(Resume) \
+ F(IteratorNextForYieldStar) \
F(CreateClass) \
F(LoadSuperConstructor) \
F(PushScriptContext) \