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

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