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 |