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

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

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

Powered by Google App Engine
This is Rietveld 408576698