Commit 6b7f9dba authored by wingo@igalia.com's avatar wingo@igalia.com

yield* calls @@iterator on iterable

R=rossberg@chromium.org
BUG=v8:3422
LOG=N

Review URL: https://codereview.chromium.org/430693003

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22872 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ee52dffb
...@@ -665,6 +665,19 @@ Expression* ParserTraits::ExpressionFromString( ...@@ -665,6 +665,19 @@ Expression* ParserTraits::ExpressionFromString(
} }
Expression* ParserTraits::GetIterator(
Expression* iterable, AstNodeFactory<AstConstructionVisitor>* factory) {
Expression* iterator_symbol_literal =
factory->NewSymbolLiteral("symbolIterator", RelocInfo::kNoPosition);
int pos = iterable->position();
Expression* prop =
factory->NewProperty(iterable, iterator_symbol_literal, pos);
Zone* zone = parser_->zone();
ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(0, zone);
return factory->NewCall(prop, args, pos);
}
Literal* ParserTraits::GetLiteralTheHole( Literal* ParserTraits::GetLiteralTheHole(
int position, AstNodeFactory<AstConstructionVisitor>* factory) { int position, AstNodeFactory<AstConstructionVisitor>* factory) {
return factory->NewTheHoleLiteral(RelocInfo::kNoPosition); return factory->NewTheHoleLiteral(RelocInfo::kNoPosition);
...@@ -2773,23 +2786,9 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt, ...@@ -2773,23 +2786,9 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
Expression* assign_each; Expression* assign_each;
// var iterator = subject[Symbol.iterator](); // var iterator = subject[Symbol.iterator]();
{ assign_iterator = factory()->NewAssignment(
Expression* iterator_symbol_literal = Token::ASSIGN, factory()->NewVariableProxy(iterator),
factory()->NewSymbolLiteral("symbolIterator", RelocInfo::kNoPosition); GetIterator(subject, factory()), RelocInfo::kNoPosition);
// FIXME(wingo): Unhappily, it will be a common error that the RHS of a
// for-of doesn't have a Symbol.iterator property. We should do better
// than informing the user that "undefined is not a function".
int pos = subject->position();
Expression* iterator_property =
factory()->NewProperty(subject, iterator_symbol_literal, pos);
ZoneList<Expression*>* iterator_arguments =
new(zone()) ZoneList<Expression*>(0, zone());
Expression* iterator_call = factory()->NewCall(
iterator_property, iterator_arguments, pos);
Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
assign_iterator = factory()->NewAssignment(
Token::ASSIGN, iterator_proxy, iterator_call, RelocInfo::kNoPosition);
}
// var result = iterator.next(); // var result = iterator.next();
{ {
......
...@@ -543,6 +543,8 @@ class ParserTraits { ...@@ -543,6 +543,8 @@ class ParserTraits {
Expression* ExpressionFromString( Expression* ExpressionFromString(
int pos, Scanner* scanner, int pos, Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory); AstNodeFactory<AstConstructionVisitor>* factory);
Expression* GetIterator(Expression* iterable,
AstNodeFactory<AstConstructionVisitor>* factory);
ZoneList<v8::internal::Expression*>* NewExpressionList(int size, Zone* zone) { ZoneList<v8::internal::Expression*>* NewExpressionList(int size, Zone* zone) {
return new(zone) ZoneList<v8::internal::Expression*>(size, zone); return new(zone) ZoneList<v8::internal::Expression*>(size, zone);
} }
......
...@@ -1232,6 +1232,11 @@ class PreParserTraits { ...@@ -1232,6 +1232,11 @@ class PreParserTraits {
Scanner* scanner, Scanner* scanner,
PreParserFactory* factory = NULL); PreParserFactory* factory = NULL);
PreParserExpression GetIterator(PreParserExpression iterable,
PreParserFactory* factory) {
return PreParserExpression::Default();
}
static PreParserExpressionList NewExpressionList(int size, void* zone) { static PreParserExpressionList NewExpressionList(int size, void* zone) {
return PreParserExpressionList(); return PreParserExpressionList();
} }
...@@ -2094,6 +2099,10 @@ ParserBase<Traits>::ParseYieldExpression(bool* ok) { ...@@ -2094,6 +2099,10 @@ ParserBase<Traits>::ParseYieldExpression(bool* ok) {
break; break;
} }
} }
if (kind == Yield::DELEGATING) {
// var iterator = subject[Symbol.iterator]();
expression = this->GetIterator(expression, factory());
}
typename Traits::Type::YieldExpression yield = typename Traits::Type::YieldExpression yield =
factory()->NewYield(generator_object, expression, kind, pos); factory()->NewYield(generator_object, expression, kind, pos);
if (kind == Yield::DELEGATING) { if (kind == Yield::DELEGATING) {
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --harmony-generators --expose-gc // Flags: --harmony-generators --expose-gc --harmony-iteration
// Test generator iteration. // Test generator iteration.
...@@ -355,6 +355,32 @@ TestGenerator( ...@@ -355,6 +355,32 @@ TestGenerator(
"foo", "foo",
[undefined, undefined]); [undefined, undefined]);
// TODO(wingo): We should use TestGenerator for these, except that
// currently yield* will unconditionally propagate a throw() to the
// delegate iterator, which fails for these iterators that don't have
// throw(). See http://code.google.com/p/v8/issues/detail?id=3484.
(function() {
function* g28() {
yield* [1, 2, 3];
}
var iter = g28();
assertIteratorResult(1, false, iter.next());
assertIteratorResult(2, false, iter.next());
assertIteratorResult(3, false, iter.next());
assertIteratorResult(undefined, true, iter.next());
})();
(function() {
function* g29() {
yield* "abc";
}
var iter = g29();
assertIteratorResult("a", false, iter.next());
assertIteratorResult("b", false, iter.next());
assertIteratorResult("c", false, iter.next());
assertIteratorResult(undefined, true, iter.next());
})();
// Generator function instances. // Generator function instances.
TestGenerator(GeneratorFunction(), TestGenerator(GeneratorFunction(),
[undefined], [undefined],
...@@ -393,12 +419,16 @@ function TestDelegatingYield() { ...@@ -393,12 +419,16 @@ function TestDelegatingYield() {
function next() { function next() {
return results[i++]; return results[i++];
} }
return { next: next } var iter = { next: next };
var ret = {};
ret[Symbol.iterator] = function() { return iter; };
return ret;
} }
function* yield_results(expected) { function* yield_results(expected) {
return yield* results(expected); return yield* results(expected);
} }
function collect_results(iter) { function collect_results(iterable) {
var iter = iterable[Symbol.iterator]();
var ret = []; var ret = [];
var result; var result;
do { do {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment