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

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

Issue 10899039: Add compiler error when instantiating abstract class (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') | tests/co19/co19-runtime.status » ('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 479 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 490
491 class ClassDesc : public ValueObject { 491 class ClassDesc : public ValueObject {
492 public: 492 public:
493 ClassDesc(const Class& cls, 493 ClassDesc(const Class& cls,
494 const String& cls_name, 494 const String& cls_name,
495 bool is_interface, 495 bool is_interface,
496 intptr_t token_pos) 496 intptr_t token_pos)
497 : clazz_(cls), 497 : clazz_(cls),
498 class_name_(cls_name), 498 class_name_(cls_name),
499 is_interface_(is_interface), 499 is_interface_(is_interface),
500 is_abstract_(false),
500 token_pos_(token_pos), 501 token_pos_(token_pos),
501 functions_(GrowableObjectArray::Handle(GrowableObjectArray::New())), 502 functions_(GrowableObjectArray::Handle(GrowableObjectArray::New())),
502 fields_(GrowableObjectArray::Handle(GrowableObjectArray::New())) { 503 fields_(GrowableObjectArray::Handle(GrowableObjectArray::New())) {
503 } 504 }
504 505
505 bool FunctionNameExists(const String& name, RawFunction::Kind kind) const { 506 bool FunctionNameExists(const String& name, RawFunction::Kind kind) const {
506 // First check if a function or field of same name exists. 507 // First check if a function or field of same name exists.
507 if (NameExists<Function>(functions_, name) || 508 if (NameExists<Function>(functions_, name) ||
508 NameExists<Field>(fields_, name)) { 509 NameExists<Field>(fields_, name)) {
509 return true; 510 return true;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
565 } 566 }
566 567
567 const String& class_name() const { 568 const String& class_name() const {
568 return class_name_; 569 return class_name_;
569 } 570 }
570 571
571 bool is_interface() const { 572 bool is_interface() const {
572 return is_interface_; 573 return is_interface_;
573 } 574 }
574 575
576 void set_is_abstract() {
577 is_abstract_ = true;
578 }
579
580 bool is_abstract() const {
581 return is_abstract_;
582 }
583
575 bool has_constructor() const { 584 bool has_constructor() const {
576 Function& func = Function::Handle(); 585 Function& func = Function::Handle();
577 for (int i = 0; i < functions_.Length(); i++) { 586 for (int i = 0; i < functions_.Length(); i++) {
578 func ^= functions_.At(i); 587 func ^= functions_.At(i);
579 if (func.kind() == RawFunction::kConstructor) { 588 if (func.kind() == RawFunction::kConstructor) {
580 return true; 589 return true;
581 } 590 }
582 } 591 }
583 return false; 592 return false;
584 } 593 }
(...skipping 30 matching lines...) Expand all
615 if (name.Equals(test_name)) { 624 if (name.Equals(test_name)) {
616 return true; 625 return true;
617 } 626 }
618 } 627 }
619 return false; 628 return false;
620 } 629 }
621 630
622 const Class& clazz_; 631 const Class& clazz_;
623 const String& class_name_; 632 const String& class_name_;
624 const bool is_interface_; 633 const bool is_interface_;
634 bool is_abstract_;
625 intptr_t token_pos_; // Token index of "class" keyword. 635 intptr_t token_pos_; // Token index of "class" keyword.
626 GrowableObjectArray& functions_; 636 GrowableObjectArray& functions_;
627 GrowableObjectArray& fields_; 637 GrowableObjectArray& fields_;
628 GrowableArray<MemberDesc> members_; 638 GrowableArray<MemberDesc> members_;
629 }; 639 };
630 640
631 641
632 struct TopLevel { 642 struct TopLevel {
633 TopLevel() : 643 TopLevel() :
634 fields(GrowableObjectArray::Handle(GrowableObjectArray::New())), 644 fields(GrowableObjectArray::Handle(GrowableObjectArray::New())),
(...skipping 1833 matching lines...) Expand 10 before | Expand all | Expand 10 after
2468 } else if (method->IsConstructor() && method->has_const) { 2478 } else if (method->IsConstructor() && method->has_const) {
2469 ErrorMsg(method->name_pos, 2479 ErrorMsg(method->name_pos,
2470 "const constructor '%s' may not have a function body", 2480 "const constructor '%s' may not have a function body",
2471 method->name->ToCString()); 2481 method->name->ToCString());
2472 } 2482 }
2473 if (method->redirect_name != NULL) { 2483 if (method->redirect_name != NULL) {
2474 ErrorMsg(method->name_pos, 2484 ErrorMsg(method->name_pos,
2475 "Constructor with redirection may not have a function body"); 2485 "Constructor with redirection may not have a function body");
2476 } 2486 }
2477 ParseNativeDeclaration(); 2487 ParseNativeDeclaration();
2478 } else if (CurrentToken() == Token::kSEMICOLON) { 2488 } else {
2479 if (members->is_interface() || 2489 // We haven't found a method body. Issue error if one is required.
2480 method->has_abstract || 2490 const bool must_have_body =
2481 method->has_external || 2491 !members->is_interface() &&
2482 (method->redirect_name != NULL) || 2492 method->has_static && !method->has_external;
2483 method->IsConstructor()) { 2493 if (must_have_body) {
2484 ConsumeToken();
2485 } else {
2486 ErrorMsg(method->name_pos, 2494 ErrorMsg(method->name_pos,
2487 "function body expected for method '%s'", 2495 "function body expected for method '%s'",
2488 method->name->ToCString()); 2496 method->name->ToCString());
2489 } 2497 }
2490 } else { 2498
2491 if (members->is_interface() || 2499 if (CurrentToken() == Token::kSEMICOLON) {
2492 method->has_abstract || 2500 ConsumeToken();
2493 method->has_external || 2501 if (!members->is_interface() &&
2494 (method->redirect_name != NULL) || 2502 !method->has_static &&
2495 (method->IsConstructor() && method->has_const)) { 2503 !method->has_external &&
2496 ExpectSemicolon(); 2504 !method->IsConstructor()) {
2505 // Methods, getters and setters without a body are
2506 // implicitly abstract.
2507 method->has_abstract = true;
2508 }
2497 } else { 2509 } else {
2498 ErrorMsg(method->name_pos, 2510 // Signature is not followed by semicolon or body. Issue an
2499 "function body expected for method '%s'", 2511 // appropriate error.
2500 method->name->ToCString()); 2512 const bool must_have_semicolon =
2513 members->is_interface() ||
2514 (method->redirect_name != NULL) ||
2515 (method->IsConstructor() && method->has_const) ||
2516 method->has_external;
2517 if (must_have_semicolon) {
2518 ExpectSemicolon();
2519 } else {
2520 ErrorMsg(method->name_pos,
2521 "function body or semicolon expected for method '%s'",
2522 method->name->ToCString());
2523 }
2501 } 2524 }
2502 } 2525 }
2503 2526
2504 RawFunction::Kind function_kind; 2527 RawFunction::Kind function_kind;
2505 if (method->IsFactoryOrConstructor()) { 2528 if (method->IsFactoryOrConstructor()) {
2506 function_kind = RawFunction::kConstructor; 2529 function_kind = RawFunction::kConstructor;
2507 } else if (method->IsGetter()) { 2530 } else if (method->IsGetter()) {
2508 function_kind = RawFunction::kGetterFunction; 2531 function_kind = RawFunction::kGetterFunction;
2509 } else if (method->IsSetter()) { 2532 } else if (method->IsSetter()) {
2510 function_kind = RawFunction::kSetterFunction; 2533 function_kind = RawFunction::kSetterFunction;
2511 } else { 2534 } else {
2512 function_kind = RawFunction::kRegularFunction; 2535 function_kind = RawFunction::kRegularFunction;
2513 } 2536 }
2514 Function& func = Function::Handle( 2537 Function& func = Function::Handle(
2515 Function::New(*method->name, 2538 Function::New(*method->name,
2516 function_kind, 2539 function_kind,
2517 method->has_static, 2540 method->has_static,
2518 method->has_const, 2541 method->has_const,
2519 method->has_abstract, 2542 method->has_abstract,
2520 method->has_external, 2543 method->has_external,
2521 current_class(), 2544 current_class(),
2522 method_pos)); 2545 method_pos));
2523 func.set_result_type(*method->type); 2546 func.set_result_type(*method->type);
2524 func.set_end_token_pos(method_end_pos); 2547 func.set_end_token_pos(method_end_pos);
2525 2548
2526 // No need to resolve parameter types yet, or add parameters to local scope. 2549 // No need to resolve parameter types yet, or add parameters to local scope.
2527 ASSERT(is_top_level_); 2550 ASSERT(is_top_level_);
2528 AddFormalParamsToFunction(&method->params, func); 2551 AddFormalParamsToFunction(&method->params, func);
2529 members->AddFunction(func); 2552 members->AddFunction(func);
2553 if (method->has_abstract) {
2554 members->set_is_abstract();
2555 }
2530 } 2556 }
2531 2557
2532 2558
2533 void Parser::ParseFieldDefinition(ClassDesc* members, MemberDesc* field) { 2559 void Parser::ParseFieldDefinition(ClassDesc* members, MemberDesc* field) {
2534 TRACE_PARSER("ParseFieldDefinition"); 2560 TRACE_PARSER("ParseFieldDefinition");
2535 // The parser has read the first field name and is now at the token 2561 // The parser has read the first field name and is now at the token
2536 // after the field name. 2562 // after the field name.
2537 ASSERT(CurrentToken() == Token::kSEMICOLON || 2563 ASSERT(CurrentToken() == Token::kSEMICOLON ||
2538 CurrentToken() == Token::kCOMMA || 2564 CurrentToken() == Token::kCOMMA ||
2539 CurrentToken() == Token::kASSIGN); 2565 CurrentToken() == Token::kASSIGN);
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
2923 } else { 2949 } else {
2924 UnexpectedToken(); 2950 UnexpectedToken();
2925 } 2951 }
2926 current_member_ = NULL; 2952 current_member_ = NULL;
2927 members->AddMember(member); 2953 members->AddMember(member);
2928 } 2954 }
2929 2955
2930 2956
2931 void Parser::ParseClassDefinition(const GrowableObjectArray& pending_classes) { 2957 void Parser::ParseClassDefinition(const GrowableObjectArray& pending_classes) {
2932 TRACE_PARSER("ParseClassDefinition"); 2958 TRACE_PARSER("ParseClassDefinition");
2933 const intptr_t class_pos = TokenPos();
2934 bool is_patch = false; 2959 bool is_patch = false;
2960 bool is_abstract = false;
2935 if (is_patch_source() && 2961 if (is_patch_source() &&
2936 (CurrentToken() == Token::kIDENT) && 2962 (CurrentToken() == Token::kIDENT) &&
2937 CurrentLiteral()->Equals("patch")) { 2963 CurrentLiteral()->Equals("patch")) {
2938 ConsumeToken(); 2964 ConsumeToken();
2939 is_patch = true; 2965 is_patch = true;
2966 } else if (CurrentToken() == Token::kABSTRACT) {
2967 is_abstract = true;
2968 ConsumeToken();
2940 } 2969 }
2970 const intptr_t class_pos = TokenPos();
2941 ExpectToken(Token::kCLASS); 2971 ExpectToken(Token::kCLASS);
2942 const intptr_t classname_pos = TokenPos(); 2972 const intptr_t classname_pos = TokenPos();
2943 String& class_name = *ExpectClassIdentifier("class name expected"); 2973 String& class_name = *ExpectClassIdentifier("class name expected");
2944 if (FLAG_trace_parser) { 2974 if (FLAG_trace_parser) {
2945 OS::Print("TopLevel parsing class '%s'\n", class_name.ToCString()); 2975 OS::Print("TopLevel parsing class '%s'\n", class_name.ToCString());
2946 } 2976 }
2947 Class& cls = Class::Handle(); 2977 Class& cls = Class::Handle();
2948 Object& obj = Object::Handle(library_.LookupLocalObject(class_name)); 2978 Object& obj = Object::Handle(library_.LookupLocalObject(class_name));
2949 if (obj.IsNull()) { 2979 if (obj.IsNull()) {
2950 if (is_patch) { 2980 if (is_patch) {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
3018 AddInterfaces(interfaces_pos, cls, interfaces); 3048 AddInterfaces(interfaces_pos, cls, interfaces);
3019 } 3049 }
3020 3050
3021 ExpectToken(Token::kLBRACE); 3051 ExpectToken(Token::kLBRACE);
3022 ClassDesc members(cls, class_name, false, class_pos); 3052 ClassDesc members(cls, class_name, false, class_pos);
3023 while (CurrentToken() != Token::kRBRACE) { 3053 while (CurrentToken() != Token::kRBRACE) {
3024 ParseClassMemberDefinition(&members); 3054 ParseClassMemberDefinition(&members);
3025 } 3055 }
3026 ExpectToken(Token::kRBRACE); 3056 ExpectToken(Token::kRBRACE);
3027 3057
3058 if (is_abstract || members.is_abstract()) {
3059 cls.set_is_abstract();
3060 }
3061
3028 // Add an implicit constructor if no explicit constructor is present. No 3062 // Add an implicit constructor if no explicit constructor is present. No
3029 // implicit constructors are needed for patch classes. 3063 // implicit constructors are needed for patch classes.
3030 if (!members.has_constructor() && !is_patch) { 3064 if (!members.has_constructor() && !is_patch) {
3031 AddImplicitConstructor(&members); 3065 AddImplicitConstructor(&members);
3032 } 3066 }
3033 CheckConstructorCycles(&members); 3067 CheckConstructorCycles(&members);
3034 3068
3035 Array& array = Array::Handle(); 3069 Array& array = Array::Handle();
3036 array = Array::MakeArray(members.fields()); 3070 array = Array::MakeArray(members.fields());
3037 cls.SetFields(array); 3071 cls.SetFields(array);
(...skipping 1028 matching lines...) Expand 10 before | Expand all | Expand 10 after
4066 set_current_class(Class::Handle()); // No current class. 4100 set_current_class(Class::Handle()); // No current class.
4067 if (CurrentToken() == Token::kCLASS) { 4101 if (CurrentToken() == Token::kCLASS) {
4068 ParseClassDefinition(pending_classes); 4102 ParseClassDefinition(pending_classes);
4069 } else if ((CurrentToken() == Token::kTYPEDEF) && 4103 } else if ((CurrentToken() == Token::kTYPEDEF) &&
4070 (LookaheadToken(1) != Token::kLPAREN)) { 4104 (LookaheadToken(1) != Token::kLPAREN)) {
4071 ParseFunctionTypeAlias(pending_classes); 4105 ParseFunctionTypeAlias(pending_classes);
4072 } else if (CurrentToken() == Token::kINTERFACE) { 4106 } else if (CurrentToken() == Token::kINTERFACE) {
4073 ParseInterfaceDefinition(pending_classes); 4107 ParseInterfaceDefinition(pending_classes);
4074 } else if ((CurrentToken() == Token::kABSTRACT) && 4108 } else if ((CurrentToken() == Token::kABSTRACT) &&
4075 (LookaheadToken(1) == Token::kCLASS)) { 4109 (LookaheadToken(1) == Token::kCLASS)) {
4076 ConsumeToken(); // Consume and ignore 'abstract'.
4077 ParseClassDefinition(pending_classes); 4110 ParseClassDefinition(pending_classes);
4078 } else if (is_patch_source() && IsLiteral("patch") && 4111 } else if (is_patch_source() && IsLiteral("patch") &&
4079 (LookaheadToken(1) == Token::kCLASS)) { 4112 (LookaheadToken(1) == Token::kCLASS)) {
4080 ParseClassDefinition(pending_classes); 4113 ParseClassDefinition(pending_classes);
4081 } else { 4114 } else {
4082 set_current_class(toplevel_class); 4115 set_current_class(toplevel_class);
4083 if (IsVariableDeclaration()) { 4116 if (IsVariableDeclaration()) {
4084 ParseTopLevelVariable(&top_level); 4117 ParseTopLevelVariable(&top_level);
4085 } else if (IsFunctionDeclaration()) { 4118 } else if (IsFunctionDeclaration()) {
4086 ParseTopLevelFunction(&top_level); 4119 ParseTopLevelFunction(&top_level);
(...skipping 4362 matching lines...) Expand 10 before | Expand all | Expand 10 after
8449 // In that case, we throw a dynamic type error instead of calling the 8482 // In that case, we throw a dynamic type error instead of calling the
8450 // constructor. 8483 // constructor.
8451 if (type.IsTypeParameter()) { 8484 if (type.IsTypeParameter()) {
8452 ErrorMsg(type_pos, 8485 ErrorMsg(type_pos,
8453 "type parameter '%s' cannot be instantiated", 8486 "type parameter '%s' cannot be instantiated",
8454 String::Handle(type.UserVisibleName()).ToCString()); 8487 String::Handle(type.UserVisibleName()).ToCString());
8455 } 8488 }
8456 if (type.IsDynamicType()) { 8489 if (type.IsDynamicType()) {
8457 ErrorMsg(type_pos, "Dynamic cannot be instantiated"); 8490 ErrorMsg(type_pos, "Dynamic cannot be instantiated");
8458 } 8491 }
8459 Class& type_class = Class::Handle(type.type_class()); 8492 const Class& type_class = Class::Handle(type.type_class());
8460 String& type_class_name = String::Handle(type_class.Name()); 8493 const String& type_class_name = String::Handle(type_class.Name());
8461 AbstractTypeArguments& type_arguments = 8494 AbstractTypeArguments& type_arguments =
8462 AbstractTypeArguments::ZoneHandle(type.arguments()); 8495 AbstractTypeArguments::ZoneHandle(type.arguments());
8463 8496
8464 // The constructor class and its name are those of the parsed type, unless the 8497 // The constructor class and its name are those of the parsed type, unless the
8465 // parsed type is an interface and a default factory class is specified, in 8498 // parsed type is an interface and a default factory class is specified, in
8466 // which case constructor_class and constructor_class_name are modified below. 8499 // which case constructor_class and constructor_class_name are modified below.
8467 Class& constructor_class = Class::ZoneHandle(type_class.raw()); 8500 Class& constructor_class = Class::ZoneHandle(type_class.raw());
8468 String& constructor_class_name = String::Handle(type_class_name.raw()); 8501 String& constructor_class_name = String::Handle(type_class_name.raw());
8469 8502
8470 // The grammar allows for an optional ('.' identifier)? after the type, which 8503 // The grammar allows for an optional ('.' identifier)? after the type, which
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
8555 arguments_length -= 1; 8588 arguments_length -= 1;
8556 } 8589 }
8557 if (constructor.IsNull()) { 8590 if (constructor.IsNull()) {
8558 const String& external_constructor_name = 8591 const String& external_constructor_name =
8559 (named_constructor ? constructor_name : constructor_class_name); 8592 (named_constructor ? constructor_name : constructor_class_name);
8560 ErrorMsg(type_pos, 8593 ErrorMsg(type_pos,
8561 "class '%s' has no constructor or factory named '%s'", 8594 "class '%s' has no constructor or factory named '%s'",
8562 String::Handle(constructor_class.Name()).ToCString(), 8595 String::Handle(constructor_class.Name()).ToCString(),
8563 external_constructor_name.ToCString()); 8596 external_constructor_name.ToCString());
8564 } 8597 }
8598
8599 // It is ok to call a factory method of an abstract class, but it is
8600 // an error to instantiate an abstract class.
8601 if (constructor_class.is_abstract() && !constructor.IsFactory()) {
8602 ErrorMsg(type_pos, "Cannot instantiate abstract class %s",
8603 constructor_class_name.ToCString());
8604 }
8605
8565 String& error_message = String::Handle(); 8606 String& error_message = String::Handle();
8566 if (!constructor.AreValidArguments(arguments_length, 8607 if (!constructor.AreValidArguments(arguments_length,
8567 arguments->names(), 8608 arguments->names(),
8568 &error_message)) { 8609 &error_message)) {
8569 const String& external_constructor_name = 8610 const String& external_constructor_name =
8570 (named_constructor ? constructor_name : constructor_class_name); 8611 (named_constructor ? constructor_name : constructor_class_name);
8571 ErrorMsg(call_pos, 8612 ErrorMsg(call_pos,
8572 "invalid arguments passed to constructor '%s' for class '%s': %s", 8613 "invalid arguments passed to constructor '%s' for class '%s': %s",
8573 external_constructor_name.ToCString(), 8614 external_constructor_name.ToCString(),
8574 String::Handle(constructor_class.Name()).ToCString(), 8615 String::Handle(constructor_class.Name()).ToCString(),
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after
9240 void Parser::SkipQualIdent() { 9281 void Parser::SkipQualIdent() {
9241 ASSERT(IsIdentifier()); 9282 ASSERT(IsIdentifier());
9242 ConsumeToken(); 9283 ConsumeToken();
9243 if (CurrentToken() == Token::kPERIOD) { 9284 if (CurrentToken() == Token::kPERIOD) {
9244 ConsumeToken(); // Consume the kPERIOD token. 9285 ConsumeToken(); // Consume the kPERIOD token.
9245 ExpectIdentifier("identifier expected after '.'"); 9286 ExpectIdentifier("identifier expected after '.'");
9246 } 9287 }
9247 } 9288 }
9248 9289
9249 } // namespace dart 9290 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.cc ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698