Index: src/pattern-rewriter.cc |
diff --git a/src/pattern-rewriter.cc b/src/pattern-rewriter.cc |
deleted file mode 100644 |
index e5231155687b7b2826881537777938a85078e721..0000000000000000000000000000000000000000 |
--- a/src/pattern-rewriter.cc |
+++ /dev/null |
@@ -1,435 +0,0 @@ |
-// Copyright 2015 the V8 project authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "src/ast.h" |
-#include "src/messages.h" |
-#include "src/parameter-initializer-rewriter.h" |
-#include "src/parser.h" |
- |
-namespace v8 { |
- |
-namespace internal { |
- |
- |
-void Parser::PatternRewriter::DeclareAndInitializeVariables( |
- Block* block, const DeclarationDescriptor* declaration_descriptor, |
- const DeclarationParsingResult::Declaration* declaration, |
- ZoneList<const AstRawString*>* names, bool* ok) { |
- PatternRewriter rewriter; |
- |
- rewriter.pattern_ = declaration->pattern; |
- rewriter.initializer_position_ = declaration->initializer_position; |
- rewriter.block_ = block; |
- rewriter.descriptor_ = declaration_descriptor; |
- rewriter.names_ = names; |
- rewriter.ok_ = ok; |
- |
- rewriter.RecurseIntoSubpattern(rewriter.pattern_, declaration->initializer); |
-} |
- |
- |
-void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) { |
- Expression* value = current_value_; |
- descriptor_->scope->RemoveUnresolved(pattern); |
- |
- // Declare variable. |
- // Note that we *always* must treat the initial value via a separate init |
- // assignment for variables and constants because the value must be assigned |
- // when the variable is encountered in the source. But the variable/constant |
- // is declared (and set to 'undefined') upon entering the function within |
- // which the variable or constant is declared. Only function variables have |
- // an initial value in the declaration (because they are initialized upon |
- // entering the function). |
- // |
- // If we have a legacy const declaration, in an inner scope, the proxy |
- // is always bound to the declared variable (independent of possibly |
- // surrounding 'with' statements). |
- // For let/const declarations in harmony mode, we can also immediately |
- // pre-resolve the proxy because it resides in the same scope as the |
- // declaration. |
- Parser* parser = descriptor_->parser; |
- const AstRawString* name = pattern->raw_name(); |
- VariableProxy* proxy = parser->NewUnresolved(name, descriptor_->mode); |
- Declaration* declaration = factory()->NewVariableDeclaration( |
- proxy, descriptor_->mode, descriptor_->scope, |
- descriptor_->declaration_pos); |
- Variable* var = parser->Declare(declaration, descriptor_->declaration_kind, |
- descriptor_->mode != VAR, ok_, |
- descriptor_->hoist_scope); |
- if (!*ok_) return; |
- DCHECK_NOT_NULL(var); |
- DCHECK(!proxy->is_resolved() || proxy->var() == var); |
- var->set_initializer_position(initializer_position_); |
- |
- DCHECK(initializer_position_ != RelocInfo::kNoPosition); |
- |
- if (descriptor_->declaration_scope->num_var_or_const() > |
- kMaxNumFunctionLocals) { |
- parser->ReportMessage(MessageTemplate::kTooManyVariables); |
- *ok_ = false; |
- return; |
- } |
- if (names_) { |
- names_->Add(name, zone()); |
- } |
- |
- // Initialize variables if needed. A |
- // declaration of the form: |
- // |
- // var v = x; |
- // |
- // is syntactic sugar for: |
- // |
- // var v; v = x; |
- // |
- // In particular, we need to re-lookup 'v' (in scope_, not |
- // declaration_scope) as it may be a different 'v' than the 'v' in the |
- // declaration (e.g., if we are inside a 'with' statement or 'catch' |
- // block). |
- // |
- // However, note that const declarations are different! A const |
- // declaration of the form: |
- // |
- // const c = x; |
- // |
- // is *not* syntactic sugar for: |
- // |
- // const c; c = x; |
- // |
- // The "variable" c initialized to x is the same as the declared |
- // one - there is no re-lookup (see the last parameter of the |
- // Declare() call above). |
- Scope* initialization_scope = descriptor_->is_const |
- ? descriptor_->declaration_scope |
- : descriptor_->scope; |
- |
- |
- // Global variable declarations must be compiled in a specific |
- // way. When the script containing the global variable declaration |
- // is entered, the global variable must be declared, so that if it |
- // doesn't exist (on the global object itself, see ES5 errata) it |
- // gets created with an initial undefined value. This is handled |
- // by the declarations part of the function representing the |
- // top-level global code; see Runtime::DeclareGlobalVariable. If |
- // it already exists (in the object or in a prototype), it is |
- // *not* touched until the variable declaration statement is |
- // executed. |
- // |
- // Executing the variable declaration statement will always |
- // guarantee to give the global object an own property. |
- // This way, global variable declarations can shadow |
- // properties in the prototype chain, but only after the variable |
- // declaration statement has been executed. This is important in |
- // browsers where the global object (window) has lots of |
- // properties defined in prototype objects. |
- if (initialization_scope->is_script_scope() && |
- !IsLexicalVariableMode(descriptor_->mode)) { |
- // Compute the arguments for the runtime |
- // call.test-parsing/InitializedDeclarationsInStrictForOfError |
- ZoneList<Expression*>* arguments = |
- new (zone()) ZoneList<Expression*>(3, zone()); |
- // We have at least 1 parameter. |
- arguments->Add( |
- factory()->NewStringLiteral(name, descriptor_->declaration_pos), |
- zone()); |
- CallRuntime* initialize; |
- |
- if (descriptor_->is_const) { |
- arguments->Add(value, zone()); |
- value = NULL; // zap the value to avoid the unnecessary assignment |
- |
- // Construct the call to Runtime_InitializeConstGlobal |
- // and add it to the initialization statement block. |
- // Note that the function does different things depending on |
- // the number of arguments (1 or 2). |
- initialize = |
- factory()->NewCallRuntime(Runtime::kInitializeConstGlobal, arguments, |
- descriptor_->initialization_pos); |
- } else { |
- // Add language mode. |
- // We may want to pass singleton to avoid Literal allocations. |
- LanguageMode language_mode = initialization_scope->language_mode(); |
- arguments->Add(factory()->NewNumberLiteral(language_mode, |
- descriptor_->declaration_pos), |
- zone()); |
- |
- // Be careful not to assign a value to the global variable if |
- // we're in a with. The initialization value should not |
- // necessarily be stored in the global object in that case, |
- // which is why we need to generate a separate assignment node. |
- if (value != NULL && !descriptor_->scope->inside_with()) { |
- arguments->Add(value, zone()); |
- value = NULL; // zap the value to avoid the unnecessary assignment |
- // Construct the call to Runtime_InitializeVarGlobal |
- // and add it to the initialization statement block. |
- initialize = |
- factory()->NewCallRuntime(Runtime::kInitializeVarGlobal, arguments, |
- descriptor_->declaration_pos); |
- } else { |
- initialize = NULL; |
- } |
- } |
- |
- if (initialize != NULL) { |
- block_->statements()->Add( |
- factory()->NewExpressionStatement(initialize, RelocInfo::kNoPosition), |
- zone()); |
- } |
- } else if (value != nullptr && (descriptor_->mode == CONST_LEGACY || |
- IsLexicalVariableMode(descriptor_->mode))) { |
- // Constant initializations always assign to the declared constant which |
- // is always at the function scope level. This is only relevant for |
- // dynamically looked-up variables and constants (the |
- // start context for constant lookups is always the function context, |
- // while it is the top context for var declared variables). Sigh... |
- // For 'let' and 'const' declared variables in harmony mode the |
- // initialization also always assigns to the declared variable. |
- DCHECK_NOT_NULL(proxy); |
- DCHECK_NOT_NULL(proxy->var()); |
- DCHECK_NOT_NULL(value); |
- Assignment* assignment = factory()->NewAssignment( |
- Token::INIT, proxy, value, descriptor_->initialization_pos); |
- block_->statements()->Add( |
- factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), |
- zone()); |
- value = NULL; |
- } |
- |
- // Add an assignment node to the initialization statement block if we still |
- // have a pending initialization value. |
- if (value != NULL) { |
- DCHECK(descriptor_->mode == VAR); |
- // 'var' initializations are simply assignments (with all the consequences |
- // if they are inside a 'with' statement - they may change a 'with' object |
- // property). |
- VariableProxy* proxy = initialization_scope->NewUnresolved(factory(), name); |
- Assignment* assignment = factory()->NewAssignment( |
- Token::INIT, proxy, value, descriptor_->initialization_pos); |
- block_->statements()->Add( |
- factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), |
- zone()); |
- } |
-} |
- |
- |
-Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) { |
- auto temp = descriptor_->parser->scope_->NewTemporary( |
- ast_value_factory()->empty_string()); |
- if (value != nullptr) { |
- auto assignment = factory()->NewAssignment( |
- Token::ASSIGN, factory()->NewVariableProxy(temp), value, |
- RelocInfo::kNoPosition); |
- |
- block_->statements()->Add( |
- factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), |
- zone()); |
- } |
- return temp; |
-} |
- |
- |
-void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern) { |
- auto temp = CreateTempVar(current_value_); |
- |
- block_->statements()->Add(descriptor_->parser->BuildAssertIsCoercible(temp), |
- zone()); |
- |
- for (ObjectLiteralProperty* property : *pattern->properties()) { |
- RecurseIntoSubpattern( |
- property->value(), |
- factory()->NewProperty(factory()->NewVariableProxy(temp), |
- property->key(), RelocInfo::kNoPosition)); |
- } |
-} |
- |
- |
-void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) { |
- auto temp = CreateTempVar(current_value_); |
- |
- block_->statements()->Add(descriptor_->parser->BuildAssertIsCoercible(temp), |
- zone()); |
- |
- auto iterator = CreateTempVar(descriptor_->parser->GetIterator( |
- factory()->NewVariableProxy(temp), factory())); |
- auto done = CreateTempVar( |
- factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition)); |
- auto result = CreateTempVar(); |
- auto v = CreateTempVar(); |
- |
- Spread* spread = nullptr; |
- for (Expression* value : *node->values()) { |
- if (value->IsSpread()) { |
- spread = value->AsSpread(); |
- break; |
- } |
- |
- // if (!done) { |
- // result = IteratorNext(iterator); |
- // v = (done = result.done) ? undefined : result.value; |
- // } |
- auto next_block = |
- factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition); |
- next_block->statements()->Add( |
- 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->statements()->Add( |
- 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_->statements()->Add(if_statement, zone()); |
- |
- if (!(value->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) { |
- RecurseIntoSubpattern(value, factory()->NewVariableProxy(v)); |
- } |
- } |
- |
- if (spread != nullptr) { |
- // array = []; |
- // if (!done) %concat_iterable_to_array(array, iterator); |
- auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone()); |
- auto array = CreateTempVar(factory()->NewArrayLiteral( |
- empty_exprs, |
- // Reuse pattern's literal index - it is unused since there is no |
- // actual literal allocated. |
- node->literal_index(), is_strong(descriptor_->parser->language_mode()), |
- RelocInfo::kNoPosition)); |
- |
- auto arguments = new (zone()) ZoneList<Expression*>(2, zone()); |
- arguments->Add(factory()->NewVariableProxy(array), zone()); |
- arguments->Add(factory()->NewVariableProxy(iterator), zone()); |
- auto spread_into_array_call = |
- factory()->NewCallRuntime(Context::CONCAT_ITERABLE_TO_ARRAY_INDEX, |
- arguments, RelocInfo::kNoPosition); |
- |
- auto if_statement = factory()->NewIfStatement( |
- factory()->NewUnaryOperation(Token::NOT, |
- factory()->NewVariableProxy(done), |
- RelocInfo::kNoPosition), |
- factory()->NewExpressionStatement(spread_into_array_call, |
- RelocInfo::kNoPosition), |
- factory()->NewEmptyStatement(RelocInfo::kNoPosition), |
- RelocInfo::kNoPosition); |
- block_->statements()->Add(if_statement, zone()); |
- |
- RecurseIntoSubpattern(spread->expression(), |
- factory()->NewVariableProxy(array)); |
- } |
-} |
- |
- |
-void Parser::PatternRewriter::VisitAssignment(Assignment* node) { |
- // let {<pattern> = <init>} = <value> |
- // becomes |
- // temp = <value>; |
- // <pattern> = temp === undefined ? <init> : temp; |
- DCHECK(node->op() == Token::ASSIGN); |
- auto temp = CreateTempVar(current_value_); |
- Expression* is_undefined = factory()->NewCompareOperation( |
- Token::EQ_STRICT, factory()->NewVariableProxy(temp), |
- factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), |
- RelocInfo::kNoPosition); |
- Expression* initializer = node->value(); |
- if (descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER && |
- descriptor_->scope->is_arrow_scope()) { |
- // TODO(adamk): Only call this if necessary. |
- RewriteParameterInitializerScope( |
- descriptor_->parser->stack_limit(), initializer, |
- descriptor_->scope->outer_scope(), descriptor_->scope); |
- } |
- Expression* value = factory()->NewConditional( |
- is_undefined, initializer, factory()->NewVariableProxy(temp), |
- RelocInfo::kNoPosition); |
- RecurseIntoSubpattern(node->target(), value); |
-} |
- |
- |
-// =============== UNREACHABLE ============================= |
- |
-void Parser::PatternRewriter::Visit(AstNode* node) { UNREACHABLE(); } |
- |
-#define NOT_A_PATTERN(Node) \ |
- void Parser::PatternRewriter::Visit##Node(v8::internal::Node*) { \ |
- UNREACHABLE(); \ |
- } |
- |
-NOT_A_PATTERN(BinaryOperation) |
-NOT_A_PATTERN(Block) |
-NOT_A_PATTERN(BreakStatement) |
-NOT_A_PATTERN(Call) |
-NOT_A_PATTERN(CallNew) |
-NOT_A_PATTERN(CallRuntime) |
-NOT_A_PATTERN(CaseClause) |
-NOT_A_PATTERN(ClassLiteral) |
-NOT_A_PATTERN(CompareOperation) |
-NOT_A_PATTERN(Conditional) |
-NOT_A_PATTERN(ContinueStatement) |
-NOT_A_PATTERN(CountOperation) |
-NOT_A_PATTERN(DebuggerStatement) |
-NOT_A_PATTERN(DoExpression) |
-NOT_A_PATTERN(DoWhileStatement) |
-NOT_A_PATTERN(EmptyStatement) |
-NOT_A_PATTERN(EmptyParentheses) |
-NOT_A_PATTERN(ExportDeclaration) |
-NOT_A_PATTERN(ExpressionStatement) |
-NOT_A_PATTERN(ForInStatement) |
-NOT_A_PATTERN(ForOfStatement) |
-NOT_A_PATTERN(ForStatement) |
-NOT_A_PATTERN(FunctionDeclaration) |
-NOT_A_PATTERN(FunctionLiteral) |
-NOT_A_PATTERN(IfStatement) |
-NOT_A_PATTERN(ImportDeclaration) |
-NOT_A_PATTERN(Literal) |
-NOT_A_PATTERN(NativeFunctionLiteral) |
-NOT_A_PATTERN(Property) |
-NOT_A_PATTERN(RegExpLiteral) |
-NOT_A_PATTERN(ReturnStatement) |
-NOT_A_PATTERN(SloppyBlockFunctionStatement) |
-NOT_A_PATTERN(Spread) |
-NOT_A_PATTERN(SuperPropertyReference) |
-NOT_A_PATTERN(SuperCallReference) |
-NOT_A_PATTERN(SwitchStatement) |
-NOT_A_PATTERN(ThisFunction) |
-NOT_A_PATTERN(Throw) |
-NOT_A_PATTERN(TryCatchStatement) |
-NOT_A_PATTERN(TryFinallyStatement) |
-NOT_A_PATTERN(UnaryOperation) |
-NOT_A_PATTERN(VariableDeclaration) |
-NOT_A_PATTERN(WhileStatement) |
-NOT_A_PATTERN(WithStatement) |
-NOT_A_PATTERN(Yield) |
- |
-#undef NOT_A_PATTERN |
-} // namespace internal |
-} // namespace v8 |