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 4821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4832 library_.ReplaceObject(func, accessor_name); | 4832 library_.ReplaceObject(func, accessor_name); |
4833 } | 4833 } |
4834 if (metadata_pos >= 0) { | 4834 if (metadata_pos >= 0) { |
4835 library_.AddFunctionMetadata(func, metadata_pos); | 4835 library_.AddFunctionMetadata(func, metadata_pos); |
4836 } | 4836 } |
4837 } | 4837 } |
4838 | 4838 |
4839 | 4839 |
4840 | 4840 |
4841 RawObject* Parser::CallLibraryTagHandler(Dart_LibraryTag tag, | 4841 RawObject* Parser::CallLibraryTagHandler(Dart_LibraryTag tag, |
4842 intptr_t token_pos, | 4842 intptr_t token_pos, |
4843 const String& url) { | 4843 const String& url) { |
4844 Dart_LibraryTagHandler handler = isolate()->library_tag_handler(); | 4844 Dart_LibraryTagHandler handler = isolate()->library_tag_handler(); |
4845 if (handler == NULL) { | 4845 if (handler == NULL) { |
4846 if (url.StartsWith(Symbols::DartScheme())) { | 4846 if (url.StartsWith(Symbols::DartScheme())) { |
4847 if (tag == Dart_kCanonicalizeUrl) { | 4847 if (tag == Dart_kCanonicalizeUrl) { |
4848 return url.raw(); | 4848 return url.raw(); |
4849 } | 4849 } |
4850 return Object::null(); | 4850 return Object::null(); |
4851 } | 4851 } |
4852 ErrorMsg(token_pos, "no library handler registered"); | 4852 ErrorMsg(token_pos, "no library handler registered"); |
4853 } | 4853 } |
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5401 } | 5401 } |
5402 | 5402 |
5403 | 5403 |
5404 // Returns ast nodes of the variable initialization. | 5404 // Returns ast nodes of the variable initialization. |
5405 AstNode* Parser::ParseVariableDeclaration(const AbstractType& type, | 5405 AstNode* Parser::ParseVariableDeclaration(const AbstractType& type, |
5406 bool is_final, | 5406 bool is_final, |
5407 bool is_const) { | 5407 bool is_const) { |
5408 TRACE_PARSER("ParseVariableDeclaration"); | 5408 TRACE_PARSER("ParseVariableDeclaration"); |
5409 ASSERT(IsIdentifier()); | 5409 ASSERT(IsIdentifier()); |
5410 const intptr_t ident_pos = TokenPos(); | 5410 const intptr_t ident_pos = TokenPos(); |
5411 LocalVariable* variable = | 5411 const String& ident = *CurrentLiteral(); |
5412 new LocalVariable(ident_pos, *CurrentLiteral(), type); | 5412 LocalVariable* variable = new LocalVariable(ident_pos, ident, type); |
5413 ASSERT(current_block_ != NULL); | |
5414 ASSERT(current_block_->scope != NULL); | |
5415 ConsumeToken(); // Variable identifier. | 5413 ConsumeToken(); // Variable identifier. |
5416 AstNode* initialization = NULL; | 5414 AstNode* initialization = NULL; |
5417 if (CurrentToken() == Token::kASSIGN) { | 5415 if (CurrentToken() == Token::kASSIGN) { |
5418 // Variable initialization. | 5416 // Variable initialization. |
5419 const intptr_t assign_pos = TokenPos(); | 5417 const intptr_t assign_pos = TokenPos(); |
5420 ConsumeToken(); | 5418 ConsumeToken(); |
5421 AstNode* expr = ParseExpr(is_const, kConsumeCascades); | 5419 AstNode* expr = ParseExpr(is_const, kConsumeCascades); |
5422 initialization = new StoreLocalNode(assign_pos, variable, expr); | 5420 initialization = new StoreLocalNode(assign_pos, variable, expr); |
5423 if (is_const) { | 5421 if (is_const) { |
5424 ASSERT(expr->IsLiteralNode()); | 5422 ASSERT(expr->IsLiteralNode()); |
5425 variable->SetConstValue(expr->AsLiteralNode()->literal()); | 5423 variable->SetConstValue(expr->AsLiteralNode()->literal()); |
5426 } | 5424 } |
5427 } else if (is_final || is_const) { | 5425 } else if (is_final || is_const) { |
5428 ErrorMsg(ident_pos, | 5426 ErrorMsg(ident_pos, |
5429 "missing initialization of 'final' or 'const' variable"); | 5427 "missing initialization of 'final' or 'const' variable"); |
5430 } else { | 5428 } else { |
5431 // Initialize variable with null. | 5429 // Initialize variable with null. |
5432 AstNode* null_expr = new LiteralNode(ident_pos, Instance::ZoneHandle()); | 5430 AstNode* null_expr = new LiteralNode(ident_pos, Instance::ZoneHandle()); |
5433 initialization = new StoreLocalNode(ident_pos, variable, null_expr); | 5431 initialization = new StoreLocalNode(ident_pos, variable, null_expr); |
5434 } | 5432 } |
| 5433 |
| 5434 ASSERT(current_block_ != NULL); |
| 5435 const intptr_t previous_pos = |
| 5436 current_block_->scope->PreviousReferencePos(ident); |
| 5437 if (previous_pos >= 0) { |
| 5438 ASSERT(!script_.IsNull()); |
| 5439 if (previous_pos > ident_pos) { |
| 5440 ErrorMsg(ident_pos, |
| 5441 "initializer of '%s' may not refer to itself", |
| 5442 ident.ToCString()); |
| 5443 |
| 5444 } else { |
| 5445 intptr_t line_number; |
| 5446 script_.GetTokenLocation(previous_pos, &line_number, NULL); |
| 5447 ErrorMsg(ident_pos, |
| 5448 "identifier '%s' previously used in line %" Pd "", |
| 5449 ident.ToCString(), |
| 5450 line_number); |
| 5451 } |
| 5452 } |
| 5453 |
5435 // Add variable to scope after parsing the initalizer expression. | 5454 // Add variable to scope after parsing the initalizer expression. |
5436 // The expression must not be able to refer to the variable. | 5455 // The expression must not be able to refer to the variable. |
5437 if (!current_block_->scope->AddVariable(variable)) { | 5456 if (!current_block_->scope->AddVariable(variable)) { |
5438 LocalVariable* existing_var = | 5457 LocalVariable* existing_var = |
5439 current_block_->scope->LookupVariable(variable->name(), true); | 5458 current_block_->scope->LookupVariable(variable->name(), true); |
5440 ASSERT(existing_var != NULL); | 5459 ASSERT(existing_var != NULL); |
5441 if (existing_var->owner() == current_block_->scope) { | 5460 if (existing_var->owner() == current_block_->scope) { |
5442 ErrorMsg(ident_pos, "identifier '%s' already defined", | 5461 ErrorMsg(ident_pos, "identifier '%s' already defined", |
5443 variable->name().ToCString()); | 5462 variable->name().ToCString()); |
5444 } else { | 5463 } else { |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5539 ASSERT(CurrentToken() == Token::kLPAREN); | 5558 ASSERT(CurrentToken() == Token::kLPAREN); |
5540 function_name = &Symbols::AnonymousClosure(); | 5559 function_name = &Symbols::AnonymousClosure(); |
5541 } else { | 5560 } else { |
5542 if (CurrentToken() == Token::kVOID) { | 5561 if (CurrentToken() == Token::kVOID) { |
5543 ConsumeToken(); | 5562 ConsumeToken(); |
5544 result_type = Type::VoidType(); | 5563 result_type = Type::VoidType(); |
5545 } else if ((CurrentToken() == Token::kIDENT) && | 5564 } else if ((CurrentToken() == Token::kIDENT) && |
5546 (LookaheadToken(1) != Token::kLPAREN)) { | 5565 (LookaheadToken(1) != Token::kLPAREN)) { |
5547 result_type = ParseType(ClassFinalizer::kCanonicalize); | 5566 result_type = ParseType(ClassFinalizer::kCanonicalize); |
5548 } | 5567 } |
| 5568 const intptr_t name_pos = TokenPos(); |
5549 variable_name = ExpectIdentifier("function name expected"); | 5569 variable_name = ExpectIdentifier("function name expected"); |
5550 function_name = variable_name; | 5570 function_name = variable_name; |
| 5571 |
| 5572 // Check that the function name has not been referenced |
| 5573 // before this declaration. |
| 5574 ASSERT(current_block_ != NULL); |
| 5575 const intptr_t previous_pos = |
| 5576 current_block_->scope->PreviousReferencePos(*function_name); |
| 5577 if (previous_pos >= 0) { |
| 5578 ASSERT(!script_.IsNull()); |
| 5579 intptr_t line_number; |
| 5580 script_.GetTokenLocation(previous_pos, &line_number, NULL); |
| 5581 ErrorMsg(name_pos, |
| 5582 "identifier '%s' previously used in line %" Pd "", |
| 5583 function_name->ToCString(), |
| 5584 line_number); |
| 5585 } |
5551 } | 5586 } |
5552 | 5587 |
5553 if (CurrentToken() != Token::kLPAREN) { | 5588 if (CurrentToken() != Token::kLPAREN) { |
5554 ErrorMsg("'(' expected"); | 5589 ErrorMsg("'(' expected"); |
5555 } | 5590 } |
5556 | 5591 |
5557 // Check whether we have parsed this closure function before, in a previous | 5592 // Check whether we have parsed this closure function before, in a previous |
5558 // compilation. If so, reuse the function object, else create a new one | 5593 // compilation. If so, reuse the function object, else create a new one |
5559 // and register it in the current class. | 5594 // and register it in the current class. |
5560 // Note that we cannot share the same closure function between the closurized | 5595 // Note that we cannot share the same closure function between the closurized |
(...skipping 3350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8911 | 8946 |
8912 // Do a lookup for the identifier in the block scope and the class scope | 8947 // Do a lookup for the identifier in the block scope and the class scope |
8913 // return true if the identifier is found, false otherwise. | 8948 // return true if the identifier is found, false otherwise. |
8914 // If node is non NULL return an AST node corresponding to the identifier. | 8949 // If node is non NULL return an AST node corresponding to the identifier. |
8915 bool Parser::ResolveIdentInLocalScope(intptr_t ident_pos, | 8950 bool Parser::ResolveIdentInLocalScope(intptr_t ident_pos, |
8916 const String &ident, | 8951 const String &ident, |
8917 AstNode** node) { | 8952 AstNode** node) { |
8918 TRACE_PARSER("ResolveIdentInLocalScope"); | 8953 TRACE_PARSER("ResolveIdentInLocalScope"); |
8919 // First try to find the identifier in the nested local scopes. | 8954 // First try to find the identifier in the nested local scopes. |
8920 LocalVariable* local = LookupLocalScope(ident); | 8955 LocalVariable* local = LookupLocalScope(ident); |
| 8956 if (current_block_ != NULL) { |
| 8957 current_block_->scope->AddReferencedName(ident_pos, ident); |
| 8958 } |
8921 if (local != NULL) { | 8959 if (local != NULL) { |
8922 if (node != NULL) { | 8960 if (node != NULL) { |
8923 if (local->IsConst()) { | 8961 if (local->IsConst()) { |
8924 *node = new LiteralNode(ident_pos, *local->ConstValue()); | 8962 *node = new LiteralNode(ident_pos, *local->ConstValue()); |
8925 } else { | 8963 } else { |
8926 *node = new LoadLocalNode(ident_pos, local); | 8964 *node = new LoadLocalNode(ident_pos, local); |
8927 } | 8965 } |
8928 } | 8966 } |
8929 return true; | 8967 return true; |
8930 } | 8968 } |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9255 // Parses type = [ident "."] ident ["<" type { "," type } ">"], then resolve and | 9293 // Parses type = [ident "."] ident ["<" type { "," type } ">"], then resolve and |
9256 // finalize it according to the given type finalization mode. | 9294 // finalize it according to the given type finalization mode. |
9257 RawAbstractType* Parser::ParseType( | 9295 RawAbstractType* Parser::ParseType( |
9258 ClassFinalizer::FinalizationKind finalization) { | 9296 ClassFinalizer::FinalizationKind finalization) { |
9259 TRACE_PARSER("ParseType"); | 9297 TRACE_PARSER("ParseType"); |
9260 if (CurrentToken() != Token::kIDENT) { | 9298 if (CurrentToken() != Token::kIDENT) { |
9261 ErrorMsg("type name expected"); | 9299 ErrorMsg("type name expected"); |
9262 } | 9300 } |
9263 QualIdent type_name; | 9301 QualIdent type_name; |
9264 if (finalization == ClassFinalizer::kIgnore) { | 9302 if (finalization == ClassFinalizer::kIgnore) { |
| 9303 if (!is_top_level_ && (current_block_ != NULL)) { |
| 9304 // Add the library prefix or type class name to the list of referenced |
| 9305 // names of this scope, even if the type is ignored. |
| 9306 current_block_->scope->AddReferencedName(TokenPos(), *CurrentLiteral()); |
| 9307 } |
9265 SkipQualIdent(); | 9308 SkipQualIdent(); |
9266 } else { | 9309 } else { |
9267 ParseQualIdent(&type_name); | 9310 ParseQualIdent(&type_name); |
9268 // An identifier cannot be resolved in a local scope when top level parsing. | 9311 // An identifier cannot be resolved in a local scope when top level parsing. |
9269 if (!is_top_level_ && | 9312 if (!is_top_level_ && |
9270 (type_name.lib_prefix == NULL) && | 9313 (type_name.lib_prefix == NULL) && |
9271 ResolveIdentInLocalScope(type_name.ident_pos, *type_name.ident, NULL)) { | 9314 ResolveIdentInLocalScope(type_name.ident_pos, *type_name.ident, NULL)) { |
9272 // The type is malformed. Skip over its type arguments. | 9315 // The type is malformed. Skip over its type arguments. |
9273 ParseTypeArguments(ClassFinalizer::kIgnore); | 9316 ParseTypeArguments(ClassFinalizer::kIgnore); |
9274 if (finalization == ClassFinalizer::kCanonicalizeWellFormed) { | 9317 if (finalization == ClassFinalizer::kCanonicalizeWellFormed) { |
(...skipping 1461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10736 void Parser::SkipQualIdent() { | 10779 void Parser::SkipQualIdent() { |
10737 ASSERT(IsIdentifier()); | 10780 ASSERT(IsIdentifier()); |
10738 ConsumeToken(); | 10781 ConsumeToken(); |
10739 if (CurrentToken() == Token::kPERIOD) { | 10782 if (CurrentToken() == Token::kPERIOD) { |
10740 ConsumeToken(); // Consume the kPERIOD token. | 10783 ConsumeToken(); // Consume the kPERIOD token. |
10741 ExpectIdentifier("identifier expected after '.'"); | 10784 ExpectIdentifier("identifier expected after '.'"); |
10742 } | 10785 } |
10743 } | 10786 } |
10744 | 10787 |
10745 } // namespace dart | 10788 } // namespace dart |
OLD | NEW |