| Index: runtime/vm/parser.cc
|
| diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
|
| index 72f078e230c2e0d2ebd48d395761846368e917e4..5a00eed55abd78bcab906aab20fb82157e5c0c77 100644
|
| --- a/runtime/vm/parser.cc
|
| +++ b/runtime/vm/parser.cc
|
| @@ -1181,16 +1181,10 @@ void Parser::ParseFunction(ParsedFunction* parsed_function) {
|
| parsed_function->set_instantiator(instantiator);
|
| }
|
| }
|
| - if (FLAG_generic_method_semantics && parser.current_function().IsGeneric()) {
|
| - const String* variable_name = &Symbols::FunctionInstantiatorVar();
|
| - const bool kTestOnly = true;
|
| - LocalVariable* instantiator =
|
| - node_sequence->scope()->LookupVariable(*variable_name, kTestOnly);
|
| - ASSERT(instantiator != NULL);
|
| - parsed_function->set_function_instantiator(instantiator);
|
| - // Function instantiator variables of parent generic functions, if any, are
|
| - // captured and accessible via the context.
|
| - }
|
| + // ParseFunc has recorded the generic function type arguments variable.
|
| + ASSERT(!FLAG_generic_method_semantics ||
|
| + !parser.current_function().IsGeneric() ||
|
| + (parsed_function->function_type_arguments() != NULL));
|
| }
|
|
|
|
|
| @@ -3471,11 +3465,23 @@ SequenceNode* Parser::ParseFunc(const Function& func, bool check_semicolon) {
|
| OpenFunctionBlock(func); // Build local scope for function.
|
|
|
| if (FLAG_generic_method_semantics && func.IsGeneric()) {
|
| - // Insert function instantiator variable to scope.
|
| - LocalVariable* function_instantiator = new (Z) LocalVariable(
|
| + // Lookup function type arguments variable in parent function scope, if any.
|
| + if (func.HasGenericParent()) {
|
| + const String* variable_name = &Symbols::FunctionTypeArgumentsVar();
|
| + LocalVariable* parent_type_arguments =
|
| + current_block_->scope->LookupVariable(*variable_name, true);
|
| + ASSERT(parent_type_arguments != NULL);
|
| + // TODO(regis): It may be too early to capture parent_type_arguments here.
|
| + // In case it is never used, we could save capturing and concatenating.
|
| + current_block_->scope->CaptureVariable(parent_type_arguments);
|
| + parsed_function_->set_parent_type_arguments(parent_type_arguments);
|
| + }
|
| + // Insert function type arguments variable to scope.
|
| + LocalVariable* function_type_arguments = new (Z) LocalVariable(
|
| TokenPosition::kNoSource, TokenPosition::kNoSource,
|
| - Symbols::FunctionInstantiatorVar(), Object::dynamic_type());
|
| - current_block_->scope->AddVariable(function_instantiator);
|
| + Symbols::FunctionTypeArgumentsVar(), Object::dynamic_type());
|
| + current_block_->scope->AddVariable(function_type_arguments);
|
| + parsed_function_->set_function_type_arguments(function_type_arguments);
|
| }
|
|
|
| ParamList params;
|
| @@ -3638,7 +3644,7 @@ SequenceNode* Parser::ParseFunc(const Function& func, bool check_semicolon) {
|
| // captured if type checks are enabled, because they may access it to
|
| // instantiate types.
|
| // If any enclosing parent of the function being parsed is generic, capture
|
| - // their function instantiators.
|
| + // their function type arguments.
|
| CaptureAllInstantiators();
|
| }
|
|
|
| @@ -5534,13 +5540,12 @@ void Parser::ParseTypeParameters(bool parameterizing_class) {
|
| } else {
|
| type_parameter_bound = I->object_store()->object_type();
|
| }
|
| + // Note that we cannot yet calculate the final index of a function type
|
| + // parameter, because we may not have parsed the parent function yet.
|
| type_parameter = TypeParameter::New(
|
| parameterizing_class ? current_class() : Class::Handle(Z),
|
| parameterizing_class ? Function::Handle(Z) : innermost_function(),
|
| - index, 0, type_parameter_name, type_parameter_bound, declaration_pos);
|
| - if (!parameterizing_class) {
|
| - type_parameter.SetIsFinalized();
|
| - }
|
| + index, type_parameter_name, type_parameter_bound, declaration_pos);
|
| type_parameters_array.Add(
|
| &AbstractType::ZoneHandle(Z, type_parameter.raw()));
|
| if (FLAG_enable_mirrors && metadata_pos.IsReal()) {
|
| @@ -7734,35 +7739,15 @@ void Parser::CaptureInstantiator() {
|
| }
|
|
|
|
|
| -void Parser::CaptureFunctionInstantiators() {
|
| +void Parser::CaptureFunctionTypeArguments() {
|
| ASSERT(InGenericFunctionScope());
|
| ASSERT(FunctionLevel() > 0);
|
| if (!FLAG_generic_method_semantics) {
|
| return;
|
| }
|
| - // Capture function instantiators starting at parent of innermost function.
|
| - intptr_t variable_function_level = FunctionLevel() - 1;
|
| - const String* variable_name = &Symbols::FunctionInstantiatorVar();
|
| - LocalScope* scope = current_block_->scope;
|
| - do {
|
| - while (scope->function_level() > variable_function_level) {
|
| - scope = scope->parent();
|
| - }
|
| - // Function instantiator is in top scope at that function level.
|
| - LocalScope* parent_scope = scope->parent();
|
| - while ((parent_scope != NULL) &&
|
| - (parent_scope->function_level() == scope->function_level())) {
|
| - scope = parent_scope;
|
| - parent_scope = scope->parent();
|
| - }
|
| - LocalVariable* function_instantiator_var =
|
| - scope->LookupVariable(*variable_name, true);
|
| - if (function_instantiator_var != NULL) {
|
| - current_block_->scope->CaptureVariable(function_instantiator_var);
|
| - }
|
| - scope = scope->parent();
|
| - variable_function_level--;
|
| - } while (variable_function_level >= 0);
|
| + const String* variable_name = &Symbols::FunctionTypeArgumentsVar();
|
| + current_block_->scope->CaptureVariable(
|
| + current_block_->scope->LookupVariable(*variable_name, true));
|
| }
|
|
|
|
|
| @@ -7770,8 +7755,8 @@ void Parser::CaptureAllInstantiators() {
|
| if (IsInstantiatorRequired()) {
|
| CaptureInstantiator();
|
| }
|
| - if (AreFunctionInstantiatorsRequired()) {
|
| - CaptureFunctionInstantiators();
|
| + if (innermost_function().HasGenericParent()) {
|
| + CaptureFunctionTypeArguments();
|
| }
|
| }
|
|
|
| @@ -8028,14 +8013,6 @@ AstNode* Parser::ParseFunctionStatement(bool is_literal) {
|
| }
|
| }
|
|
|
| - if (!found_func && !result_type.IsFinalized()) {
|
| - // Now that type parameters are declared, the result type can be resolved
|
| - // and finalized.
|
| - ResolveType(&result_type);
|
| - result_type = CanonicalizeType(result_type);
|
| - function.set_result_type(result_type);
|
| - }
|
| -
|
| CheckToken(Token::kLPAREN);
|
|
|
| // The function type needs to be finalized at compile time, since the closure
|
| @@ -8082,11 +8059,12 @@ AstNode* Parser::ParseFunctionStatement(bool is_literal) {
|
| // variables of this function's scope that are referenced by the local
|
| // function (and its inner nested functions) will be marked as captured.
|
|
|
| - ASSERT(AbstractType::Handle(Z, function.result_type()).IsResolved());
|
| + ResolveType(&result_type); // Parameter types are resolved in ParseFunc.
|
| + function.set_result_type(result_type);
|
| statements = Parser::ParseFunc(function, !is_literal);
|
| INC_STAT(thread(), num_functions_parsed, 1);
|
|
|
| - // Now that the local function has formal parameters, lookup the signature
|
| + // Now that the local function has formal parameters, finalize its signature
|
| signature_type = function.SignatureType();
|
| signature_type ^= CanonicalizeType(signature_type);
|
| function.SetSignatureType(signature_type);
|
| @@ -11923,9 +11901,9 @@ AstNode* Parser::LoadTypeParameter(PrimaryNode* primary) {
|
| Type& type = Type::ZoneHandle(Z, Type::DynamicType());
|
| return new (Z) TypeNode(primary_pos, type);
|
| }
|
| - if (type_parameter.parent_level() > 0) {
|
| - // Make sure that the function instantiators are captured.
|
| - CaptureFunctionInstantiators();
|
| + if (FunctionLevel() > 0) {
|
| + // Make sure that the parent function type arguments are captured.
|
| + CaptureFunctionTypeArguments();
|
| }
|
| }
|
| ASSERT(type_parameter.IsFinalized());
|
| @@ -12429,7 +12407,6 @@ void Parser::ResolveType(AbstractType* type) {
|
| return;
|
| }
|
| if (FLAG_generic_method_semantics) {
|
| - ASSERT(type_parameter.IsFinalized());
|
| ASSERT(!type_parameter.IsMalformed());
|
| *type = type_parameter.raw();
|
| } else {
|
| @@ -12567,19 +12544,6 @@ bool Parser::IsInstantiatorRequired() const {
|
| }
|
|
|
|
|
| -bool Parser::AreFunctionInstantiatorsRequired() const {
|
| - ASSERT(!innermost_function().IsNull());
|
| - Function& parent = Function::Handle(innermost_function().parent_function());
|
| - while (!parent.IsNull()) {
|
| - if (parent.IsGeneric()) {
|
| - return true;
|
| - }
|
| - parent = parent.parent_function();
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -
|
| bool Parser::InGenericFunctionScope() const {
|
| if (!innermost_function().IsNull()) {
|
| // With one more free tag bit in Function, we could cache this information.
|
| @@ -13750,7 +13714,7 @@ AstNode* Parser::ParseMapLiteral(TokenPosition type_pos,
|
| ASSERT(!factory_method.IsNull());
|
| if (!map_type_arguments.IsNull() && !map_type_arguments.IsInstantiated() &&
|
| (FunctionLevel() > 0)) {
|
| - // Make sure that the instantiator is captured.
|
| + // Make sure that the instantiators are captured.
|
| CaptureAllInstantiators();
|
| }
|
| TypeArguments& factory_type_args =
|
|
|