blob: 7dbebfe1178134ccaddfd8d9964f43d424268924 [file] [log] [blame]
// Copyright (c) 2018, 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.
library fasta.fangorn;
import 'dart:core' hide MapEntry;
import 'package:kernel/ast.dart'
show
Arguments,
DartType,
Expression,
ExpressionStatement,
InvalidExpression,
Let,
LibraryDependency,
MapEntry,
NamedExpression,
Statement,
TreeNode,
VariableDeclaration;
import '../parser.dart' show offsetForToken;
import '../scanner.dart' show Token;
import 'kernel_shadow_ast.dart'
show
ShadowArguments,
ShadowAsExpression,
ShadowAwaitExpression,
ShadowBoolLiteral,
ShadowCheckLibraryIsLoaded,
ShadowConditionalExpression,
ShadowDoubleLiteral,
ShadowIntLiteral,
ShadowIsExpression,
ShadowIsNotExpression,
ShadowListLiteral,
ShadowLoadLibrary,
ShadowMapLiteral,
ShadowNot,
ShadowNullLiteral,
ShadowStringConcatenation,
ShadowStringLiteral,
ShadowSymbolLiteral,
ShadowSyntheticExpression,
ShadowThisExpression,
ShadowTypeLiteral;
import 'forest.dart' show Forest;
/// A shadow tree factory.
class Fangorn extends Forest<Expression, Statement, Token, Arguments> {
const Fangorn();
@override
ShadowArguments arguments(List<Expression> positional, Token token,
{List<DartType> types, List<NamedExpression> named}) {
return new ShadowArguments(positional, types: types, named: named)
..fileOffset = offsetForToken(token);
}
@override
ShadowArguments argumentsEmpty(Token token) {
return arguments(<Expression>[], token);
}
@override
List<NamedExpression> argumentsNamed(Arguments arguments) {
return arguments.named;
}
@override
List<Expression> argumentsPositional(Arguments arguments) {
return arguments.positional;
}
@override
List<DartType> argumentsTypeArguments(Arguments arguments) {
return arguments.types;
}
@override
void argumentsSetTypeArguments(Arguments arguments, List<DartType> types) {
ShadowArguments.setNonInferrableArgumentTypes(arguments, types);
}
@override
ShadowStringLiteral asLiteralString(Expression value) => value;
@override
ShadowBoolLiteral literalBool(bool value, Token token) {
return new ShadowBoolLiteral(value)..fileOffset = offsetForToken(token);
}
@override
ShadowDoubleLiteral literalDouble(double value, Token token) {
return new ShadowDoubleLiteral(value)..fileOffset = offsetForToken(token);
}
@override
ShadowIntLiteral literalInt(int value, Token token) {
return new ShadowIntLiteral(value)..fileOffset = offsetForToken(token);
}
@override
ShadowListLiteral literalList(
Token constKeyword,
bool isConst,
Object typeArgument,
Object typeArguments,
Token leftBracket,
List<Expression> expressions,
Token rightBracket) {
// TODO(brianwilkerson): The file offset computed below will not be correct
// if there are type arguments but no `const` keyword.
return new ShadowListLiteral(expressions,
typeArgument: typeArgument, isConst: isConst)
..fileOffset = offsetForToken(constKeyword ?? leftBracket);
}
@override
ShadowMapLiteral literalMap(
Token constKeyword,
bool isConst,
DartType keyType,
DartType valueType,
Object typeArguments,
Token leftBracket,
List<MapEntry> entries,
Token rightBracket) {
// TODO(brianwilkerson): The file offset computed below will not be correct
// if there are type arguments but no `const` keyword.
return new ShadowMapLiteral(entries,
keyType: keyType, valueType: valueType, isConst: isConst)
..fileOffset = offsetForToken(constKeyword ?? leftBracket);
}
@override
ShadowNullLiteral literalNull(Token token) {
return new ShadowNullLiteral()..fileOffset = offsetForToken(token);
}
@override
ShadowStringLiteral literalString(String value, Token token) {
return new ShadowStringLiteral(value)..fileOffset = offsetForToken(token);
}
@override
ShadowSymbolLiteral literalSymbol(String value, Token token) {
return new ShadowSymbolLiteral(value)..fileOffset = offsetForToken(token);
}
@override
ShadowTypeLiteral literalType(DartType type, Token token) {
return new ShadowTypeLiteral(type)..fileOffset = offsetForToken(token);
}
@override
MapEntry mapEntry(Expression key, Token colon, Expression value) {
return new MapEntry(key, value)..fileOffset = offsetForToken(colon);
}
@override
List<MapEntry> mapEntryList(int length) {
return new List<MapEntry>.filled(length, null, growable: true);
}
@override
int readOffset(TreeNode node) => node.fileOffset;
@override
int getTypeCount(List typeArguments) => typeArguments.length;
@override
DartType getTypeAt(List typeArguments, int index) => typeArguments[index];
@override
Expression loadLibrary(LibraryDependency dependency) {
return new ShadowLoadLibrary(dependency);
}
@override
Expression checkLibraryIsLoaded(LibraryDependency dependency) {
return new ShadowCheckLibraryIsLoaded(dependency);
}
@override
Expression asExpression(Expression expression, covariant type, Token token) {
return new ShadowAsExpression(expression, type)
..fileOffset = offsetForToken(token);
}
@override
Expression awaitExpression(Expression operand, Token token) {
return new ShadowAwaitExpression(operand)
..fileOffset = offsetForToken(token);
}
@override
Expression conditionalExpression(Expression condition, Token question,
Expression thenExpression, Token colon, Expression elseExpression) {
return new ShadowConditionalExpression(
condition, thenExpression, elseExpression)
..fileOffset = offsetForToken(question);
}
@override
Expression isExpression(
Expression operand, isOperator, Token notOperator, covariant type) {
int offset = offsetForToken(isOperator);
if (notOperator != null) {
return new ShadowIsNotExpression(operand, type, offset);
}
return new ShadowIsExpression(operand, type)..fileOffset = offset;
}
@override
Expression notExpression(Expression operand, Token token) {
return new ShadowNot(operand)..fileOffset = offsetForToken(token);
}
@override
Expression stringConcatenationExpression(
List<Expression> expressions, Token token) {
return new ShadowStringConcatenation(expressions)
..fileOffset = offsetForToken(token);
}
@override
Expression thisExpression(Token token) {
return new ShadowThisExpression()..fileOffset = offsetForToken(token);
}
@override
bool isErroneousNode(TreeNode node) {
if (node is ExpressionStatement) {
ExpressionStatement statement = node;
node = statement.expression;
}
if (node is VariableDeclaration) {
VariableDeclaration variable = node;
node = variable.initializer;
}
if (node is ShadowSyntheticExpression) {
ShadowSyntheticExpression synth = node;
node = synth.desugared;
}
if (node is Let) {
Let let = node;
node = let.variable.initializer;
}
return node is InvalidExpression;
}
}