OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/parser.h" | 5 #include "vm/parser.h" |
6 | 6 |
7 #include "vm/bigint_operations.h" | 7 #include "vm/bigint_operations.h" |
8 #include "vm/class_finalizer.h" | 8 #include "vm/class_finalizer.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/compiler_stats.h" | 10 #include "vm/compiler_stats.h" |
(...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
841 // field.value = transition_sentinel; | 841 // field.value = transition_sentinel; |
842 // field.value = expr; | 842 // field.value = expr; |
843 // } | 843 // } |
844 // return field.value; // Type check is executed here in checked mode. | 844 // return field.value; // Type check is executed here in checked mode. |
845 | 845 |
846 // Generate code checking for circular dependency in field initialization. | 846 // Generate code checking for circular dependency in field initialization. |
847 AstNode* compare_circular = new ComparisonNode( | 847 AstNode* compare_circular = new ComparisonNode( |
848 TokenPos(), | 848 TokenPos(), |
849 Token::kEQ_STRICT, | 849 Token::kEQ_STRICT, |
850 new LoadStaticFieldNode(TokenPos(), field), | 850 new LoadStaticFieldNode(TokenPos(), field), |
851 new LiteralNode(TokenPos(), | 851 new LiteralNode(TokenPos(), Object::transition_sentinel())); |
852 Instance::ZoneHandle(Object::transition_sentinel()))); | |
853 // Set field to null prior to throwing exception, so that subsequent | 852 // Set field to null prior to throwing exception, so that subsequent |
854 // accesses to the field do not throw again, since initializers should only | 853 // accesses to the field do not throw again, since initializers should only |
855 // be executed once. | 854 // be executed once. |
856 SequenceNode* report_circular = new SequenceNode(TokenPos(), NULL); | 855 SequenceNode* report_circular = new SequenceNode(TokenPos(), NULL); |
857 report_circular->Add( | 856 report_circular->Add( |
858 new StoreStaticFieldNode( | 857 new StoreStaticFieldNode( |
859 TokenPos(), | 858 TokenPos(), |
860 field, | 859 field, |
861 new LiteralNode(TokenPos(), Instance::ZoneHandle()))); | 860 new LiteralNode(TokenPos(), Instance::ZoneHandle()))); |
862 // TODO(regis): Exception to throw is not specified by spec. | 861 // TODO(regis): Exception to throw is not specified by spec. |
863 const String& circular_error = String::ZoneHandle( | 862 const String& circular_error = String::ZoneHandle( |
864 Symbols::New("circular dependency in field initialization")); | 863 Symbols::New("circular dependency in field initialization")); |
865 report_circular->Add( | 864 report_circular->Add( |
866 new ThrowNode(TokenPos(), | 865 new ThrowNode(TokenPos(), |
867 new LiteralNode(TokenPos(), circular_error), | 866 new LiteralNode(TokenPos(), circular_error), |
868 NULL)); | 867 NULL)); |
869 AstNode* circular_check = | 868 AstNode* circular_check = |
870 new IfNode(TokenPos(), compare_circular, report_circular, NULL); | 869 new IfNode(TokenPos(), compare_circular, report_circular, NULL); |
871 current_block_->statements->Add(circular_check); | 870 current_block_->statements->Add(circular_check); |
872 | 871 |
873 // Generate code checking for uninitialized field. | 872 // Generate code checking for uninitialized field. |
874 AstNode* compare_uninitialized = new ComparisonNode( | 873 AstNode* compare_uninitialized = new ComparisonNode( |
875 TokenPos(), | 874 TokenPos(), |
876 Token::kEQ_STRICT, | 875 Token::kEQ_STRICT, |
877 new LoadStaticFieldNode(TokenPos(), field), | 876 new LoadStaticFieldNode(TokenPos(), field), |
878 new LiteralNode(TokenPos(), | 877 new LiteralNode(TokenPos(), Object::sentinel())); |
879 Instance::ZoneHandle(Object::sentinel()))); | |
880 SequenceNode* initialize_field = new SequenceNode(TokenPos(), NULL); | 878 SequenceNode* initialize_field = new SequenceNode(TokenPos(), NULL); |
881 initialize_field->Add( | 879 initialize_field->Add( |
882 new StoreStaticFieldNode( | 880 new StoreStaticFieldNode( |
883 TokenPos(), | 881 TokenPos(), |
884 field, | 882 field, |
885 new LiteralNode( | 883 new LiteralNode( |
886 TokenPos(), | 884 TokenPos(), Object::transition_sentinel()))); |
887 Instance::ZoneHandle(Object::transition_sentinel())))); | |
888 // TODO(hausner): If evaluation of the field value throws an exception, | 885 // TODO(hausner): If evaluation of the field value throws an exception, |
889 // we leave the field value as 'transition_sentinel', which is wrong. | 886 // we leave the field value as 'transition_sentinel', which is wrong. |
890 // A second reference to the field later throws a circular dependency | 887 // A second reference to the field later throws a circular dependency |
891 // exception. The field should instead be set to null after an exception. | 888 // exception. The field should instead be set to null after an exception. |
892 initialize_field->Add(new StoreStaticFieldNode(TokenPos(), field, expr)); | 889 initialize_field->Add(new StoreStaticFieldNode(TokenPos(), field, expr)); |
893 AstNode* uninitialized_check = | 890 AstNode* uninitialized_check = |
894 new IfNode(TokenPos(), compare_uninitialized, initialize_field, NULL); | 891 new IfNode(TokenPos(), compare_uninitialized, initialize_field, NULL); |
895 current_block_->statements->Add(uninitialized_check); | 892 current_block_->statements->Add(uninitialized_check); |
896 | 893 |
897 // Generate code returning the field value. | 894 // Generate code returning the field value. |
(...skipping 1812 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2710 } | 2707 } |
2711 Function& getter = Function::Handle(); | 2708 Function& getter = Function::Handle(); |
2712 Function& setter = Function::Handle(); | 2709 Function& setter = Function::Handle(); |
2713 Field& class_field = Field::Handle(); | 2710 Field& class_field = Field::Handle(); |
2714 Instance& init_value = Instance::Handle(); | 2711 Instance& init_value = Instance::Handle(); |
2715 while (true) { | 2712 while (true) { |
2716 bool has_initializer = CurrentToken() == Token::kASSIGN; | 2713 bool has_initializer = CurrentToken() == Token::kASSIGN; |
2717 bool has_simple_literal = false; | 2714 bool has_simple_literal = false; |
2718 if (has_initializer) { | 2715 if (has_initializer) { |
2719 ConsumeToken(); | 2716 ConsumeToken(); |
2720 init_value = Object::sentinel(); | 2717 init_value = Object::sentinel().raw(); |
2721 // For static const fields, the initialization expression | 2718 // For static const fields, the initialization expression |
2722 // will be parsed through the kConstImplicitGetter method | 2719 // will be parsed through the kConstImplicitGetter method |
2723 // invocation/compilation. | 2720 // invocation/compilation. |
2724 // For instance fields, the expression is parsed when a constructor | 2721 // For instance fields, the expression is parsed when a constructor |
2725 // is compiled. | 2722 // is compiled. |
2726 // For static fields with very simple initializer expressions | 2723 // For static fields with very simple initializer expressions |
2727 // (e.g. a literal number or string) we optimize away the | 2724 // (e.g. a literal number or string) we optimize away the |
2728 // kConstImplicitGetter and initialize the field here. | 2725 // kConstImplicitGetter and initialize the field here. |
2729 | 2726 |
2730 if (field->has_static && (field->has_final || field->has_const) && | 2727 if (field->has_static && (field->has_final || field->has_const) && |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3098 cls ^= obj.raw(); | 3095 cls ^= obj.raw(); |
3099 if (is_patch) { | 3096 if (is_patch) { |
3100 String& patch = String::Handle(Symbols::New("patch ")); | 3097 String& patch = String::Handle(Symbols::New("patch ")); |
3101 patch = String::Concat(patch, class_name); | 3098 patch = String::Concat(patch, class_name); |
3102 patch = Symbols::New(patch); | 3099 patch = Symbols::New(patch); |
3103 cls = Class::New(patch, script_, classname_pos); | 3100 cls = Class::New(patch, script_, classname_pos); |
3104 cls.set_library(library_); | 3101 cls.set_library(library_); |
3105 } else { | 3102 } else { |
3106 // Not patching a class, but it has been found. This must be one of the | 3103 // Not patching a class, but it has been found. This must be one of the |
3107 // pre-registered classes from object.cc or a duplicate definition. | 3104 // pre-registered classes from object.cc or a duplicate definition. |
3108 if (cls.functions() != Object::empty_array()) { | 3105 if (cls.functions() != Object::empty_array().raw()) { |
3109 ErrorMsg(classname_pos, "class '%s' is already defined", | 3106 ErrorMsg(classname_pos, "class '%s' is already defined", |
3110 class_name.ToCString()); | 3107 class_name.ToCString()); |
3111 } | 3108 } |
3112 // Pre-registered classes need their scripts connected at this time. | 3109 // Pre-registered classes need their scripts connected at this time. |
3113 cls.set_script(script_); | 3110 cls.set_script(script_); |
3114 } | 3111 } |
3115 } | 3112 } |
3116 ASSERT(!cls.IsNull()); | 3113 ASSERT(!cls.IsNull()); |
3117 ASSERT(cls.functions() == Object::empty_array()); | 3114 ASSERT(cls.functions() == Object::empty_array().raw()); |
3118 set_current_class(cls); | 3115 set_current_class(cls); |
3119 ParseTypeParameters(cls); | 3116 ParseTypeParameters(cls); |
3120 Type& super_type = Type::Handle(); | 3117 Type& super_type = Type::Handle(); |
3121 if (CurrentToken() == Token::kEXTENDS) { | 3118 if (CurrentToken() == Token::kEXTENDS) { |
3122 ConsumeToken(); | 3119 ConsumeToken(); |
3123 const intptr_t type_pos = TokenPos(); | 3120 const intptr_t type_pos = TokenPos(); |
3124 const AbstractType& type = AbstractType::Handle( | 3121 const AbstractType& type = AbstractType::Handle( |
3125 ParseType(ClassFinalizer::kTryResolve)); | 3122 ParseType(ClassFinalizer::kTryResolve)); |
3126 if (type.IsTypeParameter()) { | 3123 if (type.IsTypeParameter()) { |
3127 ErrorMsg(type_pos, | 3124 ErrorMsg(type_pos, |
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3684 } | 3681 } |
3685 | 3682 |
3686 field = Field::New(var_name, is_static, is_final, is_const, | 3683 field = Field::New(var_name, is_static, is_final, is_const, |
3687 current_class(), name_pos); | 3684 current_class(), name_pos); |
3688 field.set_type(type); | 3685 field.set_type(type); |
3689 field.set_value(Instance::Handle(Instance::null())); | 3686 field.set_value(Instance::Handle(Instance::null())); |
3690 top_level->fields.Add(field); | 3687 top_level->fields.Add(field); |
3691 library_.AddObject(field, var_name); | 3688 library_.AddObject(field, var_name); |
3692 if (CurrentToken() == Token::kASSIGN) { | 3689 if (CurrentToken() == Token::kASSIGN) { |
3693 ConsumeToken(); | 3690 ConsumeToken(); |
3694 Instance& field_value = Instance::Handle(Object::sentinel()); | 3691 Instance& field_value = Instance::Handle(Object::sentinel().raw()); |
3695 bool has_simple_literal = false; | 3692 bool has_simple_literal = false; |
3696 if (is_final && (LookaheadToken(1) == Token::kSEMICOLON)) { | 3693 if (is_final && (LookaheadToken(1) == Token::kSEMICOLON)) { |
3697 has_simple_literal = IsSimpleLiteral(type, &field_value); | 3694 has_simple_literal = IsSimpleLiteral(type, &field_value); |
3698 } | 3695 } |
3699 SkipExpr(); | 3696 SkipExpr(); |
3700 field.set_value(field_value); | 3697 field.set_value(field_value); |
3701 if (!has_simple_literal) { | 3698 if (!has_simple_literal) { |
3702 // Create a static const getter. | 3699 // Create a static const getter. |
3703 String& getter_name = String::ZoneHandle(Field::GetterSymbol(var_name)); | 3700 String& getter_name = String::ZoneHandle(Field::GetterSymbol(var_name)); |
3704 getter = Function::New(getter_name, | 3701 getter = Function::New(getter_name, |
(...skipping 3496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7201 // If the static field has an initializer, initialize the field at compile | 7198 // If the static field has an initializer, initialize the field at compile |
7202 // time, which is only possible if the field is const. | 7199 // time, which is only possible if the field is const. |
7203 AstNode* initializing_getter = RunStaticFieldInitializer(field); | 7200 AstNode* initializing_getter = RunStaticFieldInitializer(field); |
7204 if (initializing_getter != NULL) { | 7201 if (initializing_getter != NULL) { |
7205 // The field is not yet initialized and could not be initialized at compile | 7202 // The field is not yet initialized and could not be initialized at compile |
7206 // time. The getter will initialize the field. | 7203 // time. The getter will initialize the field. |
7207 return initializing_getter; | 7204 return initializing_getter; |
7208 } | 7205 } |
7209 // The field is initialized. | 7206 // The field is initialized. |
7210 if (field.is_const()) { | 7207 if (field.is_const()) { |
7211 ASSERT(field.value() != Object::sentinel()); | 7208 ASSERT(field.value() != Object::sentinel().raw()); |
7212 ASSERT(field.value() != Object::transition_sentinel()); | 7209 ASSERT(field.value() != Object::transition_sentinel().raw()); |
7213 return new LiteralNode(ident_pos, Instance::ZoneHandle(field.value())); | 7210 return new LiteralNode(ident_pos, Instance::ZoneHandle(field.value())); |
7214 } | 7211 } |
7215 // Access the field directly. | 7212 // Access the field directly. |
7216 return new LoadStaticFieldNode(ident_pos, Field::ZoneHandle(field.raw())); | 7213 return new LoadStaticFieldNode(ident_pos, Field::ZoneHandle(field.raw())); |
7217 } | 7214 } |
7218 | 7215 |
7219 | 7216 |
7220 AstNode* Parser::ParseStaticFieldAccess(const Class& cls, | 7217 AstNode* Parser::ParseStaticFieldAccess(const Class& cls, |
7221 const String& field_name, | 7218 const String& field_name, |
7222 intptr_t ident_pos, | 7219 intptr_t ident_pos, |
(...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7815 return current_class().NumTypeParameters() > 0; | 7812 return current_class().NumTypeParameters() > 0; |
7816 } | 7813 } |
7817 | 7814 |
7818 | 7815 |
7819 // If the field is already initialized, return no ast (NULL). | 7816 // If the field is already initialized, return no ast (NULL). |
7820 // Otherwise, if the field is constant, initialize the field and return no ast. | 7817 // Otherwise, if the field is constant, initialize the field and return no ast. |
7821 // If the field is not initialized and not const, return the ast for the getter. | 7818 // If the field is not initialized and not const, return the ast for the getter. |
7822 AstNode* Parser::RunStaticFieldInitializer(const Field& field) { | 7819 AstNode* Parser::RunStaticFieldInitializer(const Field& field) { |
7823 ASSERT(field.is_static()); | 7820 ASSERT(field.is_static()); |
7824 const Instance& value = Instance::Handle(field.value()); | 7821 const Instance& value = Instance::Handle(field.value()); |
7825 if (value.raw() == Object::transition_sentinel()) { | 7822 if (value.raw() == Object::transition_sentinel().raw()) { |
7826 if (field.is_const()) { | 7823 if (field.is_const()) { |
7827 ErrorMsg("circular dependency while initializing static field '%s'", | 7824 ErrorMsg("circular dependency while initializing static field '%s'", |
7828 String::Handle(field.name()).ToCString()); | 7825 String::Handle(field.name()).ToCString()); |
7829 } else { | 7826 } else { |
7830 // The implicit static getter will throw the exception if necessary. | 7827 // The implicit static getter will throw the exception if necessary. |
7831 return new StaticGetterNode(TokenPos(), | 7828 return new StaticGetterNode(TokenPos(), |
7832 NULL, | 7829 NULL, |
7833 false, | 7830 false, |
7834 Class::ZoneHandle(field.owner()), | 7831 Class::ZoneHandle(field.owner()), |
7835 String::ZoneHandle(field.name())); | 7832 String::ZoneHandle(field.name())); |
7836 } | 7833 } |
7837 } else if (value.raw() == Object::sentinel()) { | 7834 } else if (value.raw() == Object::sentinel().raw()) { |
7838 // This field has not been referenced yet and thus the value has | 7835 // This field has not been referenced yet and thus the value has |
7839 // not been evaluated. If the field is const, call the static getter method | 7836 // not been evaluated. If the field is const, call the static getter method |
7840 // to evaluate the expression and canonicalize the value. | 7837 // to evaluate the expression and canonicalize the value. |
7841 if (field.is_const()) { | 7838 if (field.is_const()) { |
7842 field.set_value(Instance::Handle(Object::transition_sentinel())); | 7839 field.set_value(Object::transition_sentinel()); |
7843 const String& field_name = String::Handle(field.name()); | 7840 const String& field_name = String::Handle(field.name()); |
7844 const String& getter_name = | 7841 const String& getter_name = |
7845 String::Handle(Field::GetterName(field_name)); | 7842 String::Handle(Field::GetterName(field_name)); |
7846 const Class& cls = Class::Handle(field.owner()); | 7843 const Class& cls = Class::Handle(field.owner()); |
7847 const int kNumArguments = 0; // no arguments. | 7844 const int kNumArguments = 0; // no arguments. |
7848 const Array& kNoArgumentNames = Array::Handle(); | 7845 const Array& kNoArgumentNames = Array::Handle(); |
7849 const Function& func = | 7846 const Function& func = |
7850 Function::Handle(Resolver::ResolveStatic(cls, | 7847 Function::Handle(Resolver::ResolveStatic(cls, |
7851 getter_name, | 7848 getter_name, |
7852 kNumArguments, | 7849 kNumArguments, |
7853 kNoArgumentNames, | 7850 kNoArgumentNames, |
7854 Resolver::kIsQualified)); | 7851 Resolver::kIsQualified)); |
7855 ASSERT(!func.IsNull()); | 7852 ASSERT(!func.IsNull()); |
7856 ASSERT(func.kind() == RawFunction::kConstImplicitGetter); | 7853 ASSERT(func.kind() == RawFunction::kConstImplicitGetter); |
7857 const Array& args = Array::Handle(Object::empty_array()); | 7854 Object& const_value = Object::Handle( |
7858 Object& const_value = Object::Handle(DartEntry::InvokeStatic(func, args)); | 7855 DartEntry::InvokeStatic(func, Object::empty_array())); |
7859 if (const_value.IsError()) { | 7856 if (const_value.IsError()) { |
7860 const Error& error = Error::Cast(const_value); | 7857 const Error& error = Error::Cast(const_value); |
7861 if (error.IsUnhandledException()) { | 7858 if (error.IsUnhandledException()) { |
7862 field.set_value(Instance::Handle()); | 7859 field.set_value(Instance::Handle()); |
7863 // It is a compile-time error if evaluation of a compile-time constant | 7860 // It is a compile-time error if evaluation of a compile-time constant |
7864 // would raise an exception. | 7861 // would raise an exception. |
7865 AppendErrorMsg(error, TokenPos(), | 7862 AppendErrorMsg(error, TokenPos(), |
7866 "error initializing const field '%s'", | 7863 "error initializing const field '%s'", |
7867 String::Handle(field.name()).ToCString()); | 7864 String::Handle(field.name()).ToCString()); |
7868 } else { | 7865 } else { |
(...skipping 1828 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9697 void Parser::SkipQualIdent() { | 9694 void Parser::SkipQualIdent() { |
9698 ASSERT(IsIdentifier()); | 9695 ASSERT(IsIdentifier()); |
9699 ConsumeToken(); | 9696 ConsumeToken(); |
9700 if (CurrentToken() == Token::kPERIOD) { | 9697 if (CurrentToken() == Token::kPERIOD) { |
9701 ConsumeToken(); // Consume the kPERIOD token. | 9698 ConsumeToken(); // Consume the kPERIOD token. |
9702 ExpectIdentifier("identifier expected after '.'"); | 9699 ExpectIdentifier("identifier expected after '.'"); |
9703 } | 9700 } |
9704 } | 9701 } |
9705 | 9702 |
9706 } // namespace dart | 9703 } // namespace dart |
OLD | NEW |