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 |