Skip to content

Commit

Permalink
Fix parsing [a]sync[*] function body modifiers with Fasta.
Browse files Browse the repository at this point in the history
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 .
  • Loading branch information
scheglov committed Mar 2, 2017
1 parent b17f4b2 commit ce58e89
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 60 deletions.
25 changes: 0 additions & 25 deletions pkg/analyzer/test/generated/parser_fasta_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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() {
Expand Down
4 changes: 4 additions & 0 deletions pkg/compiler/lib/src/parser/node_listener.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
58 changes: 28 additions & 30 deletions pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions pkg/front_end/lib/src/fasta/kernel/body_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 4 additions & 0 deletions pkg/front_end/lib/src/fasta/parser/listener.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
8 changes: 4 additions & 4 deletions pkg/front_end/lib/src/fasta/parser/parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand All @@ -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;
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/front_end/lib/src/fasta/source/diet_listener.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions pkg/front_end/lib/src/fasta/source/stack_listener.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ enum NullValue {
FieldInitializer,
FormalParameters,
FunctionBody,
FunctionBodyAsyncToken,
FunctionBodyStarToken,
IdentifierList,
Initializers,
Metadata,
Expand Down

0 comments on commit ce58e89

Please sign in to comment.