| 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 741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 752 break; | 752 break; |
| 753 case RawFunction::kConstImplicitGetter: | 753 case RawFunction::kConstImplicitGetter: |
| 754 node_sequence = parser.ParseStaticConstGetter(func); | 754 node_sequence = parser.ParseStaticConstGetter(func); |
| 755 break; | 755 break; |
| 756 default: | 756 default: |
| 757 UNREACHABLE(); | 757 UNREACHABLE(); |
| 758 } | 758 } |
| 759 | 759 |
| 760 if (!HasReturnNode(node_sequence)) { | 760 if (!HasReturnNode(node_sequence)) { |
| 761 // Add implicit return node. | 761 // Add implicit return node. |
| 762 node_sequence->Add(new ReturnNode(parser.TokenPos())); | 762 node_sequence->Add(new ReturnNode(func.end_token_pos())); |
| 763 } | 763 } |
| 764 if (parser.expression_temp_ != NULL) { | 764 if (parser.expression_temp_ != NULL) { |
| 765 parsed_function->set_expression_temp_var(parser.expression_temp_); | 765 parsed_function->set_expression_temp_var(parser.expression_temp_); |
| 766 } | 766 } |
| 767 if (parsed_function->has_expression_temp_var()) { | 767 if (parsed_function->has_expression_temp_var()) { |
| 768 node_sequence->scope()->AddVariable(parsed_function->expression_temp_var()); | 768 node_sequence->scope()->AddVariable(parsed_function->expression_temp_var()); |
| 769 } | 769 } |
| 770 parsed_function->SetNodeSequence(node_sequence); | 770 parsed_function->SetNodeSequence(node_sequence); |
| 771 | 771 |
| 772 // The instantiator may be required at run time for generic type checks or | 772 // The instantiator may be required at run time for generic type checks or |
| (...skipping 27 matching lines...) Expand all Loading... |
| 800 TRACE_PARSER("ParseStaticConstGetter"); | 800 TRACE_PARSER("ParseStaticConstGetter"); |
| 801 ParamList params; | 801 ParamList params; |
| 802 ASSERT(func.num_fixed_parameters() == 0); // static. | 802 ASSERT(func.num_fixed_parameters() == 0); // static. |
| 803 ASSERT(!func.HasOptionalParameters()); | 803 ASSERT(!func.HasOptionalParameters()); |
| 804 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); | 804 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); |
| 805 | 805 |
| 806 // Build local scope for function and populate with the formal parameters. | 806 // Build local scope for function and populate with the formal parameters. |
| 807 OpenFunctionBlock(func); | 807 OpenFunctionBlock(func); |
| 808 AddFormalParamsToScope(¶ms, current_block_->scope); | 808 AddFormalParamsToScope(¶ms, current_block_->scope); |
| 809 | 809 |
| 810 intptr_t ident_pos = TokenPos(); |
| 810 const String& field_name = *ExpectIdentifier("field name expected"); | 811 const String& field_name = *ExpectIdentifier("field name expected"); |
| 811 const Class& field_class = Class::Handle(func.Owner()); | 812 const Class& field_class = Class::Handle(func.Owner()); |
| 812 const Field& field = | 813 const Field& field = |
| 813 Field::ZoneHandle(field_class.LookupStaticField(field_name)); | 814 Field::ZoneHandle(field_class.LookupStaticField(field_name)); |
| 814 | 815 |
| 815 // Static const fields must have an initializer. | 816 // Static const fields must have an initializer. |
| 816 ExpectToken(Token::kASSIGN); | 817 ExpectToken(Token::kASSIGN); |
| 817 | 818 |
| 818 // We don't want to use ParseConstExpr() here because we don't want | 819 // We don't want to use ParseConstExpr() here because we don't want |
| 819 // the constant folding code to create, compile and execute a code | 820 // the constant folding code to create, compile and execute a code |
| 820 // fragment to evaluate the expression. Instead, we just make sure | 821 // fragment to evaluate the expression. Instead, we just make sure |
| 821 // the static const field initializer is a constant expression and | 822 // the static const field initializer is a constant expression and |
| 822 // leave the evaluation to the getter function. | 823 // leave the evaluation to the getter function. |
| 823 const intptr_t expr_pos = TokenPos(); | 824 const intptr_t expr_pos = TokenPos(); |
| 824 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); | 825 AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); |
| 825 | 826 |
| 826 if (field.is_const()) { | 827 if (field.is_const()) { |
| 827 // This getter will only be called once at compile time. | 828 // This getter will only be called once at compile time. |
| 828 if (expr->EvalConstExpr() == NULL) { | 829 if (expr->EvalConstExpr() == NULL) { |
| 829 ErrorMsg(expr_pos, "initializer must be a compile-time constant"); | 830 ErrorMsg(expr_pos, "initializer must be a compile-time constant"); |
| 830 } | 831 } |
| 831 ReturnNode* return_node = new ReturnNode(TokenPos(), expr); | 832 ReturnNode* return_node = new ReturnNode(ident_pos, expr); |
| 832 current_block_->statements->Add(return_node); | 833 current_block_->statements->Add(return_node); |
| 833 } else { | 834 } else { |
| 834 // This getter may be called each time the static field is accessed. | 835 // This getter may be called each time the static field is accessed. |
| 835 // The following generated code lazily initializes the field: | 836 // The following generated code lazily initializes the field: |
| 836 // if (field.value === transition_sentinel) { | 837 // if (field.value === transition_sentinel) { |
| 837 // field.value = null; | 838 // field.value = null; |
| 838 // throw("circular dependency in field initialization"); | 839 // throw("circular dependency in field initialization"); |
| 839 // } | 840 // } |
| 840 // if (field.value === sentinel) { | 841 // if (field.value === sentinel) { |
| 841 // field.value = transition_sentinel; | 842 // field.value = transition_sentinel; |
| 842 // field.value = expr; | 843 // field.value = expr; |
| 843 // } | 844 // } |
| 844 // return field.value; // Type check is executed here in checked mode. | 845 // return field.value; // Type check is executed here in checked mode. |
| 845 | 846 |
| 846 // Generate code checking for circular dependency in field initialization. | 847 // Generate code checking for circular dependency in field initialization. |
| 847 AstNode* compare_circular = new ComparisonNode( | 848 AstNode* compare_circular = new ComparisonNode( |
| 848 TokenPos(), | 849 ident_pos, |
| 849 Token::kEQ_STRICT, | 850 Token::kEQ_STRICT, |
| 850 new LoadStaticFieldNode(TokenPos(), field), | 851 new LoadStaticFieldNode(ident_pos, field), |
| 851 new LiteralNode(TokenPos(), Object::transition_sentinel())); | 852 new LiteralNode(ident_pos, Object::transition_sentinel())); |
| 852 // Set field to null prior to throwing exception, so that subsequent | 853 // Set field to null prior to throwing exception, so that subsequent |
| 853 // accesses to the field do not throw again, since initializers should only | 854 // accesses to the field do not throw again, since initializers should only |
| 854 // be executed once. | 855 // be executed once. |
| 855 SequenceNode* report_circular = new SequenceNode(TokenPos(), NULL); | 856 SequenceNode* report_circular = new SequenceNode(ident_pos, NULL); |
| 856 report_circular->Add( | 857 report_circular->Add( |
| 857 new StoreStaticFieldNode( | 858 new StoreStaticFieldNode( |
| 858 TokenPos(), | 859 ident_pos, |
| 859 field, | 860 field, |
| 860 new LiteralNode(TokenPos(), Instance::ZoneHandle()))); | 861 new LiteralNode(ident_pos, Instance::ZoneHandle()))); |
| 861 // TODO(regis): Exception to throw is not specified by spec. | 862 // TODO(regis): Exception to throw is not specified by spec. |
| 862 const String& circular_error = String::ZoneHandle( | 863 const String& circular_error = String::ZoneHandle( |
| 863 Symbols::New("circular dependency in field initialization")); | 864 Symbols::New("circular dependency in field initialization")); |
| 864 report_circular->Add( | 865 report_circular->Add( |
| 865 new ThrowNode(TokenPos(), | 866 new ThrowNode(ident_pos, |
| 866 new LiteralNode(TokenPos(), circular_error), | 867 new LiteralNode(ident_pos, circular_error), |
| 867 NULL)); | 868 NULL)); |
| 868 AstNode* circular_check = | 869 AstNode* circular_check = |
| 869 new IfNode(TokenPos(), compare_circular, report_circular, NULL); | 870 new IfNode(ident_pos, compare_circular, report_circular, NULL); |
| 870 current_block_->statements->Add(circular_check); | 871 current_block_->statements->Add(circular_check); |
| 871 | 872 |
| 872 // Generate code checking for uninitialized field. | 873 // Generate code checking for uninitialized field. |
| 873 AstNode* compare_uninitialized = new ComparisonNode( | 874 AstNode* compare_uninitialized = new ComparisonNode( |
| 874 TokenPos(), | 875 ident_pos, |
| 875 Token::kEQ_STRICT, | 876 Token::kEQ_STRICT, |
| 876 new LoadStaticFieldNode(TokenPos(), field), | 877 new LoadStaticFieldNode(ident_pos, field), |
| 877 new LiteralNode(TokenPos(), Object::sentinel())); | 878 new LiteralNode(ident_pos, Object::sentinel())); |
| 878 SequenceNode* initialize_field = new SequenceNode(TokenPos(), NULL); | 879 SequenceNode* initialize_field = new SequenceNode(ident_pos, NULL); |
| 879 initialize_field->Add( | 880 initialize_field->Add( |
| 880 new StoreStaticFieldNode( | 881 new StoreStaticFieldNode( |
| 881 TokenPos(), | 882 ident_pos, |
| 882 field, | 883 field, |
| 883 new LiteralNode( | 884 new LiteralNode(ident_pos, Object::transition_sentinel()))); |
| 884 TokenPos(), Object::transition_sentinel()))); | |
| 885 // TODO(hausner): If evaluation of the field value throws an exception, | 885 // TODO(hausner): If evaluation of the field value throws an exception, |
| 886 // we leave the field value as 'transition_sentinel', which is wrong. | 886 // we leave the field value as 'transition_sentinel', which is wrong. |
| 887 // A second reference to the field later throws a circular dependency | 887 // A second reference to the field later throws a circular dependency |
| 888 // 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. |
| 889 initialize_field->Add(new StoreStaticFieldNode(TokenPos(), field, expr)); | 889 initialize_field->Add(new StoreStaticFieldNode(ident_pos, field, expr)); |
| 890 AstNode* uninitialized_check = | 890 AstNode* uninitialized_check = |
| 891 new IfNode(TokenPos(), compare_uninitialized, initialize_field, NULL); | 891 new IfNode(ident_pos, compare_uninitialized, initialize_field, NULL); |
| 892 current_block_->statements->Add(uninitialized_check); | 892 current_block_->statements->Add(uninitialized_check); |
| 893 | 893 |
| 894 // Generate code returning the field value. | 894 // Generate code returning the field value. |
| 895 ReturnNode* return_node = | 895 ReturnNode* return_node = |
| 896 new ReturnNode(TokenPos(), | 896 new ReturnNode(ident_pos, |
| 897 new LoadStaticFieldNode(TokenPos(), field)); | 897 new LoadStaticFieldNode(ident_pos, field)); |
| 898 current_block_->statements->Add(return_node); | 898 current_block_->statements->Add(return_node); |
| 899 } | 899 } |
| 900 return CloseBlock(); | 900 return CloseBlock(); |
| 901 } | 901 } |
| 902 | 902 |
| 903 | 903 |
| 904 // Create AstNodes for an implicit instance getter method: | 904 // Create AstNodes for an implicit instance getter method: |
| 905 // LoadLocalNode 0 ('this'); | 905 // LoadLocalNode 0 ('this'); |
| 906 // LoadInstanceFieldNode (field_name); | 906 // LoadInstanceFieldNode (field_name); |
| 907 // ReturnNode (field's value); | 907 // ReturnNode (field's value); |
| 908 SequenceNode* Parser::ParseInstanceGetter(const Function& func) { | 908 SequenceNode* Parser::ParseInstanceGetter(const Function& func) { |
| 909 TRACE_PARSER("ParseInstanceGetter"); | 909 TRACE_PARSER("ParseInstanceGetter"); |
| 910 ParamList params; | 910 ParamList params; |
| 911 // func.token_pos() points to the name of the field. |
| 912 intptr_t ident_pos = func.token_pos(); |
| 911 ASSERT(current_class().raw() == func.Owner()); | 913 ASSERT(current_class().raw() == func.Owner()); |
| 912 params.AddReceiver(ReceiverType(TokenPos())); | 914 params.AddReceiver(ReceiverType(ident_pos)); |
| 913 ASSERT(func.num_fixed_parameters() == 1); // receiver. | 915 ASSERT(func.num_fixed_parameters() == 1); // receiver. |
| 914 ASSERT(!func.HasOptionalParameters()); | 916 ASSERT(!func.HasOptionalParameters()); |
| 915 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); | 917 ASSERT(AbstractType::Handle(func.result_type()).IsResolved()); |
| 916 | 918 |
| 917 // Build local scope for function and populate with the formal parameters. | 919 // Build local scope for function and populate with the formal parameters. |
| 918 OpenFunctionBlock(func); | 920 OpenFunctionBlock(func); |
| 919 AddFormalParamsToScope(¶ms, current_block_->scope); | 921 AddFormalParamsToScope(¶ms, current_block_->scope); |
| 920 | 922 |
| 921 // Receiver is local 0. | 923 // Receiver is local 0. |
| 922 LocalVariable* receiver = current_block_->scope->VariableAt(0); | 924 LocalVariable* receiver = current_block_->scope->VariableAt(0); |
| 923 LoadLocalNode* load_receiver = new LoadLocalNode(TokenPos(), receiver); | 925 LoadLocalNode* load_receiver = new LoadLocalNode(ident_pos, receiver); |
| 924 // TokenPos() returns the function's token position which points to the | |
| 925 // name of the field; | |
| 926 ASSERT(IsIdentifier()); | 926 ASSERT(IsIdentifier()); |
| 927 const String& field_name = *CurrentLiteral(); | 927 const String& field_name = *CurrentLiteral(); |
| 928 const Class& field_class = Class::Handle(func.Owner()); | 928 const Class& field_class = Class::Handle(func.Owner()); |
| 929 const Field& field = | 929 const Field& field = |
| 930 Field::ZoneHandle(field_class.LookupInstanceField(field_name)); | 930 Field::ZoneHandle(field_class.LookupInstanceField(field_name)); |
| 931 | 931 |
| 932 LoadInstanceFieldNode* load_field = | 932 LoadInstanceFieldNode* load_field = |
| 933 new LoadInstanceFieldNode(TokenPos(), load_receiver, field); | 933 new LoadInstanceFieldNode(ident_pos, load_receiver, field); |
| 934 | 934 |
| 935 ReturnNode* return_node = new ReturnNode(TokenPos(), load_field); | 935 ReturnNode* return_node = new ReturnNode(ident_pos, load_field); |
| 936 current_block_->statements->Add(return_node); | 936 current_block_->statements->Add(return_node); |
| 937 return CloseBlock(); | 937 return CloseBlock(); |
| 938 } | 938 } |
| 939 | 939 |
| 940 | 940 |
| 941 // Create AstNodes for an implicit instance setter method: | 941 // Create AstNodes for an implicit instance setter method: |
| 942 // LoadLocalNode 0 ('this') | 942 // LoadLocalNode 0 ('this') |
| 943 // LoadLocalNode 1 ('value') | 943 // LoadLocalNode 1 ('value') |
| 944 // SetInstanceField (field_name); | 944 // SetInstanceField (field_name); |
| 945 // ReturnNode (void); | 945 // ReturnNode (void); |
| 946 SequenceNode* Parser::ParseInstanceSetter(const Function& func) { | 946 SequenceNode* Parser::ParseInstanceSetter(const Function& func) { |
| 947 TRACE_PARSER("ParseInstanceSetter"); | 947 TRACE_PARSER("ParseInstanceSetter"); |
| 948 // TokenPos() returns the function's token position which points to | 948 // func.token_pos() points to the name of the field. |
| 949 // the name of the field; we can use it to form the field_name. | 949 intptr_t ident_pos = func.token_pos(); |
| 950 const String& field_name = *CurrentLiteral(); | 950 const String& field_name = *CurrentLiteral(); |
| 951 const Class& field_class = Class::ZoneHandle(func.Owner()); | 951 const Class& field_class = Class::ZoneHandle(func.Owner()); |
| 952 const Field& field = | 952 const Field& field = |
| 953 Field::ZoneHandle(field_class.LookupInstanceField(field_name)); | 953 Field::ZoneHandle(field_class.LookupInstanceField(field_name)); |
| 954 const AbstractType& field_type = AbstractType::ZoneHandle(field.type()); | 954 const AbstractType& field_type = AbstractType::ZoneHandle(field.type()); |
| 955 | 955 |
| 956 ParamList params; | 956 ParamList params; |
| 957 ASSERT(current_class().raw() == func.Owner()); | 957 ASSERT(current_class().raw() == func.Owner()); |
| 958 params.AddReceiver(ReceiverType(TokenPos())); | 958 params.AddReceiver(ReceiverType(ident_pos)); |
| 959 params.AddFinalParameter(TokenPos(), | 959 params.AddFinalParameter(ident_pos, |
| 960 &String::ZoneHandle(Symbols::Value()), | 960 &String::ZoneHandle(Symbols::Value()), |
| 961 &field_type); | 961 &field_type); |
| 962 ASSERT(func.num_fixed_parameters() == 2); // receiver, value. | 962 ASSERT(func.num_fixed_parameters() == 2); // receiver, value. |
| 963 ASSERT(!func.HasOptionalParameters()); | 963 ASSERT(!func.HasOptionalParameters()); |
| 964 ASSERT(AbstractType::Handle(func.result_type()).IsVoidType()); | 964 ASSERT(AbstractType::Handle(func.result_type()).IsVoidType()); |
| 965 | 965 |
| 966 // Build local scope for function and populate with the formal parameters. | 966 // Build local scope for function and populate with the formal parameters. |
| 967 OpenFunctionBlock(func); | 967 OpenFunctionBlock(func); |
| 968 AddFormalParamsToScope(¶ms, current_block_->scope); | 968 AddFormalParamsToScope(¶ms, current_block_->scope); |
| 969 | 969 |
| 970 LoadLocalNode* receiver = | 970 LoadLocalNode* receiver = |
| 971 new LoadLocalNode(TokenPos(), current_block_->scope->VariableAt(0)); | 971 new LoadLocalNode(ident_pos, current_block_->scope->VariableAt(0)); |
| 972 LoadLocalNode* value = | 972 LoadLocalNode* value = |
| 973 new LoadLocalNode(TokenPos(), current_block_->scope->VariableAt(1)); | 973 new LoadLocalNode(ident_pos, current_block_->scope->VariableAt(1)); |
| 974 | 974 |
| 975 StoreInstanceFieldNode* store_field = | 975 StoreInstanceFieldNode* store_field = |
| 976 new StoreInstanceFieldNode(TokenPos(), receiver, field, value); | 976 new StoreInstanceFieldNode(ident_pos, receiver, field, value); |
| 977 | 977 |
| 978 current_block_->statements->Add(store_field); | 978 current_block_->statements->Add(store_field); |
| 979 current_block_->statements->Add(new ReturnNode(TokenPos())); | 979 current_block_->statements->Add(new ReturnNode(ident_pos)); |
| 980 return CloseBlock(); | 980 return CloseBlock(); |
| 981 } | 981 } |
| 982 | 982 |
| 983 | 983 |
| 984 void Parser::SkipBlock() { | 984 void Parser::SkipBlock() { |
| 985 ASSERT(CurrentToken() == Token::kLBRACE); | 985 ASSERT(CurrentToken() == Token::kLBRACE); |
| 986 GrowableArray<Token::Kind> token_stack(8); | 986 GrowableArray<Token::Kind> token_stack(8); |
| 987 const intptr_t block_start_pos = TokenPos(); | 987 const intptr_t block_start_pos = TokenPos(); |
| 988 bool is_match = true; | 988 bool is_match = true; |
| 989 bool unexpected_token_found = false; | 989 bool unexpected_token_found = false; |
| (...skipping 1604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2594 ErrorMsg(method->name_pos, | 2594 ErrorMsg(method->name_pos, |
| 2595 "Constructor with redirection may not have a function body"); | 2595 "Constructor with redirection may not have a function body"); |
| 2596 } | 2596 } |
| 2597 if (CurrentToken() == Token::kLBRACE) { | 2597 if (CurrentToken() == Token::kLBRACE) { |
| 2598 SkipBlock(); | 2598 SkipBlock(); |
| 2599 } else { | 2599 } else { |
| 2600 ConsumeToken(); | 2600 ConsumeToken(); |
| 2601 SkipExpr(); | 2601 SkipExpr(); |
| 2602 ExpectSemicolon(); | 2602 ExpectSemicolon(); |
| 2603 } | 2603 } |
| 2604 method_end_pos = TokenPos(); | 2604 method_end_pos = TokenPos() - 1; |
| 2605 } else if (IsLiteral("native")) { | 2605 } else if (IsLiteral("native")) { |
| 2606 if (method->has_abstract) { | 2606 if (method->has_abstract) { |
| 2607 ErrorMsg(method->name_pos, | 2607 ErrorMsg(method->name_pos, |
| 2608 "abstract method '%s' may not have a function body", | 2608 "abstract method '%s' may not have a function body", |
| 2609 method->name->ToCString()); | 2609 method->name->ToCString()); |
| 2610 } else if (method->IsFactoryOrConstructor() && method->has_const) { | 2610 } else if (method->IsFactoryOrConstructor() && method->has_const) { |
| 2611 ErrorMsg(method->name_pos, | 2611 ErrorMsg(method->name_pos, |
| 2612 "const constructor or factory '%s' may not be native", | 2612 "const constructor or factory '%s' may not be native", |
| 2613 method->name->ToCString()); | 2613 method->name->ToCString()); |
| 2614 } | 2614 } |
| (...skipping 1173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3788 const intptr_t function_pos = TokenPos(); | 3788 const intptr_t function_pos = TokenPos(); |
| 3789 ParamList params; | 3789 ParamList params; |
| 3790 const bool allow_explicit_default_values = true; | 3790 const bool allow_explicit_default_values = true; |
| 3791 ParseFormalParameterList(allow_explicit_default_values, ¶ms); | 3791 ParseFormalParameterList(allow_explicit_default_values, ¶ms); |
| 3792 | 3792 |
| 3793 intptr_t function_end_pos = function_pos; | 3793 intptr_t function_end_pos = function_pos; |
| 3794 if (is_external) { | 3794 if (is_external) { |
| 3795 ExpectSemicolon(); | 3795 ExpectSemicolon(); |
| 3796 } else if (CurrentToken() == Token::kLBRACE) { | 3796 } else if (CurrentToken() == Token::kLBRACE) { |
| 3797 SkipBlock(); | 3797 SkipBlock(); |
| 3798 function_end_pos = TokenPos(); | 3798 function_end_pos = TokenPos() - 1; |
| 3799 } else if (CurrentToken() == Token::kARROW) { | 3799 } else if (CurrentToken() == Token::kARROW) { |
| 3800 ConsumeToken(); | 3800 ConsumeToken(); |
| 3801 SkipExpr(); | 3801 SkipExpr(); |
| 3802 ExpectSemicolon(); | 3802 ExpectSemicolon(); |
| 3803 function_end_pos = TokenPos(); | 3803 function_end_pos = TokenPos() - 1; |
| 3804 } else if (IsLiteral("native")) { | 3804 } else if (IsLiteral("native")) { |
| 3805 ParseNativeDeclaration(); | 3805 ParseNativeDeclaration(); |
| 3806 } else { | 3806 } else { |
| 3807 ErrorMsg("function block expected"); | 3807 ErrorMsg("function block expected"); |
| 3808 } | 3808 } |
| 3809 Function& func = Function::Handle( | 3809 Function& func = Function::Handle( |
| 3810 Function::New(func_name, | 3810 Function::New(func_name, |
| 3811 RawFunction::kRegularFunction, | 3811 RawFunction::kRegularFunction, |
| 3812 is_static, | 3812 is_static, |
| 3813 /* is_const = */ false, | 3813 /* is_const = */ false, |
| (...skipping 1011 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4825 if (!current_block_->scope->AddVariable(function_variable)) { | 4825 if (!current_block_->scope->AddVariable(function_variable)) { |
| 4826 ErrorMsg(ident_pos, "identifier '%s' already defined", | 4826 ErrorMsg(ident_pos, "identifier '%s' already defined", |
| 4827 function_variable->name().ToCString()); | 4827 function_variable->name().ToCString()); |
| 4828 } | 4828 } |
| 4829 } | 4829 } |
| 4830 | 4830 |
| 4831 // Parse the local function. | 4831 // Parse the local function. |
| 4832 Array& default_parameter_values = Array::Handle(); | 4832 Array& default_parameter_values = Array::Handle(); |
| 4833 SequenceNode* statements = Parser::ParseFunc(function, | 4833 SequenceNode* statements = Parser::ParseFunc(function, |
| 4834 default_parameter_values); | 4834 default_parameter_values); |
| 4835 ASSERT(is_new_closure || (function.end_token_pos() == TokenPos())); | 4835 ASSERT(is_new_closure || (function.end_token_pos() == (TokenPos() - 1))); |
| 4836 function.set_end_token_pos(TokenPos()); | 4836 function.set_end_token_pos(TokenPos() - 1); |
| 4837 | 4837 |
| 4838 // Now that the local function has formal parameters, lookup the signature | 4838 // Now that the local function has formal parameters, lookup the signature |
| 4839 // class in the current library (but not in its imports) and only create a new | 4839 // class in the current library (but not in its imports) and only create a new |
| 4840 // canonical signature class if it does not exist yet. | 4840 // canonical signature class if it does not exist yet. |
| 4841 const String& signature = String::Handle(function.Signature()); | 4841 const String& signature = String::Handle(function.Signature()); |
| 4842 Class& signature_class = Class::ZoneHandle(); | 4842 Class& signature_class = Class::ZoneHandle(); |
| 4843 if (!is_new_closure) { | 4843 if (!is_new_closure) { |
| 4844 signature_class = function.signature_class(); | 4844 signature_class = function.signature_class(); |
| 4845 } | 4845 } |
| 4846 if (signature_class.IsNull()) { | 4846 if (signature_class.IsNull()) { |
| (...skipping 4860 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9707 void Parser::SkipQualIdent() { | 9707 void Parser::SkipQualIdent() { |
| 9708 ASSERT(IsIdentifier()); | 9708 ASSERT(IsIdentifier()); |
| 9709 ConsumeToken(); | 9709 ConsumeToken(); |
| 9710 if (CurrentToken() == Token::kPERIOD) { | 9710 if (CurrentToken() == Token::kPERIOD) { |
| 9711 ConsumeToken(); // Consume the kPERIOD token. | 9711 ConsumeToken(); // Consume the kPERIOD token. |
| 9712 ExpectIdentifier("identifier expected after '.'"); | 9712 ExpectIdentifier("identifier expected after '.'"); |
| 9713 } | 9713 } |
| 9714 } | 9714 } |
| 9715 | 9715 |
| 9716 } // namespace dart | 9716 } // namespace dart |
| OLD | NEW |