| 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 "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
| 8 #include "vm/bigint_operations.h" | 8 #include "vm/bigint_operations.h" |
| 9 #include "vm/bootstrap.h" | 9 #include "vm/bootstrap.h" |
| 10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
| (...skipping 3130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3141 Function& getter = Function::Handle(); | 3141 Function& getter = Function::Handle(); |
| 3142 Function& setter = Function::Handle(); | 3142 Function& setter = Function::Handle(); |
| 3143 Field& class_field = Field::Handle(); | 3143 Field& class_field = Field::Handle(); |
| 3144 Instance& init_value = Instance::Handle(); | 3144 Instance& init_value = Instance::Handle(); |
| 3145 while (true) { | 3145 while (true) { |
| 3146 bool has_initializer = CurrentToken() == Token::kASSIGN; | 3146 bool has_initializer = CurrentToken() == Token::kASSIGN; |
| 3147 bool has_simple_literal = false; | 3147 bool has_simple_literal = false; |
| 3148 if (has_initializer) { | 3148 if (has_initializer) { |
| 3149 ConsumeToken(); | 3149 ConsumeToken(); |
| 3150 init_value = Object::sentinel().raw(); | 3150 init_value = Object::sentinel().raw(); |
| 3151 // For static const fields, the initialization expression | 3151 // For static const fields and static final non-const fields, the |
| 3152 // will be parsed through the kImplicitStaticFinalGetter method | 3152 // initialization expression will be parsed through the |
| 3153 // invocation/compilation. | 3153 // kImplicitStaticFinalGetter method invocation/compilation. |
| 3154 // For instance fields, the expression is parsed when a constructor | 3154 // For instance fields, the expression is parsed when a constructor |
| 3155 // is compiled. | 3155 // is compiled. |
| 3156 // For static const fields with very simple initializer expressions | 3156 // For static const fields and static final non-const fields with very |
| 3157 // (e.g. a literal number or string) we optimize away the | 3157 // simple initializer expressions (e.g. a literal number or string), we |
| 3158 // kImplicitStaticFinalGetter and initialize the field here. | 3158 // optimize away the kImplicitStaticFinalGetter and initialize the field |
| 3159 // We also do it for static final non-const fields, but only in production | 3159 // here. However, the class finalizer will check the value type for |
| 3160 // mode. | 3160 // assignability once the declared field type can be resolved. If the |
| 3161 // value is not assignable (assuming checked mode and disregarding actual |
| 3162 // mode), the field value is reset and a kImplicitStaticFinalGetter is |
| 3163 // created at finalization time. |
| 3161 | 3164 |
| 3162 if (field->has_static && | 3165 if (field->has_static && (field->has_const || field->has_final) && |
| 3163 (field->has_const || | |
| 3164 (!FLAG_enable_type_checks && field->has_final)) && | |
| 3165 (LookaheadToken(1) == Token::kSEMICOLON)) { | 3166 (LookaheadToken(1) == Token::kSEMICOLON)) { |
| 3166 has_simple_literal = IsSimpleLiteral(*field->type, &init_value); | 3167 has_simple_literal = IsSimpleLiteral(*field->type, &init_value); |
| 3167 } | 3168 } |
| 3168 SkipExpr(); | 3169 SkipExpr(); |
| 3169 } else { | 3170 } else { |
| 3170 if (field->has_const || (field->has_static && field->has_final)) { | 3171 if (field->has_const || (field->has_static && field->has_final)) { |
| 3171 ErrorMsg(field->name_pos, | 3172 ErrorMsg(field->name_pos, |
| 3172 "%s%s field '%s' must have an initializer expression", | 3173 "%s%s field '%s' must have an initializer expression", |
| 3173 field->has_static ? "static " : "", | 3174 field->has_static ? "static " : "", |
| 3174 field->has_const ? "const" : "final", | 3175 field->has_const ? "const" : "final", |
| (...skipping 1070 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4245 } | 4246 } |
| 4246 | 4247 |
| 4247 | 4248 |
| 4248 void Parser::ParseTopLevelVariable(TopLevel* top_level, | 4249 void Parser::ParseTopLevelVariable(TopLevel* top_level, |
| 4249 intptr_t metadata_pos) { | 4250 intptr_t metadata_pos) { |
| 4250 TRACE_PARSER("ParseTopLevelVariable"); | 4251 TRACE_PARSER("ParseTopLevelVariable"); |
| 4251 const bool is_const = (CurrentToken() == Token::kCONST); | 4252 const bool is_const = (CurrentToken() == Token::kCONST); |
| 4252 // Const fields are implicitly final. | 4253 // Const fields are implicitly final. |
| 4253 const bool is_final = is_const || (CurrentToken() == Token::kFINAL); | 4254 const bool is_final = is_const || (CurrentToken() == Token::kFINAL); |
| 4254 const bool is_static = true; | 4255 const bool is_static = true; |
| 4255 const AbstractType& type = | 4256 const AbstractType& type = AbstractType::ZoneHandle(ParseConstFinalVarOrType( |
| 4256 AbstractType::ZoneHandle(ParseConstFinalVarOrType( | 4257 ClassFinalizer::kResolveTypeParameters)); |
| 4257 FLAG_enable_type_checks ? ClassFinalizer::kResolveTypeParameters : | |
| 4258 ClassFinalizer::kIgnore)); | |
| 4259 Field& field = Field::Handle(); | 4258 Field& field = Field::Handle(); |
| 4260 Function& getter = Function::Handle(); | 4259 Function& getter = Function::Handle(); |
| 4261 while (true) { | 4260 while (true) { |
| 4262 const intptr_t name_pos = TokenPos(); | 4261 const intptr_t name_pos = TokenPos(); |
| 4263 String& var_name = *ExpectIdentifier("variable name expected"); | 4262 String& var_name = *ExpectIdentifier("variable name expected"); |
| 4264 | 4263 |
| 4265 if (library_.LookupLocalObject(var_name) != Object::null()) { | 4264 if (library_.LookupLocalObject(var_name) != Object::null()) { |
| 4266 ErrorMsg(name_pos, "'%s' is already defined", var_name.ToCString()); | 4265 ErrorMsg(name_pos, "'%s' is already defined", var_name.ToCString()); |
| 4267 } | 4266 } |
| 4268 String& accessor_name = String::Handle(Field::GetterName(var_name)); | 4267 String& accessor_name = String::Handle(Field::GetterName(var_name)); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4286 field.set_value(Instance::Handle(Instance::null())); | 4285 field.set_value(Instance::Handle(Instance::null())); |
| 4287 top_level->fields.Add(field); | 4286 top_level->fields.Add(field); |
| 4288 library_.AddObject(field, var_name); | 4287 library_.AddObject(field, var_name); |
| 4289 if (metadata_pos >= 0) { | 4288 if (metadata_pos >= 0) { |
| 4290 library_.AddFieldMetadata(field, metadata_pos); | 4289 library_.AddFieldMetadata(field, metadata_pos); |
| 4291 } | 4290 } |
| 4292 if (CurrentToken() == Token::kASSIGN) { | 4291 if (CurrentToken() == Token::kASSIGN) { |
| 4293 ConsumeToken(); | 4292 ConsumeToken(); |
| 4294 Instance& field_value = Instance::Handle(Object::sentinel().raw()); | 4293 Instance& field_value = Instance::Handle(Object::sentinel().raw()); |
| 4295 bool has_simple_literal = false; | 4294 bool has_simple_literal = false; |
| 4296 if ((is_const || (!FLAG_enable_type_checks && is_final)) && | 4295 if ((is_const || is_final) && (LookaheadToken(1) == Token::kSEMICOLON)) { |
| 4297 (LookaheadToken(1) == Token::kSEMICOLON)) { | |
| 4298 has_simple_literal = IsSimpleLiteral(type, &field_value); | 4296 has_simple_literal = IsSimpleLiteral(type, &field_value); |
| 4299 } | 4297 } |
| 4300 SkipExpr(); | 4298 SkipExpr(); |
| 4301 field.set_value(field_value); | 4299 field.set_value(field_value); |
| 4302 if (!has_simple_literal) { | 4300 if (!has_simple_literal) { |
| 4303 // Create a static const getter. | 4301 // Create a static final getter. |
| 4304 String& getter_name = String::ZoneHandle(Field::GetterSymbol(var_name)); | 4302 String& getter_name = String::Handle(Field::GetterSymbol(var_name)); |
| 4305 getter = Function::New(getter_name, | 4303 getter = Function::New(getter_name, |
| 4306 RawFunction::kImplicitStaticFinalGetter, | 4304 RawFunction::kImplicitStaticFinalGetter, |
| 4307 is_static, | 4305 is_static, |
| 4308 is_const, | 4306 is_const, |
| 4309 /* is_abstract = */ false, | 4307 /* is_abstract = */ false, |
| 4310 /* is_external = */ false, | 4308 /* is_external = */ false, |
| 4311 current_class(), | 4309 current_class(), |
| 4312 name_pos); | 4310 name_pos); |
| 4313 getter.set_result_type(type); | 4311 getter.set_result_type(type); |
| 4314 top_level->functions.Add(getter); | 4312 top_level->functions.Add(getter); |
| (...skipping 6028 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10343 void Parser::SkipQualIdent() { | 10341 void Parser::SkipQualIdent() { |
| 10344 ASSERT(IsIdentifier()); | 10342 ASSERT(IsIdentifier()); |
| 10345 ConsumeToken(); | 10343 ConsumeToken(); |
| 10346 if (CurrentToken() == Token::kPERIOD) { | 10344 if (CurrentToken() == Token::kPERIOD) { |
| 10347 ConsumeToken(); // Consume the kPERIOD token. | 10345 ConsumeToken(); // Consume the kPERIOD token. |
| 10348 ExpectIdentifier("identifier expected after '.'"); | 10346 ExpectIdentifier("identifier expected after '.'"); |
| 10349 } | 10347 } |
| 10350 } | 10348 } |
| 10351 | 10349 |
| 10352 } // namespace dart | 10350 } // namespace dart |
| OLD | NEW |