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

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

Issue 1088493002: Assignment expressions in tree IR. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 8 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 4131146bf82a0f6d21ab6d99f2932731ec78073d..12b7ad23f3d6dd23c1f17f7079f6e7e7d7584f39 100644
--- a/pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend_ast_emitter.dart
@@ -142,6 +142,25 @@ class BuilderContext<T> {
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) {
@@ -301,11 +320,7 @@ class ASTEmitter
// 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 context.variableNames.keys) {
- if (!context.declaredVariables.contains(variable)) {
- context.addDeclaration(variable);
- }
- }
+ context.declareRemainingVariables();
// Add constant declarations.
List<VariableDeclaration> constants = <VariableDeclaration>[];
@@ -370,12 +385,7 @@ class ASTEmitter
// 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 context.variableNames.keys) {
- if (!context.declaredVariables.contains(variable) &&
- !context.handlerVariables.contains(variable)) {
- context.addDeclaration(variable);
- }
- }
+ context.declareRemainingVariables();
// Add constant declarations.
List<VariableDeclaration> constants = <VariableDeclaration>[];
@@ -498,13 +508,28 @@ class ASTEmitter
@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);
@@ -515,58 +540,45 @@ class ASTEmitter
bool isNullLiteral(Expression exp) => exp is Literal && exp.value.isNull;
- @override
- void visitAssign(tree.Assign stmt,
- BuilderContext<Statement> context) {
+ 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 (stmt.variable.element is FunctionElement &&
- stmt.value is tree.FunctionExpression &&
- !context.declaredVariables.contains(stmt.variable) &&
- stmt.variable.writeCount == 1) {
- tree.FunctionExpression functionExp = stmt.value;
+ 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(stmt.variable);
+ context.declaredVariables.add(assign.variable);
- visitStatement(stmt.next, context);
+ visitStatement(statement.next, context);
return;
}
- bool isFirstOccurrence = (context.variableNames[stmt.variable] == null);
- bool isDeclaredHere = stmt.variable.host == context.currentElement;
- String name = context.getVariableName(stmt.variable);
- Expression definition = visitExpression(stmt.value, context);
+ 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;
+ String name = context.getVariableName(assign.variable);
// Try to pull into initializer.
- if (context.firstStatement == stmt && isFirstOccurrence && isDeclaredHere) {
+ if (isFirstStatement && isFirstOccurrence && isDeclaredHere) {
if (isNullLiteral(definition)) definition = null;
- context.addDeclaration(stmt.variable, definition);
- context.firstStatement = stmt.next;
- visitStatement(stmt.next, context);
- return;
- }
-
- // Emit a variable declaration if we are required to do so.
- // For captured variables, this ensures that a fresh 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;
- context.declaredVariables.add(stmt.variable);
- context.addStatement(new VariableDeclarations([decl]));
- visitStatement(stmt.next, context);
+ context.addDeclaration(assign.variable, definition);
+ context.firstStatement = statement.next;
+ visitStatement(statement.next, context);
return;
}
context.addStatement(new ExpressionStatement(makeAssignment(
- context.makeVariableAccess(stmt.variable),
+ context.makeVariableAccess(assign.variable),
definition)));
- visitStatement(stmt.next, context);
+ visitStatement(statement.next, context);
}
@override
@@ -653,6 +665,7 @@ class ASTEmitter
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);
@@ -878,6 +891,14 @@ class ASTEmitter
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,
@@ -907,10 +928,12 @@ class ASTEmitter
BuilderContext context) {
Kevin Millikin (Google) 2015/04/14 08:41:00 Goofy indentation here.
asgerf 2015/04/14 10:12:14 Fixed
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)) {
+ if (!context.declaredVariables.contains(variable) &&
+ !inner.declaredVariables.contains(variable)) {
inner.addDeclaration(variable);
}
}
@@ -1290,7 +1313,10 @@ class UnshadowParameters extends tree.RecursiveVisitor {
param.element);
definition.parameters[i] = newParam;
definition.replaceEachBody((tree.Statement body) {
- return new tree.Assign(param, new tree.VariableUse(newParam), 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.

Powered by Google App Engine
This is Rietveld 408576698