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

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

Issue 763993002: Extract BuilderContext from ASTEmitter (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 6 years 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
« no previous file with comments | « pkg/compiler/lib/src/constants/expressions.dart ('k') | pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 8a86eda794f38ae280b234949db7f41412ce990d..af68cc362342b90974df7f1d4b94a6d957912f4f 100644
--- a/pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart
@@ -16,36 +16,39 @@ import '../tree/tree.dart' as tree show Modifiers;
/// Translates the dart_tree IR to Dart backend AST.
ExecutableDefinition emit(tree.ExecutableDefinition definition) {
- return new ASTEmitter().emit(definition);
+ return new ASTEmitter().emit(definition, new BuilderContext<Statement>());
}
-/// 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> {
+// 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.
- List<VariableDeclaration> variables = <VariableDeclaration>[];
+ final List<VariableDeclaration> variables = <VariableDeclaration>[];
/// Maps variables to their name.
- Map<tree.Variable, String> variableNames = <tree.Variable, String>{};
+ final Map<tree.Variable, String> variableNames = <tree.Variable, String>{};
/// Maps local constants to their name.
- Map<VariableElement, String> constantNames = <VariableElement, String>{};
+ final Map<VariableElement, String> constantNames =
+ <VariableElement, String>{};
/// Variables that have had their declaration created.
- Set<tree.Variable> declaredVariables = new Set<tree.Variable>();
+ final Set<tree.Variable> declaredVariables = new Set<tree.Variable>();
/// Variable names that have already been used. Used to avoid name clashes.
- Set<String> usedVariableNames;
+ final Set<String> usedVariableNames;
/// Statements emitted by the most recent call to [visitStatement].
- List<Statement> statementBuffer = <Statement>[];
+ List<T> _statementBuffer = <T>[];
/// The element currently being emitted.
ExecutableElement currentElement;
/// Bookkeeping object needed to synthesize a variable declaration.
- modelx.VariableList variableList
+ final modelx.VariableList variableList
= new modelx.VariableList(tree.Modifiers.EMPTY);
/// Input to [visitStatement]. Denotes the statement that will execute next
@@ -54,45 +57,162 @@ class ASTEmitter extends tree.Visitor<dynamic, Expression> {
tree.Statement fallthrough = null;
/// Labels that could not be eliminated using fallthrough.
- Set<tree.Label> usedLabels = new Set<tree.Label>();
+ final 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;
+ BuilderContext() : usedVariableNames = new Set<String>();
- ASTEmitter() : usedVariableNames = new Set<String>();
-
- ASTEmitter.inner(ASTEmitter parent)
- : this.parent = parent,
+ BuilderContext.inner(BuilderContext<T> parent)
+ : this._parent = parent,
usedVariableNames = parent.usedVariableNames;
- ExecutableDefinition emit(tree.ExecutableDefinition definition) {
+ // TODO(johnniwinther): Fully encapsulate handling of parameter, variable
+ // and local funciton 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);
+ }
+
+ /// 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 != 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;
+ }
+
+ 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.Visitor1<dynamic, Expression, BuilderContext<Statement>> {
+
+ ExecutableDefinition emit(tree.ExecutableDefinition definition,
+ BuilderContext<Statement> context) {
if (definition is tree.FieldDefinition) {
- return emitField(definition);
+ return emitField(definition, context);
}
assert(definition is tree.FunctionDefinition);
- return emitFunction(definition);
+ return emitFunction(definition, context);
}
- FieldDefinition emitField(tree.FieldDefinition definition) {
- currentElement = definition.element;
- visitStatement(definition.body);
+ FieldDefinition emitField(tree.FieldDefinition definition,
+ BuilderContext<Statement> context) {
+ context.currentElement = definition.element;
+ visitStatement(definition.body, context);
List<Statement> bodyParts;
- for (tree.Variable variable in variableNames.keys) {
- if (!declaredVariables.contains(variable)) {
- addDeclaration(variable);
+ for (tree.Variable variable in context.variableNames.keys) {
+ if (!context.declaredVariables.contains(variable)) {
+ context.addDeclaration(variable);
}
}
- if (variables.length > 0) {
+ if (context.variables.length > 0) {
bodyParts = new List<Statement>();
- bodyParts.add(new VariableDeclarations(variables));
- bodyParts.addAll(statementBuffer);
+ bodyParts.add(new VariableDeclarations(context.variables));
+ bodyParts.addAll(context.statements);
} else {
- bodyParts = statementBuffer;
+ bodyParts = context.statements;
}
return new FieldDefinition(definition.element, ensureExpression(bodyParts));
@@ -115,42 +235,52 @@ class ASTEmitter extends tree.Visitor<dynamic, Expression> {
return new CallFunction(function, []);
}
- FunctionExpression emitFunction(tree.FunctionDefinition definition) {
- currentElement = definition.element;
+ FunctionExpression emitFunction(tree.FunctionDefinition definition,
+ BuilderContext<Statement> context) {
+ context.currentElement = definition.element;
- Parameters parameters = emitRootParameters(definition);
+ Parameters parameters = emitRootParameters(definition, context);
// Declare parameters.
for (tree.Variable param in definition.parameters) {
- variableNames[param] = param.element.name;
- usedVariableNames.add(param.element.name);
- declaredVariables.add(param);
+ context.variableNames[param] = param.element.name;
+ context.usedVariableNames.add(param.element.name);
+ context.declaredVariables.add(param);
}
Statement body;
if (definition.isAbstract) {
body = new EmptyStatement();
} else {
- firstStatement = definition.body;
- visitStatement(definition.body);
- removeTrailingReturn();
+ context.firstStatement = definition.body;
+ visitStatement(definition.body, context);
+ context.removeTrailingReturn((Statement statement) {
+ if (statement is Return) {
+ Expression expr = statement.expression;
+ if (expr is Literal && expr.value.isNull) {
+ return true;
+ }
+ }
+ return false;
+ });
// 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);
+ for (tree.Variable variable in context.variableNames.keys) {
+ if (!context.declaredVariables.contains(variable)) {
+ context.addDeclaration(variable);
}
}
// Add constant declarations.
List<VariableDeclaration> constants = <VariableDeclaration>[];
for (ConstDeclaration constDecl in definition.localConstants) {
- if (!constantNames.containsKey(constDecl.element))
+ if (!context.constantNames.containsKey(constDecl.element)) {
continue; // Discard unused constants declarations.
- String name = getConstantName(constDecl.element);
- Expression value = emitConstant(constDecl.expression);
+ }
+ String name = context.getConstantName(constDecl.element);
+ Expression value = emitConstant(constDecl.expression, context);
VariableDeclaration decl = new VariableDeclaration(name, value);
decl.element = constDecl.element;
constants.add(decl);
@@ -160,49 +290,30 @@ class ASTEmitter extends tree.Visitor<dynamic, Expression> {
if (constants.length > 0) {
bodyParts.add(new VariableDeclarations(constants, isConst: true));
}
- if (variables.length > 0) {
- bodyParts.add(new VariableDeclarations(variables));
+ if (context.variables.length > 0) {
+ bodyParts.add(new VariableDeclarations(context.variables));
}
- bodyParts.addAll(statementBuffer);
+ bodyParts.addAll(context.statements);
body = new Block(bodyParts);
}
- FunctionType functionType = currentElement.type;
+ FunctionType functionType = context.currentElement.type;
return new FunctionExpression(
parameters,
body,
- name: currentElement.name,
+ name: context.currentElement.name,
returnType: emitOptionalType(functionType.returnType),
- isGetter: currentElement.isGetter,
- isSetter: currentElement.isSetter)
- ..element = currentElement;
- }
-
- 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();
- }
+ isGetter: context.currentElement.isGetter,
+ isSetter: context.currentElement.isSetter)
+ ..element = context.currentElement;
}
/// TODO(johnniwinther): Remove this when issue 21283 has been resolved.
int pseudoNameCounter = 0;
Parameter emitParameter(DartType type,
+ BuilderContext<Statement> context,
{String name,
Element element,
ConstantExpression defaultValue}) {
@@ -216,7 +327,8 @@ class ASTEmitter extends tree.Visitor<dynamic, Expression> {
if (type.isFunctionType) {
FunctionType functionType = type;
TypeAnnotation returnType = emitOptionalType(functionType.returnType);
- Parameters innerParameters = emitParametersFromType(functionType);
+ Parameters innerParameters =
+ emitParametersFromType(functionType, context);
parameter = new Parameter.function(name, returnType, innerParameters);
} else {
TypeAnnotation typeAnnotation = emitOptionalType(type);
@@ -224,21 +336,22 @@ class ASTEmitter extends tree.Visitor<dynamic, Expression> {
}
parameter.element = element;
if (defaultValue != null && !defaultValue.value.isNull) {
- parameter.defaultValue = emitConstant(defaultValue);
+ parameter.defaultValue = emitConstant(defaultValue, context);
}
return parameter;
}
- Parameters emitParametersFromType(FunctionType functionType) {
+ Parameters emitParametersFromType(FunctionType functionType,
+ BuilderContext<Statement> context) {
if (functionType.namedParameters.isEmpty) {
return new Parameters(
- emitParameters(functionType.parameterTypes),
- emitParameters(functionType.optionalParameterTypes),
+ emitParameters(functionType.parameterTypes, context),
+ emitParameters(functionType.optionalParameterTypes, context),
false);
} else {
return new Parameters(
- emitParameters(functionType.parameterTypes),
- emitParameters(functionType.namedParameterTypes,
+ emitParameters(functionType.parameterTypes, context),
+ emitParameters(functionType.namedParameterTypes, context,
names: functionType.namedParameters),
true);
}
@@ -246,6 +359,7 @@ class ASTEmitter extends tree.Visitor<dynamic, Expression> {
List<Parameter> emitParameters(
Iterable<DartType> parameterTypes,
+ BuilderContext<Statement> context,
{Iterable<String> names: const <String>[],
Iterable<ConstantExpression> defaultValues: const <ConstantExpression>[],
Iterable<Element> elements: const <Element>[]}) {
@@ -256,7 +370,7 @@ class ASTEmitter extends tree.Visitor<dynamic, Expression> {
name.moveNext();
defaultValue.moveNext();
element.moveNext();
- return emitParameter(type,
+ return emitParameter(type, context,
name: name.current,
defaultValue: defaultValue.current,
element: element.current);
@@ -265,16 +379,18 @@ class ASTEmitter extends tree.Visitor<dynamic, Expression> {
/// Emits parameters that are not nested inside other parameters.
/// Root parameters can have default values, while inner parameters cannot.
- Parameters emitRootParameters(tree.FunctionDefinition function) {
+ Parameters emitRootParameters(tree.FunctionDefinition function,
+ BuilderContext<Statement> context) {
FunctionType functionType = function.element.type;
List<Parameter> required = emitParameters(
- functionType.parameterTypes,
+ functionType.parameterTypes, context,
elements: function.parameters.map((p) => p.element));
bool optionalParametersAreNamed = !functionType.namedParameters.isEmpty;
List<Parameter> optional = emitParameters(
optionalParametersAreNamed
? functionType.namedParameterTypes
: functionType.optionalParameterTypes,
+ context,
defaultValues: function.defaultParameterValues,
elements: function.parameters.skip(required.length)
.map((p) => p.element));
@@ -321,117 +437,75 @@ class ASTEmitter extends tree.Visitor<dynamic, Expression> {
return new Assignment(target, '=', value);
}
- void visitExpressionStatement(tree.ExpressionStatement stmt) {
- Expression e = visitExpression(stmt.expression);
- statementBuffer.add(new ExpressionStatement(e));
- visitStatement(stmt.next);
+ 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 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)));
+ void addLabeledStatement(tree.Label label,
+ Statement statement,
+ BuilderContext<Statement> context) {
+ if (context.removeUsedLabel(label)) {
+ context.addStatement(new LabeledStatement(label.name, statement));
} else {
- savedBuffer.add(new Block(statementBuffer));
+ context.addStatement(statement);
}
- 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 != 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;
+ @override
+ void visitExpressionStatement(tree.ExpressionStatement stmt,
+ BuilderContext<Statement> context) {
+ Expression e = visitExpression(stmt.expression, context);
+ context.addStatement(new ExpressionStatement(e));
- // 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;
+ visitStatement(stmt.next, context);
}
- 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;
+ @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 visitAssign(tree.Assign stmt) {
+ @override
+ void visitAssign(tree.Assign stmt,
+ 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 (stmt.variable.element is FunctionElement &&
stmt.definition is tree.FunctionExpression &&
- !declaredVariables.contains(stmt.variable)) {
+ !context.declaredVariables.contains(stmt.variable)) {
tree.FunctionExpression functionExp = stmt.definition;
- FunctionExpression function = makeSubFunction(functionExp.definition);
+ FunctionExpression function =
+ makeSubFunction(functionExp.definition, context);
FunctionDeclaration decl = new FunctionDeclaration(function);
- statementBuffer.add(decl);
- declaredVariables.add(stmt.variable);
- visitStatement(stmt.next);
+ context.addStatement(decl);
+ context.declaredVariables.add(stmt.variable);
+
+ visitStatement(stmt.next, context);
return;
}
- bool isFirstOccurrence = (variableNames[stmt.variable] == null);
- bool isDeclaredHere = stmt.variable.host == currentElement;
- String name = getVariableName(stmt.variable);
- Expression definition = visitExpression(stmt.definition);
+ bool isFirstOccurrence = (context.variableNames[stmt.variable] == null);
+ bool isDeclaredHere = stmt.variable.host == context.currentElement;
+ String name = context.getVariableName(stmt.variable);
+ Expression definition = visitExpression(stmt.definition, context);
// Try to pull into initializer.
- if (firstStatement == stmt && isFirstOccurrence && isDeclaredHere) {
+ if (context.firstStatement == stmt && isFirstOccurrence && isDeclaredHere) {
if (isNullLiteral(definition)) definition = null;
- addDeclaration(stmt.variable, definition);
- firstStatement = stmt.next;
- visitStatement(stmt.next);
+ context.addDeclaration(stmt.variable, definition);
+ context.firstStatement = stmt.next;
+ visitStatement(stmt.next, context);
return;
}
@@ -443,125 +517,121 @@ class ASTEmitter extends tree.Visitor<dynamic, Expression> {
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);
+ context.declaredVariables.add(stmt.variable);
+ context.addStatement(new VariableDeclarations([decl]));
+ visitStatement(stmt.next, context);
return;
}
- statementBuffer.add(new ExpressionStatement(makeAssignment(
- visitVariable(stmt.variable),
+ context.addStatement(new ExpressionStatement(makeAssignment(
+ visitVariable(stmt.variable, context),
definition)));
- visitStatement(stmt.next);
+ visitStatement(stmt.next, context);
}
- void visitReturn(tree.Return stmt) {
- Expression inner = visitExpression(stmt.value);
- statementBuffer.add(new Return(inner));
+ @override
+ void visitReturn(tree.Return stmt,
+ BuilderContext<Statement> context) {
+ Expression inner = visitExpression(stmt.value, context);
+ context.addStatement(new Return(inner));
}
- void visitBreak(tree.Break stmt) {
- tree.Statement fall = fallthrough;
+ @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 {
- usedLabels.add(stmt.target);
- statementBuffer.add(new Break(stmt.target.name));
+ context.useLabel(stmt.target);
+ context.addStatement(new Break(stmt.target.name));
}
}
- void visitContinue(tree.Continue stmt) {
- tree.Statement fall = fallthrough;
+ @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 {
- usedLabels.add(stmt.target);
- statementBuffer.add(new Continue(stmt.target.name));
+ context.useLabel(stmt.target);
+ context.addStatement(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;
+ @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));
}
- 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;
+ @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);
}
- 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);
+ @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);
}
- Expression visitConstant(tree.Constant exp) {
- return emitConstant(exp.expression);
+ @override
+ Expression visitConstant(tree.Constant exp,
+ BuilderContext<Statement> context) {
+ return emitConstant(exp.expression, context);
}
- Expression visitThis(tree.This exp) {
+ @override
+ Expression visitThis(tree.This exp,
+ BuilderContext<Statement> context) {
return new This();
}
- Expression visitReifyTypeVar(tree.ReifyTypeVar exp) {
+ @override
+ Expression visitReifyTypeVar(tree.ReifyTypeVar exp,
+ BuilderContext<Statement> context) {
return new ReifyTypeVar(exp.typeVariable.name)
..element = exp.typeVariable;
}
- Expression visitLiteralList(tree.LiteralList exp) {
- return new LiteralList(
- exp.values.map(visitExpression).toList(growable: false),
+ 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: emitOptionalType(exp.type.typeArguments.single));
}
- Expression visitLiteralMap(tree.LiteralMap exp) {
+ @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),
- visitExpression(exp.entries[i].value)));
+ (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(createTypeAnnotation)
@@ -569,25 +639,30 @@ class ASTEmitter extends tree.Visitor<dynamic, Expression> {
return new LiteralMap(entries, typeArguments: typeArguments);
}
- Expression visitTypeOperator(tree.TypeOperator exp) {
- return new TypeOperator(visitExpression(exp.receiver),
+ @override
+ Expression visitTypeOperator(tree.TypeOperator exp,
+ BuilderContext<Statement> context) {
+ return new TypeOperator(visitExpression(exp.receiver, context),
exp.operator,
createTypeAnnotation(exp.type));
}
- List<Argument> emitArguments(tree.Invoke exp) {
+ List<Argument> emitArguments(tree.Invoke exp,
+ BuilderContext<Statement> context) {
List<tree.Expression> args = exp.arguments;
int positionalArgumentCount = exp.selector.positionalArgumentCount;
List<Argument> result = new List<Argument>.generate(positionalArgumentCount,
- (i) => visitExpression(exp.arguments[i]));
+ (i) => visitExpression(exp.arguments[i], context));
for (int i = 0; i < exp.selector.namedArgumentCount; ++i) {
result.add(new NamedArgument(exp.selector.namedArguments[i],
- visitExpression(exp.arguments[positionalArgumentCount + i])));
+ visitExpression(exp.arguments[positionalArgumentCount + i], context)));
}
return result;
}
- Expression visitInvokeStatic(tree.InvokeStatic exp) {
+ @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;
@@ -596,10 +671,11 @@ class ASTEmitter extends tree.Visitor<dynamic, Expression> {
return new Assignment(
new Identifier(exp.target.name)..element = exp.target,
'=',
- visitExpression(exp.arguments[0]));
+ visitExpression(exp.arguments[0], context));
case SelectorKind.CALL:
- return new CallStatic(null, exp.target.name, emitArguments(exp))
+ return new CallStatic(
+ null, exp.target.name, emitArguments(exp, context))
..element = exp.target;
default:
@@ -607,8 +683,9 @@ class ASTEmitter extends tree.Visitor<dynamic, Expression> {
}
}
- Expression emitMethodCall(tree.Invoke exp, Receiver receiver) {
- List<Argument> args = emitArguments(exp);
+ Expression emitMethodCall(tree.Invoke exp, Receiver receiver,
+ BuilderContext<Statement> context) {
+ List<Argument> args = emitArguments(exp, context);
switch (exp.selector.kind) {
case SelectorKind.CALL:
if (exp.selector.name == "call") {
@@ -646,17 +723,23 @@ class ASTEmitter extends tree.Visitor<dynamic, Expression> {
}
}
- Expression visitInvokeMethod(tree.InvokeMethod exp) {
- Expression receiver = visitExpression(exp.receiver);
- return emitMethodCall(exp, receiver);
+ @override
+ Expression visitInvokeMethod(tree.InvokeMethod exp,
+ BuilderContext<Statement> context) {
+ Expression receiver = visitExpression(exp.receiver, context);
+ return emitMethodCall(exp, receiver, context);
}
- Expression visitInvokeSuperMethod(tree.InvokeSuperMethod exp) {
- return emitMethodCall(exp, new SuperReceiver());
+ @override
+ Expression visitInvokeSuperMethod(tree.InvokeSuperMethod exp,
+ BuilderContext<Statement> context) {
+ return emitMethodCall(exp, new SuperReceiver(), context);
}
- Expression visitInvokeConstructor(tree.InvokeConstructor exp) {
- List args = emitArguments(exp);
+ @override
+ Expression visitInvokeConstructor(tree.InvokeConstructor exp,
+ BuilderContext<Statement> context) {
+ List args = emitArguments(exp, context);
FunctionElement constructor = exp.target;
String name = constructor.name.isEmpty ? null : constructor.name;
return new CallNew(createTypeAnnotation(exp.type),
@@ -667,63 +750,78 @@ class ASTEmitter extends tree.Visitor<dynamic, Expression> {
..dartType = exp.type;
}
- Expression visitConcatenateStrings(tree.ConcatenateStrings exp) {
- List args = exp.arguments.map(visitExpression).toList(growable:false);
- return new StringConcat(args);
+ @override
+ Expression visitConcatenateStrings(tree.ConcatenateStrings exp,
+ BuilderContext<Statement> context) {
+ return new StringConcat(visitExpressions(exp.arguments, context));
}
- Expression visitConditional(tree.Conditional exp) {
+ @override
+ Expression visitConditional(tree.Conditional exp,
+ BuilderContext<Statement> context) {
return new Conditional(
- visitExpression(exp.condition),
- visitExpression(exp.thenExpression),
- visitExpression(exp.elseExpression));
+ visitExpression(exp.condition, context),
+ visitExpression(exp.thenExpression, context),
+ visitExpression(exp.elseExpression, context));
}
- Expression visitLogicalOperator(tree.LogicalOperator exp) {
- return new BinaryOperator(visitExpression(exp.left),
+ @override
+ Expression visitLogicalOperator(tree.LogicalOperator exp,
+ BuilderContext<Statement> context) {
+ return new BinaryOperator(visitExpression(exp.left, context),
exp.operator,
- visitExpression(exp.right));
+ visitExpression(exp.right, context));
}
- Expression visitNot(tree.Not exp) {
- return new UnaryOperator('!', visitExpression(exp.operand));
+ @override
+ Expression visitNot(tree.Not exp,
+ BuilderContext<Statement> context) {
+ return new UnaryOperator('!', visitExpression(exp.operand, context));
}
- Expression visitVariable(tree.Variable exp) {
- return new Identifier(getVariableName(exp))
+ @override
+ Expression visitVariable(tree.Variable exp,
+ BuilderContext<Statement> context) {
+ return new Identifier(context.getVariableName(exp))
..element = exp.element;
}
- FunctionExpression makeSubFunction(tree.FunctionDefinition function) {
- return new ASTEmitter.inner(this).emit(function);
+ FunctionExpression makeSubFunction(tree.FunctionDefinition function,
+ BuilderContext<Statement> context) {
+ return emit(function, new BuilderContext<Statement>.inner(context));
}
- Expression visitFunctionExpression(tree.FunctionExpression exp) {
- return makeSubFunction(exp.definition)..name = null;
+ @override
+ Expression visitFunctionExpression(tree.FunctionExpression exp,
+ BuilderContext<Statement> context) {
+ return makeSubFunction(exp.definition, context)..name = null;
}
- void visitFunctionDeclaration(tree.FunctionDeclaration node) {
- assert(variableNames[node.variable] == null);
- String name = getVariableName(node.variable);
- FunctionExpression inner = makeSubFunction(node.definition);
+ @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);
- declaredVariables.add(node.variable);
- statementBuffer.add(decl);
- visitStatement(node.next);
+ context.declaredVariables.add(node.variable);
+ context.addStatement(decl);
+ visitStatement(node.next, context);
}
- /// 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,
+ BuilderContext<Statement> context) {
+ return const ConstantEmitter().visit(exp, context);
}
+}
- Expression emitConstant(ConstantExpression exp) {
- return new ConstantEmitter(this).visit(exp);
+/// Like [createTypeAnnotation] except the dynamic type is converted to null.
+TypeAnnotation emitOptionalType(DartType type) {
+ if (type.treatAsDynamic) {
+ return null;
+ } else {
+ return createTypeAnnotation(type);
}
}
@@ -753,9 +851,9 @@ TypeAnnotation createTypeAnnotation(DartType type) {
}
}
-class ConstantEmitter extends ConstantExpressionVisitor<Null, Expression> {
- ASTEmitter parent;
- ConstantEmitter(this.parent);
+class ConstantEmitter
+ extends ConstantExpressionVisitor<BuilderContext<Statement>, Expression> {
+ const ConstantEmitter();
Expression handlePrimitiveConstant(PrimitiveConstantValue value) {
// Num constants may be negative, while literals must be non-negative:
@@ -774,14 +872,21 @@ class ConstantEmitter extends ConstantExpressionVisitor<Null, Expression> {
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 visitPrimitive(PrimitiveConstantExpression exp, [_]) {
+ Expression visitPrimitive(PrimitiveConstantExpression 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, [_]) {
+ Expression negatedLiteral(NumConstantValue constant) {
assert(constant.primitiveValue.isNegative);
NumConstantValue positiveConstant;
if (constant.isInt) {
@@ -795,19 +900,21 @@ class ConstantEmitter extends ConstantExpressionVisitor<Null, Expression> {
}
@override
- Expression visitList(ListConstantExpression exp, [_]) {
+ Expression visitList(ListConstantExpression exp,
+ BuilderContext<Statement> context) {
return new LiteralList(
- exp.values.map(visit).toList(growable: false),
+ visitExpressions(exp.values, context),
isConst: true,
- typeArgument: parent.emitOptionalType(exp.type.typeArguments.single));
+ typeArgument: emitOptionalType(exp.type.typeArguments.single));
}
@override
- Expression visitMap(MapConstantExpression exp, [_]) {
+ Expression visitMap(MapConstantExpression exp,
+ BuilderContext<Statement> context) {
List<LiteralMapEntry> entries = new List<LiteralMapEntry>.generate(
exp.values.length,
- (i) => new LiteralMapEntry(visit(exp.keys[i]),
- visit(exp.values[i])));
+ (i) => new LiteralMapEntry(visit(exp.keys[i], context),
+ visit(exp.values[i], context)));
List<TypeAnnotation> typeArguments = exp.type.treatAsRaw
? null
: exp.type.typeArguments.map(createTypeAnnotation).toList();
@@ -815,14 +922,15 @@ class ConstantEmitter extends ConstantExpressionVisitor<Null, Expression> {
}
@override
- Expression visitConstructed(ConstructedConstantExpresssion exp, [_]) {
+ Expression visitConstructed(ConstructedConstantExpresssion exp,
+ BuilderContext<Statement> context) {
int positionalArgumentCount = exp.selector.positionalArgumentCount;
List<Argument> args = new List<Argument>.generate(
positionalArgumentCount,
- (i) => visit(exp.arguments[i]));
+ (i) => visit(exp.arguments[i], context));
for (int i = 0; i < exp.selector.namedArgumentCount; ++i) {
args.add(new NamedArgument(exp.selector.namedArguments[i],
- visit(exp.arguments[positionalArgumentCount + i])));
+ visit(exp.arguments[positionalArgumentCount + i], context)));
}
FunctionElement constructor = exp.target;
@@ -836,46 +944,54 @@ class ConstantEmitter extends ConstantExpressionVisitor<Null, Expression> {
}
@override
- Expression visitConcatenate(ConcatenateConstantExpression exp, [_]) {
- return new StringConcat(exp.arguments.map(visit).toList(growable: false));
+ Expression visitConcatenate(ConcatenateConstantExpression exp,
+ BuilderContext<Statement> context) {
+
+ return new StringConcat(visitExpressions(exp.arguments, context));
}
@override
- Expression visitSymbol(SymbolConstantExpression exp, [_]) {
+ Expression visitSymbol(SymbolConstantExpression exp,
+ BuilderContext<Statement> context) {
return new LiteralSymbol(exp.name);
}
@override
- Expression visitType(TypeConstantExpression exp, [_]) {
+ Expression visitType(TypeConstantExpression exp,
+ BuilderContext<Statement> context) {
DartType type = exp.type;
return new LiteralType(type.name)
..type = type;
}
@override
- Expression visitVariable(VariableConstantExpression exp, [_]) {
+ 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 = parent.getConstantName(element);
+ String name = context.getConstantName(element);
return new Identifier(name)
..element = element;
}
@override
- Expression visitFunction(FunctionConstantExpression exp, [_]) {
+ Expression visitFunction(FunctionConstantExpression exp,
+ BuilderContext<Statement> context) {
return new Identifier(exp.element.name)
..element = exp.element;
}
@override
- Expression visitBinary(BinaryConstantExpression exp, [_]) {
+ Expression visitBinary(BinaryConstantExpression exp,
+ BuilderContext<Statement> context) {
return handlePrimitiveConstant(exp.value);
}
@override
- Expression visitConditional(ConditionalConstantExpression exp, [_]) {
+ Expression visitConditional(ConditionalConstantExpression exp,
+ BuilderContext<Statement> context) {
if (exp.condition.value.isTrue) {
return exp.trueExp.accept(this);
} else {
@@ -884,7 +1000,8 @@ class ConstantEmitter extends ConstantExpressionVisitor<Null, Expression> {
}
@override
- Expression visitUnary(UnaryConstantExpression exp, [_]) {
+ Expression visitUnary(UnaryConstantExpression exp,
+ BuilderContext<Statement> context) {
return handlePrimitiveConstant(exp.value);
}
}
« no previous file with comments | « pkg/compiler/lib/src/constants/expressions.dart ('k') | pkg/compiler/lib/src/tree_ir/tree_ir_nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698