| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_SCOPES_H_ | 5 #ifndef V8_SCOPES_H_ |
| 6 #define V8_SCOPES_H_ | 6 #define V8_SCOPES_H_ |
| 7 | 7 |
| 8 #include "src/ast.h" | 8 #include "src/ast.h" |
| 9 #include "src/zone.h" | 9 #include "src/zone.h" |
| 10 | 10 |
| 11 namespace v8 { | 11 namespace v8 { |
| 12 namespace internal { | 12 namespace internal { |
| 13 | 13 |
| 14 class CompilationInfo; | 14 class CompilationInfo; |
| 15 | 15 |
| 16 | 16 |
| 17 // A hash map to support fast variable declaration and lookup. | 17 // A hash map to support fast variable declaration and lookup. |
| 18 class VariableMap: public ZoneHashMap { | 18 class VariableMap: public ZoneHashMap { |
| 19 public: | 19 public: |
| 20 explicit VariableMap(Zone* zone); | 20 explicit VariableMap(Zone* zone); |
| 21 | 21 |
| 22 virtual ~VariableMap(); | 22 virtual ~VariableMap(); |
| 23 | 23 |
| 24 Variable* Declare(Scope* scope, | 24 Variable* Declare(Scope* scope, |
| 25 Handle<String> name, | 25 const AstString* name, |
| 26 VariableMode mode, | 26 VariableMode mode, |
| 27 bool is_valid_lhs, | 27 bool is_valid_lhs, |
| 28 Variable::Kind kind, | 28 Variable::Kind kind, |
| 29 InitializationFlag initialization_flag, | 29 InitializationFlag initialization_flag, |
| 30 Interface* interface = Interface::NewValue()); | 30 Interface* interface = Interface::NewValue()); |
| 31 | 31 |
| 32 Variable* Lookup(Handle<String> name); | 32 Variable* Lookup(const AstString* name); |
| 33 | 33 |
| 34 Zone* zone() const { return zone_; } | 34 Zone* zone() const { return zone_; } |
| 35 | 35 |
| 36 private: | 36 private: |
| 37 Zone* zone_; | 37 Zone* zone_; |
| 38 }; | 38 }; |
| 39 | 39 |
| 40 | 40 |
| 41 // The dynamic scope part holds hash maps for the variables that will | 41 // The dynamic scope part holds hash maps for the variables that will |
| 42 // be looked up dynamically from within eval and with scopes. The objects | 42 // be looked up dynamically from within eval and with scopes. The objects |
| (...skipping 24 matching lines...) Expand all Loading... |
| 67 // corresponding variable (though some are bound during parse time). Variable | 67 // corresponding variable (though some are bound during parse time). Variable |
| 68 // allocation binds each unresolved VariableProxy to one Variable and assigns | 68 // allocation binds each unresolved VariableProxy to one Variable and assigns |
| 69 // a location. Note that many VariableProxy nodes may refer to the same Java- | 69 // a location. Note that many VariableProxy nodes may refer to the same Java- |
| 70 // Script variable. | 70 // Script variable. |
| 71 | 71 |
| 72 class Scope: public ZoneObject { | 72 class Scope: public ZoneObject { |
| 73 public: | 73 public: |
| 74 // --------------------------------------------------------------------------- | 74 // --------------------------------------------------------------------------- |
| 75 // Construction | 75 // Construction |
| 76 | 76 |
| 77 Scope(Scope* outer_scope, ScopeType scope_type, Zone* zone); | 77 Scope(Scope* outer_scope, ScopeType scope_type, |
| 78 AstValueFactory* value_factory, Zone* zone); |
| 78 | 79 |
| 79 // Compute top scope and allocate variables. For lazy compilation the top | 80 // Compute top scope and allocate variables. For lazy compilation the top |
| 80 // scope only contains the single lazily compiled function, so this | 81 // scope only contains the single lazily compiled function, so this |
| 81 // doesn't re-allocate variables repeatedly. | 82 // doesn't re-allocate variables repeatedly. |
| 82 static bool Analyze(CompilationInfo* info); | 83 static bool Analyze(CompilationInfo* info); |
| 83 | 84 |
| 84 static Scope* DeserializeScopeChain(Context* context, Scope* global_scope, | 85 static Scope* DeserializeScopeChain(Context* context, Scope* global_scope, |
| 85 Zone* zone); | 86 Zone* zone); |
| 86 | 87 |
| 87 // The scope name is only used for printing/debugging. | 88 // The scope name is only used for printing/debugging. |
| 88 void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; } | 89 void SetScopeName(const AstString* scope_name) { scope_name_ = scope_name; } |
| 89 | 90 |
| 90 void Initialize(); | 91 void Initialize(); |
| 91 | 92 |
| 92 // Checks if the block scope is redundant, i.e. it does not contain any | 93 // Checks if the block scope is redundant, i.e. it does not contain any |
| 93 // block scoped declarations. In that case it is removed from the scope | 94 // block scoped declarations. In that case it is removed from the scope |
| 94 // tree and its children are reparented. | 95 // tree and its children are reparented. |
| 95 Scope* FinalizeBlockScope(); | 96 Scope* FinalizeBlockScope(); |
| 96 | 97 |
| 97 Zone* zone() const { return zone_; } | 98 Zone* zone() const { return zone_; } |
| 98 | 99 |
| 99 // --------------------------------------------------------------------------- | 100 // --------------------------------------------------------------------------- |
| 100 // Declarations | 101 // Declarations |
| 101 | 102 |
| 102 // Lookup a variable in this scope. Returns the variable or NULL if not found. | 103 // Lookup a variable in this scope. Returns the variable or NULL if not found. |
| 103 Variable* LookupLocal(Handle<String> name); | 104 Variable* LookupLocal(const AstString* name); |
| 104 | 105 |
| 105 // This lookup corresponds to a lookup in the "intermediate" scope sitting | 106 // This lookup corresponds to a lookup in the "intermediate" scope sitting |
| 106 // between this scope and the outer scope. (ECMA-262, 3rd., requires that | 107 // between this scope and the outer scope. (ECMA-262, 3rd., requires that |
| 107 // the name of named function literal is kept in an intermediate scope | 108 // the name of named function literal is kept in an intermediate scope |
| 108 // in between this scope and the next outer scope.) | 109 // in between this scope and the next outer scope.) |
| 109 Variable* LookupFunctionVar(Handle<String> name, | 110 Variable* LookupFunctionVar(const AstString* name, |
| 110 AstNodeFactory<AstNullVisitor>* factory); | 111 AstNodeFactory<AstNullVisitor>* factory); |
| 111 | 112 |
| 112 // Lookup a variable in this scope or outer scopes. | 113 // Lookup a variable in this scope or outer scopes. |
| 113 // Returns the variable or NULL if not found. | 114 // Returns the variable or NULL if not found. |
| 114 Variable* Lookup(Handle<String> name); | 115 Variable* Lookup(const AstString* name); |
| 115 | 116 |
| 116 // Declare the function variable for a function literal. This variable | 117 // Declare the function variable for a function literal. This variable |
| 117 // is in an intermediate scope between this function scope and the the | 118 // is in an intermediate scope between this function scope and the the |
| 118 // outer scope. Only possible for function scopes; at most one variable. | 119 // outer scope. Only possible for function scopes; at most one variable. |
| 119 void DeclareFunctionVar(VariableDeclaration* declaration) { | 120 void DeclareFunctionVar(VariableDeclaration* declaration) { |
| 120 ASSERT(is_function_scope()); | 121 ASSERT(is_function_scope()); |
| 121 function_ = declaration; | 122 function_ = declaration; |
| 122 } | 123 } |
| 123 | 124 |
| 124 // Declare a parameter in this scope. When there are duplicated | 125 // Declare a parameter in this scope. When there are duplicated |
| 125 // parameters the rightmost one 'wins'. However, the implementation | 126 // parameters the rightmost one 'wins'. However, the implementation |
| 126 // expects all parameters to be declared and from left to right. | 127 // expects all parameters to be declared and from left to right. |
| 127 void DeclareParameter(Handle<String> name, VariableMode mode); | 128 void DeclareParameter(const AstString* name, VariableMode mode); |
| 128 | 129 |
| 129 // Declare a local variable in this scope. If the variable has been | 130 // Declare a local variable in this scope. If the variable has been |
| 130 // declared before, the previously declared variable is returned. | 131 // declared before, the previously declared variable is returned. |
| 131 Variable* DeclareLocal(Handle<String> name, | 132 Variable* DeclareLocal(const AstString* name, |
| 132 VariableMode mode, | 133 VariableMode mode, |
| 133 InitializationFlag init_flag, | 134 InitializationFlag init_flag, |
| 134 Interface* interface = Interface::NewValue()); | 135 Interface* interface = Interface::NewValue()); |
| 135 | 136 |
| 136 // Declare an implicit global variable in this scope which must be a | 137 // Declare an implicit global variable in this scope which must be a |
| 137 // global scope. The variable was introduced (possibly from an inner | 138 // global scope. The variable was introduced (possibly from an inner |
| 138 // scope) by a reference to an unresolved variable with no intervening | 139 // scope) by a reference to an unresolved variable with no intervening |
| 139 // with statements or eval calls. | 140 // with statements or eval calls. |
| 140 Variable* DeclareDynamicGlobal(Handle<String> name); | 141 Variable* DeclareDynamicGlobal(const AstString* name); |
| 141 | 142 |
| 142 // Create a new unresolved variable. | 143 // Create a new unresolved variable. |
| 143 template<class Visitor> | 144 template<class Visitor> |
| 144 VariableProxy* NewUnresolved(AstNodeFactory<Visitor>* factory, | 145 VariableProxy* NewUnresolved(AstNodeFactory<Visitor>* factory, |
| 145 Handle<String> name, | 146 const AstString* name, |
| 146 Interface* interface = Interface::NewValue(), | 147 Interface* interface = Interface::NewValue(), |
| 147 int position = RelocInfo::kNoPosition) { | 148 int position = RelocInfo::kNoPosition) { |
| 148 // Note that we must not share the unresolved variables with | 149 // Note that we must not share the unresolved variables with |
| 149 // the same name because they may be removed selectively via | 150 // the same name because they may be removed selectively via |
| 150 // RemoveUnresolved(). | 151 // RemoveUnresolved(). |
| 151 ASSERT(!already_resolved()); | 152 ASSERT(!already_resolved()); |
| 152 VariableProxy* proxy = | 153 VariableProxy* proxy = |
| 153 factory->NewVariableProxy(name, false, interface, position); | 154 factory->NewVariableProxy(name, false, interface, position); |
| 154 unresolved_.Add(proxy, zone_); | 155 unresolved_.Add(proxy, zone_); |
| 155 return proxy; | 156 return proxy; |
| 156 } | 157 } |
| 157 | 158 |
| 158 // Remove a unresolved variable. During parsing, an unresolved variable | 159 // Remove a unresolved variable. During parsing, an unresolved variable |
| 159 // may have been added optimistically, but then only the variable name | 160 // may have been added optimistically, but then only the variable name |
| 160 // was used (typically for labels). If the variable was not declared, the | 161 // was used (typically for labels). If the variable was not declared, the |
| 161 // addition introduced a new unresolved variable which may end up being | 162 // addition introduced a new unresolved variable which may end up being |
| 162 // allocated globally as a "ghost" variable. RemoveUnresolved removes | 163 // allocated globally as a "ghost" variable. RemoveUnresolved removes |
| 163 // such a variable again if it was added; otherwise this is a no-op. | 164 // such a variable again if it was added; otherwise this is a no-op. |
| 164 void RemoveUnresolved(VariableProxy* var); | 165 void RemoveUnresolved(VariableProxy* var); |
| 165 | 166 |
| 166 // Creates a new internal variable in this scope. The name is only used | 167 // Creates a new internal variable in this scope. The name is only used |
| 167 // for printing and cannot be used to find the variable. In particular, | 168 // for printing and cannot be used to find the variable. In particular, |
| 168 // the only way to get hold of the temporary is by keeping the Variable* | 169 // the only way to get hold of the temporary is by keeping the Variable* |
| 169 // around. | 170 // around. |
| 170 Variable* NewInternal(Handle<String> name); | 171 Variable* NewInternal(const AstString* name); |
| 171 | 172 |
| 172 // Creates a new temporary variable in this scope. The name is only used | 173 // Creates a new temporary variable in this scope. The name is only used |
| 173 // for printing and cannot be used to find the variable. In particular, | 174 // for printing and cannot be used to find the variable. In particular, |
| 174 // the only way to get hold of the temporary is by keeping the Variable* | 175 // the only way to get hold of the temporary is by keeping the Variable* |
| 175 // around. The name should not clash with a legitimate variable names. | 176 // around. The name should not clash with a legitimate variable names. |
| 176 Variable* NewTemporary(Handle<String> name); | 177 Variable* NewTemporary(const AstString* name); |
| 177 | 178 |
| 178 // Adds the specific declaration node to the list of declarations in | 179 // Adds the specific declaration node to the list of declarations in |
| 179 // this scope. The declarations are processed as part of entering | 180 // this scope. The declarations are processed as part of entering |
| 180 // the scope; see codegen.cc:ProcessDeclarations. | 181 // the scope; see codegen.cc:ProcessDeclarations. |
| 181 void AddDeclaration(Declaration* declaration); | 182 void AddDeclaration(Declaration* declaration); |
| 182 | 183 |
| 183 // --------------------------------------------------------------------------- | 184 // --------------------------------------------------------------------------- |
| 184 // Illegal redeclaration support. | 185 // Illegal redeclaration support. |
| 185 | 186 |
| 186 // Set an expression node that will be executed when the scope is | 187 // Set an expression node that will be executed when the scope is |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 | 384 |
| 384 // Get the chain of nested scopes within this scope for the source statement | 385 // Get the chain of nested scopes within this scope for the source statement |
| 385 // position. The scopes will be added to the list from the outermost scope to | 386 // position. The scopes will be added to the list from the outermost scope to |
| 386 // the innermost scope. Only nested block, catch or with scopes are tracked | 387 // the innermost scope. Only nested block, catch or with scopes are tracked |
| 387 // and will be returned, but no inner function scopes. | 388 // and will be returned, but no inner function scopes. |
| 388 void GetNestedScopeChain(List<Handle<ScopeInfo> >* chain, | 389 void GetNestedScopeChain(List<Handle<ScopeInfo> >* chain, |
| 389 int statement_position); | 390 int statement_position); |
| 390 | 391 |
| 391 // --------------------------------------------------------------------------- | 392 // --------------------------------------------------------------------------- |
| 392 // Strict mode support. | 393 // Strict mode support. |
| 393 bool IsDeclared(Handle<String> name) { | 394 bool IsDeclared(const AstString* name) { |
| 394 // During formal parameter list parsing the scope only contains | 395 // During formal parameter list parsing the scope only contains |
| 395 // two variables inserted at initialization: "this" and "arguments". | 396 // two variables inserted at initialization: "this" and "arguments". |
| 396 // "this" is an invalid parameter name and "arguments" is invalid parameter | 397 // "this" is an invalid parameter name and "arguments" is invalid parameter |
| 397 // name in strict mode. Therefore looking up with the map which includes | 398 // name in strict mode. Therefore looking up with the map which includes |
| 398 // "this" and "arguments" in addition to all formal parameters is safe. | 399 // "this" and "arguments" in addition to all formal parameters is safe. |
| 399 return variables_.Lookup(name) != NULL; | 400 return variables_.Lookup(name) != NULL; |
| 400 } | 401 } |
| 401 | 402 |
| 402 // --------------------------------------------------------------------------- | 403 // --------------------------------------------------------------------------- |
| 403 // Debugging. | 404 // Debugging. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 414 Isolate* const isolate_; | 415 Isolate* const isolate_; |
| 415 | 416 |
| 416 // Scope tree. | 417 // Scope tree. |
| 417 Scope* outer_scope_; // the immediately enclosing outer scope, or NULL | 418 Scope* outer_scope_; // the immediately enclosing outer scope, or NULL |
| 418 ZoneList<Scope*> inner_scopes_; // the immediately enclosed inner scopes | 419 ZoneList<Scope*> inner_scopes_; // the immediately enclosed inner scopes |
| 419 | 420 |
| 420 // The scope type. | 421 // The scope type. |
| 421 ScopeType scope_type_; | 422 ScopeType scope_type_; |
| 422 | 423 |
| 423 // Debugging support. | 424 // Debugging support. |
| 424 Handle<String> scope_name_; | 425 const AstString* scope_name_; |
| 425 | 426 |
| 426 // The variables declared in this scope: | 427 // The variables declared in this scope: |
| 427 // | 428 // |
| 428 // All user-declared variables (incl. parameters). For global scopes | 429 // All user-declared variables (incl. parameters). For global scopes |
| 429 // variables may be implicitly 'declared' by being used (possibly in | 430 // variables may be implicitly 'declared' by being used (possibly in |
| 430 // an inner scope) with no intervening with statements or eval calls. | 431 // an inner scope) with no intervening with statements or eval calls. |
| 431 VariableMap variables_; | 432 VariableMap variables_; |
| 432 // Compiler-allocated (user-invisible) internals. | 433 // Compiler-allocated (user-invisible) internals. |
| 433 ZoneList<Variable*> internals_; | 434 ZoneList<Variable*> internals_; |
| 434 // Compiler-allocated (user-invisible) temporaries. | 435 // Compiler-allocated (user-invisible) temporaries. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 | 491 |
| 491 // For module scopes, the host scope's internal variable binding this module. | 492 // For module scopes, the host scope's internal variable binding this module. |
| 492 Variable* module_var_; | 493 Variable* module_var_; |
| 493 | 494 |
| 494 // Serialized scope info support. | 495 // Serialized scope info support. |
| 495 Handle<ScopeInfo> scope_info_; | 496 Handle<ScopeInfo> scope_info_; |
| 496 bool already_resolved() { return already_resolved_; } | 497 bool already_resolved() { return already_resolved_; } |
| 497 | 498 |
| 498 // Create a non-local variable with a given name. | 499 // Create a non-local variable with a given name. |
| 499 // These variables are looked up dynamically at runtime. | 500 // These variables are looked up dynamically at runtime. |
| 500 Variable* NonLocal(Handle<String> name, VariableMode mode); | 501 Variable* NonLocal(const AstString* name, VariableMode mode); |
| 501 | 502 |
| 502 // Variable resolution. | 503 // Variable resolution. |
| 503 // Possible results of a recursive variable lookup telling if and how a | 504 // Possible results of a recursive variable lookup telling if and how a |
| 504 // variable is bound. These are returned in the output parameter *binding_kind | 505 // variable is bound. These are returned in the output parameter *binding_kind |
| 505 // of the LookupRecursive function. | 506 // of the LookupRecursive function. |
| 506 enum BindingKind { | 507 enum BindingKind { |
| 507 // The variable reference could be statically resolved to a variable binding | 508 // The variable reference could be statically resolved to a variable binding |
| 508 // which is returned. There is no 'with' statement between the reference and | 509 // which is returned. There is no 'with' statement between the reference and |
| 509 // the binding and no scope between the reference scope (inclusive) and | 510 // the binding and no scope between the reference scope (inclusive) and |
| 510 // binding scope (exclusive) makes a sloppy 'eval' call. | 511 // binding scope (exclusive) makes a sloppy 'eval' call. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 541 // The variable potentially references a property of the 'with' object. | 542 // The variable potentially references a property of the 'with' object. |
| 542 // * The code is being executed as part of a call to 'eval' and the calling | 543 // * The code is being executed as part of a call to 'eval' and the calling |
| 543 // context chain contains either a variable binding for the name or it | 544 // context chain contains either a variable binding for the name or it |
| 544 // contains a 'with' context. | 545 // contains a 'with' context. |
| 545 DYNAMIC_LOOKUP | 546 DYNAMIC_LOOKUP |
| 546 }; | 547 }; |
| 547 | 548 |
| 548 // Lookup a variable reference given by name recursively starting with this | 549 // Lookup a variable reference given by name recursively starting with this |
| 549 // scope. If the code is executed because of a call to 'eval', the context | 550 // scope. If the code is executed because of a call to 'eval', the context |
| 550 // parameter should be set to the calling context of 'eval'. | 551 // parameter should be set to the calling context of 'eval'. |
| 551 Variable* LookupRecursive(Handle<String> name, | 552 Variable* LookupRecursive(const AstString* name, |
| 552 BindingKind* binding_kind, | 553 BindingKind* binding_kind, |
| 553 AstNodeFactory<AstNullVisitor>* factory); | 554 AstNodeFactory<AstNullVisitor>* factory); |
| 554 MUST_USE_RESULT | 555 MUST_USE_RESULT |
| 555 bool ResolveVariable(CompilationInfo* info, | 556 bool ResolveVariable(CompilationInfo* info, |
| 556 VariableProxy* proxy, | 557 VariableProxy* proxy, |
| 557 AstNodeFactory<AstNullVisitor>* factory); | 558 AstNodeFactory<AstNullVisitor>* factory); |
| 558 MUST_USE_RESULT | 559 MUST_USE_RESULT |
| 559 bool ResolveVariablesRecursively(CompilationInfo* info, | 560 bool ResolveVariablesRecursively(CompilationInfo* info, |
| 560 AstNodeFactory<AstNullVisitor>* factory); | 561 AstNodeFactory<AstNullVisitor>* factory); |
| 561 | 562 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 585 // In the case of code compiled and run using 'eval', the context | 586 // In the case of code compiled and run using 'eval', the context |
| 586 // parameter is the context in which eval was called. In all other | 587 // parameter is the context in which eval was called. In all other |
| 587 // cases the context parameter is an empty handle. | 588 // cases the context parameter is an empty handle. |
| 588 MUST_USE_RESULT | 589 MUST_USE_RESULT |
| 589 bool AllocateVariables(CompilationInfo* info, | 590 bool AllocateVariables(CompilationInfo* info, |
| 590 AstNodeFactory<AstNullVisitor>* factory); | 591 AstNodeFactory<AstNullVisitor>* factory); |
| 591 | 592 |
| 592 private: | 593 private: |
| 593 // Construct a scope based on the scope info. | 594 // Construct a scope based on the scope info. |
| 594 Scope(Scope* inner_scope, ScopeType type, Handle<ScopeInfo> scope_info, | 595 Scope(Scope* inner_scope, ScopeType type, Handle<ScopeInfo> scope_info, |
| 595 Zone* zone); | 596 AstValueFactory* value_factory, Zone* zone); |
| 596 | 597 |
| 597 // Construct a catch scope with a binding for the name. | 598 // Construct a catch scope with a binding for the name. |
| 598 Scope(Scope* inner_scope, Handle<String> catch_variable_name, Zone* zone); | 599 Scope(Scope* inner_scope, |
| 600 const AstString* catch_variable_name, |
| 601 AstValueFactory* value_factory, Zone* zone); |
| 599 | 602 |
| 600 void AddInnerScope(Scope* inner_scope) { | 603 void AddInnerScope(Scope* inner_scope) { |
| 601 if (inner_scope != NULL) { | 604 if (inner_scope != NULL) { |
| 602 inner_scopes_.Add(inner_scope, zone_); | 605 inner_scopes_.Add(inner_scope, zone_); |
| 603 inner_scope->outer_scope_ = this; | 606 inner_scope->outer_scope_ = this; |
| 604 } | 607 } |
| 605 } | 608 } |
| 606 | 609 |
| 607 void SetDefaults(ScopeType type, | 610 void SetDefaults(ScopeType type, |
| 608 Scope* outer_scope, | 611 Scope* outer_scope, |
| 609 Handle<ScopeInfo> scope_info); | 612 Handle<ScopeInfo> scope_info); |
| 610 | 613 |
| 614 AstValueFactory* ast_value_factory_; |
| 611 Zone* zone_; | 615 Zone* zone_; |
| 612 }; | 616 }; |
| 613 | 617 |
| 614 } } // namespace v8::internal | 618 } } // namespace v8::internal |
| 615 | 619 |
| 616 #endif // V8_SCOPES_H_ | 620 #endif // V8_SCOPES_H_ |
| OLD | NEW |