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