Fix parsing [a]sync[*] function body modifiers with Fasta.

The Fasta'a parser is crazy as it is now. It says that something is a
return statement, but it is actually an expression function body. That
seems too much dart2js specific.

R=paulberry@google.com, ahe@google.com
BUG=

Review-Url: https://codereview.chromium.org/2728773002 .
This commit is contained in:
Konstantin Shcheglov 2017-03-01 16:20:20 -08:00
parent b17f4b2b5d
commit ce58e89d3c
8 changed files with 50 additions and 60 deletions

View file

@ -57,13 +57,6 @@ class ClassMemberParserTest_Fasta extends FastaParserTestCase
super.test_constFactory();
}
@override
@assertFailingTest
void test_parseAwaitExpression_asStatement_inAsync() {
// TODO(paulberry): Add support for async
super.test_parseAwaitExpression_asStatement_inAsync();
}
@override
@failingTest
void test_parseClassMember_constructor_withInitializers() {
@ -459,24 +452,6 @@ class ExpressionParserTest_Fasta extends FastaParserTestCase
super.test_parseExpression_assign_compound();
}
@override
@failingTest
void test_parseExpression_function_async() {
super.test_parseExpression_function_async();
}
@override
@failingTest
void test_parseExpression_function_asyncStar() {
super.test_parseExpression_function_asyncStar();
}
@override
@failingTest
void test_parseExpression_function_syncStar() {
super.test_parseExpression_function_syncStar();
}
@override
@failingTest
void test_parseExpression_superMethodInvocation_typeArgumentComments() {

View file

@ -302,6 +302,10 @@ class NodeListener extends ElementListener {
pushNode(new RedirectingFactoryBody(beginToken, endToken, popNode()));
}
void endExpressionFunctionBody(Token arrowToken, Token endToken) {
endReturnStatement(true, arrowToken, endToken);
}
@override
void endReturnStatement(
bool hasExpression, Token beginToken, Token endToken) {

View file

@ -13,14 +13,12 @@ import 'package:front_end/src/fasta/parser/parser.dart'
show FormalParameterType;
import 'package:front_end/src/fasta/scanner/token.dart'
show BeginGroupToken, Token;
import 'package:kernel/ast.dart' show AsyncMarker;
import '../errors.dart' show internalError;
import '../kernel/kernel_builder.dart'
show Builder, KernelLibraryBuilder, ProcedureBuilder;
import '../parser/identifier_context.dart' show IdentifierContext;
import '../quote.dart';
import '../source/outline_builder.dart' show asyncMarkerFromTokens;
import '../source/scope_listener.dart'
show JumpTargetKind, NullValue, Scope, ScopeListener;
import 'analyzer.dart' show toKernel;
@ -222,13 +220,22 @@ class AstBuilder extends ScopeListener {
if (beginToken != null) {
exitLocalScope();
}
push(ast.block(
toAnalyzerToken(beginToken), statements, toAnalyzerToken(endToken)));
Block block = ast.block(
toAnalyzerToken(beginToken), statements, toAnalyzerToken(endToken));
analyzer.Token star = pop();
analyzer.Token asyncKeyword = pop();
push(ast.blockFunctionBody(asyncKeyword, star, block));
}
void finishFunction(formals, asyncModifier, Statement body) {
void finishFunction(formals, asyncModifier, FunctionBody body) {
debugEvent("finishFunction");
var kernel = toKernel(body, elementStore, library.library, scope);
Statement bodyStatement;
if (body is ExpressionFunctionBody) {
bodyStatement = ast.returnStatement(null, body.expression, null);
} else {
bodyStatement = (body as BlockFunctionBody).block;
}
var kernel = toKernel(bodyStatement, elementStore, library.library, scope);
if (member is ProcedureBuilder) {
ProcedureBuilder builder = member;
builder.body = kernel;
@ -299,6 +306,16 @@ class AstBuilder extends ScopeListener {
push(ast.integerLiteral(toAnalyzerToken(token), int.parse(token.value)));
}
void endExpressionFunctionBody(Token arrowToken, Token endToken) {
debugEvent("ExpressionFunctionBody");
Expression expression = pop();
analyzer.Token star = pop();
analyzer.Token asyncKeyword = pop();
assert(star == null);
push(ast.expressionFunctionBody(asyncKeyword, toAnalyzerToken(arrowToken),
expression, toAnalyzerToken(endToken)));
}
void endReturnStatement(
bool hasExpression, Token beginToken, Token endToken) {
debugEvent("ReturnStatement");
@ -430,7 +447,8 @@ class AstBuilder extends ScopeListener {
void handleAsyncModifier(Token asyncToken, Token starToken) {
debugEvent("AsyncModifier");
push(asyncMarkerFromTokens(asyncToken, starToken));
push(toAnalyzerToken(asyncToken) ?? NullValue.FunctionBodyAsyncToken);
push(toAnalyzerToken(starToken) ?? NullValue.FunctionBodyStarToken);
}
void endAwaitExpression(Token beginToken, Token endToken) {
@ -766,31 +784,11 @@ class AstBuilder extends ScopeListener {
}
}
FunctionBody _endFunctionBody() {
AstNode body = pop();
// TODO(paulberry): asyncMarker should have a type that allows constructing
// the necessary analyzer AST data structures.
AsyncMarker asyncMarker = pop();
assert(asyncMarker == AsyncMarker.Sync);
analyzer.Token asyncKeyword = null;
analyzer.Token star = null;
if (body is Block) {
return ast.blockFunctionBody(asyncKeyword, star, body);
} else if (body is ReturnStatement) {
assert(star == null);
return ast.expressionFunctionBody(
asyncKeyword, body.returnKeyword, body.expression, body.semicolon);
} else {
return internalError(
'Unexpected function body type: ${body.runtimeType}');
}
}
void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
// TODO(paulberry): set up scopes properly to resolve parameters and type
// variables.
debugEvent("TopLevelMethod");
FunctionBody body = _endFunctionBody();
FunctionBody body = pop();
FormalParameterList parameters = pop();
TypeParameterList typeParameters = pop();
SimpleIdentifier name = pop();
@ -1115,7 +1113,7 @@ class AstBuilder extends ScopeListener {
// in constructors, so the logic should be shared with BodyBuilder as much
// as possible.
debugEvent("UnnamedFunction");
var body = _endFunctionBody();
FunctionBody body = pop();
FormalParameterList parameters = pop();
TypeParameterList typeParameters = pop();
push(ast.functionExpression(typeParameters, parameters, body));
@ -1178,7 +1176,7 @@ class AstBuilder extends ScopeListener {
@override
void endMethod(Token getOrSet, Token beginToken, Token endToken) {
debugEvent("Method");
FunctionBody body = _endFunctionBody();
FunctionBody body = pop();
ConstructorName redirectedConstructor = null; // TODO(paulberry)
List<ConstructorInitializer> initializers = null; // TODO(paulberry)
Token separator = null; // TODO(paulberry)

View file

@ -841,6 +841,12 @@ class BodyBuilder extends ScopeListener<JumpTarget> implements BuilderHelper {
push(new IntLiteral(int.parse(token.value)));
}
@override
void endExpressionFunctionBody(Token arrowToken, Token endToken) {
debugEvent("ExpressionFunctionBody");
endReturnStatement(true, arrowToken, endToken);
}
@override
void endReturnStatement(
bool hasExpression, Token beginToken, Token endToken) {

View file

@ -551,6 +551,10 @@ class Listener {
void beginReturnStatement(Token token) {}
void endExpressionFunctionBody(Token arrowToken, Token endToken) {
logEvent("ExpressionFunctionBody");
}
void endReturnStatement(
bool hasExpression, Token beginToken, Token endToken) {
logEvent("ReturnStatement");

View file

@ -2016,9 +2016,9 @@ class Parser {
token = parseExpression(token.next);
if (!isExpression) {
expectSemicolon(token);
listener.endReturnStatement(true, begin, token);
listener.endExpressionFunctionBody(begin, token);
} else {
listener.endReturnStatement(true, begin, null);
listener.endExpressionFunctionBody(begin, null);
}
return token;
} else if (optional('=', token)) {
@ -2028,9 +2028,9 @@ class Parser {
token = parseExpression(token.next);
if (!isExpression) {
expectSemicolon(token);
listener.endReturnStatement(true, begin, token);
listener.endExpressionFunctionBody(begin, token);
} else {
listener.endReturnStatement(true, begin, null);
listener.endExpressionFunctionBody(begin, null);
}
return token;
}

View file

@ -496,7 +496,8 @@ class DietListener extends StackListener {
listener.prepareInitializers();
token = parser.parseInitializersOpt(token);
token = parser.parseAsyncModifier(token);
AsyncMarker asyncModifier = listener.pop();
AsyncMarker asyncModifier =
astKind == AstKind.Analyzer ? null : listener.pop();
bool isExpression = false;
bool allowAbstract = true;
parser.parseFunctionBody(token, isExpression, allowAbstract);

View file

@ -32,6 +32,8 @@ enum NullValue {
FieldInitializer,
FormalParameters,
FunctionBody,
FunctionBodyAsyncToken,
FunctionBodyStarToken,
IdentifierList,
Initializers,
Metadata,