70a453f55f
This adds an ExperimentalFeatures interface to make the parser able to know which experimental feature is currently supported. This generalizes the existing dependency on patterns and enhanced parts, and facilitates reporting of unsupported features directly within the parser, avoid the need for duplicate handling of this within analyzer+CFE. Change-Id: If1752745ee4d753e4b463f2017f440223cd98737 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/455700 Commit-Queue: Johnni Winther <johnniwinther@google.com> Reviewed-by: Jens Johansen <jensj@google.com>
126 lines
3.3 KiB
Dart
126 lines
3.3 KiB
Dart
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import 'dart:io';
|
|
import 'dart:typed_data';
|
|
|
|
import 'package:_fe_analyzer_shared/src/messages/codes.dart';
|
|
import 'package:_fe_analyzer_shared/src/parser/experimental_features.dart';
|
|
import 'package:_fe_analyzer_shared/src/parser/forwarding_listener.dart';
|
|
import 'package:_fe_analyzer_shared/src/parser/listener.dart';
|
|
import 'package:_fe_analyzer_shared/src/parser/parser_impl.dart';
|
|
import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart';
|
|
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
|
|
|
|
void main(List<String> args) {
|
|
if (args.length != 1) {
|
|
throw "Expected 1 argument: <dart file>.";
|
|
}
|
|
File f = new File(args.single);
|
|
if (!f.existsSync()) {
|
|
throw "File $f doesn't exist.";
|
|
}
|
|
Uint8List contentBytes = f.readAsBytesSync();
|
|
ScannerResult scanResult = scan(
|
|
contentBytes,
|
|
configuration: new ScannerConfiguration(enableTripleShift: true),
|
|
includeComments: true,
|
|
);
|
|
|
|
const int iterations = 1000;
|
|
|
|
int countTokens = 0;
|
|
{
|
|
Token t = scanResult.tokens;
|
|
while (!t.isEof) {
|
|
countTokens++;
|
|
t = t.next!;
|
|
}
|
|
}
|
|
|
|
// TODO: Should we make 1000 copies of the tokens?
|
|
// Or maybe scan 1000 times?
|
|
/*
|
|
List<Token> tokenStarts = [];
|
|
tokenStarts.add(scanResult.tokens);
|
|
while (tokenStarts.length < iterations) {
|
|
tokenStarts.add(
|
|
scan(
|
|
contentBytes,
|
|
configuration: new ScannerConfiguration(enableTripleShift: true),
|
|
includeComments: true,
|
|
).tokens,
|
|
);
|
|
}
|
|
*/
|
|
|
|
Listener listener = new NullListener();
|
|
if (f.path == "42") {
|
|
// Let's not let it optimize too many things away or do weird optimizations
|
|
// that it can't do in practise.
|
|
listener = new FooListener(f.uri);
|
|
}
|
|
|
|
int numErrors = 0;
|
|
Stopwatch stopwatch = new Stopwatch()..start();
|
|
int lengthProcessed = countTokens;
|
|
|
|
for (int i = 0; i < iterations; i++) {
|
|
Parser parser = new Parser(
|
|
listener,
|
|
experimentalFeatures: const DefaultExperimentalFeatures(),
|
|
);
|
|
Token after = parser.parseUnit(scanResult.tokens);
|
|
if (!after.isEof) {
|
|
throw "parsed returned before eof?!?";
|
|
}
|
|
if (listener is NullListener && listener.hasErrors) {
|
|
numErrors++;
|
|
}
|
|
// Or maybe - maybe as an option - do another scan here?
|
|
}
|
|
|
|
stopwatch.stop();
|
|
print(
|
|
"Parsed $lengthProcessed tokens $iterations times "
|
|
"in ${stopwatch.elapsed}",
|
|
);
|
|
print("Found errors $numErrors times");
|
|
double lengthPerMicrosecond =
|
|
(lengthProcessed * iterations) / stopwatch.elapsedMicroseconds;
|
|
print("That's $lengthPerMicrosecond tokens per microsecond");
|
|
print("");
|
|
}
|
|
|
|
class FooListener extends StackListener {
|
|
List<Message> problems = [];
|
|
|
|
@override
|
|
final Uri uri;
|
|
|
|
FooListener(this.uri);
|
|
|
|
@override
|
|
void addProblem(
|
|
Message message,
|
|
int charOffset,
|
|
int length, {
|
|
bool wasHandled = false,
|
|
List<LocatedMessage>? context,
|
|
}) {
|
|
if (charOffset == 42) {
|
|
throw "$message $charOffset $length $wasHandled $context";
|
|
}
|
|
problems.add(message);
|
|
}
|
|
|
|
@override
|
|
Never internalProblem(Message message, int charOffset, Uri uri) {
|
|
throw UnimplementedError();
|
|
}
|
|
|
|
@override
|
|
bool get isDartLibrary => false;
|
|
}
|