Skip to content

Commit

Permalink
[_fe_analyzer_shared] Support deferencing of StaticGet
Browse files Browse the repository at this point in the history
This adds support for replacement a [StaticGet] with the constant
initializer of the referenced constant during evaluation of macro
metadata. Currently constants defined in the same library or
compilation is supported. For full support the constant initializers
need to be included in the outlines/summaries.

Change-Id: I219f85dded63342d4e3f957f0b7321badbe376a4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/392907
Commit-Queue: Johnni Winther <[email protected]>
Reviewed-by: Konstantin Shcheglov <[email protected]>
Reviewed-by: Jens Johansen <[email protected]>
  • Loading branch information
johnniwinther authored and Commit Queue committed Nov 11, 2024
1 parent 48d8741 commit 4177d28
Show file tree
Hide file tree
Showing 19 changed files with 343 additions and 99 deletions.
40 changes: 37 additions & 3 deletions pkg/_fe_analyzer_shared/lib/src/metadata/evaluate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,55 @@

import 'ast.dart';

typedef GetFieldInitializer = Expression? Function(
FieldReference fieldReference);

/// Evaluates an [expression] based on the semantics that can be deduced from
/// the syntax.
Expression evaluateExpression(Expression expression) {
return new Evaluator().evaluate(expression);
///
/// If [getFieldInitializer] is provided, it is used to get constant initializer
/// expressions of const [StaticGet]s in [expression]. The evaluated constant
/// initializer expressions are used as the evaluation result of the
/// [StaticGet]s.
///
/// If [dereferences] is provided, the field references of [StaticGet]s, for
/// which [getFieldInitializer] has provided a constant initializer
/// [Expression], are mapped to there corresponding in constant initializer
/// [Expression]s in [dereferences].
Expression evaluateExpression(Expression expression,
{GetFieldInitializer? getFieldInitializer,
Map<FieldReference, Expression>? dereferences}) {
return new Evaluator(
getFieldInitializer: getFieldInitializer, dereferences: dereferences)
.evaluate(expression);
}

class Evaluator {
final GetFieldInitializer? _getFieldInitializer;
final Map<FieldReference, Expression>? _dereferences;

Evaluator(
{required GetFieldInitializer? getFieldInitializer,
required Map<FieldReference, Expression>? dereferences})
: _getFieldInitializer = getFieldInitializer,
_dereferences = dereferences;

Expression evaluate(Expression expression) {
return _visitExpression(expression);
}

Expression _visitExpression(Expression expression) {
switch (expression) {
case StaticGet():
// TODO(johnniwinther): Support inlining constant values.
if (_getFieldInitializer != null) {
Expression? result = _getFieldInitializer(expression.reference);
if (result != null) {
if (_dereferences != null) {
_dereferences[expression.reference] = result;
}
return _visitExpression(result);
}
}
return expression;
case InvalidExpression():
case FunctionTearOff():
Expand Down
12 changes: 12 additions & 0 deletions pkg/_fe_analyzer_shared/lib/src/metadata/parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,18 @@ Expression parseAnnotation(
return listener.pop() as Expression;
}

/// Parses the expression beginning at [initializerToken].
Expression parseExpression(
Token initializerToken, Uri fileUri, Scope scope, References references,
{required bool isDartLibrary, bool delayLookupForTesting = false}) {
AnnotationsListener listener = new AnnotationsListener(
fileUri, scope, references,
delayLookup: delayLookupForTesting, isDartLibrary: isDartLibrary);
Parser parser = new Parser(listener, useImplicitCreationExpression: false);
parser.parseExpression(parser.syntheticPreviousToken(initializerToken));
return listener._popExpression();
}

/// A [Scope] extended to include function type parameters.
class FunctionTypeParameterScope implements Scope {
final Scope parentScope;
Expand Down
16 changes: 13 additions & 3 deletions pkg/_fe_analyzer_shared/lib/src/testing/metadata_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,23 @@ Expression unwrap(Expression expression) {

/// Creates a list containing structured and readable textual representation of
/// the [resolved] expression and the result of evaluating [resolved].
List<String> evaluationToText(Expression resolved) {
///
/// If [getFieldInitializer] is provided, it is used to dereference constant
/// field references during evaluation.
List<String> evaluationToText(Expression resolved,
{GetFieldInitializer? getFieldInitializer}) {
List<String> list = [];

Expression unwrappedResolved = unwrap(resolved);
list.add('resolved=${expressionToText(unwrappedResolved)}');
list.add(
'evaluate=${expressionToText(evaluateExpression(unwrappedResolved))}');

Map<FieldReference, Expression> dereferences = {};
Expression evaluated = evaluateExpression(unwrappedResolved,
getFieldInitializer: getFieldInitializer, dereferences: dereferences);
list.add('evaluate=${expressionToText(evaluated)}');
for (MapEntry<FieldReference, Expression> entry in dereferences.entries) {
list.add('${entry.key.name}=${expressionToText(entry.value)}');
}

return list;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,6 @@ void binary19() {}
@Helper(1 + constInt)
/*member: binary20:
resolved=BinaryExpression(IntegerLiteral(1) + StaticGet(constInt))
evaluate=BinaryExpression(IntegerLiteral(1) + StaticGet(constInt))*/
evaluate=IntegerLiteral(value=43)
constInt=IntegerLiteral(42)*/
void binary20() {}
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@ void equalityExpression6() {}
@Helper(constInt == 1)
/*member: equalityExpression7:
resolved=EqualityExpression(StaticGet(constInt) == IntegerLiteral(1))
evaluate=EqualityExpression(StaticGet(constInt) == IntegerLiteral(1))*/
evaluate=BooleanLiteral(false)
constInt=IntegerLiteral(42)*/
void equalityExpression7() {}

@Helper(constInt != 1)
/*member: equalityExpression8:
resolved=EqualityExpression(StaticGet(constInt) != IntegerLiteral(1))
evaluate=EqualityExpression(StaticGet(constInt) != IntegerLiteral(1))*/
evaluate=BooleanLiteral(true)
constInt=IntegerLiteral(42)*/
void equalityExpression8() {}

Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ resolved=IfNull(
??
IntegerLiteral(0)
)
evaluate=IfNull(
StaticGet(constNullableInt)
??
IntegerLiteral(0)
)*/
evaluate=IntegerLiteral(42)
constNullableInt=IntegerLiteral(42)*/
void ifNull5() {}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ void listLiteral3() {}
@Helper([?constInt])
/*member: listLiteral4:
resolved=ListLiteral([ExpressionElement(?StaticGet(constInt))])
evaluate=ListLiteral([ExpressionElement(?StaticGet(constInt))])*/
evaluate=ListLiteral([ExpressionElement(IntegerLiteral(42))])
constInt=IntegerLiteral(42)*/
void listLiteral4() {}

@Helper([if (true) 1])
Expand All @@ -57,9 +58,8 @@ void listLiteral6() {}
resolved=ListLiteral([IfElement(
StaticGet(constBool),
ExpressionElement(IntegerLiteral(1)))])
evaluate=ListLiteral([IfElement(
StaticGet(constBool),
ExpressionElement(IntegerLiteral(1)))])*/
evaluate=ListLiteral([ExpressionElement(IntegerLiteral(1))])
constBool=BooleanLiteral(true)*/
void listLiteral7() {}

@Helper([if (true) 1 else 2])
Expand All @@ -86,10 +86,8 @@ resolved=ListLiteral([IfElement(
StaticGet(constBool),
ExpressionElement(IntegerLiteral(1)),
ExpressionElement(IntegerLiteral(2)))])
evaluate=ListLiteral([IfElement(
StaticGet(constBool),
ExpressionElement(IntegerLiteral(1)),
ExpressionElement(IntegerLiteral(2)))])*/
evaluate=ListLiteral([ExpressionElement(IntegerLiteral(1))])
constBool=BooleanLiteral(true)*/
void listLiteral10() {}

@Helper([...[0, 1]])
Expand All @@ -105,7 +103,12 @@ void listLiteral11() {}
@Helper([...constList])
/*member: listLiteral12:
resolved=ListLiteral([SpreadElement(...StaticGet(constList))])
evaluate=ListLiteral([SpreadElement(...StaticGet(constList))])*/
evaluate=ListLiteral([
ExpressionElement(IntegerLiteral(2)),
ExpressionElement(IntegerLiteral(3))])
constList=ListLiteral([
ExpressionElement(IntegerLiteral(2)),
ExpressionElement(IntegerLiteral(3))])*/
void listLiteral12() {}

@Helper([...?[0, 1]])
Expand All @@ -121,7 +124,12 @@ void listLiteral13() {}
@Helper([...?constList])
/*member: listLiteral14:
resolved=ListLiteral([SpreadElement(?...StaticGet(constList))])
evaluate=ListLiteral([SpreadElement(?...StaticGet(constList))])*/
evaluate=ListLiteral([
ExpressionElement(IntegerLiteral(2)),
ExpressionElement(IntegerLiteral(3))])
constList=ListLiteral([
ExpressionElement(IntegerLiteral(2)),
ExpressionElement(IntegerLiteral(3))])*/
void listLiteral14() {}

@Helper([...?null])
Expand All @@ -135,7 +143,8 @@ void listLiteral15() {}
resolved=ListLiteral([IfElement(
StaticGet(constBool),
ExpressionElement(?NullLiteral()))])
evaluate=ListLiteral([])*/
evaluate=ListLiteral([])
constBool=BooleanLiteral(true)*/
void listLiteral16() {}

@Helper([if (constBool) ?null else 2])
Expand All @@ -144,9 +153,8 @@ resolved=ListLiteral([IfElement(
StaticGet(constBool),
ExpressionElement(?NullLiteral()),
ExpressionElement(IntegerLiteral(2)))])
evaluate=ListLiteral([IfElement(
UnaryExpression(!StaticGet(constBool)),
ExpressionElement(IntegerLiteral(2)))])*/
evaluate=ListLiteral([])
constBool=BooleanLiteral(true)*/
void listLiteral17() {}

@Helper([if (constBool) 1 else ?null])
Expand All @@ -155,9 +163,8 @@ resolved=ListLiteral([IfElement(
StaticGet(constBool),
ExpressionElement(IntegerLiteral(1)),
ExpressionElement(?NullLiteral()))])
evaluate=ListLiteral([IfElement(
StaticGet(constBool),
ExpressionElement(IntegerLiteral(1)))])*/
evaluate=ListLiteral([ExpressionElement(IntegerLiteral(1))])
constBool=BooleanLiteral(true)*/
void listLiteral18() {}

@Helper([if (constBool) ?null else ?null])
Expand All @@ -166,47 +173,53 @@ resolved=ListLiteral([IfElement(
StaticGet(constBool),
ExpressionElement(?NullLiteral()),
ExpressionElement(?NullLiteral()))])
evaluate=ListLiteral([])*/
evaluate=ListLiteral([])
constBool=BooleanLiteral(true)*/
void listLiteral19() {}

@Helper([if (constBool) ...[]])
/*member: listLiteral20:
resolved=ListLiteral([IfElement(
StaticGet(constBool),
SpreadElement(...ListLiteral([])))])
evaluate=ListLiteral([])*/
evaluate=ListLiteral([])
constBool=BooleanLiteral(true)*/
void listLiteral20() {}

@Helper([if (constBool) ...{}])
/*member: listLiteral21:
resolved=ListLiteral([IfElement(
StaticGet(constBool),
SpreadElement(...SetOrMapLiteral({})))])
evaluate=ListLiteral([])*/
evaluate=ListLiteral([])
constBool=BooleanLiteral(true)*/
void listLiteral21() {}

@Helper([if (constBool) ...?[]])
/*member: listLiteral22:
resolved=ListLiteral([IfElement(
StaticGet(constBool),
SpreadElement(?...ListLiteral([])))])
evaluate=ListLiteral([])*/
evaluate=ListLiteral([])
constBool=BooleanLiteral(true)*/
void listLiteral22() {}

@Helper([if (constBool) ...?{}])
/*member: listLiteral23:
resolved=ListLiteral([IfElement(
StaticGet(constBool),
SpreadElement(?...SetOrMapLiteral({})))])
evaluate=ListLiteral([])*/
evaluate=ListLiteral([])
constBool=BooleanLiteral(true)*/
void listLiteral23() {}

@Helper([if (constBool) ...?null])
/*member: listLiteral24:
resolved=ListLiteral([IfElement(
StaticGet(constBool),
SpreadElement(?...NullLiteral()))])
evaluate=ListLiteral([])*/
evaluate=ListLiteral([])
constBool=BooleanLiteral(true)*/
void listLiteral24() {}

@Helper([if (constBool) if (constBool) ?null else ?null])
Expand All @@ -217,5 +230,7 @@ resolved=ListLiteral([IfElement(
StaticGet(constBool),
ExpressionElement(?NullLiteral()),
ExpressionElement(?NullLiteral())))])
evaluate=ListLiteral([])*/
evaluate=ListLiteral([])
constBool=BooleanLiteral(true)
constBool=BooleanLiteral(true)*/
void listLiteral25() {}
12 changes: 8 additions & 4 deletions pkg/_fe_analyzer_shared/test/metadata/evaluate_data/logical.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,27 @@ void logicalExpression8() {}
@Helper(constBool && true)
/*member: logicalExpression9:
resolved=LogicalExpression(StaticGet(constBool) && BooleanLiteral(true))
evaluate=LogicalExpression(StaticGet(constBool) && BooleanLiteral(true))*/
evaluate=BooleanLiteral(true)
constBool=BooleanLiteral(true)*/
void logicalExpression9() {}

@Helper(constBool && false)
/*member: logicalExpression10:
resolved=LogicalExpression(StaticGet(constBool) && BooleanLiteral(false))
evaluate=LogicalExpression(StaticGet(constBool) && BooleanLiteral(false))*/
evaluate=BooleanLiteral(false)
constBool=BooleanLiteral(true)*/
void logicalExpression10() {}

@Helper(constBool || true)
/*member: logicalExpression11:
resolved=LogicalExpression(StaticGet(constBool) || BooleanLiteral(true))
evaluate=LogicalExpression(StaticGet(constBool) || BooleanLiteral(true))*/
evaluate=BooleanLiteral(true)
constBool=BooleanLiteral(true)*/
void logicalExpression11() {}

@Helper(constBool || false)
/*member: logicalExpression12:
resolved=LogicalExpression(StaticGet(constBool) || BooleanLiteral(false))
evaluate=LogicalExpression(StaticGet(constBool) || BooleanLiteral(false))*/
evaluate=BooleanLiteral(true)
constBool=BooleanLiteral(true)*/
void logicalExpression12() {}
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ void nullCheck2() {}
@Helper(constInt!)
/*member: nullCheck3:
resolved=NullCheck(StaticGet(constInt))
evaluate=NullCheck(StaticGet(constInt))*/
evaluate=IntegerLiteral(42)
constInt=IntegerLiteral(42)*/
void nullCheck3() {}
Loading

0 comments on commit 4177d28

Please sign in to comment.