Chromium Code Reviews| Index: lib/src/compiler/code_generator.dart |
| diff --git a/lib/src/compiler/code_generator.dart b/lib/src/compiler/code_generator.dart |
| index a45ce215ce5ed0313a5f76def2feb2a1f76eeba1..a309a490dff36a92604d1b71430ff3f05fb23933 100644 |
| --- a/lib/src/compiler/code_generator.dart |
| +++ b/lib/src/compiler/code_generator.dart |
| @@ -81,7 +81,8 @@ class CodeGenerator extends GeneralizingAstVisitor |
| final _privateNames = |
| new HashMap<LibraryElement, HashMap<String, JS.TemporaryId>>(); |
| - final _temps = new HashMap<Element, JS.TemporaryId>(); |
| + final _initializingFormalTemps = |
| + new HashMap<ParameterElement, JS.TemporaryId>(); |
| final _dartxVar = new JS.Identifier('dartx'); |
| final _runtimeLibVar = new JS.Identifier('dart'); |
| @@ -1913,11 +1914,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
| } |
| if (element is TemporaryVariableElement) { |
| - if (name[0] == '#') { |
| - return new JS.InterpolatedExpression(name.substring(1)); |
| - } else { |
| - return _getTemp(element, name); |
| - } |
| + return element.variable; |
|
vsm
2016/04/21 21:50:48
This doesn't match the return type of this functio
Jennifer Messerly
2016/04/21 21:53:25
JS.Expression visitSimpleIdentifier ... and we're
vsm
2016/04/21 22:06:22
Oh, I missed that TemporaryVariableElement is our
|
| } |
| return new JS.Identifier(name); |
| @@ -1931,16 +1928,14 @@ class CodeGenerator extends GeneralizingAstVisitor |
| /// Rename private names so they don't shadow the private field symbol. |
| /// The renamer would handle this, but it would prefer to rename the |
| /// temporary used for the private symbol. Instead rename the parameter. |
| - return _getTemp(element, '${element.name.substring(1)}'); |
| + return _initializingFormalTemps.putIfAbsent( |
| + element, () => new JS.TemporaryId(element.name.substring(1))); |
| } |
| var type = declaration ? emitTypeRef(element.type) : null; |
| return new JS.Identifier(element.name, type: type); |
| } |
| - JS.TemporaryId _getTemp(Element key, String name) => |
| - _temps.putIfAbsent(key, () => new JS.TemporaryId(name)); |
| - |
| List<Annotation> _parameterMetadata(FormalParameter p) => |
| (p is NormalFormalParameter) |
| ? p.metadata |
| @@ -2086,7 +2081,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
| // Handle the left hand side, to ensure each of its subexpressions are |
| // evaluated only once. |
| - var vars = <String, JS.Expression>{}; |
| + var vars = <JS.MetaLetVariable, JS.Expression>{}; |
| var x = _bindLeftHandSide(vars, left, context: left); |
| // Capture the result of evaluating the left hand side in a temp. |
| var t = _bindValue(vars, 't', x, context: x); |
| @@ -2097,7 +2092,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
| // Desugar `x += y` as `x = x + y`, ensuring that if `x` has subexpressions |
| // (for example, x is IndexExpression) we evaluate those once. |
| - var vars = <String, JS.Expression>{}; |
| + var vars = <JS.MetaLetVariable, JS.Expression>{}; |
| var lhs = _bindLeftHandSide(vars, left, context: context); |
| var inc = AstBuilder.binaryExpression(lhs, op, right); |
| inc.staticElement = element; |
| @@ -2146,7 +2141,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
| // |
| // However with MetaLet, we get clean code in statement or void context, |
| // or when one of the expressions is stateless, which seems common. |
| - var vars = <String, JS.Expression>{}; |
| + var vars = <JS.MetaLetVariable, JS.Expression>{}; |
| var left = _bindValue(vars, 'l', node.target); |
| var body = js.call('# == null ? null : #', |
| [_visit(left), _emitSet(_stripNullAwareOp(node, left), right)]); |
| @@ -2722,7 +2717,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
| // This should be a hint or warning for dead code. |
| if (!isNullable(left)) return _visit(left); |
| - var vars = <String, JS.Expression>{}; |
| + var vars = <JS.MetaLetVariable, JS.Expression>{}; |
| // Desugar `l ?? r` as `l != null ? l : r` |
| var l = _visit(_bindValue(vars, 'l', left, context: left)); |
| return new JS.MetaLet(vars, [ |
| @@ -2771,7 +2766,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
| bool _isNull(Expression expr) => expr is NullLiteral; |
| SimpleIdentifier _createTemporary(String name, DartType type, |
| - {bool nullable: true}) { |
| + {bool nullable: true, JS.Expression variable}) { |
| // We use an invalid source location to signal that this is a temporary. |
| // See [_isTemporary]. |
| // TODO(jmesserly): alternatives are |
| @@ -2781,7 +2776,10 @@ class CodeGenerator extends GeneralizingAstVisitor |
| // * create a new subtype of LocalVariableElementImpl to mark a temp. |
| var id = |
| new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, name, -1)); |
| - id.staticElement = new TemporaryVariableElement.forNode(id); |
| + |
| + variable ??= new JS.TemporaryId(name); |
| + |
| + id.staticElement = new TemporaryVariableElement.forNode(id, variable); |
| id.staticType = type; |
| DynamicInvoke.set(id, type.isDynamic); |
| addTemporaryVariable(id.staticElement, nullable: nullable); |
| @@ -2811,7 +2809,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
| /// unless [expr] is a SimpleIdentifier, in which case a temporary is not |
| /// needed. |
| Expression _bindLeftHandSide( |
| - Map<String, JS.Expression> scope, Expression expr, |
| + Map<JS.MetaLetVariable, JS.Expression> scope, Expression expr, |
| {Expression context}) { |
| Expression result; |
| if (expr is IndexExpression) { |
| @@ -2855,14 +2853,15 @@ class CodeGenerator extends GeneralizingAstVisitor |
| /// variables), then the resulting code will be simplified automatically. |
| /// |
| /// [scope] will be mutated to contain the new temporary's initialization. |
| - Expression _bindValue( |
| - Map<String, JS.Expression> scope, String name, Expression expr, |
| + Expression _bindValue(Map<JS.MetaLetVariable, JS.Expression> scope, |
| + String name, Expression expr, |
| {Expression context}) { |
| // No need to do anything for stateless expressions. |
| if (isStateless(_currentFunction, expr, context)) return expr; |
| - var t = _createTemporary('#$name', getStaticType(expr)); |
| - scope[name] = _visit(expr); |
| + var variable = new JS.MetaLetVariable(name); |
| + var t = _createTemporary(name, getStaticType(expr), variable: variable); |
| + scope[variable] = _visit(expr); |
| return t; |
| } |
| @@ -2900,7 +2899,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
| // Handle the left hand side, to ensure each of its subexpressions are |
| // evaluated only once. |
| - var vars = <String, JS.Expression>{}; |
| + var vars = <JS.MetaLetVariable, JS.Expression>{}; |
| var left = _bindLeftHandSide(vars, expr, context: expr); |
| // Desugar `x++` as `(x1 = x0 + 1, x0)` where `x0` is the original value |
| @@ -2927,7 +2926,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
| return js.call('$op#', _visit(expr)); |
| } else if (op.lexeme == '++' || op.lexeme == '--') { |
| // We need a null check, so the increment must be expanded out. |
| - var vars = <String, JS.Expression>{}; |
| + var vars = <JS.MetaLetVariable, JS.Expression>{}; |
| var x = _bindLeftHandSide(vars, expr, context: expr); |
| var one = AstBuilder.integerLiteral(1)..staticType = types.intType; |
| @@ -2960,7 +2959,7 @@ class CodeGenerator extends GeneralizingAstVisitor |
| JS.Node visitCascadeExpression(CascadeExpression node) { |
| var savedCascadeTemp = _cascadeTarget; |
| - var vars = <String, JS.Expression>{}; |
| + var vars = <JS.MetaLetVariable, JS.Expression>{}; |
| _cascadeTarget = _bindValue(vars, '_', node.target, context: node); |
| var sections = _visitList(node.cascadeSections) as List<JS.Expression>; |
| sections.add(_visit(_cascadeTarget)); |
| @@ -3779,7 +3778,9 @@ JS.LiteralString _propertyName(String name) => js.string(name, "'"); |
| /// variable. These objects use instance equality, and should be shared |
| /// everywhere in the tree where they are treated as the same variable. |
| class TemporaryVariableElement extends LocalVariableElementImpl { |
| - TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| + final JS.Expression variable; |
| + TemporaryVariableElement.forNode(Identifier name, this.variable) |
| + : super.forNode(name); |
| int get hashCode => identityHashCode(this); |
| bool operator ==(Object other) => identical(this, other); |