Let parser handle factory modifiers.

R=johnniwinther@google.com

Review-Url: https://codereview.chromium.org/2721623002 .
This commit is contained in:
Peter von der Ahé 2017-03-01 11:38:01 +01:00
parent ea4a89ba03
commit bb72d5e8a0
7 changed files with 81 additions and 40 deletions

View file

@ -164,15 +164,8 @@ class NodeListener extends ElementListener {
typeParameters = functionType.typeParameters;
formals = functionType.formals;
}
pushNode(new Typedef(
isGeneralizedTypeAlias,
templateParameters,
returnType,
name,
typeParameters,
formals,
typedefKeyword,
endToken));
pushNode(new Typedef(isGeneralizedTypeAlias, templateParameters, returnType,
name, typeParameters, formals, typedefKeyword, endToken));
}
void handleNoName(Token token) {
@ -234,8 +227,8 @@ class NodeListener extends ElementListener {
}
@override
void endFormalParameter(Token covariantKeyword, Token thisKeyword,
FormalParameterType kind) {
void endFormalParameter(
Token covariantKeyword, Token thisKeyword, FormalParameterType kind) {
Expression name = popNode();
if (thisKeyword != null) {
Identifier thisIdentifier = new Identifier(thisKeyword);
@ -757,8 +750,8 @@ class NodeListener extends ElementListener {
}
@override
void endFunctionTypedFormalParameter(Token covariantKeyword,
Token thisKeyword, FormalParameterType kind) {
void endFunctionTypedFormalParameter(
Token covariantKeyword, Token thisKeyword, FormalParameterType kind) {
NodeList formals = popNode();
NodeList typeVariables = popNode();
Identifier name = popNode();
@ -777,8 +770,7 @@ class NodeListener extends ElementListener {
}
@override
void handleFormalParameterWithoutValue(Token token) {
}
void handleFormalParameterWithoutValue(Token token) {}
@override
void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
@ -865,6 +857,7 @@ class NodeListener extends ElementListener {
AsyncModifier asyncModifier = popNode();
NodeList formals = popNode();
Node name = popNode();
popNode(); // Discard modifiers. They're recomputed below.
// TODO(ahe): Move this parsing to the parser.
int modifierCount = 0;

View file

@ -201,6 +201,7 @@ class KernelLibraryBuilder
void addFactoryMethod(
List<MetadataBuilder> metadata,
int modifiers,
ConstructorReferenceBuilder constructorName,
List<FormalParameterBuilder> formals,
AsyncMarker asyncModifier,
@ -216,7 +217,7 @@ class KernelLibraryBuilder
assert(constructorName.suffix == null);
KernelProcedureBuilder procedure = new KernelProcedureBuilder(
metadata,
staticMask,
staticMask | modifiers,
null,
name,
<TypeVariableBuilder>[],

View file

@ -4,21 +4,46 @@
library fasta.verifier;
import 'package:kernel/ast.dart' show ExpressionStatement, Program;
import 'package:kernel/ast.dart'
show
Class,
ExpressionStatement,
Field,
Library,
Procedure,
Program,
TreeNode;
import 'package:kernel/verifier.dart' show VerifyingVisitor;
import 'package:kernel/verifier.dart' show VerificationError, VerifyingVisitor;
import '../errors.dart' show printUnexpected;
import 'redirecting_factory_body.dart' show RedirectingFactoryBody;
void verifyProgram(Program program, {bool isOutline: false}) {
program.accept(new FastaVerifyingVisitor(isOutline));
FastaVerifyingVisitor verifier = new FastaVerifyingVisitor(isOutline);
program.accept(verifier);
if (verifier.errors.isNotEmpty) {
throw verifier.errors.first;
}
}
class FastaVerifyingVisitor extends VerifyingVisitor {
final List<VerificationError> errors = <VerificationError>[];
String fileUri;
FastaVerifyingVisitor(bool isOutline) {
this.isOutline = isOutline;
}
@override
problem(TreeNode node, String details) {
VerificationError error = new VerificationError(context, node, details);
printUnexpected(Uri.parse(fileUri), node.fileOffset, "$error");
errors.add(error);
}
@override
visitExpressionStatement(ExpressionStatement node) {
// Bypass verification of the [StaticGet] in [RedirectingFactoryBody] as
@ -27,4 +52,24 @@ class FastaVerifyingVisitor extends VerifyingVisitor {
super.visitExpressionStatement(node);
}
}
visitLibrary(Library node) {
fileUri = node.fileUri;
super.visitLibrary(node);
}
visitClass(Class node) {
fileUri = node.fileUri;
super.visitClass(node);
}
visitField(Field node) {
fileUri = node.fileUri;
super.visitField(node);
}
visitProcedure(Procedure node) {
fileUri = node.fileUri;
super.visitProcedure(node);
}
}

View file

@ -1816,24 +1816,26 @@ class Parser {
Token parseFactoryMethod(Token token) {
assert(isFactoryDeclaration(token));
Token start = token;
Token externalModifier;
if (identical(token.stringValue, 'external')) {
externalModifier = token;
token = token.next;
}
if (optional('const', token)) {
token = token.next; // Skip const.
bool isExternal = false;
int modifierCount = 0;
while (isModifier(token)) {
if (optional('external', token)) {
isExternal = true;
}
token = parseModifier(token);
modifierCount++;
}
listener.handleModifiers(modifierCount);
Token factoryKeyword = token;
listener.beginFactoryMethod(factoryKeyword);
token = token.next; // Skip 'factory'.
token = expect('factory', token);
token = parseConstructorReference(token);
token = parseFormalParameters(token);
token = parseAsyncModifier(token);
if (optional('=', token)) {
token = parseRedirectingFactoryBody(token);
} else {
token = parseFunctionBody(token, false, externalModifier != null);
token = parseFunctionBody(token, false, isExternal);
}
listener.endFactoryMethod(start, token);
return token.next;

View file

@ -543,8 +543,9 @@ class OutlineBuilder extends UnhandledListener {
AsyncMarker asyncModifier = pop();
List<FormalParameterBuilder> formals = pop();
var name = pop();
int modifiers = Modifier.validate(pop());
List<MetadataBuilder> metadata = pop();
library.addFactoryMethod(metadata, name, formals, asyncModifier,
library.addFactoryMethod(metadata, modifiers, name, formals, asyncModifier,
redirectionTarget, beginToken.charOffset, nativeMethodName);
nativeMethodName = null;
}

View file

@ -211,6 +211,7 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
void addFactoryMethod(
List<MetadataBuilder> metadata,
int modifiers,
ConstructorReferenceBuilder name,
List<FormalParameterBuilder> formals,
AsyncMarker asyncModifier,

View file

@ -20,29 +20,27 @@ Future main() async {
Uri sourceCompiler = await Isolate.resolvePackageUri(
Uri.parse("package:front_end/src/fasta/bin/compile.dart"));
Uri packages = await Isolate.packageConfig;
Directory tmp = await Directory.systemTemp.createTemp("fasta_bootstrap");
Uri compiledOnceOutput = tmp.uri.resolve("fasta1.dill");
Uri compiledTwiceOutput = tmp.uri.resolve("fasta2.dill");
try {
Directory tmp = await Directory.systemTemp.createTemp("fasta_bootstrap");
Uri compiledOnceOutput = tmp.uri.resolve("fasta1.dill");
Uri compiledTwiceOutput = tmp.uri.resolve("fasta2.dill");
try {
await runCompiler(sourceCompiler, sourceCompiler, compiledOnceOutput);
await runCompiler(
compiledOnceOutput, sourceCompiler, compiledTwiceOutput);
} finally {
await tmp.delete(recursive: true);
}
await runCompiler(sourceCompiler, sourceCompiler, compiledOnceOutput);
await runCompiler(compiledOnceOutput, sourceCompiler, compiledTwiceOutput);
} finally {
asyncEnd();
await tmp.delete(recursive: true);
}
asyncEnd();
}
Future runCompiler(Uri compiler, Uri input, Uri output) async {
Uri patchedSdk = await computePatchedSdk();
Uri dartVm = Uri.base.resolve(Platform.resolvedExecutable);
StdioProcess result = await StdioProcess.run(dartVm.toFilePath(), <String>[
"-c",
compiler.toFilePath(),
"--compile-sdk=${patchedSdk.toFilePath()}",
"--output=${output.toFilePath()}",
"--verify",
input.toFilePath(),
]);
print(result.output);