| 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 763 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 ASSERT(!func.is_static()); | 774 ASSERT(!func.is_static()); |
| 775 node_sequence = parser.ParseInstanceGetter(func); | 775 node_sequence = parser.ParseInstanceGetter(func); |
| 776 break; | 776 break; |
| 777 case RawFunction::kImplicitSetter: | 777 case RawFunction::kImplicitSetter: |
| 778 ASSERT(!func.is_static()); | 778 ASSERT(!func.is_static()); |
| 779 node_sequence = parser.ParseInstanceSetter(func); | 779 node_sequence = parser.ParseInstanceSetter(func); |
| 780 break; | 780 break; |
| 781 case RawFunction::kImplicitStaticFinalGetter: | 781 case RawFunction::kImplicitStaticFinalGetter: |
| 782 node_sequence = parser.ParseStaticFinalGetter(func); | 782 node_sequence = parser.ParseStaticFinalGetter(func); |
| 783 break; | 783 break; |
| 784 case RawFunction::kStaticInitializer: |
| 785 node_sequence = parser.ParseStaticInitializer(func); |
| 786 break; |
| 784 case RawFunction::kMethodExtractor: | 787 case RawFunction::kMethodExtractor: |
| 785 node_sequence = parser.ParseMethodExtractor(func); | 788 node_sequence = parser.ParseMethodExtractor(func); |
| 786 break; | 789 break; |
| 787 case RawFunction::kNoSuchMethodDispatcher: | 790 case RawFunction::kNoSuchMethodDispatcher: |
| 788 node_sequence = | 791 node_sequence = |
| 789 parser.ParseNoSuchMethodDispatcher(func, default_parameter_values); | 792 parser.ParseNoSuchMethodDispatcher(func, default_parameter_values); |
| 790 break; | 793 break; |
| 791 case RawFunction::kInvokeFieldDispatcher: | 794 case RawFunction::kInvokeFieldDispatcher: |
| 792 node_sequence = | 795 node_sequence = |
| 793 parser.ParseInvokeFieldDispatcher(func, default_parameter_values); | 796 parser.ParseInvokeFieldDispatcher(func, default_parameter_values); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 900 // Build local scope for function and populate with the formal parameters. | 903 // Build local scope for function and populate with the formal parameters. |
| 901 OpenFunctionBlock(func); | 904 OpenFunctionBlock(func); |
| 902 AddFormalParamsToScope(¶ms, current_block_->scope); | 905 AddFormalParamsToScope(¶ms, current_block_->scope); |
| 903 | 906 |
| 904 intptr_t ident_pos = TokenPos(); | 907 intptr_t ident_pos = TokenPos(); |
| 905 const String& field_name = *ExpectIdentifier("field name expected"); | 908 const String& field_name = *ExpectIdentifier("field name expected"); |
| 906 const Class& field_class = Class::Handle(func.Owner()); | 909 const Class& field_class = Class::Handle(func.Owner()); |
| 907 const Field& field = | 910 const Field& field = |
| 908 Field::ZoneHandle(field_class.LookupStaticField(field_name)); | 911 Field::ZoneHandle(field_class.LookupStaticField(field_name)); |
| 909 | 912 |
| 910 if (!field.is_const() && | 913 // Static final fields must have an initializer. |
| 911 (field.value() != Object::transition_sentinel().raw()) && | |
| 912 (field.value() != Object::sentinel().raw())) { | |
| 913 // The field has already been initialized at compile time (this can | |
| 914 // happen, e.g., if we are recompiling for optimization). There is no | |
| 915 // need to check for initialization and compile the potentially very | |
| 916 // large initialization code. By skipping this code, the deoptimization | |
| 917 // ids will not line up with the original code, but this is safe because | |
| 918 // LoadStaticField does not deoptimize. | |
| 919 LoadStaticFieldNode* load_node = new LoadStaticFieldNode(ident_pos, field); | |
| 920 ReturnNode* return_node = new ReturnNode(ident_pos, load_node); | |
| 921 current_block_->statements->Add(return_node); | |
| 922 return CloseBlock(); | |
| 923 } | |
| 924 | |
| 925 // Static const fields must have an initializer. | |
| 926 ExpectToken(Token::kASSIGN); | 914 ExpectToken(Token::kASSIGN); |
| 927 | 915 |
| 928 // We don't want to use ParseConstExpr() here because we don't want | |
| 929 // the constant folding code to create, compile and execute a code | |
| 930 // fragment to evaluate the expression. Instead, we just make sure | |
| 931 // the static const field initializer is a constant expression and | |
| 932 // leave the evaluation to the getter function. | |
| 933 const intptr_t expr_pos = TokenPos(); | 916 const intptr_t expr_pos = TokenPos(); |
| 934 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); | |
| 935 | |
| 936 if (field.is_const()) { | 917 if (field.is_const()) { |
| 918 // We don't want to use ParseConstExpr() here because we don't want |
| 919 // the constant folding code to create, compile and execute a code |
| 920 // fragment to evaluate the expression. Instead, we just make sure |
| 921 // the static const field initializer is a constant expression and |
| 922 // leave the evaluation to the getter function. |
| 923 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
| 937 // This getter will only be called once at compile time. | 924 // This getter will only be called once at compile time. |
| 938 if (expr->EvalConstExpr() == NULL) { | 925 if (expr->EvalConstExpr() == NULL) { |
| 939 ErrorMsg(expr_pos, "initializer is not a valid compile-time constant"); | 926 ErrorMsg(expr_pos, "initializer is not a valid compile-time constant"); |
| 940 } | 927 } |
| 941 ReturnNode* return_node = new ReturnNode(ident_pos, expr); | 928 ReturnNode* return_node = new ReturnNode(ident_pos, expr); |
| 942 current_block_->statements->Add(return_node); | 929 current_block_->statements->Add(return_node); |
| 943 } else { | 930 } else { |
| 944 // This getter may be called each time the static field is accessed. | 931 // This getter may be called each time the static field is accessed. |
| 945 // The following generated code lazily initializes the field: | 932 // The following generated code lazily initializes the field: |
| 946 // if (field.value === transition_sentinel) { | 933 // if (field.value === transition_sentinel) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 988 SequenceNode* initialize_field = new SequenceNode(ident_pos, NULL); | 975 SequenceNode* initialize_field = new SequenceNode(ident_pos, NULL); |
| 989 initialize_field->Add( | 976 initialize_field->Add( |
| 990 new StoreStaticFieldNode( | 977 new StoreStaticFieldNode( |
| 991 ident_pos, | 978 ident_pos, |
| 992 field, | 979 field, |
| 993 new LiteralNode(ident_pos, Object::transition_sentinel()))); | 980 new LiteralNode(ident_pos, Object::transition_sentinel()))); |
| 994 // TODO(hausner): If evaluation of the field value throws an exception, | 981 // TODO(hausner): If evaluation of the field value throws an exception, |
| 995 // we leave the field value as 'transition_sentinel', which is wrong. | 982 // we leave the field value as 'transition_sentinel', which is wrong. |
| 996 // A second reference to the field later throws a circular dependency | 983 // A second reference to the field later throws a circular dependency |
| 997 // exception. The field should instead be set to null after an exception. | 984 // exception. The field should instead be set to null after an exception. |
| 998 initialize_field->Add(new StoreStaticFieldNode(ident_pos, field, expr)); | 985 const String& init_name = |
| 986 String::Handle(Symbols::New(String::Handle( |
| 987 String::Concat(Symbols::InitPrefix(), String::Handle(field.name()))))); |
| 988 const Function& init_function = Function::ZoneHandle( |
| 989 field_class.LookupStaticFunction(init_name)); |
| 990 ASSERT(!init_function.IsNull()); |
| 991 ArgumentListNode* arguments = new ArgumentListNode(expr_pos); |
| 992 StaticCallNode* init_call = |
| 993 new StaticCallNode(expr_pos, init_function, arguments); |
| 994 |
| 995 initialize_field->Add(new StoreStaticFieldNode(ident_pos, |
| 996 field, |
| 997 init_call)); |
| 999 AstNode* uninitialized_check = | 998 AstNode* uninitialized_check = |
| 1000 new IfNode(ident_pos, compare_uninitialized, initialize_field, NULL); | 999 new IfNode(ident_pos, compare_uninitialized, initialize_field, NULL); |
| 1001 current_block_->statements->Add(uninitialized_check); | 1000 current_block_->statements->Add(uninitialized_check); |
| 1002 | 1001 |
| 1003 // Generate code returning the field value. | 1002 // Generate code returning the field value. |
| 1004 ReturnNode* return_node = | 1003 ReturnNode* return_node = |
| 1005 new ReturnNode(ident_pos, | 1004 new ReturnNode(ident_pos, |
| 1006 new LoadStaticFieldNode(ident_pos, field)); | 1005 new LoadStaticFieldNode(ident_pos, field)); |
| 1007 current_block_->statements->Add(return_node); | 1006 current_block_->statements->Add(return_node); |
| 1008 } | 1007 } |
| 1009 return CloseBlock(); | 1008 return CloseBlock(); |
| 1010 } | 1009 } |
| 1011 | 1010 |
| 1012 | 1011 |
| 1012 SequenceNode* Parser::ParseStaticInitializer(const Function& func) { |
| 1013 TRACE_PARSER("ParseStaticInitializer"); |
| 1014 ParamList params; |
| 1015 ASSERT(func.num_fixed_parameters() == 0); // static. |
| 1016 ASSERT(!func.HasOptionalParameters()); |
| 1017 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); |
| 1018 |
| 1019 // Build local scope for function and populate with the formal parameters. |
| 1020 OpenFunctionBlock(func); |
| 1021 AddFormalParamsToScope(¶ms, current_block_->scope); |
| 1022 |
| 1023 intptr_t expr_pos = func.token_pos(); |
| 1024 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
| 1025 ReturnNode* return_node = new ReturnNode(expr_pos, expr); |
| 1026 current_block_->statements->Add(return_node); |
| 1027 return CloseBlock(); |
| 1028 } |
| 1029 |
| 1030 |
| 1013 // Create AstNodes for an implicit instance getter method: | 1031 // Create AstNodes for an implicit instance getter method: |
| 1014 // LoadLocalNode 0 ('this'); | 1032 // LoadLocalNode 0 ('this'); |
| 1015 // LoadInstanceFieldNode (field_name); | 1033 // LoadInstanceFieldNode (field_name); |
| 1016 // ReturnNode (field's value); | 1034 // ReturnNode (field's value); |
| 1017 SequenceNode* Parser::ParseInstanceGetter(const Function& func) { | 1035 SequenceNode* Parser::ParseInstanceGetter(const Function& func) { |
| 1018 TRACE_PARSER("ParseInstanceGetter"); | 1036 TRACE_PARSER("ParseInstanceGetter"); |
| 1019 ParamList params; | 1037 ParamList params; |
| 1020 // func.token_pos() points to the name of the field. | 1038 // func.token_pos() points to the name of the field. |
| 1021 intptr_t ident_pos = func.token_pos(); | 1039 intptr_t ident_pos = func.token_pos(); |
| 1022 ASSERT(current_class().raw() == func.Owner()); | 1040 ASSERT(current_class().raw() == func.Owner()); |
| (...skipping 2219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3242 if (field->has_factory) { | 3260 if (field->has_factory) { |
| 3243 ErrorMsg("keyword 'factory' not allowed in field declaration"); | 3261 ErrorMsg("keyword 'factory' not allowed in field declaration"); |
| 3244 } | 3262 } |
| 3245 if (!field->has_static && field->has_const) { | 3263 if (!field->has_static && field->has_const) { |
| 3246 ErrorMsg(field->name_pos, "instance field may not be 'const'"); | 3264 ErrorMsg(field->name_pos, "instance field may not be 'const'"); |
| 3247 } | 3265 } |
| 3248 Function& getter = Function::Handle(); | 3266 Function& getter = Function::Handle(); |
| 3249 Function& setter = Function::Handle(); | 3267 Function& setter = Function::Handle(); |
| 3250 Field& class_field = Field::ZoneHandle(); | 3268 Field& class_field = Field::ZoneHandle(); |
| 3251 Instance& init_value = Instance::Handle(); | 3269 Instance& init_value = Instance::Handle(); |
| 3270 intptr_t expr_pos = -1; |
| 3252 while (true) { | 3271 while (true) { |
| 3253 bool has_initializer = CurrentToken() == Token::kASSIGN; | 3272 bool has_initializer = CurrentToken() == Token::kASSIGN; |
| 3254 bool has_simple_literal = false; | 3273 bool has_simple_literal = false; |
| 3255 if (has_initializer) { | 3274 if (has_initializer) { |
| 3256 ConsumeToken(); | 3275 ConsumeToken(); |
| 3257 init_value = Object::sentinel().raw(); | 3276 init_value = Object::sentinel().raw(); |
| 3258 // For static const fields and static final non-const fields, the | 3277 // For static const fields and static final non-const fields, the |
| 3259 // initialization expression will be parsed through the | 3278 // initialization expression will be parsed through the |
| 3260 // kImplicitStaticFinalGetter method invocation/compilation. | 3279 // kImplicitStaticFinalGetter method invocation/compilation. |
| 3261 // For instance fields, the expression is parsed when a constructor | 3280 // For instance fields, the expression is parsed when a constructor |
| 3262 // is compiled. | 3281 // is compiled. |
| 3263 // For static const fields and static final non-const fields with very | 3282 // For static const fields and static final non-const fields with very |
| 3264 // simple initializer expressions (e.g. a literal number or string), we | 3283 // simple initializer expressions (e.g. a literal number or string), we |
| 3265 // optimize away the kImplicitStaticFinalGetter and initialize the field | 3284 // optimize away the kImplicitStaticFinalGetter and initialize the field |
| 3266 // here. However, the class finalizer will check the value type for | 3285 // here. However, the class finalizer will check the value type for |
| 3267 // assignability once the declared field type can be resolved. If the | 3286 // assignability once the declared field type can be resolved. If the |
| 3268 // value is not assignable (assuming checked mode and disregarding actual | 3287 // value is not assignable (assuming checked mode and disregarding actual |
| 3269 // mode), the field value is reset and a kImplicitStaticFinalGetter is | 3288 // mode), the field value is reset and a kImplicitStaticFinalGetter is |
| 3270 // created at finalization time. | 3289 // created at finalization time. |
| 3271 | 3290 |
| 3272 if (field->has_static && (field->has_const || field->has_final) && | 3291 if (field->has_static && (field->has_const || field->has_final) && |
| 3273 (LookaheadToken(1) == Token::kSEMICOLON)) { | 3292 (LookaheadToken(1) == Token::kSEMICOLON)) { |
| 3274 has_simple_literal = IsSimpleLiteral(*field->type, &init_value); | 3293 has_simple_literal = IsSimpleLiteral(*field->type, &init_value); |
| 3275 } | 3294 } |
| 3295 expr_pos = TokenPos(); |
| 3276 SkipExpr(); | 3296 SkipExpr(); |
| 3277 } else { | 3297 } else { |
| 3278 // Static const and static final fields must have an initializer. | 3298 // Static const and static final fields must have an initializer. |
| 3279 // Static const fields are implicitly final. | 3299 // Static const fields are implicitly final. |
| 3280 if (field->has_static && field->has_final) { | 3300 if (field->has_static && field->has_final) { |
| 3281 ErrorMsg(field->name_pos, | 3301 ErrorMsg(field->name_pos, |
| 3282 "static %s field '%s' must have an initializer expression", | 3302 "static %s field '%s' must have an initializer expression", |
| 3283 field->has_const ? "const" : "final", | 3303 field->has_const ? "const" : "final", |
| 3284 field->name->ToCString()); | 3304 field->name->ToCString()); |
| 3285 } | 3305 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3309 getter = Function::New(getter_name, | 3329 getter = Function::New(getter_name, |
| 3310 RawFunction::kImplicitStaticFinalGetter, | 3330 RawFunction::kImplicitStaticFinalGetter, |
| 3311 field->has_static, | 3331 field->has_static, |
| 3312 field->has_const, | 3332 field->has_const, |
| 3313 /* is_abstract = */ false, | 3333 /* is_abstract = */ false, |
| 3314 /* is_external = */ false, | 3334 /* is_external = */ false, |
| 3315 current_class(), | 3335 current_class(), |
| 3316 field->name_pos); | 3336 field->name_pos); |
| 3317 getter.set_result_type(*field->type); | 3337 getter.set_result_type(*field->type); |
| 3318 members->AddFunction(getter); | 3338 members->AddFunction(getter); |
| 3339 |
| 3340 // Create initializer function. |
| 3341 const Function& init_function = Function::ZoneHandle( |
| 3342 Function::NewStaticInitializer(*field->name, |
| 3343 *field->type, |
| 3344 current_class(), |
| 3345 expr_pos)); |
| 3346 members->AddFunction(init_function); |
| 3319 } | 3347 } |
| 3320 } | 3348 } |
| 3321 | 3349 |
| 3322 // For instance fields, we create implicit getter and setter methods. | 3350 // For instance fields, we create implicit getter and setter methods. |
| 3323 if (!field->has_static) { | 3351 if (!field->has_static) { |
| 3324 String& getter_name = String::Handle(Field::GetterSymbol(*field->name)); | 3352 String& getter_name = String::Handle(Field::GetterSymbol(*field->name)); |
| 3325 getter = Function::New(getter_name, RawFunction::kImplicitGetter, | 3353 getter = Function::New(getter_name, RawFunction::kImplicitGetter, |
| 3326 field->has_static, | 3354 field->has_static, |
| 3327 field->has_final, | 3355 field->has_final, |
| 3328 /* is_abstract = */ false, | 3356 /* is_abstract = */ false, |
| (...skipping 1088 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4417 if (metadata_pos >= 0) { | 4445 if (metadata_pos >= 0) { |
| 4418 library_.AddFieldMetadata(field, metadata_pos); | 4446 library_.AddFieldMetadata(field, metadata_pos); |
| 4419 } | 4447 } |
| 4420 if (CurrentToken() == Token::kASSIGN) { | 4448 if (CurrentToken() == Token::kASSIGN) { |
| 4421 ConsumeToken(); | 4449 ConsumeToken(); |
| 4422 Instance& field_value = Instance::Handle(Object::sentinel().raw()); | 4450 Instance& field_value = Instance::Handle(Object::sentinel().raw()); |
| 4423 bool has_simple_literal = false; | 4451 bool has_simple_literal = false; |
| 4424 if ((is_const || is_final) && (LookaheadToken(1) == Token::kSEMICOLON)) { | 4452 if ((is_const || is_final) && (LookaheadToken(1) == Token::kSEMICOLON)) { |
| 4425 has_simple_literal = IsSimpleLiteral(type, &field_value); | 4453 has_simple_literal = IsSimpleLiteral(type, &field_value); |
| 4426 } | 4454 } |
| 4455 const intptr_t expr_pos = TokenPos(); |
| 4427 SkipExpr(); | 4456 SkipExpr(); |
| 4428 field.set_value(field_value); | 4457 field.set_value(field_value); |
| 4429 if (!has_simple_literal) { | 4458 if (!has_simple_literal) { |
| 4430 // Create a static final getter. | 4459 // Create a static final getter. |
| 4431 String& getter_name = String::Handle(Field::GetterSymbol(var_name)); | 4460 String& getter_name = String::Handle(Field::GetterSymbol(var_name)); |
| 4432 getter = Function::New(getter_name, | 4461 getter = Function::New(getter_name, |
| 4433 RawFunction::kImplicitStaticFinalGetter, | 4462 RawFunction::kImplicitStaticFinalGetter, |
| 4434 is_static, | 4463 is_static, |
| 4435 is_const, | 4464 is_const, |
| 4436 /* is_abstract = */ false, | 4465 /* is_abstract = */ false, |
| 4437 /* is_external = */ false, | 4466 /* is_external = */ false, |
| 4438 current_class(), | 4467 current_class(), |
| 4439 name_pos); | 4468 name_pos); |
| 4440 getter.set_result_type(type); | 4469 getter.set_result_type(type); |
| 4441 top_level->functions.Add(getter); | 4470 top_level->functions.Add(getter); |
| 4471 |
| 4472 // Create initializer function. |
| 4473 const Function& init_function = Function::ZoneHandle( |
| 4474 Function::NewStaticInitializer(var_name, |
| 4475 type, |
| 4476 current_class(), |
| 4477 expr_pos)); |
| 4478 top_level->functions.Add(init_function); |
| 4442 } | 4479 } |
| 4443 } else if (is_final) { | 4480 } else if (is_final) { |
| 4444 ErrorMsg(name_pos, "missing initializer for final or const variable"); | 4481 ErrorMsg(name_pos, "missing initializer for final or const variable"); |
| 4445 } | 4482 } |
| 4446 | 4483 |
| 4447 if (CurrentToken() == Token::kCOMMA) { | 4484 if (CurrentToken() == Token::kCOMMA) { |
| 4448 ConsumeToken(); | 4485 ConsumeToken(); |
| 4449 } else if (CurrentToken() == Token::kSEMICOLON) { | 4486 } else if (CurrentToken() == Token::kSEMICOLON) { |
| 4450 ConsumeToken(); | 4487 ConsumeToken(); |
| 4451 break; | 4488 break; |
| (...skipping 6136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10588 void Parser::SkipQualIdent() { | 10625 void Parser::SkipQualIdent() { |
| 10589 ASSERT(IsIdentifier()); | 10626 ASSERT(IsIdentifier()); |
| 10590 ConsumeToken(); | 10627 ConsumeToken(); |
| 10591 if (CurrentToken() == Token::kPERIOD) { | 10628 if (CurrentToken() == Token::kPERIOD) { |
| 10592 ConsumeToken(); // Consume the kPERIOD token. | 10629 ConsumeToken(); // Consume the kPERIOD token. |
| 10593 ExpectIdentifier("identifier expected after '.'"); | 10630 ExpectIdentifier("identifier expected after '.'"); |
| 10594 } | 10631 } |
| 10595 } | 10632 } |
| 10596 | 10633 |
| 10597 } // namespace dart | 10634 } // namespace dart |
| OLD | NEW |