Skip to content

Commit fcd684e

Browse files
Chloe Stefantsovacommit-bot@chromium.org
Chloe Stefantsova
authored andcommitted
[cfe] Allow named arguments anywhere by the CFE
Change-Id: I36ecafe821fe328bd27cb40dafca78ad0bf5dd81 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/214803 Commit-Queue: Chloe Stefantsova <[email protected]> Reviewed-by: Johnni Winther <[email protected]>
1 parent 8062c4c commit fcd684e

25 files changed

+1671
-145
lines changed

pkg/front_end/lib/src/api_prototype/compiler_options.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ class CompilerOptions {
126126
Map<ExperimentalFlag, Version>? experimentEnabledVersionForTesting;
127127
Map<ExperimentalFlag, Version>? experimentReleasedVersionForTesting;
128128

129+
bool enableUnscheduledExperiments = false;
130+
129131
/// Environment map used when evaluating `bool.fromEnvironment`,
130132
/// `int.fromEnvironment` and `String.fromEnvironment` during constant
131133
/// evaluation. If the map is `null`, all environment constants will be left
@@ -357,6 +359,9 @@ class CompilerOptions {
357359
if (currentSdkVersion != other.currentSdkVersion) return false;
358360
if (emitDeps != other.emitDeps) return false;
359361
if (!equalSets(invocationModes, other.invocationModes)) return false;
362+
if (enableUnscheduledExperiments != other.enableUnscheduledExperiments) {
363+
return false;
364+
}
360365

361366
return true;
362367
}

pkg/front_end/lib/src/base/command_line_options.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ class Flags {
2929
static const String compileSdk = "--compile-sdk";
3030
static const String dumpIr = "--dump-ir";
3131
static const String enableExperiment = "--enable-experiment";
32+
static const String enableUnscheduledExperiments =
33+
"--enable-unscheduled-experiments";
3234
static const String excludeSource = "--exclude-source";
3335
static const String omitPlatform = "--omit-platform";
3436
static const String fatal = "--fatal";
@@ -59,6 +61,8 @@ class Options {
5961
const Option(Flags.dumpIr, const BoolValue(false));
6062
static const Option<List<String>?> enableExperiment =
6163
const Option(Flags.enableExperiment, const StringListValue());
64+
static const Option<bool> enableUnscheduledExperiments =
65+
const Option(Flags.enableUnscheduledExperiments, const BoolValue(false));
6266
static const Option<bool> excludeSource =
6367
const Option(Flags.excludeSource, const BoolValue(false));
6468
static const Option<bool> omitPlatform =

pkg/front_end/lib/src/base/processed_options.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ class ProcessedOptions {
186186

187187
bool get warnOnReachabilityCheck => _raw.warnOnReachabilityCheck;
188188

189+
bool get enableUnscheduledExperiments => _raw.enableUnscheduledExperiments;
190+
189191
/// The entry-points provided to the compiler.
190192
final List<Uri> inputs;
191193

pkg/front_end/lib/src/fasta/builder/factory_builder.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ class RedirectingFactoryBuilder extends SourceFactoryBuilder {
401401
unhandled("${targetBuilder.runtimeType}", "buildOutlineExpressions",
402402
charOffset, fileUri);
403403
}
404-
Arguments targetInvocationArguments;
404+
ArgumentsImpl targetInvocationArguments;
405405
{
406406
List<Expression> positionalArguments = <Expression>[];
407407
for (VariableDeclaration parameter

pkg/front_end/lib/src/fasta/kernel/body_builder.dart

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,11 @@ class BodyBuilder extends ScopeListener<JumpTarget>
451451
return libraryBuilder.enableConstructorTearOffsInLibrary;
452452
}
453453

454+
@override
455+
bool get enableNamedArgumentsAnywhereInLibrary {
456+
return libraryBuilder.enableNamedArgumentsAnywhereInLibrary;
457+
}
458+
454459
void _enterLocalState({bool inLateLocalInitializer: false}) {
455460
_localInitializerState =
456461
_localInitializerState.prepend(inLateLocalInitializer);
@@ -1700,35 +1705,72 @@ class BodyBuilder extends ScopeListener<JumpTarget>
17001705
push(new ParserRecovery(beginToken.charOffset));
17011706
return;
17021707
}
1708+
List<Object?>? argumentsOriginalOrder;
1709+
if (libraryBuilder.enableNamedArgumentsAnywhereInLibrary) {
1710+
argumentsOriginalOrder = new List<Object?>.from(arguments);
1711+
}
17031712
int firstNamedArgumentIndex = arguments.length;
1713+
int positionalCount = 0;
1714+
bool hasNamedBeforePositional = false;
17041715
for (int i = 0; i < arguments.length; i++) {
17051716
Object? node = arguments[i];
17061717
if (node is NamedExpression) {
17071718
firstNamedArgumentIndex =
17081719
i < firstNamedArgumentIndex ? i : firstNamedArgumentIndex;
17091720
} else {
1721+
positionalCount++;
17101722
Expression argument = toValue(node);
17111723
arguments[i] = argument;
1724+
argumentsOriginalOrder?[i] = argument;
17121725
if (i > firstNamedArgumentIndex) {
1713-
arguments[i] = new NamedExpression(
1714-
"#$i",
1715-
buildProblem(fasta.messageExpectedNamedArgument,
1716-
argument.fileOffset, noLength))
1717-
..fileOffset = beginToken.charOffset;
1726+
hasNamedBeforePositional = true;
1727+
if (!libraryBuilder.enableNamedArgumentsAnywhereInLibrary) {
1728+
arguments[i] = new NamedExpression(
1729+
"#$i",
1730+
buildProblem(fasta.messageExpectedNamedArgument,
1731+
argument.fileOffset, noLength))
1732+
..fileOffset = beginToken.charOffset;
1733+
}
17181734
}
17191735
}
17201736
}
1737+
if (!hasNamedBeforePositional) {
1738+
argumentsOriginalOrder = null;
1739+
}
17211740
if (firstNamedArgumentIndex < arguments.length) {
1722-
List<Expression> positional = new List<Expression>.from(
1723-
arguments.getRange(0, firstNamedArgumentIndex));
1724-
List<NamedExpression> named = new List<NamedExpression>.from(
1725-
arguments.getRange(firstNamedArgumentIndex, arguments.length));
1726-
push(forest.createArguments(beginToken.offset, positional, named: named));
1741+
List<Expression> positional;
1742+
List<NamedExpression> named;
1743+
if (libraryBuilder.enableNamedArgumentsAnywhereInLibrary) {
1744+
positional =
1745+
new List<Expression>.filled(positionalCount, dummyExpression);
1746+
named = new List<NamedExpression>.filled(
1747+
arguments.length - positionalCount, dummyNamedExpression);
1748+
int positionalIndex = 0;
1749+
int namedIndex = 0;
1750+
for (int i = 0; i < arguments.length; i++) {
1751+
if (arguments[i] is NamedExpression) {
1752+
named[namedIndex++] = arguments[i] as NamedExpression;
1753+
} else {
1754+
positional[positionalIndex++] = arguments[i] as Expression;
1755+
}
1756+
}
1757+
assert(
1758+
positionalIndex == positional.length && namedIndex == named.length);
1759+
} else {
1760+
positional = new List<Expression>.from(
1761+
arguments.getRange(0, firstNamedArgumentIndex));
1762+
named = new List<NamedExpression>.from(
1763+
arguments.getRange(firstNamedArgumentIndex, arguments.length));
1764+
}
1765+
1766+
push(forest.createArguments(beginToken.offset, positional,
1767+
named: named, argumentsOriginalOrder: argumentsOriginalOrder));
17271768
} else {
17281769
// TODO(kmillikin): Find a way to avoid allocating a second list in the
17291770
// case where there were no named arguments, which is a common one.
17301771
push(forest.createArguments(
1731-
beginToken.offset, new List<Expression>.from(arguments)));
1772+
beginToken.offset, new List<Expression>.from(arguments),
1773+
argumentsOriginalOrder: argumentsOriginalOrder));
17321774
}
17331775
assert(checkState(beginToken, [ValueKinds.Arguments]));
17341776
}
@@ -1831,7 +1873,7 @@ class BodyBuilder extends ScopeListener<JumpTarget>
18311873
} else if (arguments == null) {
18321874
push(receiver);
18331875
} else {
1834-
push(finishSend(receiver, typeArguments, arguments as Arguments,
1876+
push(finishSend(receiver, typeArguments, arguments as ArgumentsImpl,
18351877
beginToken.charOffset,
18361878
isTypeArgumentsInForest: isInForest));
18371879
}
@@ -1847,8 +1889,11 @@ class BodyBuilder extends ScopeListener<JumpTarget>
18471889
}
18481890

18491891
@override
1850-
Expression_Generator_Initializer finishSend(Object receiver,
1851-
List<UnresolvedType>? typeArguments, Arguments arguments, int charOffset,
1892+
Expression_Generator_Initializer finishSend(
1893+
Object receiver,
1894+
List<UnresolvedType>? typeArguments,
1895+
ArgumentsImpl arguments,
1896+
int charOffset,
18521897
{bool isTypeArgumentsInForest = false}) {
18531898
if (receiver is Generator) {
18541899
return receiver.doInvocation(charOffset, typeArguments, arguments,

pkg/front_end/lib/src/fasta/kernel/expression_generator.dart

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ abstract class Generator {
217217
/// If the invocation has explicit type arguments
218218
/// [buildTypeWithResolvedArguments] called instead.
219219
Expression_Generator_Initializer doInvocation(
220-
int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
220+
int offset, List<UnresolvedType>? typeArguments, ArgumentsImpl arguments,
221221
{bool isTypeArgumentsInForest = false});
222222

223223
Expression_Generator buildSelectorAccess(
@@ -1774,7 +1774,7 @@ class ExtensionInstanceAccessGenerator extends Generator {
17741774

17751775
@override
17761776
Expression doInvocation(
1777-
int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
1777+
int offset, List<UnresolvedType>? typeArguments, ArgumentsImpl arguments,
17781778
{bool isTypeArgumentsInForest = false}) {
17791779
if (invokeTarget != null) {
17801780
return _helper.buildExtensionMethodInvocation(
@@ -1789,7 +1789,8 @@ class ExtensionInstanceAccessGenerator extends Generator {
17891789
extensionTypeArguments: _createExtensionTypeArguments(),
17901790
typeArguments: arguments.types,
17911791
positionalArguments: arguments.positional,
1792-
namedArguments: arguments.named),
1792+
namedArguments: arguments.named,
1793+
argumentsOriginalOrder: arguments.argumentsOriginalOrder),
17931794
isTearOff: false);
17941795
} else {
17951796
return _helper.forest.createExpressionInvocation(
@@ -2649,8 +2650,8 @@ class ExplicitExtensionAccessGenerator extends Generator {
26492650
Generator generator =
26502651
_createInstanceAccess(send.token, send.name, isNullAware: isNullAware);
26512652
if (send.arguments != null) {
2652-
return generator.doInvocation(
2653-
offsetForToken(send.token), send.typeArguments, send.arguments!,
2653+
return generator.doInvocation(offsetForToken(send.token),
2654+
send.typeArguments, send.arguments! as ArgumentsImpl,
26542655
isTypeArgumentsInForest: send.isTypeArgumentsInForest);
26552656
} else {
26562657
return generator;
@@ -2676,7 +2677,7 @@ class ExplicitExtensionAccessGenerator extends Generator {
26762677

26772678
@override
26782679
Expression_Generator_Initializer doInvocation(
2679-
int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
2680+
int offset, List<UnresolvedType>? typeArguments, ArgumentsImpl arguments,
26802681
{bool isTypeArgumentsInForest = false}) {
26812682
Generator generator = _createInstanceAccess(token, callName);
26822683
return generator.doInvocation(offset, typeArguments, arguments,
@@ -2935,7 +2936,7 @@ class DeferredAccessGenerator extends Generator {
29352936

29362937
@override
29372938
Expression_Generator_Initializer doInvocation(
2938-
int offset, List<UnresolvedType>? typeArguments, Arguments arguments,
2939+
int offset, List<UnresolvedType>? typeArguments, ArgumentsImpl arguments,
29392940
{bool isTypeArgumentsInForest = false}) {
29402941
Object suffix = suffixGenerator.doInvocation(
29412942
offset, typeArguments, arguments,
@@ -3126,7 +3127,7 @@ class TypeUseGenerator extends AbstractReadOnlyAccessGenerator {
31263127
Selector send, int operatorOffset, bool isNullAware) {
31273128
int nameOffset = offsetForToken(send.token);
31283129
Name name = send.name;
3129-
Arguments? arguments = send.arguments;
3130+
ArgumentsImpl? arguments = send.arguments as ArgumentsImpl?;
31303131

31313132
TypeDeclarationBuilder? declarationBuilder = declaration;
31323133
TypeAliasBuilder? aliasBuilder;
@@ -4067,8 +4068,8 @@ class PrefixUseGenerator extends Generator {
40674068
"'${send.name.text}' != ${send.token.lexeme}");
40684069
Object result = qualifiedLookup(send.token);
40694070
if (send is InvocationSelector) {
4070-
result = _helper.finishSend(
4071-
result, send.typeArguments, send.arguments, send.fileOffset,
4071+
result = _helper.finishSend(result, send.typeArguments,
4072+
send.arguments as ArgumentsImpl, send.fileOffset,
40724073
isTypeArgumentsInForest: send.isTypeArgumentsInForest);
40734074
}
40744075
if (isNullAware) {

pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,14 @@ abstract class ExpressionGeneratorHelper implements InferenceHelper {
5454

5555
bool get enableConstructorTearOffsInLibrary;
5656

57+
bool get enableNamedArgumentsAnywhereInLibrary;
58+
5759
Expression_Generator_Builder scopeLookup(
5860
Scope scope, String name, Token token,
5961
{bool isQualified: false, PrefixBuilder? prefix});
6062

6163
Expression_Generator_Initializer finishSend(Object receiver,
62-
List<UnresolvedType>? typeArguments, Arguments arguments, int offset,
64+
List<UnresolvedType>? typeArguments, ArgumentsImpl arguments, int offset,
6365
{bool isTypeArgumentsInForest = false});
6466

6567
Initializer buildInvalidInitializer(Expression expression,

pkg/front_end/lib/src/fasta/kernel/forest.dart

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,25 @@ import 'internal_ast.dart';
2727
class Forest {
2828
const Forest();
2929

30-
Arguments createArguments(int fileOffset, List<Expression> positional,
30+
ArgumentsImpl createArguments(int fileOffset, List<Expression> positional,
3131
{List<DartType>? types,
3232
List<NamedExpression>? named,
33-
bool hasExplicitTypeArguments = true}) {
33+
bool hasExplicitTypeArguments = true,
34+
List<Object?>? argumentsOriginalOrder}) {
3435
// ignore: unnecessary_null_comparison
3536
assert(fileOffset != null);
3637
if (!hasExplicitTypeArguments) {
37-
ArgumentsImpl arguments =
38-
new ArgumentsImpl(positional, types: <DartType>[], named: named);
38+
ArgumentsImpl arguments = new ArgumentsImpl(positional,
39+
types: <DartType>[],
40+
named: named,
41+
argumentsOriginalOrder: argumentsOriginalOrder);
3942
arguments.types.addAll(types!);
4043
return arguments;
4144
} else {
42-
return new ArgumentsImpl(positional, types: types, named: named)
45+
return new ArgumentsImpl(positional,
46+
types: types,
47+
named: named,
48+
argumentsOriginalOrder: argumentsOriginalOrder)
4349
..fileOffset = fileOffset;
4450
}
4551
}
@@ -53,7 +59,8 @@ class Forest {
5359
int? extensionTypeArgumentOffset,
5460
List<DartType> typeArguments = const <DartType>[],
5561
List<Expression> positionalArguments = const <Expression>[],
56-
List<NamedExpression> namedArguments = const <NamedExpression>[]}) {
62+
List<NamedExpression> namedArguments = const <NamedExpression>[],
63+
List<Object?>? argumentsOriginalOrder}) {
5764
// ignore: unnecessary_null_comparison
5865
assert(fileOffset != null);
5966
return new ArgumentsImpl.forExtensionMethod(
@@ -62,11 +69,12 @@ class Forest {
6269
extensionTypeArgumentOffset: extensionTypeArgumentOffset,
6370
typeArguments: typeArguments,
6471
positionalArguments: positionalArguments,
65-
namedArguments: namedArguments)
72+
namedArguments: namedArguments,
73+
argumentsOriginalOrder: argumentsOriginalOrder)
6674
..fileOffset = fileOffset;
6775
}
6876

69-
Arguments createArgumentsEmpty(int fileOffset) {
77+
ArgumentsImpl createArgumentsEmpty(int fileOffset) {
7078
// ignore: unnecessary_null_comparison
7179
assert(fileOffset != null);
7280
return createArguments(fileOffset, <Expression>[]);

0 commit comments

Comments
 (0)