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

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

Issue 11414019: Disallow const native factories (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 1 month 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 | « no previous file | tests/language/const_native_factory_test.dart » ('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 2421 matching lines...) Expand 10 before | Expand all | Expand 10 after
2432 ErrorMsg(method->name_pos, "keyword var not allowed for methods"); 2432 ErrorMsg(method->name_pos, "keyword var not allowed for methods");
2433 } 2433 }
2434 if (method->has_final) { 2434 if (method->has_final) {
2435 ErrorMsg(method->name_pos, "'final' not allowed for methods"); 2435 ErrorMsg(method->name_pos, "'final' not allowed for methods");
2436 } 2436 }
2437 if (method->has_abstract && method->has_static) { 2437 if (method->has_abstract && method->has_static) {
2438 ErrorMsg(method->name_pos, 2438 ErrorMsg(method->name_pos,
2439 "static method '%s' cannot be abstract", 2439 "static method '%s' cannot be abstract",
2440 method->name->ToCString()); 2440 method->name->ToCString());
2441 } 2441 }
2442 if (method->has_const && !(method->IsConstructor() || method->IsFactory())) { 2442 if (method->has_const && !method->IsFactoryOrConstructor()) {
2443 ErrorMsg(method->name_pos, "'const' not allowed for methods"); 2443 ErrorMsg(method->name_pos, "'const' not allowed for methods");
2444 } 2444 }
2445 if (method->IsFactoryOrConstructor() && method->has_abstract) { 2445 if (method->has_abstract && method->IsFactoryOrConstructor()) {
2446 ErrorMsg(method->name_pos, "constructor cannot be abstract"); 2446 ErrorMsg(method->name_pos, "constructor cannot be abstract");
2447 } 2447 }
2448 if (method->IsConstructor() && method->has_const) { 2448 if (method->has_const && method->IsConstructor()) {
2449 Class& cls = Class::Handle(library_.LookupClass(members->class_name())); 2449 Class& cls = Class::Handle(library_.LookupClass(members->class_name()));
2450 cls.set_is_const(); 2450 cls.set_is_const();
2451 } 2451 }
2452 if (method->has_abstract && members->is_interface()) { 2452 if (method->has_abstract && members->is_interface()) {
2453 ErrorMsg(method->name_pos, 2453 ErrorMsg(method->name_pos,
2454 "'abstract' method only allowed in class definition"); 2454 "'abstract' method only allowed in class definition");
2455 } 2455 }
2456 if (method->has_external && members->is_interface()) { 2456 if (method->has_external && members->is_interface()) {
2457 ErrorMsg(method->name_pos, 2457 ErrorMsg(method->name_pos,
2458 "'external' method only allowed in class definition"); 2458 "'external' method only allowed in class definition");
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
2605 if ((CurrentToken() == Token::kLBRACE) || 2605 if ((CurrentToken() == Token::kLBRACE) ||
2606 (CurrentToken() == Token::kARROW)) { 2606 (CurrentToken() == Token::kARROW)) {
2607 if (method->has_abstract) { 2607 if (method->has_abstract) {
2608 ErrorMsg(method->name_pos, 2608 ErrorMsg(method->name_pos,
2609 "abstract method '%s' may not have a function body", 2609 "abstract method '%s' may not have a function body",
2610 method->name->ToCString()); 2610 method->name->ToCString());
2611 } else if (method->has_external) { 2611 } else if (method->has_external) {
2612 ErrorMsg(method->name_pos, 2612 ErrorMsg(method->name_pos,
2613 "external method '%s' may not have a function body", 2613 "external method '%s' may not have a function body",
2614 method->name->ToCString()); 2614 method->name->ToCString());
2615 } else if (method->IsConstructor() && method->has_const) { 2615 } else if (method->IsFactoryOrConstructor() && method->has_const) {
2616 ErrorMsg(method->name_pos, 2616 ErrorMsg(method->name_pos,
2617 "const constructor '%s' may not have a function body", 2617 "const constructor or factory '%s' may not have a function body",
2618 method->name->ToCString());
2619 } else if (method->IsFactory() && method->has_const) {
2620 ErrorMsg(method->name_pos,
2621 "const factory '%s' may not have a function body",
2622 method->name->ToCString()); 2618 method->name->ToCString());
2623 } else if (members->is_interface()) { 2619 } else if (members->is_interface()) {
2624 ErrorMsg(method->name_pos, 2620 ErrorMsg(method->name_pos,
2625 "function body not allowed in interface declaration"); 2621 "function body not allowed in interface declaration");
2626 } 2622 }
2627 if (method->redirect_name != NULL) { 2623 if (method->redirect_name != NULL) {
2628 ErrorMsg(method->name_pos, 2624 ErrorMsg(method->name_pos,
2629 "Constructor with redirection may not have a function body"); 2625 "Constructor with redirection may not have a function body");
2630 } 2626 }
2631 if (CurrentToken() == Token::kLBRACE) { 2627 if (CurrentToken() == Token::kLBRACE) {
2632 SkipBlock(); 2628 SkipBlock();
2633 } else { 2629 } else {
2634 ConsumeToken(); 2630 ConsumeToken();
2635 SkipExpr(); 2631 SkipExpr();
2636 ExpectSemicolon(); 2632 ExpectSemicolon();
2637 } 2633 }
2638 method_end_pos = TokenPos(); 2634 method_end_pos = TokenPos();
2639 } else if (IsLiteral("native")) { 2635 } else if (IsLiteral("native")) {
2640 if (method->has_abstract) { 2636 if (method->has_abstract) {
2641 ErrorMsg(method->name_pos, 2637 ErrorMsg(method->name_pos,
2642 "abstract method '%s' may not have a function body", 2638 "abstract method '%s' may not have a function body",
2643 method->name->ToCString()); 2639 method->name->ToCString());
2644 } else if (members->is_interface()) { 2640 } else if (members->is_interface()) {
2645 ErrorMsg(method->name_pos, 2641 ErrorMsg(method->name_pos,
2646 "function body not allowed in interface declaration"); 2642 "function body not allowed in interface declaration");
2647 } else if (method->IsConstructor() && method->has_const) { 2643 } else if (method->IsFactoryOrConstructor() && method->has_const) {
2648 ErrorMsg(method->name_pos, 2644 ErrorMsg(method->name_pos,
2649 "const constructor '%s' may not have a function body", 2645 "const constructor or factory '%s' may not be native",
2650 method->name->ToCString()); 2646 method->name->ToCString());
2651 } 2647 }
2652 if (method->redirect_name != NULL) { 2648 if (method->redirect_name != NULL) {
2653 ErrorMsg(method->name_pos, 2649 ErrorMsg(method->name_pos,
2654 "Constructor with redirection may not have a function body"); 2650 "Constructor with redirection may not have a function body");
2655 } 2651 }
2656 ParseNativeDeclaration(); 2652 ParseNativeDeclaration();
2657 } else { 2653 } else {
2658 // We haven't found a method body. Issue error if one is required. 2654 // We haven't found a method body. Issue error if one is required.
2659 const bool must_have_body = 2655 const bool must_have_body =
(...skipping 5433 matching lines...) Expand 10 before | Expand all | Expand 10 after
8093 8089
8094 8090
8095 RawObject* Parser::EvaluateConstConstructorCall( 8091 RawObject* Parser::EvaluateConstConstructorCall(
8096 const Class& type_class, 8092 const Class& type_class,
8097 const AbstractTypeArguments& type_arguments, 8093 const AbstractTypeArguments& type_arguments,
8098 const Function& constructor, 8094 const Function& constructor,
8099 ArgumentListNode* arguments) { 8095 ArgumentListNode* arguments) {
8100 // +2 for implicit receiver and construction phase arguments. 8096 // +2 for implicit receiver and construction phase arguments.
8101 GrowableArray<const Object*> arg_values(arguments->length() + 2); 8097 GrowableArray<const Object*> arg_values(arguments->length() + 2);
8102 Instance& instance = Instance::Handle(); 8098 Instance& instance = Instance::Handle();
8103 if (!constructor.IsFactory()) { 8099 ASSERT(!constructor.IsFactory());
8104 instance = Instance::New(type_class, Heap::kOld); 8100 instance = Instance::New(type_class, Heap::kOld);
8105 if (!type_arguments.IsNull()) { 8101 if (!type_arguments.IsNull()) {
8106 if (!type_arguments.IsInstantiated()) { 8102 if (!type_arguments.IsInstantiated()) {
8107 ErrorMsg("type must be constant in const constructor"); 8103 ErrorMsg("type must be constant in const constructor");
8108 }
8109 instance.SetTypeArguments(
8110 AbstractTypeArguments::Handle(type_arguments.Canonicalize()));
8111 } 8104 }
8112 arg_values.Add(&instance); 8105 instance.SetTypeArguments(
8113 arg_values.Add(&Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); 8106 AbstractTypeArguments::Handle(type_arguments.Canonicalize()));
8114 } else {
8115 // Prepend type_arguments to list of arguments to factory.
8116 ASSERT(type_arguments.IsZoneHandle());
8117 arg_values.Add(&type_arguments);
8118 } 8107 }
8108 arg_values.Add(&instance);
8109 arg_values.Add(&Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll)));
8119 for (int i = 0; i < arguments->length(); i++) { 8110 for (int i = 0; i < arguments->length(); i++) {
8120 AstNode* arg = arguments->NodeAt(i); 8111 AstNode* arg = arguments->NodeAt(i);
8121 // Arguments have been evaluated to a literal value already. 8112 // Arguments have been evaluated to a literal value already.
8122 ASSERT(arg->IsLiteralNode()); 8113 ASSERT(arg->IsLiteralNode());
8123 arg_values.Add(&arg->AsLiteralNode()->literal()); 8114 arg_values.Add(&arg->AsLiteralNode()->literal());
8124 } 8115 }
8125 const Array& opt_arg_names = arguments->names(); 8116 const Array& opt_arg_names = arguments->names();
8126 const Object& result = Object::Handle( 8117 const Object& result = Object::Handle(
8127 DartEntry::InvokeStatic(constructor, arg_values, opt_arg_names)); 8118 DartEntry::InvokeStatic(constructor, arg_values, opt_arg_names));
8128 if (result.IsError()) { 8119 if (result.IsError()) {
8129 if (result.IsUnhandledException()) { 8120 if (result.IsUnhandledException()) {
8130 return result.raw(); 8121 return result.raw();
8131 } else { 8122 } else {
8132 Isolate::Current()->long_jump_base()->Jump(1, Error::Cast(result)); 8123 Isolate::Current()->long_jump_base()->Jump(1, Error::Cast(result));
8133 UNREACHABLE(); 8124 UNREACHABLE();
8134 return Object::null(); 8125 return Object::null();
8135 } 8126 }
8136 } else { 8127 } else {
8137 if (constructor.IsFactory()) {
8138 // The factory method returns the allocated object.
8139 instance ^= result.raw();
8140 }
8141 if (!instance.IsNull()) { 8128 if (!instance.IsNull()) {
8142 instance ^= instance.Canonicalize(); 8129 instance ^= instance.Canonicalize();
8143 } 8130 }
8144 return instance.raw(); 8131 return instance.raw();
8145 } 8132 }
8146 } 8133 }
8147 8134
8148 8135
8149 // Do a lookup for the identifier in the block scope and the class scope 8136 // Do a lookup for the identifier in the block scope and the class scope
8150 // return true if the identifier is found, false otherwise. 8137 // return true if the identifier is found, false otherwise.
(...skipping 1860 matching lines...) Expand 10 before | Expand all | Expand 10 after
10011 void Parser::SkipQualIdent() { 9998 void Parser::SkipQualIdent() {
10012 ASSERT(IsIdentifier()); 9999 ASSERT(IsIdentifier());
10013 ConsumeToken(); 10000 ConsumeToken();
10014 if (CurrentToken() == Token::kPERIOD) { 10001 if (CurrentToken() == Token::kPERIOD) {
10015 ConsumeToken(); // Consume the kPERIOD token. 10002 ConsumeToken(); // Consume the kPERIOD token.
10016 ExpectIdentifier("identifier expected after '.'"); 10003 ExpectIdentifier("identifier expected after '.'");
10017 } 10004 }
10018 } 10005 }
10019 10006
10020 } // namespace dart 10007 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | tests/language/const_native_factory_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698