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

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

Issue 10689083: Compile an instance setter call when a static getter is declared, but no field (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 5 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/ast.cc ('k') | tests/language/getter_no_setter_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 732 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 } 743 }
744 parsed_function->SetNodeSequence(node_sequence); 744 parsed_function->SetNodeSequence(node_sequence);
745 745
746 // The instantiator may be required at run time for generic type checks or 746 // The instantiator may be required at run time for generic type checks or
747 // allocation of generic types. 747 // allocation of generic types.
748 if (parser.IsInstantiatorRequired()) { 748 if (parser.IsInstantiatorRequired()) {
749 // In the case of a local function, only set the instantiator if the 749 // In the case of a local function, only set the instantiator if the
750 // receiver was captured. 750 // receiver was captured.
751 const bool kTestOnly = true; 751 const bool kTestOnly = true;
752 LocalVariable* receiver = 752 LocalVariable* receiver =
753 parser.LookupReceiver(node_sequence->scope(), 753 parser.LookupReceiver(node_sequence->scope(), kTestOnly);
754 kTestOnly);
755 if (!parser.current_function().IsLocalFunction() || 754 if (!parser.current_function().IsLocalFunction() ||
756 ((receiver != NULL) && receiver->is_captured())) { 755 ((receiver != NULL) && receiver->is_captured())) {
757 parsed_function->set_instantiator( 756 parsed_function->set_instantiator(
758 new LoadLocalNode(node_sequence->token_pos(), *receiver)); 757 new LoadLocalNode(node_sequence->token_pos(), *receiver));
759 } 758 }
760 } 759 }
761 760
762 parsed_function->set_default_parameter_values(default_parameter_values); 761 parsed_function->set_default_parameter_values(default_parameter_values);
763 isolate->set_ast_node_id(prev_ast_node_id); 762 isolate->set_ast_node_id(prev_ast_node_id);
764 } 763 }
(...skipping 3255 matching lines...) Expand 10 before | Expand all | Expand 10 after
4020 if (native_function == NULL) { 4019 if (native_function == NULL) {
4021 ErrorMsg(native_pos, "native function '%s' cannot be found", 4020 ErrorMsg(native_pos, "native function '%s' cannot be found",
4022 native_name.ToCString()); 4021 native_name.ToCString());
4023 } 4022 }
4024 4023
4025 const bool has_opt_params = (params->num_optional_parameters > 0); 4024 const bool has_opt_params = (params->num_optional_parameters > 0);
4026 4025
4027 // Now add the NativeBodyNode and return statement. 4026 // Now add the NativeBodyNode and return statement.
4028 current_block_->statements->Add( 4027 current_block_->statements->Add(
4029 new ReturnNode(TokenPos(), new NativeBodyNode(TokenPos(), 4028 new ReturnNode(TokenPos(), new NativeBodyNode(TokenPos(),
4030 native_name, 4029 native_name,
4031 native_function, 4030 native_function,
4032 num_parameters, 4031 num_parameters,
4033 has_opt_params, 4032 has_opt_params,
4034 is_instance_closure))); 4033 is_instance_closure)));
4035 } 4034 }
4036 4035
4037 4036
4038 LocalVariable* Parser::LookupReceiver(LocalScope* from_scope, 4037 LocalVariable* Parser::LookupReceiver(LocalScope* from_scope, bool test_only) {
4039 bool test_only) {
4040 const String& this_name = String::Handle(String::NewSymbol(kThisName)); 4038 const String& this_name = String::Handle(String::NewSymbol(kThisName));
4041 return from_scope->LookupVariable(this_name, test_only); 4039 return from_scope->LookupVariable(this_name, test_only);
4042 } 4040 }
4043 4041
4044 4042
4045 LocalVariable* Parser::LookupPhaseParameter() { 4043 LocalVariable* Parser::LookupPhaseParameter() {
4046 const String& phase_name = 4044 const String& phase_name =
4047 String::Handle(String::NewSymbol(kPhaseParameterName)); 4045 String::Handle(String::NewSymbol(kPhaseParameterName));
4048 const bool kTestOnly = false; 4046 const bool kTestOnly = false;
4049 return current_block_->scope->LookupVariable(phase_name, kTestOnly); 4047 return current_block_->scope->LookupVariable(phase_name, kTestOnly);
(...skipping 2353 matching lines...) Expand 10 before | Expand all | Expand 10 after
6403 const Array& kNoArgumentNames = Array::Handle(); 6401 const Array& kNoArgumentNames = Array::Handle();
6404 func = Resolver::ResolveStatic(cls, 6402 func = Resolver::ResolveStatic(cls,
6405 getter_name, 6403 getter_name,
6406 kNumArguments, 6404 kNumArguments,
6407 kNoArgumentNames, 6405 kNoArgumentNames,
6408 Resolver::kIsQualified); 6406 Resolver::kIsQualified);
6409 if (!func.IsNull()) { 6407 if (!func.IsNull()) {
6410 ASSERT(func.kind() != RawFunction::kConstImplicitGetter); 6408 ASSERT(func.kind() != RawFunction::kConstImplicitGetter);
6411 EnsureExpressionTemp(); 6409 EnsureExpressionTemp();
6412 closure = new StaticGetterNode(call_pos, 6410 closure = new StaticGetterNode(call_pos,
6411 NULL,
6413 Class::ZoneHandle(cls.raw()), 6412 Class::ZoneHandle(cls.raw()),
6414 func_name); 6413 func_name);
6415 return new ClosureCallNode(call_pos, closure, arguments); 6414 return new ClosureCallNode(call_pos, closure, arguments);
6416 } 6415 }
6417 } else { 6416 } else {
6418 EnsureExpressionTemp(); 6417 EnsureExpressionTemp();
6419 closure = GenerateStaticFieldLookup(field, call_pos); 6418 closure = GenerateStaticFieldLookup(field, call_pos);
6420 return new ClosureCallNode(call_pos, closure, arguments); 6419 return new ClosureCallNode(call_pos, closure, arguments);
6421 } 6420 }
6422 // Could not resolve static method: throw an exception if the arguments 6421 // Could not resolve static method: throw an exception if the arguments
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
6539 AstNode* value = ParseExpr(kAllowConst); 6538 AstNode* value = ParseExpr(kAllowConst);
6540 AstNode* load_access = NULL; 6539 AstNode* load_access = NULL;
6541 if (field.IsNull()) { 6540 if (field.IsNull()) {
6542 // No field found, we must have at least a setter function defined. 6541 // No field found, we must have at least a setter function defined.
6543 ASSERT(!func.IsNull()); 6542 ASSERT(!func.IsNull());
6544 // Explicit setter function for the field found, field does not exist. 6543 // Explicit setter function for the field found, field does not exist.
6545 // Create a getter node first in case it is needed. If getter node 6544 // Create a getter node first in case it is needed. If getter node
6546 // is used as part of, e.g., "+=", and the explicit getter does not 6545 // is used as part of, e.g., "+=", and the explicit getter does not
6547 // exist, and error will be reported by the code generator. 6546 // exist, and error will be reported by the code generator.
6548 load_access = new StaticGetterNode(call_pos, 6547 load_access = new StaticGetterNode(call_pos,
6548 NULL,
6549 Class::ZoneHandle(cls.raw()), 6549 Class::ZoneHandle(cls.raw()),
6550 String::ZoneHandle(field_name.raw())); 6550 String::ZoneHandle(field_name.raw()));
6551 } else { 6551 } else {
6552 // Field exists. 6552 // Field exists.
6553 if (field.is_final()) { 6553 if (field.is_final()) {
6554 // Field has been marked as final, report an error as the field 6554 // Field has been marked as final, report an error as the field
6555 // is not settable. 6555 // is not settable.
6556 ErrorMsg(ident_pos, 6556 ErrorMsg(ident_pos,
6557 "field '%s' is const static, cannot assign to it", 6557 "field '%s' is const static, cannot assign to it",
6558 field_name.ToCString()); 6558 field_name.ToCString());
(...skipping 22 matching lines...) Expand all
6581 if (func.IsNull()) { 6581 if (func.IsNull()) {
6582 // No field or explicit getter function, this is an error. 6582 // No field or explicit getter function, this is an error.
6583 ErrorMsg(ident_pos, 6583 ErrorMsg(ident_pos,
6584 "unknown static field '%s'", field_name.ToCString()); 6584 "unknown static field '%s'", field_name.ToCString());
6585 return access; 6585 return access;
6586 } 6586 }
6587 access = CreateImplicitClosureNode(func, call_pos, NULL); 6587 access = CreateImplicitClosureNode(func, call_pos, NULL);
6588 } else { 6588 } else {
6589 ASSERT(func.kind() != RawFunction::kConstImplicitGetter); 6589 ASSERT(func.kind() != RawFunction::kConstImplicitGetter);
6590 access = new StaticGetterNode(call_pos, 6590 access = new StaticGetterNode(call_pos,
6591 NULL,
6591 Class::ZoneHandle(cls.raw()), 6592 Class::ZoneHandle(cls.raw()),
6592 field_name); 6593 field_name);
6593 } 6594 }
6594 } else { 6595 } else {
6595 return GenerateStaticFieldLookup(field, TokenPos()); 6596 return GenerateStaticFieldLookup(field, TokenPos());
6596 } 6597 }
6597 } 6598 }
6598 return access; 6599 return access;
6599 } 6600 }
6600 6601
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
6957 AstNode* Parser::RunStaticFieldInitializer(const Field& field) { 6958 AstNode* Parser::RunStaticFieldInitializer(const Field& field) {
6958 ASSERT(field.is_static()); 6959 ASSERT(field.is_static());
6959 const Instance& value = Instance::Handle(field.value()); 6960 const Instance& value = Instance::Handle(field.value());
6960 if (value.raw() == Object::transition_sentinel()) { 6961 if (value.raw() == Object::transition_sentinel()) {
6961 if (field.is_const()) { 6962 if (field.is_const()) {
6962 ErrorMsg("circular dependency while initializing static field '%s'", 6963 ErrorMsg("circular dependency while initializing static field '%s'",
6963 String::Handle(field.name()).ToCString()); 6964 String::Handle(field.name()).ToCString());
6964 } else { 6965 } else {
6965 // The implicit static getter will throw the exception if necessary. 6966 // The implicit static getter will throw the exception if necessary.
6966 return new StaticGetterNode(TokenPos(), 6967 return new StaticGetterNode(TokenPos(),
6968 NULL,
6967 Class::ZoneHandle(field.owner()), 6969 Class::ZoneHandle(field.owner()),
6968 String::ZoneHandle(field.name())); 6970 String::ZoneHandle(field.name()));
6969 } 6971 }
6970 } else if (value.raw() == Object::sentinel()) { 6972 } else if (value.raw() == Object::sentinel()) {
6971 // This field has not been referenced yet and thus the value has 6973 // This field has not been referenced yet and thus the value has
6972 // not been evaluated. If the field is const, call the static getter method 6974 // not been evaluated. If the field is const, call the static getter method
6973 // to evaluate the expression and canonicalize the value. 6975 // to evaluate the expression and canonicalize the value.
6974 if (field.is_const()) { 6976 if (field.is_const()) {
6975 field.set_value(Instance::Handle(Object::transition_sentinel())); 6977 field.set_value(Instance::Handle(Object::transition_sentinel()));
6976 const String& field_name = String::Handle(field.name()); 6978 const String& field_name = String::Handle(field.name());
(...skipping 28 matching lines...) Expand all
7005 } 7007 }
7006 ASSERT(const_value.IsNull() || const_value.IsInstance()); 7008 ASSERT(const_value.IsNull() || const_value.IsInstance());
7007 Instance& instance = Instance::Handle(); 7009 Instance& instance = Instance::Handle();
7008 instance ^= const_value.raw(); 7010 instance ^= const_value.raw();
7009 if (!instance.IsNull()) { 7011 if (!instance.IsNull()) {
7010 instance ^= instance.Canonicalize(); 7012 instance ^= instance.Canonicalize();
7011 } 7013 }
7012 field.set_value(instance); 7014 field.set_value(instance);
7013 } else { 7015 } else {
7014 return new StaticGetterNode(TokenPos(), 7016 return new StaticGetterNode(TokenPos(),
7017 NULL,
7015 Class::ZoneHandle(field.owner()), 7018 Class::ZoneHandle(field.owner()),
7016 String::ZoneHandle(field.name())); 7019 String::ZoneHandle(field.name()));
7017 } 7020 }
7018 } 7021 }
7019 return NULL; 7022 return NULL;
7020 } 7023 }
7021 7024
7022 7025
7023 RawObject* Parser::EvaluateConstConstructorCall( 7026 RawObject* Parser::EvaluateConstConstructorCall(
7024 const Class& type_class, 7027 const Class& type_class,
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
7128 if (func.IsDynamicFunction()) { 7131 if (func.IsDynamicFunction()) {
7129 if (node != NULL) { 7132 if (node != NULL) {
7130 CheckInstanceFieldAccess(ident_pos, ident); 7133 CheckInstanceFieldAccess(ident_pos, ident);
7131 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); 7134 ASSERT(AbstractType::Handle(func.result_type()).IsResolved());
7132 *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident); 7135 *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident);
7133 } 7136 }
7134 return true; 7137 return true;
7135 } else if (func.IsStaticFunction()) { 7138 } else if (func.IsStaticFunction()) {
7136 if (node != NULL) { 7139 if (node != NULL) {
7137 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); 7140 ASSERT(AbstractType::Handle(func.result_type()).IsResolved());
7141 // The static getter may be changed later into an instance setter.
7142 AstNode* receiver = NULL;
7143 const bool kTestOnly = true;
7144 if ((!current_function().is_static() ||
7145 current_function().IsInFactoryScope()) &&
7146 (LookupReceiver(current_block_->scope, kTestOnly) != NULL)) {
7147 receiver = LoadReceiver(ident_pos);
7148 }
7138 *node = new StaticGetterNode(ident_pos, 7149 *node = new StaticGetterNode(ident_pos,
7150 receiver,
7139 Class::ZoneHandle(isolate, cls.raw()), 7151 Class::ZoneHandle(isolate, cls.raw()),
7140 ident); 7152 ident);
7141 } 7153 }
7142 return true; 7154 return true;
7143 } 7155 }
7144 } 7156 }
7145 func = cls.LookupSetterFunction(ident); 7157 func = cls.LookupSetterFunction(ident);
7146 if (!func.IsNull()) { 7158 if (!func.IsNull()) {
7147 if (func.IsDynamicFunction()) { 7159 if (func.IsDynamicFunction()) {
7148 if (node != NULL) { 7160 if (node != NULL) {
7149 // We create a getter node even though a getter doesn't exist as 7161 // We create a getter node even though a getter doesn't exist as
7150 // it could be followed by an assignment which will convert it to 7162 // it could be followed by an assignment which will convert it to
7151 // a setter node. If there is no assignment we will get an error 7163 // a setter node. If there is no assignment we will get an error
7152 // when we try to invoke the getter. 7164 // when we try to invoke the getter.
7153 CheckInstanceFieldAccess(ident_pos, ident); 7165 CheckInstanceFieldAccess(ident_pos, ident);
7154 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); 7166 ASSERT(AbstractType::Handle(func.result_type()).IsResolved());
7155 *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident); 7167 *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident);
7156 } 7168 }
7157 return true; 7169 return true;
7158 } else if (func.IsStaticFunction()) { 7170 } else if (func.IsStaticFunction()) {
7159 if (node != NULL) { 7171 if (node != NULL) {
7160 // We create a getter node even though a getter doesn't exist as 7172 // We create a getter node even though a getter doesn't exist as
7161 // it could be followed by an assignment which will convert it to 7173 // it could be followed by an assignment which will convert it to
7162 // a setter node. If there is no assignment we will get an error 7174 // a setter node. If there is no assignment we will get an error
7163 // when we try to invoke the getter. 7175 // when we try to invoke the getter.
7164 *node = new StaticGetterNode(ident_pos, 7176 *node = new StaticGetterNode(ident_pos,
7177 NULL,
7165 Class::ZoneHandle(isolate, cls.raw()), 7178 Class::ZoneHandle(isolate, cls.raw()),
7166 ident); 7179 ident);
7167 } 7180 }
7168 return true; 7181 return true;
7169 } 7182 }
7170 } 7183 }
7171 7184
7172 // Nothing found in scope of current class. 7185 // Nothing found in scope of current class.
7173 if (node != NULL) { 7186 if (node != NULL) {
7174 *node = NULL; 7187 *node = NULL;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
7226 } else { 7239 } else {
7227 obj = lib.LookupObject(accessor_name); 7240 obj = lib.LookupObject(accessor_name);
7228 } 7241 }
7229 } 7242 }
7230 if (!obj.IsNull()) { 7243 if (!obj.IsNull()) {
7231 ASSERT(obj.IsFunction()); 7244 ASSERT(obj.IsFunction());
7232 const Function& func = Function::Cast(obj); 7245 const Function& func = Function::Cast(obj);
7233 ASSERT(func.is_static()); 7246 ASSERT(func.is_static());
7234 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); 7247 ASSERT(AbstractType::Handle(func.result_type()).IsResolved());
7235 return new StaticGetterNode(qual_ident.ident_pos, 7248 return new StaticGetterNode(qual_ident.ident_pos,
7249 NULL,
7236 Class::ZoneHandle(func.owner()), 7250 Class::ZoneHandle(func.owner()),
7237 *qual_ident.ident); 7251 *qual_ident.ident);
7238 } 7252 }
7239 if (qual_ident.lib_prefix != NULL) { 7253 if (qual_ident.lib_prefix != NULL) {
7240 return NULL; 7254 return NULL;
7241 } 7255 }
7242 // Lexically unresolved primary identifiers are referenced by their name. 7256 // Lexically unresolved primary identifiers are referenced by their name.
7243 return new PrimaryNode(qual_ident.ident_pos, *qual_ident.ident); 7257 return new PrimaryNode(qual_ident.ident_pos, *qual_ident.ident);
7244 } 7258 }
7245 7259
(...skipping 1374 matching lines...) Expand 10 before | Expand all | Expand 10 after
8620 void Parser::SkipQualIdent() { 8634 void Parser::SkipQualIdent() {
8621 ASSERT(IsIdentifier()); 8635 ASSERT(IsIdentifier());
8622 ConsumeToken(); 8636 ConsumeToken();
8623 if (CurrentToken() == Token::kPERIOD) { 8637 if (CurrentToken() == Token::kPERIOD) {
8624 ConsumeToken(); // Consume the kPERIOD token. 8638 ConsumeToken(); // Consume the kPERIOD token.
8625 ExpectIdentifier("identifier expected after '.'"); 8639 ExpectIdentifier("identifier expected after '.'");
8626 } 8640 }
8627 } 8641 }
8628 8642
8629 } // namespace dart 8643 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/ast.cc ('k') | tests/language/getter_no_setter_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698