| 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 |