return proxy()->var()->IsStackAllocated();
}
-bool VariableDeclaration::IsInlineable() const {
- return Declaration::IsInlineable() && fun() == NULL;
+bool FunctionDeclaration::IsInlineable() const {
+ return false;
}
}
INCREASE_NODE_COUNT(VariableDeclaration)
+INCREASE_NODE_COUNT(FunctionDeclaration)
INCREASE_NODE_COUNT(ModuleDeclaration)
INCREASE_NODE_COUNT(ModuleLiteral)
INCREASE_NODE_COUNT(ModuleVariable)
#define DECLARATION_NODE_LIST(V) \
V(VariableDeclaration) \
+ V(FunctionDeclaration) \
V(ModuleDeclaration) \
#define MODULE_NODE_LIST(V) \
VariableProxy* proxy() const { return proxy_; }
VariableMode mode() const { return mode_; }
Scope* scope() const { return scope_; }
+ virtual InitializationFlag initialization() const = 0;
virtual bool IsInlineable() const;
virtual Declaration* AsDeclaration() { return this; }
- virtual VariableDeclaration* AsVariableDeclaration() { return NULL; }
protected:
Declaration(VariableProxy* proxy,
public:
DECLARE_NODE_TYPE(VariableDeclaration)
- virtual VariableDeclaration* AsVariableDeclaration() { return this; }
+ virtual InitializationFlag initialization() const {
+ return mode() == VAR ? kCreatedInitialized : kNeedsInitialization;
+ }
+
+ protected:
+ template<class> friend class AstNodeFactory;
+
+ VariableDeclaration(VariableProxy* proxy,
+ VariableMode mode,
+ Scope* scope)
+ : Declaration(proxy, mode, scope) {
+ }
+};
+
- FunctionLiteral* fun() const { return fun_; } // may be NULL
+class FunctionDeclaration: public Declaration {
+ public:
+ DECLARE_NODE_TYPE(FunctionDeclaration)
+
+ FunctionLiteral* fun() const { return fun_; }
+ virtual InitializationFlag initialization() const {
+ return kCreatedInitialized;
+ }
virtual bool IsInlineable() const;
protected:
template<class> friend class AstNodeFactory;
- VariableDeclaration(VariableProxy* proxy,
+ FunctionDeclaration(VariableProxy* proxy,
VariableMode mode,
FunctionLiteral* fun,
Scope* scope)
: Declaration(proxy, mode, scope),
fun_(fun) {
- // At the moment there are no "const functions"'s in JavaScript...
- ASSERT(fun == NULL || mode == VAR || mode == LET);
+ // At the moment there are no "const functions" in JavaScript...
+ ASSERT(mode == VAR || mode == LET);
+ ASSERT(fun != NULL);
}
private:
DECLARE_NODE_TYPE(ModuleDeclaration)
Module* module() const { return module_; }
+ virtual InitializationFlag initialization() const {
+ return kCreatedInitialized;
+ }
protected:
template<class> friend class AstNodeFactory;
VariableDeclaration* NewVariableDeclaration(VariableProxy* proxy,
VariableMode mode,
- FunctionLiteral* fun,
Scope* scope) {
VariableDeclaration* decl =
- new(zone_) VariableDeclaration(proxy, mode, fun, scope);
+ new(zone_) VariableDeclaration(proxy, mode, scope);
VISIT_AND_RETURN(VariableDeclaration, decl)
}
+ FunctionDeclaration* NewFunctionDeclaration(VariableProxy* proxy,
+ VariableMode mode,
+ FunctionLiteral* fun,
+ Scope* scope) {
+ FunctionDeclaration* decl =
+ new(zone_) FunctionDeclaration(proxy, mode, fun, scope);
+ VISIT_AND_RETURN(FunctionDeclaration, decl)
+ }
+
ModuleDeclaration* NewModuleDeclaration(VariableProxy* proxy,
Module* module,
Scope* scope) {
VariableDeclaration* decl) {
}
+void BreakableStatementChecker::VisitFunctionDeclaration(
+ FunctionDeclaration* decl) {
+}
+
void BreakableStatementChecker::VisitModuleDeclaration(
ModuleDeclaration* decl) {
}
isolate()->factory()->NewFixedArray(2 * global_count_, TENURED);
int length = declarations->length();
for (int j = 0, i = 0; i < length; i++) {
- VariableDeclaration* decl = declarations->at(i)->AsVariableDeclaration();
- if (decl != NULL) {
- Variable* var = decl->proxy()->var();
-
- if (var->IsUnallocated()) {
- array->set(j++, *(var->name()));
- if (decl->fun() == NULL) {
- if (var->binding_needs_init()) {
- // In case this binding needs initialization use the hole.
- array->set_the_hole(j++);
- } else {
- array->set_undefined(j++);
- }
+ Declaration* decl = declarations->at(i);
+ Variable* var = decl->proxy()->var();
+
+ if (var->IsUnallocated()) {
+ array->set(j++, *(var->name()));
+ FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration();
+ if (fun_decl == NULL) {
+ if (var->binding_needs_init()) {
+ // In case this binding needs initialization use the hole.
+ array->set_the_hole(j++);
} else {
- Handle<SharedFunctionInfo> function =
- Compiler::BuildFunctionInfo(decl->fun(), script());
- // Check for stack-overflow exception.
- if (function.is_null()) {
- SetStackOverflow();
- return;
- }
- array->set(j++, *function);
+ array->set_undefined(j++);
}
+ } else {
+ Handle<SharedFunctionInfo> function =
+ Compiler::BuildFunctionInfo(fun_decl->fun(), script());
+ // Check for stack-overflow exception.
+ if (function.is_null()) {
+ SetStackOverflow();
+ return;
+ }
+ array->set(j++, *function);
}
}
}
void FullCodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
+ EmitDeclaration(decl->proxy(), decl->mode(), NULL);
+}
+
+
+void FullCodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
EmitDeclaration(decl->proxy(), decl->mode(), decl->fun());
}
void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* decl) {
- // TODO(rossberg)
+ EmitDeclaration(decl->proxy(), decl->mode(), NULL);
}
// Handle implicit declaration of the function name in named function
// expressions before other declarations.
if (scope->is_function_scope() && scope->function() != NULL) {
- HandleVariableDeclaration(scope->function(), CONST, NULL, NULL);
+ HandleDeclaration(scope->function(), CONST, NULL, NULL);
}
VisitDeclarations(scope->declarations());
AddSimulate(AstNode::kDeclarationsId);
}
-void HGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
- UNREACHABLE();
-}
-
void HGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
int length = declarations->length();
int global_count = 0;
for (int i = 0; i < declarations->length(); i++) {
- VariableDeclaration* decl = declarations->at(i)->AsVariableDeclaration();
- if (decl == NULL) continue;
- HandleVariableDeclaration(decl->proxy(),
- decl->mode(),
- decl->fun(),
- &global_count);
+ Declaration* decl = declarations->at(i);
+ FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration();
+ HandleDeclaration(decl->proxy(),
+ decl->mode(),
+ fun_decl != NULL ? fun_decl->fun() : NULL,
+ &global_count);
}
// Batch declare global functions and variables.
Handle<FixedArray> array =
isolate()->factory()->NewFixedArray(2 * global_count, TENURED);
for (int j = 0, i = 0; i < length; i++) {
- VariableDeclaration* decl = declarations->at(i)->AsVariableDeclaration();
- if (decl == NULL) continue;
+ Declaration* decl = declarations->at(i);
Variable* var = decl->proxy()->var();
if (var->IsUnallocated()) {
array->set(j++, *(var->name()));
- if (decl->fun() == NULL) {
+ FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration();
+ if (fun_decl == NULL) {
if (var->binding_needs_init()) {
// In case this binding needs initialization use the hole.
array->set_the_hole(j++);
}
} else {
Handle<SharedFunctionInfo> function =
- Compiler::BuildFunctionInfo(decl->fun(), info()->script());
+ Compiler::BuildFunctionInfo(fun_decl->fun(), info()->script());
// Check for stack-overflow exception.
if (function.is_null()) {
SetStackOverflow();
}
-void HGraphBuilder::HandleVariableDeclaration(VariableProxy* proxy,
- VariableMode mode,
- FunctionLiteral* function,
- int* global_count) {
+void HGraphBuilder::HandleDeclaration(VariableProxy* proxy,
+ VariableMode mode,
+ FunctionLiteral* function,
+ int* global_count) {
Variable* var = proxy->var();
bool binding_needs_init =
(mode == CONST || mode == CONST_HARMONY || mode == LET);
}
+void HGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
+ UNREACHABLE();
+}
+
+
+void HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
+ UNREACHABLE();
+}
+
+
void HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* decl) {
// TODO(rossberg)
}
INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_DECLARATION)
#undef INLINE_FUNCTION_GENERATOR_DECLARATION
- void HandleVariableDeclaration(VariableProxy* proxy,
- VariableMode mode,
- FunctionLiteral* function,
- int* global_count);
+ void HandleDeclaration(VariableProxy* proxy,
+ VariableMode mode,
+ FunctionLiteral* function,
+ int* global_count);
void VisitDelete(UnaryOperation* expr);
void VisitVoid(UnaryOperation* expr);
// Create new block with one expected declaration.
Block* block = factory()->NewBlock(NULL, 1, true);
Handle<String> name = ParseIdentifier(CHECK_OK);
- // top_scope_->AddDeclaration(
- // factory()->NewModuleDeclaration(proxy, module, top_scope_));
- VariableProxy* proxy = Declare(name, LET, NULL, true, CHECK_OK);
- Module* module = ParseModule(ok);
+ Module* module = ParseModule(CHECK_OK);
+ VariableProxy* proxy = NewUnresolved(name, LET);
+ Declaration* declaration =
+ factory()->NewModuleDeclaration(proxy, module, top_scope_);
+ Declare(declaration, true, CHECK_OK);
+
// TODO(rossberg): Add initialization statement to block.
- USE(proxy);
- USE(module);
+
return block;
}
}
-VariableProxy* Parser::Declare(Handle<String> name,
- VariableMode mode,
- FunctionLiteral* fun,
- bool resolve,
- bool* ok) {
- Variable* var = NULL;
+VariableProxy* Parser::NewUnresolved(Handle<String> name, VariableMode mode) {
// If we are inside a function, a declaration of a var/const variable is a
// truly local variable, and the scope of the variable is always the function
// scope.
// Let/const variables in harmony mode are always added to the immediately
// enclosing scope.
- Scope* declaration_scope = (mode == LET || mode == CONST_HARMONY)
- ? top_scope_ : top_scope_->DeclarationScope();
- InitializationFlag init_flag = (fun != NULL || mode == VAR)
- ? kCreatedInitialized : kNeedsInitialization;
+ return DeclarationScope(mode)->NewUnresolved(
+ factory(), name, scanner().location().beg_pos);
+}
+
+
+void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
+ Handle<String> name = declaration->proxy()->name();
+ VariableMode mode = declaration->mode();
+ Scope* declaration_scope = DeclarationScope(mode);
+ Variable* var = NULL;
// If a function scope exists, then we can statically declare this
// variable and also set its mode. In any case, a Declaration node
var = declaration_scope->LocalLookup(name);
if (var == NULL) {
// Declare the name.
- var = declaration_scope->DeclareLocal(name, mode, init_flag);
+ var = declaration_scope->DeclareLocal(
+ name, mode, declaration->initialization());
} else {
// The name was declared in this scope before; check for conflicting
// re-declarations. We have a conflict if either of the declarations is
Vector<const char*> args(elms, 2);
ReportMessage("redeclaration", args);
*ok = false;
- return NULL;
+ return;
}
const char* type = (var->mode() == VAR)
? "var" : var->is_const_mode() ? "const" : "let";
// semantic issue as long as we keep the source order, but it may be
// a performance issue since it may lead to repeated
// Runtime::DeclareContextSlot() calls.
- VariableProxy* proxy = declaration_scope->NewUnresolved(
- factory(), name, scanner().location().beg_pos);
- declaration_scope->AddDeclaration(
- factory()->NewVariableDeclaration(proxy, mode, fun, top_scope_));
+ declaration_scope->AddDeclaration(declaration);
if ((mode == CONST || mode == CONST_HARMONY) &&
declaration_scope->is_global_scope()) {
mode,
true,
kind,
- init_flag);
+ declaration->initialization());
var->AllocateTo(Variable::LOOKUP, -1);
resolve = true;
}
// initialization code. Thus, inside the 'with' statement, we need
// both access to the static and the dynamic context chain; the
// runtime needs to provide both.
- if (resolve && var != NULL) proxy->BindTo(var);
-
- return proxy;
+ if (resolve && var != NULL) declaration->proxy()->BindTo(var);
}
// isn't lazily compiled. The extension structures are only
// accessible while parsing the first time not when reparsing
// because of lazy compilation.
- top_scope_->DeclarationScope()->ForceEagerCompilation();
+ DeclarationScope(VAR)->ForceEagerCompilation();
// Compute the function template for the native function.
v8::Handle<v8::FunctionTemplate> fun_template =
// TODO(1240846): It's weird that native function declarations are
// introduced dynamically when we meet their declarations, whereas
// other functions are set up when entering the surrounding scope.
+ VariableProxy* proxy = NewUnresolved(name, VAR);
+ Declaration* declaration =
+ factory()->NewVariableDeclaration(proxy, VAR, top_scope_);
+ Declare(declaration, true, CHECK_OK);
SharedFunctionInfoLiteral* lit =
factory()->NewSharedFunctionInfoLiteral(shared);
- VariableProxy* var = Declare(name, VAR, NULL, true, CHECK_OK);
return factory()->NewExpressionStatement(
factory()->NewAssignment(
- Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
+ Token::INIT_VAR, proxy, lit, RelocInfo::kNoPosition));
}
// scope, we treat is as such and introduce the function with it's
// initial value upon entering the corresponding scope.
VariableMode mode = is_extended_mode() ? LET : VAR;
- Declare(name, mode, fun, true, CHECK_OK);
+ VariableProxy* proxy = NewUnresolved(name, mode);
+ Declaration* declaration =
+ factory()->NewFunctionDeclaration(proxy, mode, fun, top_scope_);
+ Declare(declaration, true, CHECK_OK);
return factory()->NewEmptyStatement();
}
UNREACHABLE(); // by current callers
}
- Scope* declaration_scope = (mode == LET || mode == CONST_HARMONY)
- ? top_scope_ : top_scope_->DeclarationScope();
+ Scope* declaration_scope = DeclarationScope(mode);
+
// The scope of a var/const declared variable anywhere inside a function
// is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
// transform a source-level var/const declaration into a (Function)
// 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.
- VariableProxy* proxy = Declare(name, mode, NULL, mode != VAR, CHECK_OK);
+ VariableProxy* proxy = NewUnresolved(name, mode);
+ Declaration* declaration =
+ factory()->NewVariableDeclaration(proxy, mode, top_scope_);
+ Declare(declaration, mode != VAR, CHECK_OK);
nvars++;
if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
ReportMessageAt(scanner().location(), "too_many_variables",
ASSERT(top_scope_ != NULL);
return top_scope_->is_extended_mode();
}
+ Scope* DeclarationScope(VariableMode mode) {
+ return (mode == LET || mode == CONST_HARMONY)
+ ? top_scope_ : top_scope_->DeclarationScope();
+ }
// Check if the given string is 'eval' or 'arguments'.
bool IsEvalOrArguments(Handle<String> string);
void CheckConflictingVarDeclarations(Scope* scope, bool* ok);
// Parser support
- VariableProxy* Declare(Handle<String> name, VariableMode mode,
- FunctionLiteral* fun,
- bool resolve,
- bool* ok);
+ VariableProxy* NewUnresolved(Handle<String> name, VariableMode mode);
+ void Declare(Declaration* declaration, bool resolve, bool* ok);
bool TargetStackContainsLabel(Handle<String> label);
BreakableStatement* LookupBreakTarget(Handle<String> label, bool* ok);
void PrettyPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
Print("var ");
PrintLiteral(node->proxy()->name(), false);
- if (node->fun() != NULL) {
- Print(" = ");
- PrintFunctionLiteral(node->fun());
- }
+ Print(";");
+}
+
+
+void PrettyPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
+ Print("function ");
+ PrintLiteral(node->proxy()->name(), false);
+ Print(" = ");
+ PrintFunctionLiteral(node->fun());
Print(";");
}
void AstPrinter::VisitVariableDeclaration(VariableDeclaration* node) {
- if (node->fun() == NULL) {
- // var or const declarations
- PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
- node->proxy()->var(),
- node->proxy()->name());
- } else {
- // function declarations
- PrintIndented("FUNCTION ");
- PrintLiteral(node->proxy()->name(), true);
- Print(" = function ");
- PrintLiteral(node->fun()->name(), false);
- Print("\n");
- }
+ PrintLiteralWithModeIndented(Variable::Mode2String(node->mode()),
+ node->proxy()->var(),
+ node->proxy()->name());
+}
+
+
+void AstPrinter::VisitFunctionDeclaration(FunctionDeclaration* node) {
+ PrintIndented("FUNCTION ");
+ PrintLiteral(node->proxy()->name(), true);
+ Print(" = function ");
+ PrintLiteral(node->fun()->name(), false);
+ Print("\n");
}
// Do nothing:
void Processor::VisitVariableDeclaration(VariableDeclaration* node) {}
+void Processor::VisitFunctionDeclaration(FunctionDeclaration* node) {}
void Processor::VisitModuleDeclaration(ModuleDeclaration* node) {}
void Processor::VisitModuleLiteral(ModuleLiteral* node) {}
void Processor::VisitModuleVariable(ModuleVariable* node) {}