bool BooleanValue() const;
+ bool IsTheHole() const { return type_ == THE_HOLE; }
+
void Internalize(Isolate* isolate);
// Can be called after Internalize has been called.
}
+// !%_IsSpecObject(result = iterator.next()) &&
+// %ThrowIteratorResultNotAnObject(result)
+Expression* Parser::BuildIteratorNextResult(Expression* iterator,
+ Variable* result, int pos) {
+ Expression* next_literal = factory()->NewStringLiteral(
+ ast_value_factory()->next_string(), RelocInfo::kNoPosition);
+ Expression* next_property =
+ factory()->NewProperty(iterator, next_literal, RelocInfo::kNoPosition);
+ ZoneList<Expression*>* next_arguments =
+ new (zone()) ZoneList<Expression*>(0, zone());
+ Expression* next_call =
+ factory()->NewCall(next_property, next_arguments, pos);
+ Expression* result_proxy = factory()->NewVariableProxy(result);
+ Expression* left =
+ factory()->NewAssignment(Token::ASSIGN, result_proxy, next_call, pos);
+
+ // %_IsSpecObject(...)
+ ZoneList<Expression*>* is_spec_object_args =
+ new (zone()) ZoneList<Expression*>(1, zone());
+ is_spec_object_args->Add(left, zone());
+ Expression* is_spec_object_call = factory()->NewCallRuntime(
+ ast_value_factory()->is_spec_object_string(),
+ Runtime::FunctionForId(Runtime::kInlineIsSpecObject), is_spec_object_args,
+ pos);
+
+ // %ThrowIteratorResultNotAnObject(result)
+ Expression* result_proxy_again = factory()->NewVariableProxy(result);
+ ZoneList<Expression*>* throw_arguments =
+ new (zone()) ZoneList<Expression*>(1, zone());
+ throw_arguments->Add(result_proxy_again, zone());
+ Expression* throw_call = factory()->NewCallRuntime(
+ ast_value_factory()->throw_iterator_result_not_an_object_string(),
+ Runtime::FunctionForId(Runtime::kThrowIteratorResultNotAnObject),
+ throw_arguments, pos);
+
+ return factory()->NewBinaryOperation(
+ Token::AND,
+ factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos),
+ throw_call, pos);
+}
+
+
void Parser::InitializeForEachStatement(ForEachStatement* stmt,
Expression* each,
Expression* subject,
{
// result = iterator.next()
Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
- Expression* next_literal = factory()->NewStringLiteral(
- ast_value_factory()->next_string(), RelocInfo::kNoPosition);
- Expression* next_property = factory()->NewProperty(
- iterator_proxy, next_literal, RelocInfo::kNoPosition);
- ZoneList<Expression*>* next_arguments =
- new (zone()) ZoneList<Expression*>(0, zone());
- Expression* next_call = factory()->NewCall(next_property, next_arguments,
- subject->position());
- Expression* result_proxy = factory()->NewVariableProxy(result);
- next_result = factory()->NewAssignment(Token::ASSIGN, result_proxy,
- next_call, subject->position());
-
- // %_IsSpecObject(...)
- ZoneList<Expression*>* is_spec_object_args =
- new (zone()) ZoneList<Expression*>(1, zone());
- is_spec_object_args->Add(next_result, zone());
- Expression* is_spec_object_call = factory()->NewCallRuntime(
- ast_value_factory()->is_spec_object_string(),
- Runtime::FunctionForId(Runtime::kInlineIsSpecObject),
- is_spec_object_args, subject->position());
-
- // %ThrowIteratorResultNotAnObject(result)
- Expression* result_proxy_again = factory()->NewVariableProxy(result);
- ZoneList<Expression*>* throw_arguments =
- new (zone()) ZoneList<Expression*>(1, zone());
- throw_arguments->Add(result_proxy_again, zone());
- Expression* throw_call = factory()->NewCallRuntime(
- ast_value_factory()->throw_iterator_result_not_an_object_string(),
- Runtime::FunctionForId(Runtime::kThrowIteratorResultNotAnObject),
- throw_arguments, subject->position());
-
- next_result = factory()->NewBinaryOperation(
- Token::AND, factory()->NewUnaryOperation(
- Token::NOT, is_spec_object_call, subject->position()),
- throw_call, subject->position());
+ next_result =
+ BuildIteratorNextResult(iterator_proxy, result, subject->position());
}
// result.done
current_value_ = old_value;
}
- Variable* CreateTempVar(Expression* value);
+ Variable* CreateTempVar(Expression* value = nullptr);
AstNodeFactory* factory() const { return descriptor_->parser->factory(); }
AstValueFactory* ast_value_factory() const {
// Support for hamony block scoped bindings.
Block* ParseScopedBlock(ZoneList<const AstRawString*>* labels, bool* ok);
+ // !%_IsSpecObject(result = iterator.next()) &&
+ // %ThrowIteratorResultNotAnObject(result)
+ Expression* BuildIteratorNextResult(Expression* iterator, Variable* result,
+ int pos);
+
+
// Initialize the components of a for-in / for-of statement.
void InitializeForEachStatement(ForEachStatement* stmt,
Expression* each,
Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) {
auto temp_scope = descriptor_->parser->scope_->DeclarationScope();
auto temp = temp_scope->NewTemporary(ast_value_factory()->empty_string());
- auto assignment =
- factory()->NewAssignment(Token::ASSIGN, factory()->NewVariableProxy(temp),
- value, RelocInfo::kNoPosition);
+ if (value != nullptr) {
+ auto assignment = factory()->NewAssignment(
+ Token::ASSIGN, factory()->NewVariableProxy(temp), value,
+ RelocInfo::kNoPosition);
- block_->AddStatement(
- factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
- zone());
+ block_->AddStatement(
+ factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
+ zone());
+ }
return temp;
}
void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
- // TODO(dslomov): implement.
+ auto iterator = CreateTempVar(
+ descriptor_->parser->GetIterator(current_value_, factory()));
+ auto done = CreateTempVar(
+ factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition));
+ auto result = CreateTempVar();
+ auto v = CreateTempVar();
+ for (Expression* value : *node->values()) {
+ // if (!done) {
+ // result = IteratorNext(iterator);
+ // v = (done = result.done) ? undefined : result.value;
+ // }
+ auto next_block =
+ factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition);
+ next_block->AddStatement(factory()->NewExpressionStatement(
+ descriptor_->parser->BuildIteratorNextResult(
+ factory()->NewVariableProxy(iterator),
+ result, RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition),
+ zone());
+
+ auto assign_to_done = factory()->NewAssignment(
+ Token::ASSIGN, factory()->NewVariableProxy(done),
+ factory()->NewProperty(
+ factory()->NewVariableProxy(result),
+ factory()->NewStringLiteral(ast_value_factory()->done_string(),
+ RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition);
+ auto next_value = factory()->NewConditional(
+ assign_to_done, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
+ factory()->NewProperty(
+ factory()->NewVariableProxy(result),
+ factory()->NewStringLiteral(ast_value_factory()->value_string(),
+ RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition);
+ next_block->AddStatement(
+ factory()->NewExpressionStatement(
+ factory()->NewAssignment(Token::ASSIGN,
+ factory()->NewVariableProxy(v), next_value,
+ RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition),
+ zone());
+
+ auto if_statement = factory()->NewIfStatement(
+ factory()->NewUnaryOperation(Token::NOT,
+ factory()->NewVariableProxy(done),
+ RelocInfo::kNoPosition),
+ next_block, factory()->NewEmptyStatement(RelocInfo::kNoPosition),
+ RelocInfo::kNoPosition);
+ block_->AddStatement(if_statement, zone());
+
+ if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
+ RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
+ }
+ }
}
TypeError);
}
}());
+
+
+(function TestArrayLiteral() {
+ var [a, b, c] = [1, 2, 3];
+ assertSame(1, a);
+ assertSame(2, b);
+ assertSame(3, c);
+}());
+
+(function TestIterators() {
+ var log = [];
+ function* f() {
+ log.push("1");
+ yield 1;
+ log.push("2");
+ yield 2;
+ log.push("3");
+ yield 3;
+ log.push("done");
+ };
+
+ (function() {
+ log = [];
+ var [a, b, c] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertSame(3, c);
+ assertArrayEquals(["1", "2", "3"], log);
+ }());
+
+ (function() {
+ log = [];
+ var [a, b, c, d] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertSame(3, c);
+ assertSame(undefined, d);
+ assertArrayEquals(["1", "2", "3", "done"], log);
+ }());
+
+ (function() {
+ log = [];
+ var [a, , c] = f();
+ assertSame(1, a);
+ assertSame(3, c);
+ assertArrayEquals(["1", "2", "3"], log);
+ }());
+
+ (function() {
+ log = [];
+ var [a, , c, d] = f();
+ assertSame(1, a);
+ assertSame(3, c);
+ assertSame(undefined, d);
+ assertArrayEquals(["1", "2", "3", "done"], log);
+ }());
+
+ (function() {
+ log = [];
+ // last comma is not an elision.
+ var [a, b,] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertArrayEquals(["1", "2"], log);
+ }());
+
+ (function() {
+ log = [];
+ // last comma is not an elision, but the comma before the last is.
+ var [a, b, ,] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertArrayEquals(["1", "2", "3"], log);
+ }());
+
+}());
+
+
+(function TestIteratorsLexical() {
+ 'use strict';
+ var log = [];
+ function* f() {
+ log.push("1");
+ yield 1;
+ log.push("2");
+ yield 2;
+ log.push("3");
+ yield 3;
+ log.push("done");
+ };
+
+ (function() {
+ log = [];
+ let [a, b, c] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertSame(3, c);
+ assertArrayEquals(["1", "2", "3"], log);
+ }());
+
+ (function() {
+ log = [];
+ let [a, b, c, d] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertSame(3, c);
+ assertSame(undefined, d);
+ assertArrayEquals(["1", "2", "3", "done"], log);
+ }());
+
+ (function() {
+ log = [];
+ let [a, , c] = f();
+ assertSame(1, a);
+ assertSame(3, c);
+ assertArrayEquals(["1", "2", "3"], log);
+ }());
+
+ (function() {
+ log = [];
+ let [a, , c, d] = f();
+ assertSame(1, a);
+ assertSame(3, c);
+ assertSame(undefined, d);
+ assertArrayEquals(["1", "2", "3", "done"], log);
+ }());
+
+ (function() {
+ log = [];
+ // last comma is not an elision.
+ let [a, b,] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertArrayEquals(["1", "2"], log);
+ }());
+
+ (function() {
+ log = [];
+ // last comma is not an elision, but the comma before the last is.
+ let [a, b, ,] = f();
+ assertSame(1, a);
+ assertSame(2, b);
+ assertArrayEquals(["1", "2", "3"], log);
+ }());
+
+}());
+
+(function TestIteratorsRecursive() {
+
+ var log = [];
+ function* f() {
+ log.push("1");
+ yield {x : 1, y : 2};
+ log.push("2");
+ yield [42, 27, 30];
+ log.push("3");
+ yield "abc";
+ log.push("done");
+ };
+
+ (function() {
+ var [{x, y}, [a, b]] = f();
+ assertSame(1, x);
+ assertSame(2, y);
+ assertSame(42, a);
+ assertSame(27, b);
+ assertArrayEquals(["1", "2"], log);
+ }());
+
+ (function() {
+ 'use strict';
+ log = [];
+ let [{x, y}, [a, b]] = f();
+ assertSame(1, x);
+ assertSame(2, y);
+ assertSame(42, a);
+ assertSame(27, b);
+ assertArrayEquals(["1", "2"], log);
+ }());
+}());