Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(166)

Side by Side Diff: runtime/vm/parser.cc

Issue 10916039: Throw AbstractClassInstantiationError if an abstract class is instantiated (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/object.cc ('k') | runtime/vm/symbols.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/object.cc ('k') | runtime/vm/symbols.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698