Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(494)

Unified Diff: pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart

Issue 1155463005: dart2js cps: Remove dart2dart from cps pipeline and clean up. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Skip tests specific to the dart backend Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart
diff --git a/pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart b/pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart
index 572634132869217746e63c133e89f32139fac834..10b056d8fbc80c9f49698bb362dfc5347e4d837e 100644
--- a/pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart
@@ -4,1024 +4,9 @@
library backend_ast_emitter;
-import '../tree_ir/tree_ir_nodes.dart' as tree;
import 'backend_ast_nodes.dart';
-import '../constants/expressions.dart';
-import '../constants/values.dart';
import '../dart_types.dart';
import '../elements/elements.dart';
-import '../elements/modelx.dart' as modelx;
-import '../universe/universe.dart';
-import '../tree/tree.dart' as tree show Modifiers;
-
-/// Translates the dart_tree IR to Dart backend AST.
-RootNode emit(tree.RootNode root) {
- return new ASTEmitter().emit(root);
-}
-
-// TODO(johnniwinther): Split into function/block state.
-class BuilderContext<T> {
- /// Builder context for the enclosing function, or null if the current
- /// function is not a local function.
- BuilderContext<T> _parent;
-
- /// Variables to be hoisted at the top of the current function.
- final List<VariableDeclaration> variables = <VariableDeclaration>[];
-
- /// Maps variables to their name.
- final Map<tree.Variable, String> variableNames;
-
- /// Maps local constants to their name.
- final Map<VariableElement, String> constantNames =
- <VariableElement, String>{};
-
- /// Variables that have had their declaration created.
- final Set<tree.Variable> declaredVariables = new Set<tree.Variable>();
-
- /// Variables that are used as catch handler parameters.
- final Set<tree.Variable> handlerVariables = new Set<tree.Variable>();
-
- /// Variable names that have already been used. Used to avoid name clashes.
- final Set<String> usedVariableNames;
-
- /// Statements emitted by the most recent call to [visitStatement].
- List<T> _statementBuffer = <T>[];
-
- /// The element currently being emitted.
- ExecutableElement currentElement;
-
- /// Bookkeeping object needed to synthesize a variable declaration.
- final modelx.VariableList variableList
- = new modelx.VariableList(tree.Modifiers.EMPTY);
-
- /// Input to [visitStatement]. Denotes the statement that will execute next
- /// if the statements produced by [visitStatement] complete normally.
- /// Set to null if control will fall over the end of the method.
- tree.Statement fallthrough = null;
-
- /// Labels that could not be eliminated using fallthrough.
- final Set<tree.Label> _usedLabels = new Set<tree.Label>();
-
- final bool inInitializer;
-
- /// The first dart_tree statement that is not converted to a variable
- /// initializer.
- tree.Statement firstStatement;
-
- BuilderContext() : usedVariableNames = new Set<String>(),
- inInitializer = false,
- variableNames = <tree.Variable, String>{};
-
- BuilderContext.inner(BuilderContext<T> parent)
- : this._parent = parent,
- usedVariableNames = parent.usedVariableNames,
- inInitializer = false,
- variableNames = <tree.Variable, String>{};
-
- BuilderContext.initializer(BuilderContext<T> parent)
- : this._parent = parent,
- usedVariableNames = parent.usedVariableNames,
- inInitializer = true,
- variableNames =
- new Map<tree.Variable, String>.from(parent.variableNames);
-
- // TODO(johnniwinther): Fully encapsulate handling of parameter, variable
- // and local function declarations.
- void addDeclaration(tree.Variable variable, [Expression initializer]) {
- assert(!declaredVariables.contains(variable));
- String name = getVariableName(variable);
- VariableDeclaration decl = new VariableDeclaration(name, initializer);
- decl.element = variable.element;
- declaredVariables.add(variable);
- variables.add(decl);
- }
-
- /// Creates an [Identifier] referring to the given variable.
- Expression makeVariableAccess(tree.Variable variable) {
- return new Identifier(getVariableName(variable))
- ..element = variable.element;
- }
-
- /// Generates a name for the given variable and synthesizes an element for it,
- /// if necessary.
- String getVariableName(tree.Variable variable) {
- // If the variable belongs to an enclosing function, ask the parent emitter
- // for the variable name.
- if (!inInitializer && variable.host != currentElement) {
- return _parent.getVariableName(variable);
- }
-
- // Get the name if we already have one.
- String name = variableNames[variable];
- if (name != null) {
- return name;
- }
-
- // Synthesize a variable name that isn't used elsewhere.
- // The [usedVariableNames] set is shared between nested emitters,
- // so this also prevents clash with variables in an enclosing/inner scope.
- // The renaming phase after codegen will further prefix local variables
- // so they cannot clash with top-level variables or fields.
- String prefix = variable.element == null ? 'v' : variable.element.name;
- int counter = 0;
- name = variable.element == null ? '$prefix$counter' : variable.element.name;
- while (!usedVariableNames.add(name)) {
- ++counter;
- name = '$prefix$counter';
- }
- variableNames[variable] = name;
-
- // Synthesize an element for the variable
- if (variable.element == null || name != variable.element.name) {
- // TODO(johnniwinther): Replace by synthetic [Entity].
- variable.element = new _SyntheticLocalVariableElement(
- name,
- currentElement,
- variableList);
- }
- return name;
- }
-
- /// Adds declarations for all variables that are still undeclared.
- void declareRemainingVariables() {
- // These variables can be referenced from other variable initializers if
- // they are set by an assignment expression, so we declare variables before
- // those with initializers.
- List<VariableDeclaration> declarations = <VariableDeclaration>[];
- for (tree.Variable variable in variableNames.keys) {
- if (!declaredVariables.contains(variable)) {
- String name = getVariableName(variable);
- VariableDeclaration decl = new VariableDeclaration(name);
- decl.element = variable.element;
- declarations.add(decl);
- declaredVariables.add(variable);
- }
- }
- // Prepend all variables at once to avoid quadratic blowup.
- variables.insertAll(0, declarations);
- }
-
- String getConstantName(VariableElement element) {
- assert(element.kind == ElementKind.VARIABLE);
- if (element.enclosingElement != currentElement) {
- return _parent.getConstantName(element);
- }
- String name = constantNames[element];
- if (name != null) {
- return name;
- }
- String prefix = element.name;
- int counter = 0;
- name = element.name;
- while (!usedVariableNames.add(name)) {
- ++counter;
- name = '$prefix$counter';
- }
- constantNames[element] = name;
- return name;
- }
-
- List<T> inSubcontext(f(BuilderContext<T> subcontext),
- {tree.Statement fallthrough}) {
- List<T> savedBuffer = this._statementBuffer;
- tree.Statement savedFallthrough = this.fallthrough;
- List<T> buffer = this._statementBuffer = <T>[];
- if (fallthrough != null) {
- this.fallthrough = fallthrough;
- }
- f(this);
- this.fallthrough = savedFallthrough;
- this._statementBuffer = savedBuffer;
- return buffer;
- }
-
- /// Removes a trailing "return null" from the current block.
- void removeTrailingReturn(bool isReturnNull(T statement)) {
- if (_statementBuffer.isEmpty) return;
- if (isReturnNull(_statementBuffer.last)) {
- _statementBuffer.removeLast();
- }
- }
-
- /// Register [label] as used.
- void useLabel(tree.Label label) {
- _usedLabels.add(label);
- }
-
- /// Remove [label] and return `true` if it was used.
- bool removeUsedLabel(tree.Label label) {
- return _usedLabels.remove(label);
- }
-
- /// Add [statement] to the current block.
- void addStatement(T statement) {
- _statementBuffer.add(statement);
- }
-
- /// The statements in the current block.
- Iterable<T> get statements => _statementBuffer;
-}
-
-/// Translates the dart_tree IR to Dart backend AST.
-/// An instance of this class should only be used once; a fresh emitter
-/// must be created for each function to be emitted.
-class ASTEmitter
- extends tree.StatementVisitor1<dynamic, BuilderContext<Statement>>
- with tree.ExpressionVisitor1<Expression, BuilderContext<Statement>>,
- tree.RootVisitor1<RootNode, BuilderContext<Statement>>,
- tree.InitializerVisitor1<Initializer, BuilderContext<Statement>> {
-
- RootNode emit(tree.RootNode node) {
- return visitRootNode(node, new BuilderContext<Statement>());
- }
-
- @override
- FieldDefinition visitFieldDefinition(tree.FieldDefinition definition,
- BuilderContext<Statement> context) {
- context.currentElement = definition.element;
- Expression initializer;
- if (!definition.isEmpty) {
- visitStatement(definition.body, context);
- List<Statement> bodyParts;
- for (tree.Variable variable in context.variableNames.keys) {
- if (!context.declaredVariables.contains(variable)) {
- context.addDeclaration(variable);
- }
- }
- if (context.variables.length > 0) {
- bodyParts = new List<Statement>();
- bodyParts.add(new VariableDeclarations(context.variables));
- bodyParts.addAll(context.statements);
- } else {
- bodyParts = context.statements;
- }
- initializer = ensureExpression(bodyParts);
- }
-
- return new FieldDefinition(definition.element, initializer);
- }
-
- /// Returns an expression that will evaluate all of [bodyParts].
- /// If [bodyParts] is a single [Return] return its value.
- /// Otherwise wrap the body-parts in an immediately invoked closure.
- Expression ensureExpression(List<Statement> bodyParts) {
- if (bodyParts.length == 1) {
- Statement onlyStatement = bodyParts.single;
- if (onlyStatement is Return) {
- return onlyStatement.expression;
- }
- }
- Statement body = new Block(bodyParts);
- FunctionExpression function =
- new FunctionExpression(new Parameters([]), body);
- function.element = null;
- return new CallFunction(function, []);
- }
-
- bool _recognizeTrailingReturn(Statement statement) {
- if (statement is Return) {
- Expression expr = statement.expression;
- if (expr == null || expr is Literal && expr.value.isNull) {
- return true;
- }
- }
- return false;
- }
-
- @override
- FunctionExpression visitConstructorDefinition(
- tree.ConstructorDefinition definition,
- BuilderContext<Statement> context) {
- context.currentElement = definition.element;
-
- Parameters parameters = emitRootParameters(
- definition, definition.defaultParameterValues, context);
-
- // Declare parameters.
- for (tree.Variable param in definition.parameters) {
- context.variableNames[param] = param.element.name;
- context.usedVariableNames.add(param.element.name);
- context.declaredVariables.add(param);
- }
-
- List<Initializer> initializers;
- Statement body;
-
- if (!definition.isEmpty) {
- initializers =
- definition.initializers.map((tree.Initializer initializer) {
- return visitInitializer(initializer, context);
- }).toList();
-
- context.firstStatement = definition.body;
- visitStatement(definition.body, context);
- context.removeTrailingReturn(_recognizeTrailingReturn);
-
- // Some of the variable declarations have already been added
- // if their first assignment could be pulled into the initializer.
- // Add the remaining variable declarations now.
- context.declareRemainingVariables();
-
- // Add constant declarations.
- List<VariableDeclaration> constants = <VariableDeclaration>[];
- for (ConstDeclaration constDecl in definition.localConstants) {
- if (!context.constantNames.containsKey(constDecl.element)) {
- continue; // Discard unused constants declarations.
- }
- String name = context.getConstantName(constDecl.element);
- Expression value =
- ConstantEmitter.createExpression(constDecl.expression, context);
- VariableDeclaration decl = new VariableDeclaration(name, value);
- decl.element = constDecl.element;
- constants.add(decl);
- }
-
- List<Statement> bodyParts = [];
- if (constants.length > 0) {
- bodyParts.add(new VariableDeclarations(constants, isConst: true));
- }
- if (context.variables.length > 0) {
- bodyParts.add(new VariableDeclarations(context.variables));
- }
- bodyParts.addAll(context.statements);
- body = new Block(bodyParts);
- }
- return new ConstructorDefinition(
- parameters,
- body,
- initializers,
- context.currentElement.name,
- definition.element.isConst)..element = context.currentElement;
- }
-
- @override
- FunctionExpression visitFunctionDefinition(
- tree.FunctionDefinition definition,
- BuilderContext<Statement> context) {
- context.currentElement = definition.element;
-
- Parameters parameters = emitRootParameters(
- definition, definition.defaultParameterValues, context);
-
- // Declare parameters.
- for (tree.Variable param in definition.parameters) {
- context.variableNames[param] = param.element.name;
- context.usedVariableNames.add(param.element.name);
- context.declaredVariables.add(param);
- }
-
- Statement body;
- if (definition.isEmpty) {
- body = new EmptyStatement();
- } else {
- context.firstStatement = definition.body;
- visitStatement(definition.body, context);
- context.removeTrailingReturn(_recognizeTrailingReturn);
-
- // Some of the variable declarations have already been added
- // if their first assignment could be pulled into the initializer.
- // Add the remaining variable declarations now.
- context.declareRemainingVariables();
-
- // Add constant declarations.
- List<VariableDeclaration> constants = <VariableDeclaration>[];
- for (ConstDeclaration constDecl in definition.localConstants) {
- if (!context.constantNames.containsKey(constDecl.element)) {
- continue; // Discard unused constants declarations.
- }
- String name = context.getConstantName(constDecl.element);
- Expression value =
- ConstantEmitter.createExpression(constDecl.expression, context);
- VariableDeclaration decl = new VariableDeclaration(name, value);
- decl.element = constDecl.element;
- constants.add(decl);
- }
-
- List<Statement> bodyParts = [];
- if (constants.length > 0) {
- bodyParts.add(new VariableDeclarations(constants, isConst: true));
- }
- if (context.variables.length > 0) {
- bodyParts.add(new VariableDeclarations(context.variables));
- }
- bodyParts.addAll(context.statements);
-
- body = new Block(bodyParts);
- }
- FunctionType functionType = context.currentElement.type;
-
- return new FunctionExpression(
- parameters,
- body,
- name: context.currentElement.name,
- returnType: TypeGenerator.createOptionalType(functionType.returnType),
- isGetter: context.currentElement.isGetter,
- isSetter: context.currentElement.isSetter)
- ..element = context.currentElement;
- }
-
- /// Emits parameters that are not nested inside other parameters.
- /// Root parameters can have default values, while inner parameters cannot.
- Parameters emitRootParameters(tree.RootNode function,
- List<ConstantExpression> defaults,
- BuilderContext<Statement> context) {
- FunctionType functionType = function.element.type;
- List<Parameter> required = TypeGenerator.createParameters(
- functionType.parameterTypes,
- context: context,
- elements: function.parameters.map((p) => p.element));
- bool optionalParametersAreNamed = !functionType.namedParameters.isEmpty;
- List<Parameter> optional = TypeGenerator.createParameters(
- optionalParametersAreNamed
- ? functionType.namedParameterTypes
- : functionType.optionalParameterTypes,
- context: context,
- defaultValues: defaults,
- elements: function.parameters.skip(required.length)
- .map((p) => p.element));
- return new Parameters(required, optional, optionalParametersAreNamed);
- }
-
- /// True if the two expressions are a reference to the same variable.
- bool isSameVariable(Receiver e1, Receiver e2) {
- return e1 is Identifier &&
- e2 is Identifier &&
- e1.element is VariableElement &&
- e1.element == e2.element;
- }
-
- Expression makeAssignment(Expression target, Expression value) {
- // Try to print as compound assignment or increment
- if (value is BinaryOperator && isCompoundableOperator(value.operator)) {
- Receiver leftOperand = value.left;
- Expression rightOperand = value.right;
- bool valid = false;
- if (isSameVariable(target, leftOperand)) {
- valid = true;
- } else if (target is FieldExpression &&
- leftOperand is FieldExpression &&
- isSameVariable(target.object, leftOperand.object) &&
- target.fieldName == leftOperand.fieldName) {
- valid = true;
- } else if (target is IndexExpression &&
- leftOperand is IndexExpression &&
- isSameVariable(target.object, leftOperand.object) &&
- isSameVariable(target.index, leftOperand.index)) {
- valid = true;
- }
- if (valid) {
- if (rightOperand is Literal && rightOperand.value.isOne &&
- (value.operator == '+' || value.operator == '-')) {
- return new Increment.prefix(target, value.operator + value.operator);
- } else {
- return new Assignment(target, value.operator + '=', rightOperand);
- }
- }
- }
- // Fall back to regular assignment
- return new Assignment(target, '=', value);
- }
-
- Block visitInSubContext(tree.Statement statement,
- BuilderContext<Statement> context,
- {tree.Statement fallthrough}) {
- return new Block(context.inSubcontext(
- (BuilderContext<Statement> subcontext) {
- visitStatement(statement, subcontext);
- }, fallthrough: fallthrough));
- }
-
- void addLabeledStatement(tree.Label label,
- Statement statement,
- BuilderContext<Statement> context) {
- if (context.removeUsedLabel(label)) {
- context.addStatement(new LabeledStatement(label.name, statement));
- } else {
- context.addStatement(statement);
- }
- }
-
- @override
- void visitExpressionStatement(tree.ExpressionStatement stmt,
- BuilderContext<Statement> context) {
- if (stmt.expression is tree.Assign) {
- emitAssignStatement(stmt.expression, stmt, context);
- return;
- }
- Expression e = visitExpression(stmt.expression, context);
- context.addStatement(new ExpressionStatement(e));
- visitStatement(stmt.next, context);
- }
-
- @override
- void visitVariableDeclaration(tree.VariableDeclaration node,
- BuilderContext<Statement> context) {
- Expression value = visitExpression(node.value, context);
- String name = context.getVariableName(node.variable);
- VariableDeclaration decl = new VariableDeclaration(name, value)
- ..element = node.variable.element;
- context.declaredVariables.add(node.variable);
- context.addStatement(new VariableDeclarations([decl]));
- visitStatement(node.next, context);
- }
-
- @override
- void visitLabeledStatement(tree.LabeledStatement stmt,
- BuilderContext<Statement> context) {
- Block block = visitInSubContext(stmt.body, context, fallthrough: stmt.next);
- addLabeledStatement(stmt.label, block, context);
-
- visitStatement(stmt.next, context);
- }
-
- bool isNullLiteral(Expression exp) => exp is Literal && exp.value.isNull;
-
- void emitAssignStatement(tree.Assign assign,
- tree.Statement statement,
- BuilderContext<Statement> context) {
- // Try to emit a local function declaration. This is useful for functions
- // that may occur in expression context, but could not be inlined anywhere.
- if (assign.variable.element is FunctionElement &&
- assign.value is tree.FunctionExpression &&
- !context.declaredVariables.contains(assign.variable) &&
- assign.variable.writeCount == 1) {
- tree.FunctionExpression functionExp = assign.value;
- FunctionExpression function =
- makeSubFunction(functionExp.definition, context);
- FunctionDeclaration decl = new FunctionDeclaration(function);
- context.addStatement(decl);
- context.declaredVariables.add(assign.variable);
-
- visitStatement(statement.next, context);
- return;
- }
-
- Expression definition = visitExpression(assign.value, context);
- bool isFirstOccurrence = (context.variableNames[assign.variable] == null);
- bool isDeclaredHere = assign.variable.host == context.currentElement;
- bool isFirstStatement = context.firstStatement == statement;
-
- // Try to pull into initializer.
- if (isFirstStatement && isFirstOccurrence && isDeclaredHere) {
- if (isNullLiteral(definition)) definition = null;
- context.addDeclaration(assign.variable, definition);
- context.firstStatement = statement.next;
- visitStatement(statement.next, context);
- return;
- }
-
- context.addStatement(new ExpressionStatement(makeAssignment(
- context.makeVariableAccess(assign.variable),
- definition)));
- visitStatement(statement.next, context);
- }
-
- @override
- void visitReturn(tree.Return stmt, BuilderContext<Statement> context) {
- if (context.currentElement.isGenerativeConstructor &&
- !context.inInitializer) {
- assert(() {
- tree.Expression value = stmt.value;
- return value is tree.Constant && value.value.isNull;
- });
- context.addStatement(new Return(null));
- } else {
- Expression inner = visitExpression(stmt.value, context);
- context.addStatement(new Return(inner));
- }
- }
-
- @override
- void visitThrow(tree.Throw stmt, BuilderContext<Statement> context) {
- Expression value = visitExpression(stmt.value, context);
- context.addStatement(new ExpressionStatement(new Throw(value)));
- }
-
- @override
- void visitRethrow(tree.Rethrow stmt, BuilderContext<Statement> context) {
- context.addStatement(new Rethrow());
- }
-
- @override
- void visitBreak(tree.Break stmt, BuilderContext<Statement> context) {
- tree.Statement fall = context.fallthrough;
- if (stmt.target.binding.next == fall) {
- // Fall through to break target
- } else if (fall is tree.Break && fall.target == stmt.target) {
- // Fall through to equivalent break
- } else {
- context.useLabel(stmt.target);
- context.addStatement(new Break(stmt.target.name));
- }
- }
-
- @override
- void visitContinue(tree.Continue stmt,
- BuilderContext<Statement> context) {
- tree.Statement fall = context.fallthrough;
- if (stmt.target.binding == fall) {
- // Fall through to continue target
- } else if (fall is tree.Continue && fall.target == stmt.target) {
- // Fall through to equivalent continue
- } else {
- context.useLabel(stmt.target);
- context.addStatement(new Continue(stmt.target.name));
- }
- }
-
- @override
- void visitIf(tree.If stmt,
- BuilderContext<Statement> context) {
- Expression condition = visitExpression(stmt.condition, context);
- Block thenBlock = visitInSubContext(stmt.thenStatement, context);
- Block elseBlock= visitInSubContext(stmt.elseStatement, context);
- context.addStatement(new If(condition, thenBlock, elseBlock));
- }
-
- @override
- void visitWhileTrue(tree.WhileTrue stmt,
- BuilderContext<Statement> context) {
- Block body = visitInSubContext(stmt.body, context, fallthrough: stmt);
- Statement statement =
- new While(new Literal(new TrueConstantValue()), body);
- addLabeledStatement(stmt.label, statement, context);
- }
-
- @override
- void visitWhileCondition(tree.WhileCondition stmt,
- BuilderContext<Statement> context) {
- Expression condition = visitExpression(stmt.condition, context);
- Block body = visitInSubContext(stmt.body, context, fallthrough: stmt);
- Statement statement = new While(condition, body);
- addLabeledStatement(stmt.label, statement, context);
-
- visitStatement(stmt.next, context);
- }
-
- @override
- void visitTry(tree.Try stmt,
- BuilderContext<Statement> context) {
- Block tryBody = visitInSubContext(stmt.tryBody, context);
- Block catchBody = visitInSubContext(stmt.catchBody, context);
- CatchBlock catchBlock;
- tree.Variable exceptionVariable = stmt.catchParameters[0];
- context.handlerVariables.add(exceptionVariable);
- VariableDeclaration exceptionParameter =
- new VariableDeclaration(context.getVariableName(exceptionVariable));
- exceptionParameter.element = exceptionVariable.element;
- stmt.catchParameters.forEach(context.declaredVariables.add);
- if (stmt.catchParameters.length == 2) {
- tree.Variable stackTraceVariable = stmt.catchParameters[1];
- context.handlerVariables.add(stackTraceVariable);
- VariableDeclaration stackTraceParameter =
- new VariableDeclaration(context.getVariableName(stackTraceVariable));
- stackTraceParameter.element = stackTraceVariable.element;
- catchBlock = new CatchBlock(catchBody,
- exceptionVar: exceptionParameter,
- stackVar: stackTraceParameter);
- } else {
- assert(stmt.catchParameters.length == 1);
- catchBlock = new CatchBlock(catchBody,
- exceptionVar: exceptionParameter);
- }
- context.addStatement(new Try(tryBody, <CatchBlock>[catchBlock], null));
- }
-
- @override
- Expression visitConstant(tree.Constant exp,
- BuilderContext<Statement> context) {
- return ConstantEmitter.createExpression(exp.expression, context);
- }
-
- @override
- Expression visitThis(tree.This exp,
- BuilderContext<Statement> context) {
- return new This();
- }
-
- @override
- Expression visitReifyTypeVar(tree.ReifyTypeVar exp,
- BuilderContext<Statement> context) {
- return new ReifyTypeVar(exp.typeVariable.name)
- ..element = exp.typeVariable;
- }
-
- List<Expression> visitExpressions(List<tree.Expression> expressions,
- BuilderContext<Statement> context) {
- return expressions.map((expression) => visitExpression(expression, context))
- .toList(growable: false);
- }
-
- @override
- Expression visitLiteralList(tree.LiteralList exp,
- BuilderContext<Statement> context) {
- return new LiteralList(visitExpressions(exp.values, context),
- typeArgument:
- TypeGenerator.createOptionalType(exp.type.typeArguments.single));
- }
-
- @override
- Expression visitLiteralMap(tree.LiteralMap exp,
- BuilderContext<Statement> context) {
- List<LiteralMapEntry> entries = new List<LiteralMapEntry>.generate(
- exp.entries.length,
- (i) => new LiteralMapEntry(
- visitExpression(exp.entries[i].key, context),
- visitExpression(exp.entries[i].value, context)));
- List<TypeAnnotation> typeArguments = exp.type.treatAsRaw
- ? null
- : exp.type.typeArguments.map(TypeGenerator.createType)
- .toList(growable: false);
- return new LiteralMap(entries, typeArguments: typeArguments);
- }
-
- @override
- Expression visitTypeOperator(tree.TypeOperator exp,
- BuilderContext<Statement> context) {
- return new TypeOperator(visitExpression(exp.value, context),
- exp.operator,
- TypeGenerator.createType(exp.type));
- }
-
- List<Argument> emitArguments(List<Expression> arguments,
- Selector selector) {
- int positionalArgumentCount = selector.positionalArgumentCount;
- List<Argument> result = new List<Argument>.generate(positionalArgumentCount,
- (i) => arguments[i]);
- for (int i = 0; i < selector.namedArgumentCount; ++i) {
- result.add(new NamedArgument(selector.namedArguments[i],
- arguments[positionalArgumentCount + i]));
- }
- return result;
- }
-
- List<Expression> visitArgumentList(List<tree.Expression> arguments,
- BuilderContext context) {
- return arguments
- .map((tree.Expression argument) => visitExpression(argument, context))
- .toList();
- }
-
- @override
- Expression visitInvokeStatic(tree.InvokeStatic exp,
- BuilderContext<Statement> context) {
- switch (exp.selector.kind) {
- case SelectorKind.GETTER:
- return new Identifier(exp.target.name)..element = exp.target;
-
- case SelectorKind.SETTER:
- return new Assignment(
- new Identifier(exp.target.name)..element = exp.target,
- '=',
- visitExpression(exp.arguments[0], context));
-
- case SelectorKind.CALL:
- return new CallStatic(
- null, exp.target.name,
- emitArguments(visitArgumentList(exp.arguments, context),
- exp.selector))
- ..element = exp.target;
-
- default:
- throw "Unexpected selector kind: ${exp.selector.kind}";
- }
- }
-
- Expression emitMethodCall(tree.Invoke exp, Receiver receiver,
- BuilderContext<Statement> context) {
- List<Argument> args =
- emitArguments(visitArgumentList(exp.arguments, context), exp.selector);
- switch (exp.selector.kind) {
- case SelectorKind.CALL:
- if (exp.selector.name == "call") {
- return new CallFunction(receiver, args);
- }
- return new CallMethod(receiver, exp.selector.name, args);
-
- case SelectorKind.OPERATOR:
- if (args.length == 0) {
- String name = exp.selector.name;
- if (name == 'unary-') {
- name = '-';
- }
- return new UnaryOperator(name, receiver);
- }
- return new BinaryOperator(receiver, exp.selector.name, args[0]);
-
- case SelectorKind.GETTER:
- return new FieldExpression(receiver, exp.selector.name);
-
- case SelectorKind.SETTER:
- return makeAssignment(
- new FieldExpression(receiver, exp.selector.name),
- args[0]);
-
- case SelectorKind.INDEX:
- Expression e = new IndexExpression(receiver, args[0]);
- if (args.length == 2) {
- e = makeAssignment(e, args[1]);
- }
- return e;
-
- default:
- throw "Unexpected selector in InvokeMethod: ${exp.selector.kind}";
- }
- }
-
- @override
- Expression visitInvokeMethod(tree.InvokeMethod exp,
- BuilderContext<Statement> context) {
- Expression receiver = visitExpression(exp.receiver, context);
- return emitMethodCall(exp, receiver, context);
- }
-
- @override
- Expression visitInvokeMethodDirectly(tree.InvokeMethodDirectly exp,
- BuilderContext<Statement> context) {
- // When targeting Dart, InvokeMethodDirectly is only used for super calls.
- // The receiver is known to be `this`, and the target method is a method
- // on the super class. So we just translate it as a method call with the
- // super receiver.
- return emitMethodCall(exp, new SuperReceiver(), context);
- }
-
- @override
- Expression visitInvokeConstructor(tree.InvokeConstructor exp,
- BuilderContext<Statement> context) {
- List<Argument> args =
- emitArguments(visitArgumentList(exp.arguments, context), exp.selector);
- FunctionElement constructor = exp.target;
- String name = constructor.name.isEmpty ? null : constructor.name;
- return new CallNew(TypeGenerator.createType(exp.type),
- args,
- constructorName: name,
- isConst: exp.constant != null)
- ..constructor = constructor
- ..dartType = exp.type;
- }
-
- @override
- Expression visitConcatenateStrings(tree.ConcatenateStrings exp,
- BuilderContext<Statement> context) {
- return new StringConcat(visitExpressions(exp.arguments, context));
- }
-
- @override
- Expression visitConditional(tree.Conditional exp,
- BuilderContext<Statement> context) {
- return new Conditional(
- visitExpression(exp.condition, context),
- visitExpression(exp.thenExpression, context),
- visitExpression(exp.elseExpression, context));
- }
-
- @override
- Expression visitLogicalOperator(tree.LogicalOperator exp,
- BuilderContext<Statement> context) {
- return new BinaryOperator(visitExpression(exp.left, context),
- exp.operator,
- visitExpression(exp.right, context));
- }
-
- @override
- Expression visitNot(tree.Not exp,
- BuilderContext<Statement> context) {
- return new UnaryOperator('!', visitExpression(exp.operand, context));
- }
-
- @override
- Expression visitVariableUse(tree.VariableUse exp,
- BuilderContext<Statement> context) {
- return context.makeVariableAccess(exp.variable);
- }
-
- @override
- Expression visitAssign(tree.Assign node, BuilderContext<Statement> context) {
- // This is called only when an assignment occurs in expression context.
- return makeAssignment(
- context.makeVariableAccess(node.variable),
- visitExpression(node.value, context));
- }
-
- FunctionExpression makeSubFunction(tree.FunctionDefinition function,
- BuilderContext<Statement> context) {
- return visitFunctionDefinition(function,
- new BuilderContext<Statement>.inner(context));
- }
-
- @override
- Expression visitFunctionExpression(tree.FunctionExpression exp,
- BuilderContext<Statement> context) {
- return makeSubFunction(exp.definition, context)..name = null;
- }
-
- @override
- void visitFunctionDeclaration(tree.FunctionDeclaration node,
- BuilderContext<Statement> context) {
- assert(context.variableNames[node.variable] == null);
- String name = context.getVariableName(node.variable);
- FunctionExpression inner = makeSubFunction(node.definition, context);
- inner.name = name;
- FunctionDeclaration decl = new FunctionDeclaration(inner);
- context.declaredVariables.add(node.variable);
- context.addStatement(decl);
- visitStatement(node.next, context);
- }
-
- List<Statement> buildInInitializerContext(tree.Statement root,
- BuilderContext context) {
- BuilderContext inner = new BuilderContext<Statement>.initializer(context);
- inner.currentElement = context.currentElement;
- inner.firstStatement = root;
- visitStatement(root, inner);
- List<Statement> bodyParts;
- for (tree.Variable variable in inner.variableNames.keys) {
- if (!context.declaredVariables.contains(variable) &&
- !inner.declaredVariables.contains(variable)) {
- inner.addDeclaration(variable);
- }
- }
- if (inner.variables.length > 0) {
- bodyParts = new List<Statement>();
- bodyParts.add(new VariableDeclarations(inner.variables));
- bodyParts.addAll(inner.statements);
- } else {
- bodyParts = inner.statements;
- }
- return bodyParts;
- }
-
- @override
- Initializer visitFieldInitializer(tree.FieldInitializer node,
- BuilderContext<Statement> context) {
- return new FieldInitializer(node.element,
- ensureExpression(buildInInitializerContext(node.body, context)));
- }
-
- @override
- Initializer visitSuperInitializer(tree.SuperInitializer node,
- BuilderContext<Statement> context) {
- List<Argument> arguments = node.arguments.map((tree.Statement argument) {
- return ensureExpression(buildInInitializerContext(argument, context));
- }).toList();
- return new SuperInitializer(node.target,
- emitArguments(arguments, node.selector));
- }
-
- @override
- Expression visitGetStatic(tree.GetStatic node,
- BuilderContext<Statement> context) {
- return new Identifier(node.element.name)..element = node.element;
- }
-
- @override
- Expression visitSetStatic(tree.SetStatic node,
- BuilderContext<Statement> context) {
- Expression target =
- new Identifier(node.element.name)..element = node.element;
- Expression value = visitExpression(node.value, context);
- return makeAssignment(target, value);
- }
-
- @override
- Expression visitTypeExpression(tree.TypeExpression node, arg) {
- throw '$node not supported by dart backend';
- }
-
- @override
- visitGetField(tree.GetField node, arg) => errorUnsupportedNode(node);
-
- @override
- visitSetField(tree.SetField node, arg) => errorUnsupportedNode(node);
-
- @override
- visitCreateBox(tree.CreateBox node, arg) => errorUnsupportedNode(node);
-
- @override
- visitCreateInstance(tree.CreateInstance node, arg) {
- return errorUnsupportedNode(node);
- }
-
- @override
- visitCreateInvocationMirror(tree.CreateInvocationMirror node, arg) {
- return errorUnsupportedNode(node);
- }
-
- @override
- Expression visitReadTypeVariable(tree.ReadTypeVariable node, arg) {
- return errorUnsupportedNode(node);
- }
-
- @override
- Expression visitReifyRuntimeType(tree.ReifyRuntimeType node, arg) {
- return errorUnsupportedNode(node);
- }
-
- errorUnsupportedNode(tree.JsSpecificNode node) {
- throw '$node not supported by dart backend';
- }
-
-}
class TypeGenerator {
@@ -1029,10 +14,8 @@ class TypeGenerator {
static int pseudoNameCounter = 0;
static Parameter emitParameter(DartType type,
- BuilderContext<Statement> context,
{String name,
- Element element,
- ConstantExpression defaultValue}) {
+ Element element}) {
if (name == null && element != null) {
name = element.name;
}
@@ -1051,10 +34,6 @@ class TypeGenerator {
parameter = new Parameter(name, type: typeAnnotation);
}
parameter.element = element;
- if (defaultValue != null && !defaultValue.value.isNull) {
- parameter.defaultValue =
- ConstantEmitter.createExpression(defaultValue, context);
- }
return parameter;
}
@@ -1076,20 +55,15 @@ class TypeGenerator {
static List<Parameter> createParameters(
Iterable<DartType> parameterTypes,
- {BuilderContext<Statement> context,
- Iterable<String> names: const <String>[],
- Iterable<ConstantExpression> defaultValues: const <ConstantExpression>[],
+ {Iterable<String> names: const <String>[],
Iterable<Element> elements: const <Element>[]}) {
Iterator<String> name = names.iterator;
- Iterator<ConstantExpression> defaultValue = defaultValues.iterator;
Iterator<Element> element = elements.iterator;
return parameterTypes.map((DartType type) {
name.moveNext();
- defaultValue.moveNext();
element.moveNext();
- return emitParameter(type, context,
+ return emitParameter(type,
name: name.current,
- defaultValue: defaultValue.current,
element: element.current);
}).toList();
}
@@ -1129,323 +103,4 @@ class TypeGenerator {
throw "Unsupported type annotation: $type";
}
}
-
-}
-
-
-class ConstantEmitter
- extends ConstantExpressionVisitor<Expression, BuilderContext<Statement>> {
- const ConstantEmitter();
-
- /// Creates the [Expression] for the constant [exp].
- static Expression createExpression(ConstantExpression exp,
- BuilderContext<Statement> context) {
- return const ConstantEmitter().visit(exp, context);
- }
-
- Expression handlePrimitiveConstant(PrimitiveConstantValue value) {
- // Num constants may be negative, while literals must be non-negative:
- // Literals are non-negative in the specification, and a negated literal
- // parses as a call to unary `-`. The AST unparser assumes literals are
- // non-negative and relies on this to avoid incorrectly generating `--`,
- // the predecrement operator.
- // Translate such constants into their positive value wrapped by
- // the unary minus operator.
- if (value.isNum) {
- NumConstantValue numConstant = value;
- if (numConstant.primitiveValue.isNegative) {
- return negatedLiteral(numConstant);
- }
- }
- return new Literal(value);
- }
-
- List<Expression> visitExpressions(List<ConstantExpression> expressions,
- BuilderContext<Statement> context) {
- return expressions.map((expression) => visit(expression, context))
- .toList(growable: false);
- }
-
- @override
- Expression visitBool(BoolConstantExpression exp,
- BuilderContext<Statement> context) {
- return handlePrimitiveConstant(exp.value);
- }
-
- @override
- Expression visitInt(IntConstantExpression exp,
- BuilderContext<Statement> context) {
- return handlePrimitiveConstant(exp.value);
- }
-
- @override
- Expression visitDouble(DoubleConstantExpression exp,
- BuilderContext<Statement> context) {
- return handlePrimitiveConstant(exp.value);
- }
-
- @override
- Expression visitString(StringConstantExpression exp,
- BuilderContext<Statement> context) {
- return handlePrimitiveConstant(exp.value);
- }
-
- @override
- Expression visitNull(NullConstantExpression exp,
- BuilderContext<Statement> context) {
- return handlePrimitiveConstant(exp.value);
- }
-
- /// Given a negative num constant, returns the corresponding positive
- /// literal wrapped by a unary minus operator.
- Expression negatedLiteral(NumConstantValue constant) {
- assert(constant.primitiveValue.isNegative);
- NumConstantValue positiveConstant;
- if (constant.isInt) {
- positiveConstant = new IntConstantValue(-constant.primitiveValue);
- } else if (constant.isDouble) {
- positiveConstant = new DoubleConstantValue(-constant.primitiveValue);
- } else {
- throw "Unexpected type of NumConstant: $constant";
- }
- return new UnaryOperator('-', new Literal(positiveConstant));
- }
-
- @override
- Expression visitList(ListConstantExpression exp,
- BuilderContext<Statement> context) {
- return new LiteralList(
- visitExpressions(exp.values, context),
- isConst: true,
- typeArgument:
- TypeGenerator.createOptionalType(exp.type.typeArguments.single));
- }
-
- @override
- Expression visitMap(MapConstantExpression exp,
- BuilderContext<Statement> context) {
- List<LiteralMapEntry> entries = new List<LiteralMapEntry>.generate(
- exp.values.length,
- (i) => new LiteralMapEntry(visit(exp.keys[i], context),
- visit(exp.values[i], context)));
- List<TypeAnnotation> typeArguments = exp.type.treatAsRaw
- ? null
- : exp.type.typeArguments.map(TypeGenerator.createType).toList();
- return new LiteralMap(entries, isConst: true, typeArguments: typeArguments);
- }
-
- @override
- Expression visitConstructed(ConstructedConstantExpression exp,
- BuilderContext<Statement> context) {
- int positionalArgumentCount = exp.callStructure.positionalArgumentCount;
- List<Argument> args = new List<Argument>.generate(
- positionalArgumentCount,
- (i) => visit(exp.arguments[i], context));
- for (int i = 0; i < exp.callStructure.namedArgumentCount; ++i) {
- args.add(new NamedArgument(exp.callStructure.namedArguments[i],
- visit(exp.arguments[positionalArgumentCount + i], context)));
- }
-
- FunctionElement constructor = exp.target;
- String name = constructor.name.isEmpty ? null : constructor.name;
- return new CallNew(TypeGenerator.createType(exp.type),
- args,
- constructorName: name,
- isConst: true)
- ..constructor = constructor
- ..dartType = exp.type;
- }
-
- @override
- Expression visitConcatenate(ConcatenateConstantExpression exp,
- BuilderContext<Statement> context) {
-
- return new StringConcat(visitExpressions(exp.expressions, context));
- }
-
- @override
- Expression visitSymbol(SymbolConstantExpression exp,
- BuilderContext<Statement> context) {
- return new LiteralSymbol(exp.name);
- }
-
- @override
- Expression visitType(TypeConstantExpression exp,
- BuilderContext<Statement> context) {
- DartType type = exp.type;
- return new LiteralType(type.name)
- ..type = type;
- }
-
- @override
- Expression visitVariable(VariableConstantExpression exp,
- BuilderContext<Statement> context) {
- Element element = exp.element;
- if (element.kind != ElementKind.VARIABLE) {
- return new Identifier(element.name)..element = element;
- }
- String name = context.getConstantName(element);
- return new Identifier(name)
- ..element = element;
- }
-
- @override
- Expression visitFunction(FunctionConstantExpression exp,
- BuilderContext<Statement> context) {
- return new Identifier(exp.element.name)
- ..element = exp.element;
- }
-
- @override
- Expression visitBinary(BinaryConstantExpression exp,
- BuilderContext<Statement> context) {
- return handlePrimitiveConstant(exp.value);
- }
-
- @override
- Expression visitIdentical(IdenticalConstantExpression exp,
- BuilderContext<Statement> context) {
- return handlePrimitiveConstant(exp.value);
- }
-
- @override
- Expression visitConditional(ConditionalConstantExpression exp,
- BuilderContext<Statement> context) {
- if (exp.condition.value.isTrue) {
- return exp.trueExp.accept(this);
- } else {
- return exp.falseExp.accept(this);
- }
- }
-
- @override
- Expression visitUnary(UnaryConstantExpression exp,
- BuilderContext<Statement> context) {
- return handlePrimitiveConstant(exp.value);
- }
-
- @override
- Expression visitNamed(NamedArgumentReference exp,
- BuilderContext<Statement> context) {
- throw new UnsupportedError("ConstantEmitter.visitNamed");
- }
-
- @override
- Expression visitPositional(PositionalArgumentReference exp,
- BuilderContext<Statement> context) {
- throw new UnsupportedError("ConstantEmitter.visitPositional");
- }
-
- @override
- Expression visitBoolFromEnvironment(
- BoolFromEnvironmentConstantExpression exp,
- BuilderContext<Statement> context) {
- return handlePrimitiveConstant(exp.value);
- }
-
- @override
- Expression visitIntFromEnvironment(
- IntFromEnvironmentConstantExpression exp,
- BuilderContext<Statement> context) {
- return handlePrimitiveConstant(exp.value);
- }
-
- @override
- Expression visitStringFromEnvironment(
- StringFromEnvironmentConstantExpression exp,
- BuilderContext<Statement> context) {
- return handlePrimitiveConstant(exp.value);
- }
-
- @override
- Expression visitDeferred(DeferredConstantExpression exp,
- BuilderContext<Statement> context) {
- return exp.expression.accept(this);
- }
-}
-
-/// Moves function parameters into a separate variable if one of its uses is
-/// shadowed by an inner function parameter.
-/// This artifact is necessary because function parameters cannot be renamed.
-class UnshadowParameters extends tree.RecursiveVisitor {
-
- /// Maps parameter names to their bindings.
- Map<String, tree.Variable> environment = <String, tree.Variable>{};
-
- /// Parameters that are currently shadowed by another parameter.
- Set<tree.Variable> shadowedParameters = new Set<tree.Variable>();
-
- /// Parameters that are used in a context where it is shadowed.
- Set<tree.Variable> hasShadowedUse = new Set<tree.Variable>();
-
- void unshadow(tree.RootNode definition) {
- if (definition.isEmpty) return;
- unshadowFunction(definition);
- }
-
- void unshadowFunction(tree.RootNode definition) {
- var oldShadow = shadowedParameters;
- var oldEnvironment = environment;
- environment = new Map<String, tree.Variable>.from(environment);
- shadowedParameters = new Set<tree.Variable>.from(shadowedParameters);
- for (tree.Variable param in definition.parameters) {
- tree.Variable oldVariable = environment[param.element.name];
- if (oldVariable != null) {
- shadowedParameters.add(oldVariable);
- }
- environment[param.element.name] = param;
- }
- definition.forEachBody(visitStatement);
- environment = oldEnvironment;
- shadowedParameters = oldShadow;
-
- for (int i=0; i<definition.parameters.length; i++) {
- tree.Variable param = definition.parameters[i];
- if (hasShadowedUse.remove(param)) {
- tree.Variable newParam = new tree.Variable(definition.element,
- param.element);
- definition.parameters[i] = newParam;
- definition.replaceEachBody((tree.Statement body) {
- return tree.Assign.makeStatement(
- param,
- new tree.VariableUse(newParam),
- body);
- });
- newParam.writeCount = 1; // Being a parameter counts as a write.
- param.writeCount--; // Not a parameter anymore.
- }
- }
- }
-
- @override
- void visitInnerFunction(tree.FunctionDefinition definition) {
- unshadowFunction(definition);
- }
-
- @override
- visitVariable(tree.Variable variable) {
- if (shadowedParameters.contains(variable)) {
- hasShadowedUse.add(variable);
- }
- }
-
-}
-
-// TODO(johnniwinther): Remove this when the dart `backend_ast` does not need
-// [Element] for entities.
-class _SyntheticLocalVariableElement extends modelx.VariableElementX
- implements LocalVariableElement {
-
- _SyntheticLocalVariableElement(String name,
- ExecutableElement enclosingElement,
- modelx.VariableList variables)
- : super(name, ElementKind.VARIABLE, enclosingElement, variables, null);
-
- ExecutableElement get executableContext => enclosingElement;
-
- ExecutableElement get memberContext => executableContext.memberContext;
-
- bool get isLocal => true;
-
- LibraryElement get implementationLibrary => enclosingElement.library;
}
« no previous file with comments | « pkg/compiler/lib/src/dart_backend/backend.dart ('k') | pkg/compiler/lib/src/dart_backend/backend_ast_nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698