Skip to content

Commit

Permalink
[cfe] Const factories when const functions enabled.
Browse files Browse the repository at this point in the history
Change-Id: Ifd24678c0ac191c5cc6f1d60443ab96f56cbba7d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/192400
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Jake Macdonald <jakemac@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Kallen Tu <kallentu@google.com>
  • Loading branch information
kallentu authored and commit-bot@chromium.org committed Apr 6, 2021
1 parent a38a2dd commit b5d4d26
Show file tree
Hide file tree
Showing 22 changed files with 363 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,11 @@ class ForwardingListener implements Listener {
listener?.handleConditionalExpressionColon();
}

@override
void handleConstFactory(Token constKeyword) {
listener?.handleConstFactory(constKeyword);
}

@override
void handleContinueStatement(
bool hasTarget, Token continueKeyword, Token endToken) {
Expand Down
4 changes: 4 additions & 0 deletions pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1360,6 +1360,10 @@ class Listener implements UnescapeErrorListener {
logEvent("ConstExpression");
}

void handleConstFactory(Token constKeyword) {
logEvent("ConstFactory");
}

/// Called before parsing a "for" control flow list, set, or map entry.
/// Ended by either [endForControlFlow] or [endForInControlFlow].
void beginForControlFlow(Token? awaitToken, Token forToken) {}
Expand Down
2 changes: 1 addition & 1 deletion pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4063,7 +4063,7 @@ class Parser {
} else {
if (varFinalOrConst != null && !optional('native', next)) {
if (optional('const', varFinalOrConst)) {
reportRecoverableError(varFinalOrConst, codes.messageConstFactory);
listener.handleConstFactory(varFinalOrConst);
}
}
token = parseFunctionBody(
Expand Down
8 changes: 8 additions & 0 deletions pkg/analyzer/lib/src/fasta/ast_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:_fe_analyzer_shared/src/messages/codes.dart'
messageAbstractLateField,
messageAbstractStaticField,
messageConstConstructorWithBody,
messageConstFactory,
messageConstructorWithTypeParameters,
messageDirectiveAfterDeclaration,
messageExpectedStatement,
Expand Down Expand Up @@ -2574,6 +2575,13 @@ class AstBuilder extends StackListener {
push(referenceOffset);
}

@override
void handleConstFactory(Token constKeyword) {
debugEvent("ConstFactory");
// TODO(kallentu): Removal of const factory error for const function feature
handleRecoverableError(messageConstFactory, constKeyword, constKeyword);
}

@override
void handleContinueStatement(
bool hasTarget, Token continueKeyword, Token semicolon) {
Expand Down
9 changes: 9 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 @@ -4768,6 +4768,15 @@ class BodyBuilder extends ScopeListener<JumpTarget>
inMetadata: false);
}

@override
void handleConstFactory(Token constKeyword) {
debugEvent("ConstFactory");
if (!libraryBuilder.enableConstFunctionsInLibrary) {
handleRecoverableError(
fasta.messageConstFactory, constKeyword, constKeyword);
}
}

@override
void beginIfControlFlow(Token ifToken) {
// TODO(danrubel): consider removing this when control flow support is added
Expand Down
5 changes: 5 additions & 0 deletions pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2783,6 +2783,11 @@ class ConstantEvaluator implements ExpressionVisitor<Constant> {
} else {
name = '${target.enclosingClass.name}.${name}';
}

if (enableConstFunctions) {
return _handleFunctionInvocation(
node.target.function, typeArguments, positionals, named);
}
}
return createInvalidExpressionConstant(node, "Invocation of $name");
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/front_end/lib/src/fasta/source/diet_listener.dart
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,11 @@ class DietListener extends StackListenerImpl {
_inRedirectingFactory = true;
}

@override
void handleConstFactory(Token constKeyword) {
debugEvent("ConstFactory");
}

@override
void handleNativeFunctionBody(Token nativeToken, Token semicolon) {
debugEvent("NativeFunctionBody");
Expand Down
8 changes: 8 additions & 0 deletions pkg/front_end/lib/src/fasta/source/outline_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2044,6 +2044,14 @@ class OutlineBuilder extends StackListenerImpl {
push(MethodBody.RedirectingFactoryBody);
}

@override
void handleConstFactory(Token constKeyword) {
debugEvent("ConstFactory");
if (!libraryBuilder.enableConstFunctionsInLibrary) {
handleRecoverableError(messageConstFactory, constKeyword, constKeyword);
}
}

@override
void endFieldInitializer(Token assignmentOperator, Token token) {
debugEvent("FieldInitializer");
Expand Down
19 changes: 19 additions & 0 deletions pkg/front_end/lib/src/fasta/util/direct_parser_ast_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1970,6 +1970,13 @@ abstract class AbstractDirectParserASTListener implements Listener {
seen(data);
}

void handleConstFactory(Token constKeyword) {
DirectParserASTContentConstFactoryHandle data =
new DirectParserASTContentConstFactoryHandle(DirectParserASTType.HANDLE,
constKeyword: constKeyword);
seen(data);
}

void beginForControlFlow(Token awaitToken, Token forToken) {
DirectParserASTContentForControlFlowBegin data =
new DirectParserASTContentForControlFlowBegin(DirectParserASTType.BEGIN,
Expand Down Expand Up @@ -5814,6 +5821,18 @@ class DirectParserASTContentConstExpressionEnd extends DirectParserASTContent {
};
}

class DirectParserASTContentConstFactoryHandle extends DirectParserASTContent {
final Token constKeyword;

DirectParserASTContentConstFactoryHandle(DirectParserASTType type,
{this.constKeyword})
: super("ConstFactory", type);

Map<String, Object> get deprecatedArguments => {
"constKeyword": constKeyword,
};
}

class DirectParserASTContentForControlFlowBegin extends DirectParserASTContent {
final Token awaitToken;
final Token forToken;
Expand Down
5 changes: 5 additions & 0 deletions pkg/front_end/test/parser_test_listener.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1765,6 +1765,11 @@ class ParserTestListener implements Listener {
doPrint('endConstExpression(' '$token)');
}

void handleConstFactory(Token constKeyword) {
seen(constKeyword);
doPrint('handleConstFactory(' '$constKeyword)');
}

void beginForControlFlow(Token? awaitToken, Token forToken) {
seen(awaitToken);
seen(forToken);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) 2021, 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.

// Tests const factories with const functions.

import "package:expect/expect.dart";

const printConst = MessageType.parse("print");

class MessageType {
static const print = MessageType._('print');

static const skip = MessageType._('skip');

final String name;

const factory MessageType.parse(String name) {
if (name == 'print') {
return MessageType.print;
}
return MessageType.skip;
}

const MessageType._(this.name);
}

void main() {
Expect.equals(printConst, MessageType.print);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "package:expect/expect.dart" as exp;

import "package:expect/expect.dart";

class MessageType extends core::Object /*hasConstConstructor*/ {
static const field self::MessageType print = #C2;
static const field self::MessageType skip = #C4;
final field core::String name;
const constructor _(core::String name) → self::MessageType
: self::MessageType::name = name, super core::Object::•()
;
static factory parse(core::String name) → self::MessageType {
if(name.{core::String::==}("print")) {
return #C2;
}
return #C4;
}
}
static const field self::MessageType printConst = #C2;
static method main() → void {
exp::Expect::equals(#C2, #C2);
}

constants {
#C1 = "print"
#C2 = self::MessageType {name:#C1}
#C3 = "skip"
#C4 = self::MessageType {name:#C3}
}


Constructor coverage from constants:
org-dartlang-testcase:///const_functions_const_factory.dart:
- MessageType._ (from org-dartlang-testcase:///const_functions_const_factory.dart:25:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "package:expect/expect.dart" as exp;

import "package:expect/expect.dart";

class MessageType extends core::Object /*hasConstConstructor*/ {
static const field self::MessageType print = #C2;
static const field self::MessageType skip = #C4;
final field core::String name;
const constructor _(core::String name) → self::MessageType
: self::MessageType::name = name, super core::Object::•()
;
static factory parse(core::String name) → self::MessageType {
if(name.{core::String::==}("print")) {
return #C2;
}
return #C4;
}
}
static const field self::MessageType printConst = #C2;
static method main() → void {
exp::Expect::equals(#C2, #C2);
}

constants {
#C1 = "print"
#C2 = self::MessageType {name:#C1}
#C3 = "skip"
#C4 = self::MessageType {name:#C3}
}


Constructor coverage from constants:
org-dartlang-testcase:///const_functions_const_factory.dart:
- MessageType._ (from org-dartlang-testcase:///const_functions_const_factory.dart:25:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import "package:expect/expect.dart";
const printConst = MessageType.parse("print");
class MessageType {
static const print = MessageType._('print');
static const skip = MessageType._('skip');
final String name;
const factory MessageType.parse(String name) {}
const MessageType._(this.name);
}
void main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import "package:expect/expect.dart";

class MessageType {
const MessageType._(this.name);
const factory MessageType.parse(String name) {}
final String name;
static const print = MessageType._('print');
static const skip = MessageType._('skip');
}

const printConst = MessageType.parse("print");
void main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "package:expect/expect.dart" as exp;

import "package:expect/expect.dart";

class MessageType extends core::Object /*hasConstConstructor*/ {
static const field self::MessageType print = #C2;
static const field self::MessageType skip = #C4;
final field core::String name;
const constructor _(core::String name) → self::MessageType
: self::MessageType::name = name, super core::Object::•()
;
static factory parse(core::String name) → self::MessageType {
if(name.{core::String::==}("print")) {
return #C2;
}
return #C4;
}
}
static const field self::MessageType printConst = #C2;
static method main() → void {
exp::Expect::equals(#C2, #C2);
}

constants {
#C1 = "print"
#C2 = self::MessageType {name:#C1}
#C3 = "skip"
#C4 = self::MessageType {name:#C3}
}


Constructor coverage from constants:
org-dartlang-testcase:///const_functions_const_factory.dart:
- MessageType._ (from org-dartlang-testcase:///const_functions_const_factory.dart:25:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;

import "package:expect/expect.dart";

class MessageType extends core::Object /*hasConstConstructor*/ {
static const field self::MessageType print = const self::MessageType::_("print");
static const field self::MessageType skip = const self::MessageType::_("skip");
final field core::String name;
const constructor _(core::String name) → self::MessageType
: self::MessageType::name = name, super core::Object::•()
;
static const factory parse(core::String name) → self::MessageType
;
}
static const field self::MessageType printConst = const self::MessageType::parse("print");
static method main() → void
;


Extra constant evaluation status:
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_functions_const_factory.dart:12:36 -> InstanceConstant(const MessageType{MessageType.name: "print"})
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_functions_const_factory.dart:14:35 -> InstanceConstant(const MessageType{MessageType.name: "skip"})
Extra constant evaluation: evaluated: 4, effectively constant: 2
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
library /*isNonNullableByDefault*/;
import self as self;
import "dart:core" as core;
import "package:expect/expect.dart" as exp;

import "package:expect/expect.dart";

class MessageType extends core::Object /*hasConstConstructor*/ {
static const field self::MessageType print = #C2;
static const field self::MessageType skip = #C4;
final field core::String name;
const constructor _(core::String name) → self::MessageType
: self::MessageType::name = name, super core::Object::•()
;
static factory parse(core::String name) → self::MessageType {
if(name.{core::String::==}("print")) {
return #C2;
}
return #C4;
}
}
static const field self::MessageType printConst = #C2;
static method main() → void {
exp::Expect::equals(#C2, #C2);
}

constants {
#C1 = "print"
#C2 = self::MessageType {name:#C1}
#C3 = "skip"
#C4 = self::MessageType {name:#C3}
}


Constructor coverage from constants:
org-dartlang-testcase:///const_functions_const_factory.dart:
- MessageType._ (from org-dartlang-testcase:///const_functions_const_factory.dart:25:9)
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
1 change: 1 addition & 0 deletions pkg/front_end/testcases/outline.status
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE.md file.

const_functions/const_functions_const_factory: VerificationError
extension_types/simple: ExpectationFileMismatchSerialized
extension_types/simple_getter_resolution: ExpectationFileMismatchSerialized
extension_types/simple_method_resolution: ExpectationFileMismatchSerialized
Expand Down
Loading

0 comments on commit b5d4d26

Please sign in to comment.