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

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

Issue 10928169: Revert change 12289 (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).
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(&params, current_block_->scope); 783 AddFormalParamsToScope(&params, 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
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
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
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
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
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
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
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
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
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
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