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