| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/parser.h" | 5 #include "vm/parser.h" |
| 6 | 6 |
| 7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "vm/bigint_operations.h" | 8 #include "vm/bigint_operations.h" |
| 9 #include "vm/bootstrap.h" | 9 #include "vm/bootstrap.h" |
| 10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
| (...skipping 5433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5444 | 5444 |
| 5445 | 5445 |
| 5446 AstNode* Parser::ParseFunctionStatement(bool is_literal) { | 5446 AstNode* Parser::ParseFunctionStatement(bool is_literal) { |
| 5447 TRACE_PARSER("ParseFunctionStatement"); | 5447 TRACE_PARSER("ParseFunctionStatement"); |
| 5448 AbstractType& result_type = AbstractType::Handle(); | 5448 AbstractType& result_type = AbstractType::Handle(); |
| 5449 const String* variable_name = NULL; | 5449 const String* variable_name = NULL; |
| 5450 const String* function_name = NULL; | 5450 const String* function_name = NULL; |
| 5451 | 5451 |
| 5452 result_type = Type::DynamicType(); | 5452 result_type = Type::DynamicType(); |
| 5453 | 5453 |
| 5454 intptr_t ident_pos = TokenPos(); | 5454 const intptr_t function_pos = TokenPos(); |
| 5455 if (is_literal) { | 5455 if (is_literal) { |
| 5456 ASSERT(CurrentToken() == Token::kLPAREN); | 5456 ASSERT(CurrentToken() == Token::kLPAREN); |
| 5457 function_name = &Symbols::AnonymousClosure(); | 5457 function_name = &Symbols::AnonymousClosure(); |
| 5458 } else { | 5458 } else { |
| 5459 if (CurrentToken() == Token::kVOID) { | 5459 if (CurrentToken() == Token::kVOID) { |
| 5460 ConsumeToken(); | 5460 ConsumeToken(); |
| 5461 result_type = Type::VoidType(); | 5461 result_type = Type::VoidType(); |
| 5462 } else if ((CurrentToken() == Token::kIDENT) && | 5462 } else if ((CurrentToken() == Token::kIDENT) && |
| 5463 (LookaheadToken(1) != Token::kLPAREN)) { | 5463 (LookaheadToken(1) != Token::kLPAREN)) { |
| 5464 result_type = ParseType(ClassFinalizer::kCanonicalize); | 5464 result_type = ParseType(ClassFinalizer::kCanonicalize); |
| 5465 } | 5465 } |
| 5466 variable_name = ExpectIdentifier("function name expected"); | 5466 variable_name = ExpectIdentifier("function name expected"); |
| 5467 function_name = variable_name; | 5467 function_name = variable_name; |
| 5468 } | 5468 } |
| 5469 | 5469 |
| 5470 if (CurrentToken() != Token::kLPAREN) { | 5470 if (CurrentToken() != Token::kLPAREN) { |
| 5471 ErrorMsg("'(' expected"); | 5471 ErrorMsg("'(' expected"); |
| 5472 } | 5472 } |
| 5473 intptr_t function_pos = TokenPos(); | |
| 5474 | 5473 |
| 5475 // Check whether we have parsed this closure function before, in a previous | 5474 // Check whether we have parsed this closure function before, in a previous |
| 5476 // compilation. If so, reuse the function object, else create a new one | 5475 // compilation. If so, reuse the function object, else create a new one |
| 5477 // and register it in the current class. | 5476 // and register it in the current class. |
| 5478 // Note that we cannot share the same closure function between the closurized | 5477 // Note that we cannot share the same closure function between the closurized |
| 5479 // and non-closurized versions of the same parent function. | 5478 // and non-closurized versions of the same parent function. |
| 5480 Function& function = Function::ZoneHandle(); | 5479 Function& function = Function::ZoneHandle(); |
| 5481 bool is_new_closure = false; | 5480 bool is_new_closure = false; |
| 5482 // TODO(hausner): There could be two different closures at the given | 5481 // TODO(hausner): There could be two different closures at the given |
| 5483 // function_pos, one enclosed in a closurized function and one enclosed in the | 5482 // function_pos, one enclosed in a closurized function and one enclosed in the |
| 5484 // non-closurized version of this same function. | 5483 // non-closurized version of this same function. |
| 5485 function = current_class().LookupClosureFunction(function_pos); | 5484 function = current_class().LookupClosureFunction(function_pos); |
| 5486 if (function.IsNull() || (function.token_pos() != function_pos) || | 5485 if (function.IsNull() || (function.token_pos() != function_pos) || |
| 5487 (function.parent_function() != innermost_function().raw())) { | 5486 (function.parent_function() != innermost_function().raw())) { |
| 5487 // The function will be registered in the lookup table by the |
| 5488 // EffectGraphVisitor::VisitClosureNode when the newly allocated closure |
| 5489 // function has been properly setup. |
| 5488 is_new_closure = true; | 5490 is_new_closure = true; |
| 5489 function = Function::NewClosureFunction(*function_name, | 5491 function = Function::NewClosureFunction(*function_name, |
| 5490 innermost_function(), | 5492 innermost_function(), |
| 5491 ident_pos); | 5493 function_pos); |
| 5492 function.set_result_type(result_type); | 5494 function.set_result_type(result_type); |
| 5493 current_class().AddClosureFunction(function); | |
| 5494 } | 5495 } |
| 5495 | 5496 |
| 5496 // The function type needs to be finalized at compile time, since the closure | 5497 // The function type needs to be finalized at compile time, since the closure |
| 5497 // may be type checked at run time when assigned to a function variable, | 5498 // may be type checked at run time when assigned to a function variable, |
| 5498 // passed as a function argument, or returned as a function result. | 5499 // passed as a function argument, or returned as a function result. |
| 5499 | 5500 |
| 5500 LocalVariable* function_variable = NULL; | 5501 LocalVariable* function_variable = NULL; |
| 5501 Type& function_type = Type::ZoneHandle(); | 5502 Type& function_type = Type::ZoneHandle(); |
| 5502 if (variable_name != NULL) { | 5503 if (variable_name != NULL) { |
| 5503 // Since the function type depends on the signature of the closure function, | 5504 // Since the function type depends on the signature of the closure function, |
| 5504 // it cannot be determined before the formal parameter list of the closure | 5505 // it cannot be determined before the formal parameter list of the closure |
| 5505 // function is parsed. Therefore, we set the function type to a new | 5506 // function is parsed. Therefore, we set the function type to a new |
| 5506 // parameterized type to be patched after the actual type is known. | 5507 // parameterized type to be patched after the actual type is known. |
| 5507 // We temporarily use the class of the Function interface. | 5508 // We temporarily use the class of the Function interface. |
| 5508 const Class& unknown_signature_class = Class::Handle( | 5509 const Class& unknown_signature_class = Class::Handle( |
| 5509 Type::Handle(Type::Function()).type_class()); | 5510 Type::Handle(Type::Function()).type_class()); |
| 5510 function_type = Type::New( | 5511 function_type = Type::New( |
| 5511 unknown_signature_class, TypeArguments::Handle(), ident_pos); | 5512 unknown_signature_class, TypeArguments::Handle(), function_pos); |
| 5512 function_type.SetIsFinalized(); // No finalization needed. | 5513 function_type.SetIsFinalized(); // No finalization needed. |
| 5513 | 5514 |
| 5514 // Add the function variable to the scope before parsing the function in | 5515 // Add the function variable to the scope before parsing the function in |
| 5515 // order to allow self reference from inside the function. | 5516 // order to allow self reference from inside the function. |
| 5516 function_variable = new LocalVariable(ident_pos, | 5517 function_variable = new LocalVariable(function_pos, |
| 5517 *variable_name, | 5518 *variable_name, |
| 5518 function_type); | 5519 function_type); |
| 5519 function_variable->set_is_final(); | 5520 function_variable->set_is_final(); |
| 5520 ASSERT(current_block_ != NULL); | 5521 ASSERT(current_block_ != NULL); |
| 5521 ASSERT(current_block_->scope != NULL); | 5522 ASSERT(current_block_->scope != NULL); |
| 5522 if (!current_block_->scope->AddVariable(function_variable)) { | 5523 if (!current_block_->scope->AddVariable(function_variable)) { |
| 5523 LocalVariable* existing_var = | 5524 LocalVariable* existing_var = |
| 5524 current_block_->scope->LookupVariable(function_variable->name(), | 5525 current_block_->scope->LookupVariable(function_variable->name(), |
| 5525 true); | 5526 true); |
| 5526 ASSERT(existing_var != NULL); | 5527 ASSERT(existing_var != NULL); |
| 5527 if (existing_var->owner() == current_block_->scope) { | 5528 if (existing_var->owner() == current_block_->scope) { |
| 5528 ErrorMsg(ident_pos, "identifier '%s' already defined", | 5529 ErrorMsg(function_pos, "identifier '%s' already defined", |
| 5529 function_variable->name().ToCString()); | 5530 function_variable->name().ToCString()); |
| 5530 } else { | 5531 } else { |
| 5531 ErrorMsg(ident_pos, | 5532 ErrorMsg(function_pos, |
| 5532 "'%s' from outer scope has already been used, cannot redefine", | 5533 "'%s' from outer scope has already been used, cannot redefine", |
| 5533 function_variable->name().ToCString()); | 5534 function_variable->name().ToCString()); |
| 5534 } | 5535 } |
| 5535 } | 5536 } |
| 5536 } | 5537 } |
| 5537 | 5538 |
| 5538 // Parse the local function. | 5539 // Parse the local function. |
| 5539 Array& default_parameter_values = Array::Handle(); | 5540 Array& default_parameter_values = Array::Handle(); |
| 5540 SequenceNode* statements = Parser::ParseFunc(function, | 5541 SequenceNode* statements = Parser::ParseFunc(function, |
| 5541 default_parameter_values); | 5542 default_parameter_values); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5634 // allocation information in a Scope object stored in the function object. | 5635 // allocation information in a Scope object stored in the function object. |
| 5635 // This Scope object is then provided to the compiler when compiling the local | 5636 // This Scope object is then provided to the compiler when compiling the local |
| 5636 // function. It would be too early to record the captured variables here, | 5637 // function. It would be too early to record the captured variables here, |
| 5637 // since further closure functions may capture more variables. | 5638 // since further closure functions may capture more variables. |
| 5638 // This Scope object is constructed after all variables have been allocated. | 5639 // This Scope object is constructed after all variables have been allocated. |
| 5639 // The local scope of the parsed function can be pruned, since contained | 5640 // The local scope of the parsed function can be pruned, since contained |
| 5640 // variables are not relevant for the compilation of the enclosing function. | 5641 // variables are not relevant for the compilation of the enclosing function. |
| 5641 // This pruning is done by omitting to hook the local scope in its parent | 5642 // This pruning is done by omitting to hook the local scope in its parent |
| 5642 // scope in the constructor of LocalScope. | 5643 // scope in the constructor of LocalScope. |
| 5643 AstNode* closure = | 5644 AstNode* closure = |
| 5644 new ClosureNode(ident_pos, function, NULL, statements->scope()); | 5645 new ClosureNode(function_pos, function, NULL, statements->scope()); |
| 5645 | 5646 |
| 5646 if (function_variable == NULL) { | 5647 if (function_variable == NULL) { |
| 5647 ASSERT(is_literal); | 5648 ASSERT(is_literal); |
| 5648 return closure; | 5649 return closure; |
| 5649 } else { | 5650 } else { |
| 5650 AstNode* initialization = | 5651 AstNode* initialization = |
| 5651 new StoreLocalNode(ident_pos, function_variable, closure); | 5652 new StoreLocalNode(function_pos, function_variable, closure); |
| 5652 return initialization; | 5653 return initialization; |
| 5653 } | 5654 } |
| 5654 } | 5655 } |
| 5655 | 5656 |
| 5656 | 5657 |
| 5657 // Returns true if the current and next tokens can be parsed as type | 5658 // Returns true if the current and next tokens can be parsed as type |
| 5658 // parameters. Current token position is not saved and restored. | 5659 // parameters. Current token position is not saved and restored. |
| 5659 bool Parser::TryParseTypeParameter() { | 5660 bool Parser::TryParseTypeParameter() { |
| 5660 if (CurrentToken() == Token::kLT) { | 5661 if (CurrentToken() == Token::kLT) { |
| 5661 // We are possibly looking at type parameters. Find closing ">". | 5662 // We are possibly looking at type parameters. Find closing ">". |
| (...skipping 4961 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10623 void Parser::SkipQualIdent() { | 10624 void Parser::SkipQualIdent() { |
| 10624 ASSERT(IsIdentifier()); | 10625 ASSERT(IsIdentifier()); |
| 10625 ConsumeToken(); | 10626 ConsumeToken(); |
| 10626 if (CurrentToken() == Token::kPERIOD) { | 10627 if (CurrentToken() == Token::kPERIOD) { |
| 10627 ConsumeToken(); // Consume the kPERIOD token. | 10628 ConsumeToken(); // Consume the kPERIOD token. |
| 10628 ExpectIdentifier("identifier expected after '.'"); | 10629 ExpectIdentifier("identifier expected after '.'"); |
| 10629 } | 10630 } |
| 10630 } | 10631 } |
| 10631 | 10632 |
| 10632 } // namespace dart | 10633 } // namespace dart |
| OLD | NEW |