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