| 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 "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 748 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 759 ((instantiator != NULL) && instantiator->is_captured())) { | 759 ((instantiator != NULL) && instantiator->is_captured())) { |
| 760 parsed_function->set_instantiator( | 760 parsed_function->set_instantiator( |
| 761 new LoadLocalNode(node_sequence->token_pos(), instantiator)); | 761 new LoadLocalNode(node_sequence->token_pos(), instantiator)); |
| 762 } | 762 } |
| 763 } | 763 } |
| 764 | 764 |
| 765 parsed_function->set_default_parameter_values(default_parameter_values); | 765 parsed_function->set_default_parameter_values(default_parameter_values); |
| 766 } | 766 } |
| 767 | 767 |
| 768 | 768 |
| 769 // TODO(regis): Implement support for non-const final static fields (currently |
| 770 // supported "final" fields are actually const fields). |
| 769 // TODO(regis): Since a const variable is implicitly final, | 771 // TODO(regis): Since a const variable is implicitly final, |
| 770 // rename ParseStaticConstGetter to ParseStaticFinalGetter and | 772 // rename ParseStaticConstGetter to ParseStaticFinalGetter and |
| 771 // rename kConstImplicitGetter to kImplicitFinalGetter. | 773 // rename kConstImplicitGetter to kImplicitFinalGetter. |
| 772 SequenceNode* Parser::ParseStaticConstGetter(const Function& func) { | 774 SequenceNode* Parser::ParseStaticConstGetter(const Function& func) { |
| 773 TRACE_PARSER("ParseStaticConstGetter"); | 775 TRACE_PARSER("ParseStaticConstGetter"); |
| 774 ParamList params; | 776 ParamList params; |
| 775 ASSERT(func.num_fixed_parameters() == 0); // static. | 777 ASSERT(func.num_fixed_parameters() == 0); // static. |
| 776 ASSERT(!func.HasOptionalParameters()); | 778 ASSERT(!func.HasOptionalParameters()); |
| 777 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); | 779 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); |
| 778 | 780 |
| 779 // Build local scope for function and populate with the formal parameters. | 781 // Build local scope for function and populate with the formal parameters. |
| 780 OpenFunctionBlock(func); | 782 OpenFunctionBlock(func); |
| 781 AddFormalParamsToScope(¶ms, current_block_->scope); | 783 AddFormalParamsToScope(¶ms, current_block_->scope); |
| 782 | 784 |
| 783 const String& field_name = *ExpectIdentifier("field name expected"); | 785 const String& field_name = *ExpectIdentifier("field name expected"); |
| 784 const Class& field_class = Class::Handle(func.Owner()); | 786 const Class& field_class = Class::Handle(func.Owner()); |
| 785 const Field& field = | 787 const Field& field = |
| 786 Field::ZoneHandle(field_class.LookupStaticField(field_name)); | 788 Field::ZoneHandle(field_class.LookupStaticField(field_name)); |
| 787 | 789 |
| 788 // Static const fields must have an initializer. | 790 // Static const fields must have an initializer. |
| 789 ExpectToken(Token::kASSIGN); | 791 ExpectToken(Token::kASSIGN); |
| 790 | 792 |
| 791 // We don't want to use ParseConstExpr() here because we don't want | 793 // We don't want to use ParseConstExpr() here because we don't want |
| 792 // the constant folding code to create, compile and execute a code | 794 // the constant folding code to create, compile and execute a code |
| 793 // fragment to evaluate the expression. Instead, we just make sure | 795 // fragment to evaluate the expression. Instead, we just make sure |
| 794 // the static const field initializer is a constant expression and | 796 // the static const field initializer is a constant expression and |
| 795 // leave the evaluation to the getter function. | 797 // leave the evaluation to the getter function. |
| 796 const intptr_t expr_pos = TokenPos(); | 798 const intptr_t expr_pos = TokenPos(); |
| 797 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); | 799 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
| 798 | 800 // TODO(hausner): Remove is_final check below once we support |
| 799 if (field.is_const()) { | 801 // non-const finals. |
| 802 if (field.is_const() || field.is_final()) { |
| 800 // This getter will only be called once at compile time. | 803 // This getter will only be called once at compile time. |
| 801 if (expr->EvalConstExpr() == NULL) { | 804 if (expr->EvalConstExpr() == NULL) { |
| 802 ErrorMsg(expr_pos, "initializer must be a compile-time constant"); | 805 ErrorMsg(expr_pos, "initializer must be a compile time constant"); |
| 803 } | 806 } |
| 804 ReturnNode* return_node = new ReturnNode(TokenPos(), expr); | 807 ReturnNode* return_node = new ReturnNode(TokenPos(), expr); |
| 805 current_block_->statements->Add(return_node); | 808 current_block_->statements->Add(return_node); |
| 806 } else { | 809 } else { |
| 807 // This getter may be called each time the static field is accessed. | 810 // This getter may be called each time the static field is accessed. |
| 808 // The following generated code lazily initializes the field: | 811 // The following generated code lazily initializes the field: |
| 809 // if (field.value === transition_sentinel) { | 812 // if (field.value === transition_sentinel) { |
| 810 // field.value = null; | 813 // field.value = null; |
| 811 // throw("circular dependency in field initialization"); | 814 // throw("circular dependency in field initialization"); |
| 812 // } | 815 // } |
| 813 // if (field.value === sentinel) { | 816 // if (field.value === sentinel) { |
| 814 // field.value = transition_sentinel; | 817 // field.value = transition_sentinel; |
| 815 // field.value = expr; | 818 // field.value = expr; |
| 816 // } | 819 // } |
| 817 // return field.value; // Type check is executed here in checked mode. | 820 // return field.value; // Type check is executed here in checked mode. |
| 818 | 821 |
| 822 // TODO(regis): Remove this check once we support proper const fields. |
| 823 if (expr->EvalConstExpr() == NULL) { |
| 824 ErrorMsg(expr_pos, "initializer must be a compile time constant"); |
| 825 } |
| 826 |
| 819 // Generate code checking for circular dependency in field initialization. | 827 // Generate code checking for circular dependency in field initialization. |
| 820 AstNode* compare_circular = new ComparisonNode( | 828 AstNode* compare_circular = new ComparisonNode( |
| 821 TokenPos(), | 829 TokenPos(), |
| 822 Token::kEQ_STRICT, | 830 Token::kEQ_STRICT, |
| 823 new LoadStaticFieldNode(TokenPos(), field), | 831 new LoadStaticFieldNode(TokenPos(), field), |
| 824 new LiteralNode(TokenPos(), | 832 new LiteralNode(TokenPos(), |
| 825 Instance::ZoneHandle(Object::transition_sentinel()))); | 833 Instance::ZoneHandle(Object::transition_sentinel()))); |
| 826 // Set field to null prior to throwing exception, so that subsequent | 834 // Set field to null prior to throwing exception, so that subsequent |
| 827 // accesses to the field do not throw again, since initializers should only | 835 // accesses to the field do not throw again, since initializers should only |
| 828 // be executed once. | 836 // be executed once. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 851 new LiteralNode(TokenPos(), | 859 new LiteralNode(TokenPos(), |
| 852 Instance::ZoneHandle(Object::sentinel()))); | 860 Instance::ZoneHandle(Object::sentinel()))); |
| 853 SequenceNode* initialize_field = new SequenceNode(TokenPos(), NULL); | 861 SequenceNode* initialize_field = new SequenceNode(TokenPos(), NULL); |
| 854 initialize_field->Add( | 862 initialize_field->Add( |
| 855 new StoreStaticFieldNode( | 863 new StoreStaticFieldNode( |
| 856 TokenPos(), | 864 TokenPos(), |
| 857 field, | 865 field, |
| 858 new LiteralNode( | 866 new LiteralNode( |
| 859 TokenPos(), | 867 TokenPos(), |
| 860 Instance::ZoneHandle(Object::transition_sentinel())))); | 868 Instance::ZoneHandle(Object::transition_sentinel())))); |
| 861 // TODO(hausner): If evaluation of the field value throws an exception, | |
| 862 // we leave the field value as 'transition_sentinel', which is wrong. | |
| 863 // A second reference to the field later throws a circular dependency | |
| 864 // exception. The field should instead be set to null after an exception. | |
| 865 initialize_field->Add(new StoreStaticFieldNode(TokenPos(), field, expr)); | 869 initialize_field->Add(new StoreStaticFieldNode(TokenPos(), field, expr)); |
| 866 AstNode* uninitialized_check = | 870 AstNode* uninitialized_check = |
| 867 new IfNode(TokenPos(), compare_uninitialized, initialize_field, NULL); | 871 new IfNode(TokenPos(), compare_uninitialized, initialize_field, NULL); |
| 868 current_block_->statements->Add(uninitialized_check); | 872 current_block_->statements->Add(uninitialized_check); |
| 869 | 873 |
| 870 // Generate code returning the field value. | 874 // Generate code returning the field value. |
| 871 ReturnNode* return_node = | 875 ReturnNode* return_node = |
| 872 new ReturnNode(TokenPos(), | 876 new ReturnNode(TokenPos(), |
| 873 new LoadStaticFieldNode(TokenPos(), field)); | 877 new LoadStaticFieldNode(TokenPos(), field)); |
| 874 current_block_->statements->Add(return_node); | 878 current_block_->statements->Add(return_node); |
| (...skipping 1786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2661 if (field->has_const || (field->has_static && field->has_final)) { | 2665 if (field->has_const || (field->has_static && field->has_final)) { |
| 2662 ErrorMsg(field->name_pos, | 2666 ErrorMsg(field->name_pos, |
| 2663 "%s%s field '%s' must have an initializer expression", | 2667 "%s%s field '%s' must have an initializer expression", |
| 2664 field->has_static ? "static " : "", | 2668 field->has_static ? "static " : "", |
| 2665 field->has_const ? "const" : "final", | 2669 field->has_const ? "const" : "final", |
| 2666 field->name->ToCString()); | 2670 field->name->ToCString()); |
| 2667 } | 2671 } |
| 2668 } | 2672 } |
| 2669 | 2673 |
| 2670 // Create the field object. | 2674 // Create the field object. |
| 2675 // TODO(hausner): For now, all static final fields are constant. Remove |
| 2676 // this when lazy init of static variables is implemented. |
| 2671 class_field = Field::New(*field->name, | 2677 class_field = Field::New(*field->name, |
| 2672 field->has_static, | 2678 field->has_static, |
| 2673 field->has_final, | 2679 field->has_final, |
| 2674 field->has_const, | 2680 field->has_const || field->has_final, |
| 2675 current_class(), | 2681 current_class(), |
| 2676 field->name_pos); | 2682 field->name_pos); |
| 2677 class_field.set_type(*field->type); | 2683 class_field.set_type(*field->type); |
| 2678 class_field.set_has_initializer(has_initializer); | 2684 class_field.set_has_initializer(has_initializer); |
| 2679 members->AddField(class_field); | 2685 members->AddField(class_field); |
| 2680 | 2686 |
| 2681 // For static const fields, set value to "uninitialized" and | 2687 // For static const fields, set value to "uninitialized" and |
| 2682 // create a kConstImplicitGetter getter method. | 2688 // create a kConstImplicitGetter getter method. |
| 2683 if (field->has_static && has_initializer) { | 2689 if (field->has_static && has_initializer) { |
| 2684 class_field.set_value(init_value); | 2690 class_field.set_value(init_value); |
| 2685 if (!has_simple_literal) { | 2691 if (!has_simple_literal) { |
| 2686 String& getter_name = String::Handle(Field::GetterSymbol(*field->name)); | 2692 String& getter_name = String::Handle(Field::GetterSymbol(*field->name)); |
| 2687 getter = Function::New(getter_name, | 2693 getter = Function::New(getter_name, |
| 2688 RawFunction::kConstImplicitGetter, | 2694 RawFunction::kConstImplicitGetter, |
| 2689 field->has_static, | 2695 field->has_static, |
| 2690 field->has_const, | 2696 field->has_final, |
| 2691 /* is_abstract = */ false, | 2697 /* is_abstract = */ false, |
| 2692 /* is_external = */ false, | 2698 /* is_external = */ false, |
| 2693 current_class(), | 2699 current_class(), |
| 2694 field->name_pos); | 2700 field->name_pos); |
| 2695 getter.set_result_type(*field->type); | 2701 getter.set_result_type(*field->type); |
| 2696 members->AddFunction(getter); | 2702 members->AddFunction(getter); |
| 2697 } | 2703 } |
| 2698 } | 2704 } |
| 2699 | 2705 |
| 2700 // For instance fields, we create implicit getter and setter methods. | 2706 // For instance fields, we create implicit getter and setter methods. |
| (...skipping 1021 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3722 } | 3728 } |
| 3723 AddInterfaceIfUnique(interfaces_pos, all_interfaces, interface); | 3729 AddInterfaceIfUnique(interfaces_pos, all_interfaces, interface); |
| 3724 } | 3730 } |
| 3725 cls_interfaces = Array::MakeArray(all_interfaces); | 3731 cls_interfaces = Array::MakeArray(all_interfaces); |
| 3726 cls.set_interfaces(cls_interfaces); | 3732 cls.set_interfaces(cls_interfaces); |
| 3727 } | 3733 } |
| 3728 | 3734 |
| 3729 | 3735 |
| 3730 void Parser::ParseTopLevelVariable(TopLevel* top_level) { | 3736 void Parser::ParseTopLevelVariable(TopLevel* top_level) { |
| 3731 TRACE_PARSER("ParseTopLevelVariable"); | 3737 TRACE_PARSER("ParseTopLevelVariable"); |
| 3738 const bool is_final = (CurrentToken() == Token::kFINAL); |
| 3732 const bool is_const = (CurrentToken() == Token::kCONST); | 3739 const bool is_const = (CurrentToken() == Token::kCONST); |
| 3733 // Const fields are implicitly final. | |
| 3734 const bool is_final = is_const || (CurrentToken() == Token::kFINAL); | |
| 3735 const bool is_static = true; | 3740 const bool is_static = true; |
| 3736 const AbstractType& type = | 3741 const AbstractType& type = |
| 3737 AbstractType::ZoneHandle(ParseConstFinalVarOrType( | 3742 AbstractType::ZoneHandle(ParseConstFinalVarOrType( |
| 3738 FLAG_enable_type_checks ? ClassFinalizer::kTryResolve : | 3743 FLAG_enable_type_checks ? ClassFinalizer::kTryResolve : |
| 3739 ClassFinalizer::kIgnore)); | 3744 ClassFinalizer::kIgnore)); |
| 3740 Field& field = Field::Handle(); | 3745 Field& field = Field::Handle(); |
| 3741 Function& getter = Function::Handle(); | 3746 Function& getter = Function::Handle(); |
| 3742 while (true) { | 3747 while (true) { |
| 3743 const intptr_t name_pos = TokenPos(); | 3748 const intptr_t name_pos = TokenPos(); |
| 3744 String& var_name = *ExpectIdentifier("variable name expected"); | 3749 String& var_name = *ExpectIdentifier("variable name expected"); |
| 3745 | 3750 |
| 3746 if (library_.LookupLocalObject(var_name) != Object::null()) { | 3751 if (library_.LookupLocalObject(var_name) != Object::null()) { |
| 3747 ErrorMsg(name_pos, "'%s' is already defined", var_name.ToCString()); | 3752 ErrorMsg(name_pos, "'%s' is already defined", var_name.ToCString()); |
| 3748 } | 3753 } |
| 3749 String& accessor_name = String::Handle(Field::GetterName(var_name)); | 3754 String& accessor_name = String::Handle(Field::GetterName(var_name)); |
| 3750 if (library_.LookupLocalObject(accessor_name) != Object::null()) { | 3755 if (library_.LookupLocalObject(accessor_name) != Object::null()) { |
| 3751 ErrorMsg(name_pos, "getter for '%s' is already defined", | 3756 ErrorMsg(name_pos, "getter for '%s' is already defined", |
| 3752 var_name.ToCString()); | 3757 var_name.ToCString()); |
| 3753 } | 3758 } |
| 3754 accessor_name = Field::SetterName(var_name); | 3759 accessor_name = Field::SetterName(var_name); |
| 3755 if (library_.LookupLocalObject(accessor_name) != Object::null()) { | 3760 if (library_.LookupLocalObject(accessor_name) != Object::null()) { |
| 3756 ErrorMsg(name_pos, "setter for '%s' is already defined", | 3761 ErrorMsg(name_pos, "setter for '%s' is already defined", |
| 3757 var_name.ToCString()); | 3762 var_name.ToCString()); |
| 3758 } | 3763 } |
| 3759 | 3764 |
| 3760 field = Field::New(var_name, is_static, is_final, is_const, | 3765 // TODO(hausner): const and final are equivalent at the moment. |
| 3761 current_class(), name_pos); | 3766 field = Field::New(var_name, |
| 3767 is_static, |
| 3768 is_final || is_const, // Const fields are also final. |
| 3769 is_const || is_final, |
| 3770 current_class(), |
| 3771 name_pos); |
| 3762 field.set_type(type); | 3772 field.set_type(type); |
| 3763 field.set_value(Instance::Handle(Instance::null())); | 3773 field.set_value(Instance::Handle(Instance::null())); |
| 3764 top_level->fields.Add(field); | 3774 top_level->fields.Add(field); |
| 3765 library_.AddObject(field, var_name); | 3775 library_.AddObject(field, var_name); |
| 3766 if (CurrentToken() == Token::kASSIGN) { | 3776 if (CurrentToken() == Token::kASSIGN) { |
| 3767 ConsumeToken(); | 3777 ConsumeToken(); |
| 3768 Instance& field_value = Instance::Handle(Object::sentinel()); | 3778 Instance& field_value = Instance::Handle(Object::sentinel()); |
| 3769 bool has_simple_literal = false; | 3779 bool has_simple_literal = false; |
| 3770 if (is_final && (LookaheadToken(1) == Token::kSEMICOLON)) { | 3780 if ((is_final || is_const) && (LookaheadToken(1) == Token::kSEMICOLON)) { |
| 3771 has_simple_literal = IsSimpleLiteral(type, &field_value); | 3781 has_simple_literal = IsSimpleLiteral(type, &field_value); |
| 3772 } | 3782 } |
| 3773 SkipExpr(); | 3783 SkipExpr(); |
| 3774 field.set_value(field_value); | 3784 field.set_value(field_value); |
| 3775 if (!has_simple_literal) { | 3785 if (!has_simple_literal) { |
| 3776 // Create a static const getter. | 3786 // Create a static const getter. |
| 3777 String& getter_name = String::ZoneHandle(Field::GetterSymbol(var_name)); | 3787 String& getter_name = String::ZoneHandle(Field::GetterSymbol(var_name)); |
| 3778 getter = Function::New(getter_name, | 3788 getter = Function::New(getter_name, |
| 3779 RawFunction::kConstImplicitGetter, | 3789 RawFunction::kConstImplicitGetter, |
| 3780 is_static, | 3790 is_static, |
| 3781 is_const, | 3791 is_final, |
| 3782 /* is_abstract = */ false, | 3792 /* is_abstract = */ false, |
| 3783 /* is_external = */ false, | 3793 /* is_external = */ false, |
| 3784 current_class(), | 3794 current_class(), |
| 3785 name_pos); | 3795 name_pos); |
| 3786 getter.set_result_type(type); | 3796 getter.set_result_type(type); |
| 3787 top_level->functions.Add(getter); | 3797 top_level->functions.Add(getter); |
| 3788 } | 3798 } |
| 3789 } else if (is_final) { | 3799 |
| 3800 } else if (is_final || is_const) { |
| 3790 ErrorMsg(name_pos, "missing initializer for final or const variable"); | 3801 ErrorMsg(name_pos, "missing initializer for final or const variable"); |
| 3791 } | 3802 } |
| 3792 | 3803 |
| 3793 if (CurrentToken() == Token::kCOMMA) { | 3804 if (CurrentToken() == Token::kCOMMA) { |
| 3794 ConsumeToken(); | 3805 ConsumeToken(); |
| 3795 } else if (CurrentToken() == Token::kSEMICOLON) { | 3806 } else if (CurrentToken() == Token::kSEMICOLON) { |
| 3796 ConsumeToken(); | 3807 ConsumeToken(); |
| 3797 break; | 3808 break; |
| 3798 } else { | 3809 } else { |
| 3799 ExpectSemicolon(); // Reports error. | 3810 ExpectSemicolon(); // Reports error. |
| (...skipping 2969 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6769 } | 6780 } |
| 6770 | 6781 |
| 6771 | 6782 |
| 6772 // Evaluates the value of the compile time constant expression | 6783 // Evaluates the value of the compile time constant expression |
| 6773 // and returns a literal node for the value. | 6784 // and returns a literal node for the value. |
| 6774 AstNode* Parser::FoldConstExpr(intptr_t expr_pos, AstNode* expr) { | 6785 AstNode* Parser::FoldConstExpr(intptr_t expr_pos, AstNode* expr) { |
| 6775 if (expr->IsLiteralNode()) { | 6786 if (expr->IsLiteralNode()) { |
| 6776 return expr; | 6787 return expr; |
| 6777 } | 6788 } |
| 6778 if (expr->EvalConstExpr() == NULL) { | 6789 if (expr->EvalConstExpr() == NULL) { |
| 6779 ErrorMsg(expr_pos, "expression must be a compile-time constant"); | 6790 ErrorMsg(expr_pos, "expression must be a compile time constant"); |
| 6780 } | 6791 } |
| 6781 return new LiteralNode(expr_pos, EvaluateConstExpr(expr)); | 6792 return new LiteralNode(expr_pos, EvaluateConstExpr(expr)); |
| 6782 } | 6793 } |
| 6783 | 6794 |
| 6784 | 6795 |
| 6785 // A compound assignment consists of a store and a load part. In order | 6796 // A compound assignment consists of a store and a load part. In order |
| 6786 // to control inputs with potential side effects, the store part stores any | 6797 // to control inputs with potential side effects, the store part stores any |
| 6787 // side effect creating inputs into locals. The load part reads then from | 6798 // side effect creating inputs into locals. The load part reads then from |
| 6788 // those locals. If expr may have side effects, it will be split into two new | 6799 // those locals. If expr may have side effects, it will be split into two new |
| 6789 // left and right nodes. 'expr' becomes the right node, left node is returned as | 6800 // left and right nodes. 'expr' becomes the right node, left node is returned as |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6924 expr = FoldConstExpr(expr_pos, expr); | 6935 expr = FoldConstExpr(expr_pos, expr); |
| 6925 } | 6936 } |
| 6926 return expr; | 6937 return expr; |
| 6927 } | 6938 } |
| 6928 // Assignment expressions. | 6939 // Assignment expressions. |
| 6929 Token::Kind assignment_op = CurrentToken(); | 6940 Token::Kind assignment_op = CurrentToken(); |
| 6930 const intptr_t assignment_pos = TokenPos(); | 6941 const intptr_t assignment_pos = TokenPos(); |
| 6931 ConsumeToken(); | 6942 ConsumeToken(); |
| 6932 const intptr_t right_expr_pos = TokenPos(); | 6943 const intptr_t right_expr_pos = TokenPos(); |
| 6933 if (require_compiletime_const && (assignment_op != Token::kASSIGN)) { | 6944 if (require_compiletime_const && (assignment_op != Token::kASSIGN)) { |
| 6934 ErrorMsg(right_expr_pos, "expression must be a compile-time constant"); | 6945 ErrorMsg(right_expr_pos, "expression must be a compile time constant"); |
| 6935 } | 6946 } |
| 6936 AstNode* right_expr = ParseExpr(require_compiletime_const, consume_cascades); | 6947 AstNode* right_expr = ParseExpr(require_compiletime_const, consume_cascades); |
| 6937 AstNode* left_expr = expr; | 6948 AstNode* left_expr = expr; |
| 6938 if (assignment_op != Token::kASSIGN) { | 6949 if (assignment_op != Token::kASSIGN) { |
| 6939 // Compound assignment: store inputs with side effects into temp. locals. | 6950 // Compound assignment: store inputs with side effects into temp. locals. |
| 6940 left_expr = PrepareCompoundAssignmentNodes(&expr); | 6951 left_expr = PrepareCompoundAssignmentNodes(&expr); |
| 6941 } | 6952 } |
| 6942 right_expr = | 6953 right_expr = |
| 6943 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr); | 6954 ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr); |
| 6944 AstNode* assign_expr = CreateAssignmentNode(left_expr, right_expr); | 6955 AstNode* assign_expr = CreateAssignmentNode(left_expr, right_expr); |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7163 intptr_t ident_pos) { | 7174 intptr_t ident_pos) { |
| 7164 // If the static field has an initializer, initialize the field at compile | 7175 // If the static field has an initializer, initialize the field at compile |
| 7165 // time, which is only possible if the field is const. | 7176 // time, which is only possible if the field is const. |
| 7166 AstNode* initializing_getter = RunStaticFieldInitializer(field); | 7177 AstNode* initializing_getter = RunStaticFieldInitializer(field); |
| 7167 if (initializing_getter != NULL) { | 7178 if (initializing_getter != NULL) { |
| 7168 // The field is not yet initialized and could not be initialized at compile | 7179 // The field is not yet initialized and could not be initialized at compile |
| 7169 // time. The getter will initialize the field. | 7180 // time. The getter will initialize the field. |
| 7170 return initializing_getter; | 7181 return initializing_getter; |
| 7171 } | 7182 } |
| 7172 // The field is initialized. | 7183 // The field is initialized. |
| 7173 if (field.is_const()) { | 7184 // TODO(hausner): Remove the is_final check when we support non-const |
| 7185 // final static variables. |
| 7186 if (field.is_const() || field.is_final()) { |
| 7174 ASSERT(field.value() != Object::sentinel()); | 7187 ASSERT(field.value() != Object::sentinel()); |
| 7175 ASSERT(field.value() != Object::transition_sentinel()); | 7188 ASSERT(field.value() != Object::transition_sentinel()); |
| 7176 return new LiteralNode(ident_pos, Instance::ZoneHandle(field.value())); | 7189 return new LiteralNode(ident_pos, Instance::ZoneHandle(field.value())); |
| 7177 } | 7190 } |
| 7178 // Access the field directly. | 7191 // Access the field directly. |
| 7179 return new LoadStaticFieldNode(ident_pos, Field::ZoneHandle(field.raw())); | 7192 return new LoadStaticFieldNode(ident_pos, Field::ZoneHandle(field.raw())); |
| 7180 } | 7193 } |
| 7181 | 7194 |
| 7182 | 7195 |
| 7183 AstNode* Parser::ParseStaticFieldAccess(const Class& cls, | 7196 AstNode* Parser::ParseStaticFieldAccess(const Class& cls, |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7732 } | 7745 } |
| 7733 | 7746 |
| 7734 | 7747 |
| 7735 // If the field is already initialized, return no ast (NULL). | 7748 // If the field is already initialized, return no ast (NULL). |
| 7736 // Otherwise, if the field is constant, initialize the field and return no ast. | 7749 // Otherwise, if the field is constant, initialize the field and return no ast. |
| 7737 // If the field is not initialized and not const, return the ast for the getter. | 7750 // If the field is not initialized and not const, return the ast for the getter. |
| 7738 AstNode* Parser::RunStaticFieldInitializer(const Field& field) { | 7751 AstNode* Parser::RunStaticFieldInitializer(const Field& field) { |
| 7739 ASSERT(field.is_static()); | 7752 ASSERT(field.is_static()); |
| 7740 const Instance& value = Instance::Handle(field.value()); | 7753 const Instance& value = Instance::Handle(field.value()); |
| 7741 if (value.raw() == Object::transition_sentinel()) { | 7754 if (value.raw() == Object::transition_sentinel()) { |
| 7742 if (field.is_const()) { | 7755 // TODO(hausner): Remove the check for is_final() once we support |
| 7756 // non-const final fields. |
| 7757 if (field.is_const() || field.is_final()) { |
| 7743 ErrorMsg("circular dependency while initializing static field '%s'", | 7758 ErrorMsg("circular dependency while initializing static field '%s'", |
| 7744 String::Handle(field.name()).ToCString()); | 7759 String::Handle(field.name()).ToCString()); |
| 7745 } else { | 7760 } else { |
| 7746 // The implicit static getter will throw the exception if necessary. | 7761 // The implicit static getter will throw the exception if necessary. |
| 7747 return new StaticGetterNode(TokenPos(), | 7762 return new StaticGetterNode(TokenPos(), |
| 7748 NULL, | 7763 NULL, |
| 7749 false, | 7764 false, |
| 7750 Class::ZoneHandle(field.owner()), | 7765 Class::ZoneHandle(field.owner()), |
| 7751 String::ZoneHandle(field.name())); | 7766 String::ZoneHandle(field.name())); |
| 7752 } | 7767 } |
| 7753 } else if (value.raw() == Object::sentinel()) { | 7768 } else if (value.raw() == Object::sentinel()) { |
| 7754 // This field has not been referenced yet and thus the value has | 7769 // This field has not been referenced yet and thus the value has |
| 7755 // not been evaluated. If the field is const, call the static getter method | 7770 // not been evaluated. If the field is const, call the static getter method |
| 7756 // to evaluate the expression and canonicalize the value. | 7771 // to evaluate the expression and canonicalize the value. |
| 7757 if (field.is_const()) { | 7772 // TODO(hausner): Remove the check for is_final() once we support |
| 7773 // non-const final fields. |
| 7774 if (field.is_const() || field.is_final()) { |
| 7758 field.set_value(Instance::Handle(Object::transition_sentinel())); | 7775 field.set_value(Instance::Handle(Object::transition_sentinel())); |
| 7759 const String& field_name = String::Handle(field.name()); | 7776 const String& field_name = String::Handle(field.name()); |
| 7760 const String& getter_name = | 7777 const String& getter_name = |
| 7761 String::Handle(Field::GetterName(field_name)); | 7778 String::Handle(Field::GetterName(field_name)); |
| 7762 const Class& cls = Class::Handle(field.owner()); | 7779 const Class& cls = Class::Handle(field.owner()); |
| 7763 GrowableArray<const Object*> arguments; // no arguments. | 7780 GrowableArray<const Object*> arguments; // no arguments. |
| 7764 const int kNumArguments = 0; // no arguments. | 7781 const int kNumArguments = 0; // no arguments. |
| 7765 const Array& kNoArgumentNames = Array::Handle(); | 7782 const Array& kNoArgumentNames = Array::Handle(); |
| 7766 const Function& func = | 7783 const Function& func = |
| 7767 Function::Handle(Resolver::ResolveStatic(cls, | 7784 Function::Handle(Resolver::ResolveStatic(cls, |
| 7768 getter_name, | 7785 getter_name, |
| 7769 kNumArguments, | 7786 kNumArguments, |
| 7770 kNoArgumentNames, | 7787 kNoArgumentNames, |
| 7771 Resolver::kIsQualified)); | 7788 Resolver::kIsQualified)); |
| 7772 ASSERT(!func.IsNull()); | 7789 ASSERT(!func.IsNull()); |
| 7773 ASSERT(func.kind() == RawFunction::kConstImplicitGetter); | 7790 ASSERT(func.kind() == RawFunction::kConstImplicitGetter); |
| 7774 Object& const_value = Object::Handle( | 7791 Object& const_value = Object::Handle( |
| 7775 DartEntry::InvokeStatic(func, arguments, kNoArgumentNames)); | 7792 DartEntry::InvokeStatic(func, arguments, kNoArgumentNames)); |
| 7776 if (const_value.IsError()) { | 7793 if (const_value.IsError()) { |
| 7777 const Error& error = Error::Cast(const_value); | 7794 const Error& error = Error::Cast(const_value); |
| 7778 if (error.IsUnhandledException()) { | 7795 if (error.IsUnhandledException()) { |
| 7779 field.set_value(Instance::Handle()); | 7796 field.set_value(Instance::Handle()); |
| 7780 // It is a compile-time error if evaluation of a compile-time constant | 7797 // It is a compile-time error if evaluation of a compile-time constant |
| 7781 // would raise an exception. | 7798 // would raise an exception. |
| 7782 AppendErrorMsg(error, TokenPos(), | 7799 AppendErrorMsg(error, TokenPos(), |
| 7783 "error initializing const field '%s'", | 7800 "error initializing final field '%s'", |
| 7784 String::Handle(field.name()).ToCString()); | 7801 String::Handle(field.name()).ToCString()); |
| 7785 } else { | 7802 } else { |
| 7786 Isolate::Current()->long_jump_base()->Jump(1, error); | 7803 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 7787 } | 7804 } |
| 7788 } | 7805 } |
| 7789 ASSERT(const_value.IsNull() || const_value.IsInstance()); | 7806 ASSERT(const_value.IsNull() || const_value.IsInstance()); |
| 7790 Instance& instance = Instance::Handle(); | 7807 Instance& instance = Instance::Handle(); |
| 7791 instance ^= const_value.raw(); | 7808 instance ^= const_value.raw(); |
| 7792 if (!instance.IsNull()) { | 7809 if (!instance.IsNull()) { |
| 7793 instance ^= instance.Canonicalize(); | 7810 instance ^= instance.Canonicalize(); |
| (...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8543 // comma after the last entry. | 8560 // comma after the last entry. |
| 8544 const String& dst_name = String::ZoneHandle(Symbols::ListLiteralElement()); | 8561 const String& dst_name = String::ZoneHandle(Symbols::ListLiteralElement()); |
| 8545 while (CurrentToken() != Token::kRBRACE) { | 8562 while (CurrentToken() != Token::kRBRACE) { |
| 8546 AstNode* key = NULL; | 8563 AstNode* key = NULL; |
| 8547 if (CurrentToken() == Token::kSTRING) { | 8564 if (CurrentToken() == Token::kSTRING) { |
| 8548 key = ParseStringLiteral(); | 8565 key = ParseStringLiteral(); |
| 8549 } | 8566 } |
| 8550 if (key == NULL) { | 8567 if (key == NULL) { |
| 8551 ErrorMsg("map entry key must be string literal"); | 8568 ErrorMsg("map entry key must be string literal"); |
| 8552 } else if (is_const && !key->IsLiteralNode()) { | 8569 } else if (is_const && !key->IsLiteralNode()) { |
| 8553 ErrorMsg("map entry key must be compile-time constant string"); | 8570 ErrorMsg("map entry key must be compile time constant string"); |
| 8554 } | 8571 } |
| 8555 ExpectToken(Token::kCOLON); | 8572 ExpectToken(Token::kCOLON); |
| 8556 const bool saved_mode = SetAllowFunctionLiterals(true); | 8573 const bool saved_mode = SetAllowFunctionLiterals(true); |
| 8557 const intptr_t value_pos = TokenPos(); | 8574 const intptr_t value_pos = TokenPos(); |
| 8558 AstNode* value = ParseExpr(is_const, kConsumeCascades); | 8575 AstNode* value = ParseExpr(is_const, kConsumeCascades); |
| 8559 SetAllowFunctionLiterals(saved_mode); | 8576 SetAllowFunctionLiterals(saved_mode); |
| 8560 if (FLAG_enable_type_checks && | 8577 if (FLAG_enable_type_checks && |
| 8561 !is_const && | 8578 !is_const && |
| 8562 !value_type.IsDynamicType()) { | 8579 !value_type.IsDynamicType()) { |
| 8563 value = new AssignableNode(value_pos, | 8580 value = new AssignableNode(value_pos, |
| (...skipping 976 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9540 void Parser::SkipQualIdent() { | 9557 void Parser::SkipQualIdent() { |
| 9541 ASSERT(IsIdentifier()); | 9558 ASSERT(IsIdentifier()); |
| 9542 ConsumeToken(); | 9559 ConsumeToken(); |
| 9543 if (CurrentToken() == Token::kPERIOD) { | 9560 if (CurrentToken() == Token::kPERIOD) { |
| 9544 ConsumeToken(); // Consume the kPERIOD token. | 9561 ConsumeToken(); // Consume the kPERIOD token. |
| 9545 ExpectIdentifier("identifier expected after '.'"); | 9562 ExpectIdentifier("identifier expected after '.'"); |
| 9546 } | 9563 } |
| 9547 } | 9564 } |
| 9548 | 9565 |
| 9549 } // namespace dart | 9566 } // namespace dart |
| OLD | NEW |