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

Unified Diff: sdk/lib/_internal/compiler/implementation/dart_backend/backend_ast_emitter.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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: sdk/lib/_internal/compiler/implementation/dart_backend/backend_ast_emitter.dart
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend_ast_emitter.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend_ast_emitter.dart
deleted file mode 100644
index 7ceefa66b585b348a223d7065953f67102d0efb0..0000000000000000000000000000000000000000
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend_ast_emitter.dart
+++ /dev/null
@@ -1,919 +0,0 @@
-// Copyright (c) 2014, 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 backend_ast_emitter;
-
-import '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.
-Expression emit(tree.FunctionDefinition definition) {
- return new ASTEmitter().emit(definition);
-}
-
-/// 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.Visitor<dynamic, Expression> {
- /// Variables to be hoisted at the top of the current function.
- List<VariableDeclaration> variables = <VariableDeclaration>[];
-
- /// Maps variables to their name.
- Map<tree.Variable, String> variableNames = <tree.Variable, String>{};
-
- /// Maps local constants to their name.
- Map<VariableElement, String> constantNames = <VariableElement, String>{};
-
- /// Variables that have had their declaration created.
- Set<tree.Variable> declaredVariables = new Set<tree.Variable>();
-
- /// Variable names that have already been used. Used to avoid name clashes.
- Set<String> usedVariableNames;
-
- /// Statements emitted by the most recent call to [visitStatement].
- List<Statement> statementBuffer = <Statement>[];
-
- /// The function currently being emitted.
- FunctionElement functionElement;
-
- /// Bookkeeping object needed to synthesize a variable declaration.
- 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.
- Set<tree.Label> usedLabels = new Set<tree.Label>();
-
- /// The first dart_tree statement that is not converted to a variable
- /// initializer.
- tree.Statement firstStatement;
-
- /// Emitter for the enclosing function, or null if the current function is
- /// not a local function.
- ASTEmitter parent;
-
- ASTEmitter() : usedVariableNames = new Set<String>();
-
- ASTEmitter.inner(ASTEmitter parent)
- : this.parent = parent,
- usedVariableNames = parent.usedVariableNames;
-
- FunctionExpression emit(tree.FunctionDefinition definition) {
- functionElement = definition.element;
-
- Parameters parameters = emitRootParameters(definition);
-
- // Declare parameters.
- for (tree.Variable param in definition.parameters) {
- variableNames[param] = param.element.name;
- usedVariableNames.add(param.element.name);
- declaredVariables.add(param);
- }
-
- Statement body;
- if (definition.isAbstract) {
- body = new EmptyStatement();
- } else {
- firstStatement = definition.body;
- visitStatement(definition.body);
- removeTrailingReturn();
-
- // 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.
- for (tree.Variable variable in variableNames.keys) {
- if (!declaredVariables.contains(variable)) {
- addDeclaration(variable);
- }
- }
-
- // Add constant declarations.
- List<VariableDeclaration> constants = <VariableDeclaration>[];
- for (ConstDeclaration constDecl in definition.localConstants) {
- if (!constantNames.containsKey(constDecl.element))
- continue; // Discard unused constants declarations.
- String name = getConstantName(constDecl.element);
- Expression value = emitConstant(constDecl.expression);
- 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 (variables.length > 0) {
- bodyParts.add(new VariableDeclarations(variables));
- }
- bodyParts.addAll(statementBuffer);
-
- body = new Block(bodyParts);
- }
- FunctionType functionType = functionElement.type;
-
- return new FunctionExpression(
- parameters,
- body,
- name: functionElement.name,
- returnType: emitOptionalType(functionType.returnType),
- isGetter: functionElement.isGetter,
- isSetter: functionElement.isSetter)
- ..element = functionElement;
- }
-
- 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);
- }
-
- /// Removes a trailing "return null" from [statementBuffer].
- void removeTrailingReturn() {
- if (statementBuffer.isEmpty) return;
- if (statementBuffer.last is! Return) return;
- Return ret = statementBuffer.last;
- Expression expr = ret.expression;
- if (expr is Literal && expr.value.isNull) {
- statementBuffer.removeLast();
- }
- }
-
- /// TODO(johnniwinther): Remove this when issue 21283 has been resolved.
- int pseudoNameCounter = 0;
-
- Parameter emitParameter(DartType type,
- {String name,
- Element element,
- ConstantExpression defaultValue}) {
- if (name == null && element != null) {
- name = element.name;
- }
- if (name == null) {
- name = '_${pseudoNameCounter++}';
- }
- Parameter parameter;
- if (type.isFunctionType) {
- FunctionType functionType = type;
- TypeAnnotation returnType = emitOptionalType(functionType.returnType);
- Parameters innerParameters = emitParametersFromType(functionType);
- parameter = new Parameter.function(name, returnType, innerParameters);
- } else {
- TypeAnnotation typeAnnotation = emitOptionalType(type);
- parameter = new Parameter(name, type: typeAnnotation);
- }
- parameter.element = element;
- if (defaultValue != null && !defaultValue.value.isNull) {
- parameter.defaultValue = emitConstant(defaultValue);
- }
- return parameter;
- }
-
- Parameters emitParametersFromType(FunctionType functionType) {
- if (functionType.namedParameters.isEmpty) {
- return new Parameters(
- emitParameters(functionType.parameterTypes),
- emitParameters(functionType.optionalParameterTypes),
- false);
- } else {
- return new Parameters(
- emitParameters(functionType.parameterTypes),
- emitParameters(functionType.namedParameterTypes,
- names: functionType.namedParameters),
- true);
- }
- }
-
- List<Parameter> emitParameters(
- Iterable<DartType> parameterTypes,
- {Iterable<String> names: const <String>[],
- Iterable<ConstantExpression> defaultValues: const <ConstantExpression>[],
- 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,
- name: name.current,
- defaultValue: defaultValue.current,
- element: element.current);
- }).toList();
- }
-
- /// Emits parameters that are not nested inside other parameters.
- /// Root parameters can have default values, while inner parameters cannot.
- Parameters emitRootParameters(tree.FunctionDefinition function) {
- FunctionType functionType = function.element.type;
- List<Parameter> required = emitParameters(
- functionType.parameterTypes,
- elements: function.parameters.map((p) => p.element));
- bool optionalParametersAreNamed = !functionType.namedParameters.isEmpty;
- List<Parameter> optional = emitParameters(
- optionalParametersAreNamed
- ? functionType.namedParameterTypes
- : functionType.optionalParameterTypes,
- defaultValues: function.defaultParameterValues,
- 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)) {
- Expression 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);
- }
-
- void visitExpressionStatement(tree.ExpressionStatement stmt) {
- Expression e = visitExpression(stmt.expression);
- statementBuffer.add(new ExpressionStatement(e));
- visitStatement(stmt.next);
- }
-
- void visitLabeledStatement(tree.LabeledStatement stmt) {
- List<Statement> savedBuffer = statementBuffer;
- tree.Statement savedFallthrough = fallthrough;
- statementBuffer = <Statement>[];
- fallthrough = stmt.next;
- visitStatement(stmt.body);
- if (usedLabels.remove(stmt.label)) {
- savedBuffer.add(new LabeledStatement(stmt.label.name,
- new Block(statementBuffer)));
- } else {
- savedBuffer.add(new Block(statementBuffer));
- }
- fallthrough = savedFallthrough;
- statementBuffer = savedBuffer;
- visitStatement(stmt.next);
- }
-
- /// 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 (variable.host.element != functionElement) {
- 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,
- functionElement,
- variableList);
- }
- return name;
- }
-
- String getConstantName(VariableElement element) {
- assert(element.kind == ElementKind.VARIABLE);
- if (element.enclosingElement != functionElement) {
- 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;
- }
-
- bool isNullLiteral(Expression exp) => exp is Literal && exp.value.isNull;
-
- void visitAssign(tree.Assign stmt) {
- // 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 (stmt.variable.element is FunctionElement &&
- stmt.definition is tree.FunctionExpression &&
- !declaredVariables.contains(stmt.variable)) {
- tree.FunctionExpression functionExp = stmt.definition;
- FunctionExpression function = makeSubFunction(functionExp.definition);
- FunctionDeclaration decl = new FunctionDeclaration(function);
- statementBuffer.add(decl);
- declaredVariables.add(stmt.variable);
- visitStatement(stmt.next);
- return;
- }
-
- bool isFirstOccurrence = (variableNames[stmt.variable] == null);
- bool isDeclaredHere = stmt.variable.host.element == functionElement;
- String name = getVariableName(stmt.variable);
- Expression definition = visitExpression(stmt.definition);
-
- // Try to pull into initializer.
- if (firstStatement == stmt && isFirstOccurrence && isDeclaredHere) {
- if (isNullLiteral(definition)) definition = null;
- addDeclaration(stmt.variable, definition);
- firstStatement = stmt.next;
- visitStatement(stmt.next);
- return;
- }
-
- // Emit a variable declaration if we are required to do so.
- // This is to ensure that a fresh closure variable is created.
- if (stmt.isDeclaration) {
- assert(isFirstOccurrence);
- assert(isDeclaredHere);
- if (isNullLiteral(definition)) definition = null;
- VariableDeclaration decl = new VariableDeclaration(name, definition)
- ..element = stmt.variable.element;
- declaredVariables.add(stmt.variable);
- statementBuffer.add(new VariableDeclarations([decl]));
- visitStatement(stmt.next);
- return;
- }
-
- statementBuffer.add(new ExpressionStatement(makeAssignment(
- visitVariable(stmt.variable),
- definition)));
- visitStatement(stmt.next);
- }
-
- void visitReturn(tree.Return stmt) {
- Expression inner = visitExpression(stmt.value);
- statementBuffer.add(new Return(inner));
- }
-
- void visitBreak(tree.Break stmt) {
- tree.Statement fall = 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 {
- usedLabels.add(stmt.target);
- statementBuffer.add(new Break(stmt.target.name));
- }
- }
-
- void visitContinue(tree.Continue stmt) {
- tree.Statement fall = 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 {
- usedLabels.add(stmt.target);
- statementBuffer.add(new Continue(stmt.target.name));
- }
- }
-
- void visitIf(tree.If stmt) {
- Expression condition = visitExpression(stmt.condition);
- List<Statement> savedBuffer = statementBuffer;
- List<Statement> thenBuffer = statementBuffer = <Statement>[];
- visitStatement(stmt.thenStatement);
- List<Statement> elseBuffer = statementBuffer = <Statement>[];
- visitStatement(stmt.elseStatement);
- savedBuffer.add(
- new If(condition, new Block(thenBuffer), new Block(elseBuffer)));
- statementBuffer = savedBuffer;
- }
-
- void visitWhileTrue(tree.WhileTrue stmt) {
- List<Statement> savedBuffer = statementBuffer;
- tree.Statement savedFallthrough = fallthrough;
- statementBuffer = <Statement>[];
- fallthrough = stmt;
-
- visitStatement(stmt.body);
- Statement body = new Block(statementBuffer);
- Statement statement = new While(new Literal(new TrueConstantValue()),
- body);
- if (usedLabels.remove(stmt.label)) {
- statement = new LabeledStatement(stmt.label.name, statement);
- }
- savedBuffer.add(statement);
-
- statementBuffer = savedBuffer;
- fallthrough = savedFallthrough;
- }
-
- void visitWhileCondition(tree.WhileCondition stmt) {
- Expression condition = visitExpression(stmt.condition);
-
- List<Statement> savedBuffer = statementBuffer;
- tree.Statement savedFallthrough = fallthrough;
- statementBuffer = <Statement>[];
- fallthrough = stmt;
-
- visitStatement(stmt.body);
- Statement body = new Block(statementBuffer);
- Statement statement;
- statement = new While(condition, body);
- if (usedLabels.remove(stmt.label)) {
- statement = new LabeledStatement(stmt.label.name, statement);
- }
- savedBuffer.add(statement);
-
- statementBuffer = savedBuffer;
- fallthrough = savedFallthrough;
-
- visitStatement(stmt.next);
- }
-
- Expression visitConstant(tree.Constant exp) {
- return emitConstant(exp.expression);
- }
-
- Expression visitThis(tree.This exp) {
- return new This();
- }
-
- Expression visitReifyTypeVar(tree.ReifyTypeVar exp) {
- return new ReifyTypeVar(exp.typeVariable.name)
- ..element = exp.typeVariable;
- }
-
- Expression visitLiteralList(tree.LiteralList exp) {
- return new LiteralList(
- exp.values.map(visitExpression).toList(growable: false),
- typeArgument: emitOptionalType(exp.type.typeArguments.single));
- }
-
- Expression visitLiteralMap(tree.LiteralMap exp) {
- List<LiteralMapEntry> entries = new List<LiteralMapEntry>.generate(
- exp.entries.length,
- (i) => new LiteralMapEntry(visitExpression(exp.entries[i].key),
- visitExpression(exp.entries[i].value)));
- List<TypeAnnotation> typeArguments = exp.type.treatAsRaw
- ? null
- : exp.type.typeArguments.map(createTypeAnnotation)
- .toList(growable: false);
- return new LiteralMap(entries, typeArguments: typeArguments);
- }
-
- Expression visitTypeOperator(tree.TypeOperator exp) {
- return new TypeOperator(visitExpression(exp.receiver),
- exp.operator,
- createTypeAnnotation(exp.type));
- }
-
- List<Argument> emitArguments(tree.Invoke exp) {
- List<tree.Expression> args = exp.arguments;
- int positionalArgumentCount = exp.selector.positionalArgumentCount;
- List<Argument> result = new List<Argument>.generate(positionalArgumentCount,
- (i) => visitExpression(exp.arguments[i]));
- for (int i = 0; i < exp.selector.namedArgumentCount; ++i) {
- result.add(new NamedArgument(exp.selector.namedArguments[i],
- visitExpression(exp.arguments[positionalArgumentCount + i])));
- }
- return result;
- }
-
- Expression visitInvokeStatic(tree.InvokeStatic exp) {
- 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]));
-
- case SelectorKind.CALL:
- return new CallStatic(null, exp.target.name, emitArguments(exp))
- ..element = exp.target;
-
- default:
- throw "Unexpected selector kind: ${exp.selector.kind}";
- }
- }
-
- Expression emitMethodCall(tree.Invoke exp, Receiver receiver) {
- List<Argument> args = emitArguments(exp);
- 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}";
- }
- }
-
- Expression visitInvokeMethod(tree.InvokeMethod exp) {
- Expression receiver = visitExpression(exp.receiver);
- return emitMethodCall(exp, receiver);
- }
-
- Expression visitInvokeSuperMethod(tree.InvokeSuperMethod exp) {
- return emitMethodCall(exp, new SuperReceiver());
- }
-
- Expression visitInvokeConstructor(tree.InvokeConstructor exp) {
- List args = emitArguments(exp);
- FunctionElement constructor = exp.target;
- String name = constructor.name.isEmpty ? null : constructor.name;
- return new CallNew(createTypeAnnotation(exp.type),
- args,
- constructorName: name,
- isConst: exp.constant != null)
- ..constructor = constructor
- ..dartType = exp.type;
- }
-
- Expression visitConcatenateStrings(tree.ConcatenateStrings exp) {
- List args = exp.arguments.map(visitExpression).toList(growable:false);
- return new StringConcat(args);
- }
-
- Expression visitConditional(tree.Conditional exp) {
- return new Conditional(
- visitExpression(exp.condition),
- visitExpression(exp.thenExpression),
- visitExpression(exp.elseExpression));
- }
-
- Expression visitLogicalOperator(tree.LogicalOperator exp) {
- return new BinaryOperator(visitExpression(exp.left),
- exp.operator,
- visitExpression(exp.right));
- }
-
- Expression visitNot(tree.Not exp) {
- return new UnaryOperator('!', visitExpression(exp.operand));
- }
-
- Expression visitVariable(tree.Variable exp) {
- return new Identifier(getVariableName(exp))
- ..element = exp.element;
- }
-
- FunctionExpression makeSubFunction(tree.FunctionDefinition function) {
- return new ASTEmitter.inner(this).emit(function);
- }
-
- Expression visitFunctionExpression(tree.FunctionExpression exp) {
- return makeSubFunction(exp.definition)..name = null;
- }
-
- void visitFunctionDeclaration(tree.FunctionDeclaration node) {
- assert(variableNames[node.variable] == null);
- String name = getVariableName(node.variable);
- FunctionExpression inner = makeSubFunction(node.definition);
- inner.name = name;
- FunctionDeclaration decl = new FunctionDeclaration(inner);
- declaredVariables.add(node.variable);
- statementBuffer.add(decl);
- visitStatement(node.next);
- }
-
- /// Like [createTypeAnnotation] except the dynamic type is converted to null.
- TypeAnnotation emitOptionalType(DartType type) {
- if (type.treatAsDynamic) {
- return null;
- } else {
- return createTypeAnnotation(type);
- }
- }
-
- Expression emitConstant(ConstantExpression exp) {
- return new ConstantEmitter(this).visit(exp);
- }
-}
-
-TypeAnnotation createTypeAnnotation(DartType type) {
- if (type is GenericType) {
- if (type.treatAsRaw) {
- return new TypeAnnotation(type.element.name)..dartType = type;
- }
- return new TypeAnnotation(
- type.element.name,
- type.typeArguments.map(createTypeAnnotation).toList(growable:false))
- ..dartType = type;
- } else if (type is VoidType) {
- return new TypeAnnotation('void')
- ..dartType = type;
- } else if (type is TypeVariableType) {
- return new TypeAnnotation(type.name)
- ..dartType = type;
- } else if (type is DynamicType) {
- return new TypeAnnotation("dynamic")
- ..dartType = type;
- } else if (type is MalformedType) {
- return new TypeAnnotation(type.name)
- ..dartType = type;
- } else {
- throw "Unsupported type annotation: $type";
- }
-}
-
-class ConstantEmitter extends ConstantExpressionVisitor<Expression> {
- ASTEmitter parent;
- ConstantEmitter(this.parent);
-
- 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);
- }
-
- @override
- Expression visitPrimitive(PrimitiveConstantExpression exp) {
- 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) {
- return new LiteralList(
- exp.values.map(visit).toList(growable: false),
- isConst: true,
- typeArgument: parent.emitOptionalType(exp.type.typeArguments.single));
- }
-
- @override
- Expression visitMap(MapConstantExpression exp) {
- List<LiteralMapEntry> entries = new List<LiteralMapEntry>.generate(
- exp.values.length,
- (i) => new LiteralMapEntry(visit(exp.keys[i]),
- visit(exp.values[i])));
- List<TypeAnnotation> typeArguments = exp.type.treatAsRaw
- ? null
- : exp.type.typeArguments.map(createTypeAnnotation).toList();
- return new LiteralMap(entries, isConst: true, typeArguments: typeArguments);
- }
-
- @override
- Expression visitConstructor(ConstructedConstantExpresssion exp) {
- int positionalArgumentCount = exp.selector.positionalArgumentCount;
- List<Argument> args = new List<Argument>.generate(
- positionalArgumentCount,
- (i) => visit(exp.arguments[i]));
- for (int i = 0; i < exp.selector.namedArgumentCount; ++i) {
- args.add(new NamedArgument(exp.selector.namedArguments[i],
- visit(exp.arguments[positionalArgumentCount + i])));
- }
-
- FunctionElement constructor = exp.target;
- String name = constructor.name.isEmpty ? null : constructor.name;
- return new CallNew(createTypeAnnotation(exp.type),
- args,
- constructorName: name,
- isConst: true)
- ..constructor = constructor
- ..dartType = exp.type;
- }
-
- @override
- Expression visitConcatenate(ConcatenateConstantExpression exp) {
- return new StringConcat(exp.arguments.map(visit).toList(growable: false));
- }
-
- @override
- Expression visitSymbol(SymbolConstantExpression exp) {
- return new LiteralSymbol(exp.name);
- }
-
- @override
- Expression visitType(TypeConstantExpression exp) {
- DartType type = exp.type;
- return new LiteralType(type.name)
- ..type = type;
- }
-
- @override
- Expression visitVariable(VariableConstantExpression exp) {
- Element element = exp.element;
- if (element.kind != ElementKind.VARIABLE) {
- return new Identifier(element.name)..element = element;
- }
- String name = parent.getConstantName(element);
- return new Identifier(name)
- ..element = element;
- }
-
- @override
- Expression visitFunction(FunctionConstantExpression exp) {
- return new Identifier(exp.element.name)
- ..element = exp.element;
- }
-
- @override
- Expression visitBinary(BinaryConstantExpression exp) {
- return handlePrimitiveConstant(exp.value);
- }
-
- @override
- Expression visitConditional(ConditionalConstantExpression exp) {
- if (exp.condition.value.isTrue) {
- return exp.trueExp.accept(this);
- } else {
- return exp.falseExp.accept(this);
- }
- }
-
- @override
- Expression visitUnary(UnaryConstantExpression exp) {
- return handlePrimitiveConstant(exp.value);
- }
-}
-
-/// 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.FunctionDefinition definition) {
- if (definition.isAbstract) return;
-
- visitFunctionDefinition(definition);
- }
-
- visitFunctionDefinition(tree.FunctionDefinition 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;
- }
- visitStatement(definition.body);
- 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, param.element);
- definition.parameters[i] = newParam;
- definition.body = new tree.Assign(param, newParam, definition.body);
- newParam.writeCount = 1; // Being a parameter counts as a write.
- }
- }
- }
-
- 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;
-}

Powered by Google App Engine
This is Rietveld 408576698