Index: pkg/front_end/lib/src/fasta/kernel/body_builder.dart |
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart |
index a21676dc59467ffbe0297e71fa73718d30fcf656..8595fd3f88ad7df6a0836c71f79ff43dea8d05db 100644 |
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart |
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart |
@@ -317,7 +317,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper { |
switchScope = outerSwitchScope; |
} |
- void declareVariable(VariableDeclaration variable) { |
+ void declareVariable(VariableDeclaration variable, Scope scope) { |
// ignore: UNUSED_LOCAL_VARIABLE |
Statement discardedStatement; |
String name = variable.name; |
@@ -1394,7 +1394,7 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper { |
VariableDeclaration variable = pop(); |
variable.fileOffset = nameToken.charOffset; |
push(variable); |
- declareVariable(variable); |
+ declareVariable(variable, scope); |
} |
@override |
@@ -2417,12 +2417,12 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper { |
// The function node is created later. |
null) |
..fileOffset = beginToken.charOffset); |
- declareVariable(variable); |
- enterLocalScope(); |
+ declareVariable(variable, scope.parent); |
} |
void enterFunction() { |
debugEvent("enterFunction"); |
+ enterFunctionTypeScope(); |
functionNestingLevel++; |
push(switchScope ?? NullValue.SwitchScope); |
switchScope = null; |
@@ -2435,6 +2435,9 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper { |
functionNestingLevel--; |
inCatchBlock = pop(); |
switchScope = pop(); |
+ List typeVariables = pop(); |
+ exitLocalScope(); |
+ push(typeVariables ?? NullValue.TypeVariables); |
} |
@override |
@@ -2446,6 +2449,11 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper { |
@override |
void beginNamedFunctionExpression(Token token) { |
debugEvent("beginNamedFunctionExpression"); |
+ List typeVariables = pop(); |
+ // Create an additional scope in which the named function expression is |
+ // declared. |
+ enterLocalScope(); |
+ push(typeVariables ?? NullValue.TypeVariables); |
enterFunction(); |
} |
@@ -2455,46 +2463,11 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper { |
enterFunction(); |
} |
- @override |
- void endNamedFunctionExpression(Token endToken) { |
- debugEvent("NamedFunctionExpression"); |
+ void pushNamedFunction(Token token, bool isFunctionExpression) { |
Statement body = popStatement(); |
AsyncMarker asyncModifier = pop(); |
- if (functionNestingLevel != 0) { |
- exitLocalScope(); |
- } |
- FormalParameters formals = pop(); |
- List<TypeParameter> typeParameters = typeVariableBuildersToKernel(pop()); |
- |
exitLocalScope(); |
- KernelFunctionDeclaration declaration = pop(); |
- VariableDeclaration variable = declaration.variable; |
- var returnType = pop(); |
- returnType ??= const DynamicType(); |
- pop(); // Modifiers. |
- exitFunction(); |
- |
- variable.initializer = new KernelFunctionExpression(formals.addToFunction( |
- new FunctionNode(body, |
- typeParameters: typeParameters, asyncMarker: asyncModifier) |
- ..fileOffset = formals.charOffset |
- ..fileEndOffset = endToken.charOffset)) |
- ..parent = variable |
- ..fileOffset = formals.charOffset; |
- push( |
- new KernelNamedFunctionExpression(variable, new VariableGet(variable))); |
- } |
- |
- @override |
- void endLocalFunctionDeclaration(Token token) { |
- debugEvent("LocalFunctionDeclaration"); |
- Statement body = popStatement(); |
- AsyncMarker asyncModifier = pop(); |
- if (functionNestingLevel != 0) { |
- exitLocalScope(); |
- } |
FormalParameters formals = pop(); |
- exitLocalScope(); |
var declaration = pop(); |
var returnType = pop(); |
var hasImplicitReturnType = returnType == null; |
@@ -2503,25 +2476,57 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper { |
exitFunction(); |
List<TypeParameter> typeParameters = typeVariableBuildersToKernel(pop()); |
FunctionNode function = formals.addToFunction(new FunctionNode(body, |
- typeParameters: typeParameters, asyncMarker: asyncModifier) |
+ typeParameters: typeParameters, |
+ asyncMarker: asyncModifier, |
+ returnType: returnType) |
..fileOffset = formals.charOffset |
..fileEndOffset = token.charOffset); |
+ |
if (declaration is FunctionDeclaration) { |
+ VariableDeclaration variable = declaration.variable; |
KernelFunctionDeclaration.setHasImplicitReturnType( |
declaration, hasImplicitReturnType); |
- function.returnType = returnType; |
- declaration.variable.type = function.functionType; |
- declaration.function = function; |
- function.parent = declaration; |
- } else { |
+ |
+ variable.type = function.functionType; |
+ if (isFunctionExpression) { |
+ variable.initializer = new KernelFunctionExpression(function) |
+ ..parent = variable |
+ ..fileOffset = formals.charOffset; |
+ exitLocalScope(); |
+ push(new KernelNamedFunctionExpression(variable)); |
+ } else { |
+ declaration.function = function; |
+ function.parent = declaration; |
+ push(declaration); |
+ } |
+ } else if (declaration is ExpressionStatement) { |
// If [declaration] isn't a [FunctionDeclaration], it must be because |
// there was a compile-time error. |
+ assert(library.hasCompileTimeErrors); |
- // TODO(paulberry): ensure that when integrating with analyzer, type |
+ // TODO(paulberry,ahe): ensure that when integrating with analyzer, type |
// inference is still performed for the dropped declaration. |
- assert(library.hasCompileTimeErrors); |
+ if (isFunctionExpression) { |
+ push(declaration.expression); |
+ } else { |
+ push(declaration); |
+ } |
+ } else { |
+ return unhandled("${declaration.runtimeType}", "pushNamedFunction", |
+ token.charOffset, uri); |
} |
- push(declaration); |
+ } |
+ |
+ @override |
+ void endNamedFunctionExpression(Token endToken) { |
+ debugEvent("NamedFunctionExpression"); |
+ pushNamedFunction(endToken, true); |
+ } |
+ |
+ @override |
+ void endLocalFunctionDeclaration(Token token) { |
+ debugEvent("LocalFunctionDeclaration"); |
+ pushNamedFunction(token, false); |
} |
@override |