diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-05-31 16:06:34 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-09-07 10:32:01 +0000 |
commit | ff5bc526b4868aef9fb3a551afc5636b308a3d83 (patch) | |
tree | 692e956d6fcfd5fc4f064dce7275abeb51429c3a /src/qml/compiler | |
parent | bd4064eabf79a6166805c877ee622931df6fb172 (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.cpp | 6 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 55 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth.cpp | 7 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 4 |
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) \ |