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 "vm/bigint_operations.h" | 7 #include "vm/bigint_operations.h" |
8 #include "vm/class_finalizer.h" | 8 #include "vm/class_finalizer.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/compiler_stats.h" | 10 #include "vm/compiler_stats.h" |
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 | 518 |
519 class ClassDesc : public ValueObject { | 519 class ClassDesc : public ValueObject { |
520 public: | 520 public: |
521 ClassDesc(const Class& cls, | 521 ClassDesc(const Class& cls, |
522 const String& cls_name, | 522 const String& cls_name, |
523 bool is_interface, | 523 bool is_interface, |
524 intptr_t token_pos) | 524 intptr_t token_pos) |
525 : clazz_(cls), | 525 : clazz_(cls), |
526 class_name_(cls_name), | 526 class_name_(cls_name), |
527 is_interface_(is_interface), | 527 is_interface_(is_interface), |
| 528 is_abstract_(false), |
528 token_pos_(token_pos), | 529 token_pos_(token_pos), |
529 functions_(GrowableObjectArray::Handle(GrowableObjectArray::New())), | 530 functions_(GrowableObjectArray::Handle(GrowableObjectArray::New())), |
530 fields_(GrowableObjectArray::Handle(GrowableObjectArray::New())) { | 531 fields_(GrowableObjectArray::Handle(GrowableObjectArray::New())) { |
531 } | 532 } |
532 | 533 |
533 bool FunctionNameExists(const String& name, RawFunction::Kind kind) const { | 534 bool FunctionNameExists(const String& name, RawFunction::Kind kind) const { |
534 // First check if a function or field of same name exists. | 535 // First check if a function or field of same name exists. |
535 if (NameExists<Function>(functions_, name) || | 536 if (NameExists<Function>(functions_, name) || |
536 NameExists<Field>(fields_, name)) { | 537 NameExists<Field>(fields_, name)) { |
537 return true; | 538 return true; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
593 } | 594 } |
594 | 595 |
595 const String& class_name() const { | 596 const String& class_name() const { |
596 return class_name_; | 597 return class_name_; |
597 } | 598 } |
598 | 599 |
599 bool is_interface() const { | 600 bool is_interface() const { |
600 return is_interface_; | 601 return is_interface_; |
601 } | 602 } |
602 | 603 |
| 604 void set_is_abstract() { |
| 605 is_abstract_ = true; |
| 606 } |
| 607 |
| 608 bool is_abstract() const { |
| 609 return is_abstract_; |
| 610 } |
| 611 |
603 bool has_constructor() const { | 612 bool has_constructor() const { |
604 Function& func = Function::Handle(); | 613 Function& func = Function::Handle(); |
605 for (int i = 0; i < functions_.Length(); i++) { | 614 for (int i = 0; i < functions_.Length(); i++) { |
606 func ^= functions_.At(i); | 615 func ^= functions_.At(i); |
607 if (func.kind() == RawFunction::kConstructor) { | 616 if (func.kind() == RawFunction::kConstructor) { |
608 return true; | 617 return true; |
609 } | 618 } |
610 } | 619 } |
611 return false; | 620 return false; |
612 } | 621 } |
(...skipping 30 matching lines...) Expand all Loading... |
643 if (name.Equals(test_name)) { | 652 if (name.Equals(test_name)) { |
644 return true; | 653 return true; |
645 } | 654 } |
646 } | 655 } |
647 return false; | 656 return false; |
648 } | 657 } |
649 | 658 |
650 const Class& clazz_; | 659 const Class& clazz_; |
651 const String& class_name_; | 660 const String& class_name_; |
652 const bool is_interface_; | 661 const bool is_interface_; |
| 662 bool is_abstract_; |
653 intptr_t token_pos_; // Token index of "class" keyword. | 663 intptr_t token_pos_; // Token index of "class" keyword. |
654 GrowableObjectArray& functions_; | 664 GrowableObjectArray& functions_; |
655 GrowableObjectArray& fields_; | 665 GrowableObjectArray& fields_; |
656 GrowableArray<MemberDesc> members_; | 666 GrowableArray<MemberDesc> members_; |
657 }; | 667 }; |
658 | 668 |
659 | 669 |
660 struct TopLevel { | 670 struct TopLevel { |
661 TopLevel() : | 671 TopLevel() : |
662 fields(GrowableObjectArray::Handle(GrowableObjectArray::New())), | 672 fields(GrowableObjectArray::Handle(GrowableObjectArray::New())), |
(...skipping 1831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2494 } else if (method->IsConstructor() && method->has_const) { | 2504 } else if (method->IsConstructor() && method->has_const) { |
2495 ErrorMsg(method->name_pos, | 2505 ErrorMsg(method->name_pos, |
2496 "const constructor '%s' may not have a function body", | 2506 "const constructor '%s' may not have a function body", |
2497 method->name->ToCString()); | 2507 method->name->ToCString()); |
2498 } | 2508 } |
2499 if (method->redirect_name != NULL) { | 2509 if (method->redirect_name != NULL) { |
2500 ErrorMsg(method->name_pos, | 2510 ErrorMsg(method->name_pos, |
2501 "Constructor with redirection may not have a function body"); | 2511 "Constructor with redirection may not have a function body"); |
2502 } | 2512 } |
2503 ParseNativeDeclaration(); | 2513 ParseNativeDeclaration(); |
2504 } else if (CurrentToken() == Token::kSEMICOLON) { | 2514 } else { |
2505 if (members->is_interface() || | 2515 // We haven't found a method body. Issue error if one is required. |
2506 method->has_abstract || | 2516 const bool must_have_body = |
2507 method->has_external || | 2517 !members->is_interface() && |
2508 (method->redirect_name != NULL) || | 2518 method->has_static && !method->has_external; |
2509 method->IsConstructor()) { | 2519 if (must_have_body) { |
2510 ConsumeToken(); | |
2511 } else { | |
2512 ErrorMsg(method->name_pos, | 2520 ErrorMsg(method->name_pos, |
2513 "function body expected for method '%s'", | 2521 "function body expected for method '%s'", |
2514 method->name->ToCString()); | 2522 method->name->ToCString()); |
2515 } | 2523 } |
2516 } else { | 2524 |
2517 if (members->is_interface() || | 2525 if (CurrentToken() == Token::kSEMICOLON) { |
2518 method->has_abstract || | 2526 ConsumeToken(); |
2519 method->has_external || | 2527 if (!members->is_interface() && |
2520 (method->redirect_name != NULL) || | 2528 !method->has_static && |
2521 (method->IsConstructor() && method->has_const)) { | 2529 !method->has_external && |
2522 ExpectSemicolon(); | 2530 !method->IsConstructor()) { |
| 2531 // Methods, getters and setters without a body are |
| 2532 // implicitly abstract. |
| 2533 method->has_abstract = true; |
| 2534 } |
2523 } else { | 2535 } else { |
2524 ErrorMsg(method->name_pos, | 2536 // Signature is not followed by semicolon or body. Issue an |
2525 "function body expected for method '%s'", | 2537 // appropriate error. |
2526 method->name->ToCString()); | 2538 const bool must_have_semicolon = |
| 2539 members->is_interface() || |
| 2540 (method->redirect_name != NULL) || |
| 2541 (method->IsConstructor() && method->has_const) || |
| 2542 method->has_external; |
| 2543 if (must_have_semicolon) { |
| 2544 ExpectSemicolon(); |
| 2545 } else { |
| 2546 ErrorMsg(method->name_pos, |
| 2547 "function body or semicolon expected for method '%s'", |
| 2548 method->name->ToCString()); |
| 2549 } |
2527 } | 2550 } |
2528 } | 2551 } |
2529 | 2552 |
2530 RawFunction::Kind function_kind; | 2553 RawFunction::Kind function_kind; |
2531 if (method->IsFactoryOrConstructor()) { | 2554 if (method->IsFactoryOrConstructor()) { |
2532 function_kind = RawFunction::kConstructor; | 2555 function_kind = RawFunction::kConstructor; |
2533 } else if (method->IsGetter()) { | 2556 } else if (method->IsGetter()) { |
2534 function_kind = RawFunction::kGetterFunction; | 2557 function_kind = RawFunction::kGetterFunction; |
2535 } else if (method->IsSetter()) { | 2558 } else if (method->IsSetter()) { |
2536 function_kind = RawFunction::kSetterFunction; | 2559 function_kind = RawFunction::kSetterFunction; |
2537 } else { | 2560 } else { |
2538 function_kind = RawFunction::kRegularFunction; | 2561 function_kind = RawFunction::kRegularFunction; |
2539 } | 2562 } |
2540 Function& func = Function::Handle( | 2563 Function& func = Function::Handle( |
2541 Function::New(*method->name, | 2564 Function::New(*method->name, |
2542 function_kind, | 2565 function_kind, |
2543 method->has_static, | 2566 method->has_static, |
2544 method->has_const, | 2567 method->has_const, |
2545 method->has_abstract, | 2568 method->has_abstract, |
2546 method->has_external, | 2569 method->has_external, |
2547 current_class(), | 2570 current_class(), |
2548 method_pos)); | 2571 method_pos)); |
2549 func.set_result_type(*method->type); | 2572 func.set_result_type(*method->type); |
2550 func.set_end_token_pos(method_end_pos); | 2573 func.set_end_token_pos(method_end_pos); |
2551 | 2574 |
2552 // No need to resolve parameter types yet, or add parameters to local scope. | 2575 // No need to resolve parameter types yet, or add parameters to local scope. |
2553 ASSERT(is_top_level_); | 2576 ASSERT(is_top_level_); |
2554 AddFormalParamsToFunction(&method->params, func); | 2577 AddFormalParamsToFunction(&method->params, func); |
2555 members->AddFunction(func); | 2578 members->AddFunction(func); |
| 2579 if (method->has_abstract) { |
| 2580 members->set_is_abstract(); |
| 2581 } |
2556 } | 2582 } |
2557 | 2583 |
2558 | 2584 |
2559 void Parser::ParseFieldDefinition(ClassDesc* members, MemberDesc* field) { | 2585 void Parser::ParseFieldDefinition(ClassDesc* members, MemberDesc* field) { |
2560 TRACE_PARSER("ParseFieldDefinition"); | 2586 TRACE_PARSER("ParseFieldDefinition"); |
2561 // The parser has read the first field name and is now at the token | 2587 // The parser has read the first field name and is now at the token |
2562 // after the field name. | 2588 // after the field name. |
2563 ASSERT(CurrentToken() == Token::kSEMICOLON || | 2589 ASSERT(CurrentToken() == Token::kSEMICOLON || |
2564 CurrentToken() == Token::kCOMMA || | 2590 CurrentToken() == Token::kCOMMA || |
2565 CurrentToken() == Token::kASSIGN); | 2591 CurrentToken() == Token::kASSIGN); |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2949 } else { | 2975 } else { |
2950 UnexpectedToken(); | 2976 UnexpectedToken(); |
2951 } | 2977 } |
2952 current_member_ = NULL; | 2978 current_member_ = NULL; |
2953 members->AddMember(member); | 2979 members->AddMember(member); |
2954 } | 2980 } |
2955 | 2981 |
2956 | 2982 |
2957 void Parser::ParseClassDefinition(const GrowableObjectArray& pending_classes) { | 2983 void Parser::ParseClassDefinition(const GrowableObjectArray& pending_classes) { |
2958 TRACE_PARSER("ParseClassDefinition"); | 2984 TRACE_PARSER("ParseClassDefinition"); |
2959 const intptr_t class_pos = TokenPos(); | |
2960 bool is_patch = false; | 2985 bool is_patch = false; |
| 2986 bool is_abstract = false; |
2961 if (is_patch_source() && | 2987 if (is_patch_source() && |
2962 (CurrentToken() == Token::kIDENT) && | 2988 (CurrentToken() == Token::kIDENT) && |
2963 CurrentLiteral()->Equals("patch")) { | 2989 CurrentLiteral()->Equals("patch")) { |
2964 ConsumeToken(); | 2990 ConsumeToken(); |
2965 is_patch = true; | 2991 is_patch = true; |
| 2992 } else if (CurrentToken() == Token::kABSTRACT) { |
| 2993 is_abstract = true; |
| 2994 ConsumeToken(); |
2966 } | 2995 } |
| 2996 const intptr_t class_pos = TokenPos(); |
2967 ExpectToken(Token::kCLASS); | 2997 ExpectToken(Token::kCLASS); |
2968 const intptr_t classname_pos = TokenPos(); | 2998 const intptr_t classname_pos = TokenPos(); |
2969 String& class_name = *ExpectClassIdentifier("class name expected"); | 2999 String& class_name = *ExpectClassIdentifier("class name expected"); |
2970 if (FLAG_trace_parser) { | 3000 if (FLAG_trace_parser) { |
2971 OS::Print("TopLevel parsing class '%s'\n", class_name.ToCString()); | 3001 OS::Print("TopLevel parsing class '%s'\n", class_name.ToCString()); |
2972 } | 3002 } |
2973 Class& cls = Class::Handle(); | 3003 Class& cls = Class::Handle(); |
2974 Object& obj = Object::Handle(library_.LookupLocalObject(class_name)); | 3004 Object& obj = Object::Handle(library_.LookupLocalObject(class_name)); |
2975 if (obj.IsNull()) { | 3005 if (obj.IsNull()) { |
2976 if (is_patch) { | 3006 if (is_patch) { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3044 AddInterfaces(interfaces_pos, cls, interfaces); | 3074 AddInterfaces(interfaces_pos, cls, interfaces); |
3045 } | 3075 } |
3046 | 3076 |
3047 ExpectToken(Token::kLBRACE); | 3077 ExpectToken(Token::kLBRACE); |
3048 ClassDesc members(cls, class_name, false, class_pos); | 3078 ClassDesc members(cls, class_name, false, class_pos); |
3049 while (CurrentToken() != Token::kRBRACE) { | 3079 while (CurrentToken() != Token::kRBRACE) { |
3050 ParseClassMemberDefinition(&members); | 3080 ParseClassMemberDefinition(&members); |
3051 } | 3081 } |
3052 ExpectToken(Token::kRBRACE); | 3082 ExpectToken(Token::kRBRACE); |
3053 | 3083 |
| 3084 if (is_abstract || members.is_abstract()) { |
| 3085 cls.set_is_abstract(); |
| 3086 } |
| 3087 |
3054 // Add an implicit constructor if no explicit constructor is present. No | 3088 // Add an implicit constructor if no explicit constructor is present. No |
3055 // implicit constructors are needed for patch classes. | 3089 // implicit constructors are needed for patch classes. |
3056 if (!members.has_constructor() && !is_patch) { | 3090 if (!members.has_constructor() && !is_patch) { |
3057 AddImplicitConstructor(&members); | 3091 AddImplicitConstructor(&members); |
3058 } | 3092 } |
3059 CheckConstructorCycles(&members); | 3093 CheckConstructorCycles(&members); |
3060 | 3094 |
3061 Array& array = Array::Handle(); | 3095 Array& array = Array::Handle(); |
3062 array = Array::MakeArray(members.fields()); | 3096 array = Array::MakeArray(members.fields()); |
3063 cls.SetFields(array); | 3097 cls.SetFields(array); |
(...skipping 1030 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4094 set_current_class(Class::Handle()); // No current class. | 4128 set_current_class(Class::Handle()); // No current class. |
4095 if (CurrentToken() == Token::kCLASS) { | 4129 if (CurrentToken() == Token::kCLASS) { |
4096 ParseClassDefinition(pending_classes); | 4130 ParseClassDefinition(pending_classes); |
4097 } else if ((CurrentToken() == Token::kTYPEDEF) && | 4131 } else if ((CurrentToken() == Token::kTYPEDEF) && |
4098 (LookaheadToken(1) != Token::kLPAREN)) { | 4132 (LookaheadToken(1) != Token::kLPAREN)) { |
4099 ParseFunctionTypeAlias(pending_classes); | 4133 ParseFunctionTypeAlias(pending_classes); |
4100 } else if (CurrentToken() == Token::kINTERFACE) { | 4134 } else if (CurrentToken() == Token::kINTERFACE) { |
4101 ParseInterfaceDefinition(pending_classes); | 4135 ParseInterfaceDefinition(pending_classes); |
4102 } else if ((CurrentToken() == Token::kABSTRACT) && | 4136 } else if ((CurrentToken() == Token::kABSTRACT) && |
4103 (LookaheadToken(1) == Token::kCLASS)) { | 4137 (LookaheadToken(1) == Token::kCLASS)) { |
4104 ConsumeToken(); // Consume and ignore 'abstract'. | |
4105 ParseClassDefinition(pending_classes); | 4138 ParseClassDefinition(pending_classes); |
4106 } else if (is_patch_source() && IsLiteral("patch") && | 4139 } else if (is_patch_source() && IsLiteral("patch") && |
4107 (LookaheadToken(1) == Token::kCLASS)) { | 4140 (LookaheadToken(1) == Token::kCLASS)) { |
4108 ParseClassDefinition(pending_classes); | 4141 ParseClassDefinition(pending_classes); |
4109 } else { | 4142 } else { |
4110 set_current_class(toplevel_class); | 4143 set_current_class(toplevel_class); |
4111 if (IsVariableDeclaration()) { | 4144 if (IsVariableDeclaration()) { |
4112 ParseTopLevelVariable(&top_level); | 4145 ParseTopLevelVariable(&top_level); |
4113 } else if (IsFunctionDeclaration()) { | 4146 } else if (IsFunctionDeclaration()) { |
4114 ParseTopLevelFunction(&top_level); | 4147 ParseTopLevelFunction(&top_level); |
(...skipping 4423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8538 // In that case, we throw a dynamic type error instead of calling the | 8571 // In that case, we throw a dynamic type error instead of calling the |
8539 // constructor. | 8572 // constructor. |
8540 if (type.IsTypeParameter()) { | 8573 if (type.IsTypeParameter()) { |
8541 ErrorMsg(type_pos, | 8574 ErrorMsg(type_pos, |
8542 "type parameter '%s' cannot be instantiated", | 8575 "type parameter '%s' cannot be instantiated", |
8543 String::Handle(type.UserVisibleName()).ToCString()); | 8576 String::Handle(type.UserVisibleName()).ToCString()); |
8544 } | 8577 } |
8545 if (type.IsDynamicType()) { | 8578 if (type.IsDynamicType()) { |
8546 ErrorMsg(type_pos, "Dynamic cannot be instantiated"); | 8579 ErrorMsg(type_pos, "Dynamic cannot be instantiated"); |
8547 } | 8580 } |
8548 Class& type_class = Class::Handle(type.type_class()); | 8581 const Class& type_class = Class::Handle(type.type_class()); |
8549 String& type_class_name = String::Handle(type_class.Name()); | 8582 const String& type_class_name = String::Handle(type_class.Name()); |
8550 AbstractTypeArguments& type_arguments = | 8583 AbstractTypeArguments& type_arguments = |
8551 AbstractTypeArguments::ZoneHandle(type.arguments()); | 8584 AbstractTypeArguments::ZoneHandle(type.arguments()); |
8552 | 8585 |
8553 // The constructor class and its name are those of the parsed type, unless the | 8586 // The constructor class and its name are those of the parsed type, unless the |
8554 // parsed type is an interface and a default factory class is specified, in | 8587 // parsed type is an interface and a default factory class is specified, in |
8555 // which case constructor_class and constructor_class_name are modified below. | 8588 // which case constructor_class and constructor_class_name are modified below. |
8556 Class& constructor_class = Class::ZoneHandle(type_class.raw()); | 8589 Class& constructor_class = Class::ZoneHandle(type_class.raw()); |
8557 String& constructor_class_name = String::Handle(type_class_name.raw()); | 8590 String& constructor_class_name = String::Handle(type_class_name.raw()); |
8558 | 8591 |
8559 // The grammar allows for an optional ('.' identifier)? after the type, which | 8592 // The grammar allows for an optional ('.' identifier)? after the type, which |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8644 arguments_length -= 1; | 8677 arguments_length -= 1; |
8645 } | 8678 } |
8646 if (constructor.IsNull()) { | 8679 if (constructor.IsNull()) { |
8647 const String& external_constructor_name = | 8680 const String& external_constructor_name = |
8648 (named_constructor ? constructor_name : constructor_class_name); | 8681 (named_constructor ? constructor_name : constructor_class_name); |
8649 ErrorMsg(type_pos, | 8682 ErrorMsg(type_pos, |
8650 "class '%s' has no constructor or factory named '%s'", | 8683 "class '%s' has no constructor or factory named '%s'", |
8651 String::Handle(constructor_class.Name()).ToCString(), | 8684 String::Handle(constructor_class.Name()).ToCString(), |
8652 external_constructor_name.ToCString()); | 8685 external_constructor_name.ToCString()); |
8653 } | 8686 } |
| 8687 |
| 8688 // It is ok to call a factory method of an abstract class, but it is |
| 8689 // a dynamic error to instantiate an abstract class. |
| 8690 if (constructor_class.is_abstract() && !constructor.IsFactory()) { |
| 8691 ArgumentListNode* arguments = new ArgumentListNode(type_pos); |
| 8692 arguments->Add(new LiteralNode( |
| 8693 TokenPos(), Integer::ZoneHandle(Integer::New(type_pos)))); |
| 8694 arguments->Add(new LiteralNode( |
| 8695 TokenPos(), String::ZoneHandle(constructor_class_name.raw()))); |
| 8696 const String& cls_name = |
| 8697 String::Handle(Symbols::AbstractClassInstantiationError()); |
| 8698 const String& func_name = String::Handle(Symbols::ThrowNew()); |
| 8699 return MakeStaticCall(cls_name, func_name, arguments); |
| 8700 } |
| 8701 |
8654 String& error_message = String::Handle(); | 8702 String& error_message = String::Handle(); |
8655 if (!constructor.AreValidArguments(arguments_length, | 8703 if (!constructor.AreValidArguments(arguments_length, |
8656 arguments->names(), | 8704 arguments->names(), |
8657 &error_message)) { | 8705 &error_message)) { |
8658 const String& external_constructor_name = | 8706 const String& external_constructor_name = |
8659 (named_constructor ? constructor_name : constructor_class_name); | 8707 (named_constructor ? constructor_name : constructor_class_name); |
8660 ErrorMsg(call_pos, | 8708 ErrorMsg(call_pos, |
8661 "invalid arguments passed to constructor '%s' for class '%s': %s", | 8709 "invalid arguments passed to constructor '%s' for class '%s': %s", |
8662 external_constructor_name.ToCString(), | 8710 external_constructor_name.ToCString(), |
8663 String::Handle(constructor_class.Name()).ToCString(), | 8711 String::Handle(constructor_class.Name()).ToCString(), |
(...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9334 void Parser::SkipQualIdent() { | 9382 void Parser::SkipQualIdent() { |
9335 ASSERT(IsIdentifier()); | 9383 ASSERT(IsIdentifier()); |
9336 ConsumeToken(); | 9384 ConsumeToken(); |
9337 if (CurrentToken() == Token::kPERIOD) { | 9385 if (CurrentToken() == Token::kPERIOD) { |
9338 ConsumeToken(); // Consume the kPERIOD token. | 9386 ConsumeToken(); // Consume the kPERIOD token. |
9339 ExpectIdentifier("identifier expected after '.'"); | 9387 ExpectIdentifier("identifier expected after '.'"); |
9340 } | 9388 } |
9341 } | 9389 } |
9342 | 9390 |
9343 } // namespace dart | 9391 } // namespace dart |
OLD | NEW |