@@ -81,7 +81,8 @@ class CodeGenerator extends GeneralizingAstVisitor
81
81
82
82
final _privateNames =
83
83
new HashMap <LibraryElement , HashMap <String , JS .TemporaryId >>();
84
- final _temps = new HashMap <Element , JS .TemporaryId >();
84
+ final _initializingFormalTemps =
85
+ new HashMap <ParameterElement , JS .TemporaryId >();
85
86
86
87
final _dartxVar = new JS .Identifier ('dartx' );
87
88
final _runtimeLibVar = new JS .Identifier ('dart' );
@@ -1912,12 +1913,9 @@ class CodeGenerator extends GeneralizingAstVisitor
1912
1913
return _emitParameter (element);
1913
1914
}
1914
1915
1916
+ // If this is one of our compiler's temporary variables, return its JS form.
1915
1917
if (element is TemporaryVariableElement ) {
1916
- if (name[0 ] == '#' ) {
1917
- return new JS .InterpolatedExpression (name.substring (1 ));
1918
- } else {
1919
- return _getTemp (element, name);
1920
- }
1918
+ return element.jsVariable;
1921
1919
}
1922
1920
1923
1921
return new JS .Identifier (name);
@@ -1931,16 +1929,14 @@ class CodeGenerator extends GeneralizingAstVisitor
1931
1929
/// Rename private names so they don't shadow the private field symbol.
1932
1930
/// The renamer would handle this, but it would prefer to rename the
1933
1931
/// temporary used for the private symbol. Instead rename the parameter.
1934
- return _getTemp (element, '${element .name .substring (1 )}' );
1932
+ return _initializingFormalTemps.putIfAbsent (
1933
+ element, () => new JS .TemporaryId (element.name.substring (1 )));
1935
1934
}
1936
1935
1937
1936
var type = declaration ? emitTypeRef (element.type) : null ;
1938
1937
return new JS .Identifier (element.name, type: type);
1939
1938
}
1940
1939
1941
- JS .TemporaryId _getTemp (Element key, String name) =>
1942
- _temps.putIfAbsent (key, () => new JS .TemporaryId (name));
1943
-
1944
1940
List <Annotation > _parameterMetadata (FormalParameter p) =>
1945
1941
(p is NormalFormalParameter )
1946
1942
? p.metadata
@@ -2086,7 +2082,7 @@ class CodeGenerator extends GeneralizingAstVisitor
2086
2082
2087
2083
// Handle the left hand side, to ensure each of its subexpressions are
2088
2084
// evaluated only once.
2089
- var vars = < String , JS .Expression > {};
2085
+ var vars = < JS . MetaLetVariable , JS .Expression > {};
2090
2086
var x = _bindLeftHandSide (vars, left, context: left);
2091
2087
// Capture the result of evaluating the left hand side in a temp.
2092
2088
var t = _bindValue (vars, 't' , x, context: x);
@@ -2097,7 +2093,7 @@ class CodeGenerator extends GeneralizingAstVisitor
2097
2093
2098
2094
// Desugar `x += y` as `x = x + y`, ensuring that if `x` has subexpressions
2099
2095
// (for example, x is IndexExpression) we evaluate those once.
2100
- var vars = < String , JS .Expression > {};
2096
+ var vars = < JS . MetaLetVariable , JS .Expression > {};
2101
2097
var lhs = _bindLeftHandSide (vars, left, context: context);
2102
2098
var inc = AstBuilder .binaryExpression (lhs, op, right);
2103
2099
inc.staticElement = element;
@@ -2146,7 +2142,7 @@ class CodeGenerator extends GeneralizingAstVisitor
2146
2142
//
2147
2143
// However with MetaLet, we get clean code in statement or void context,
2148
2144
// or when one of the expressions is stateless, which seems common.
2149
- var vars = < String , JS .Expression > {};
2145
+ var vars = < JS . MetaLetVariable , JS .Expression > {};
2150
2146
var left = _bindValue (vars, 'l' , node.target);
2151
2147
var body = js.call ('# == null ? null : #' ,
2152
2148
[_visit (left), _emitSet (_stripNullAwareOp (node, left), right)]);
@@ -2722,7 +2718,7 @@ class CodeGenerator extends GeneralizingAstVisitor
2722
2718
// This should be a hint or warning for dead code.
2723
2719
if (! isNullable (left)) return _visit (left);
2724
2720
2725
- var vars = < String , JS .Expression > {};
2721
+ var vars = < JS . MetaLetVariable , JS .Expression > {};
2726
2722
// Desugar `l ?? r` as `l != null ? l : r`
2727
2723
var l = _visit (_bindValue (vars, 'l' , left, context: left));
2728
2724
return new JS .MetaLet (vars, [
@@ -2771,7 +2767,7 @@ class CodeGenerator extends GeneralizingAstVisitor
2771
2767
bool _isNull (Expression expr) => expr is NullLiteral ;
2772
2768
2773
2769
SimpleIdentifier _createTemporary (String name, DartType type,
2774
- {bool nullable: true }) {
2770
+ {bool nullable: true , JS . Expression variable }) {
2775
2771
// We use an invalid source location to signal that this is a temporary.
2776
2772
// See [_isTemporary].
2777
2773
// TODO(jmesserly): alternatives are
@@ -2781,7 +2777,10 @@ class CodeGenerator extends GeneralizingAstVisitor
2781
2777
// * create a new subtype of LocalVariableElementImpl to mark a temp.
2782
2778
var id =
2783
2779
new SimpleIdentifier (new StringToken (TokenType .IDENTIFIER , name, - 1 ));
2784
- id.staticElement = new TemporaryVariableElement .forNode (id);
2780
+
2781
+ variable ?? = new JS .TemporaryId (name);
2782
+
2783
+ id.staticElement = new TemporaryVariableElement .forNode (id, variable);
2785
2784
id.staticType = type;
2786
2785
DynamicInvoke .set (id, type.isDynamic);
2787
2786
addTemporaryVariable (id.staticElement, nullable: nullable);
@@ -2811,7 +2810,7 @@ class CodeGenerator extends GeneralizingAstVisitor
2811
2810
/// unless [expr] is a SimpleIdentifier, in which case a temporary is not
2812
2811
/// needed.
2813
2812
Expression _bindLeftHandSide (
2814
- Map <String , JS .Expression > scope, Expression expr,
2813
+ Map <JS . MetaLetVariable , JS .Expression > scope, Expression expr,
2815
2814
{Expression context}) {
2816
2815
Expression result;
2817
2816
if (expr is IndexExpression ) {
@@ -2855,14 +2854,15 @@ class CodeGenerator extends GeneralizingAstVisitor
2855
2854
/// variables), then the resulting code will be simplified automatically.
2856
2855
///
2857
2856
/// [scope] will be mutated to contain the new temporary's initialization.
2858
- Expression _bindValue (
2859
- Map < String , JS . Expression > scope, String name, Expression expr,
2857
+ Expression _bindValue (Map < JS . MetaLetVariable , JS . Expression > scope,
2858
+ String name, Expression expr,
2860
2859
{Expression context}) {
2861
2860
// No need to do anything for stateless expressions.
2862
2861
if (isStateless (_currentFunction, expr, context)) return expr;
2863
2862
2864
- var t = _createTemporary ('#$name ' , getStaticType (expr));
2865
- scope[name] = _visit (expr);
2863
+ var variable = new JS .MetaLetVariable (name);
2864
+ var t = _createTemporary (name, getStaticType (expr), variable: variable);
2865
+ scope[variable] = _visit (expr);
2866
2866
return t;
2867
2867
}
2868
2868
@@ -2900,7 +2900,7 @@ class CodeGenerator extends GeneralizingAstVisitor
2900
2900
2901
2901
// Handle the left hand side, to ensure each of its subexpressions are
2902
2902
// evaluated only once.
2903
- var vars = < String , JS .Expression > {};
2903
+ var vars = < JS . MetaLetVariable , JS .Expression > {};
2904
2904
var left = _bindLeftHandSide (vars, expr, context: expr);
2905
2905
2906
2906
// Desugar `x++` as `(x1 = x0 + 1, x0)` where `x0` is the original value
@@ -2927,7 +2927,7 @@ class CodeGenerator extends GeneralizingAstVisitor
2927
2927
return js.call ('$op #' , _visit (expr));
2928
2928
} else if (op.lexeme == '++' || op.lexeme == '--' ) {
2929
2929
// We need a null check, so the increment must be expanded out.
2930
- var vars = < String , JS .Expression > {};
2930
+ var vars = < JS . MetaLetVariable , JS .Expression > {};
2931
2931
var x = _bindLeftHandSide (vars, expr, context: expr);
2932
2932
2933
2933
var one = AstBuilder .integerLiteral (1 )..staticType = types.intType;
@@ -2960,7 +2960,7 @@ class CodeGenerator extends GeneralizingAstVisitor
2960
2960
JS .Node visitCascadeExpression (CascadeExpression node) {
2961
2961
var savedCascadeTemp = _cascadeTarget;
2962
2962
2963
- var vars = < String , JS .Expression > {};
2963
+ var vars = < JS . MetaLetVariable , JS .Expression > {};
2964
2964
_cascadeTarget = _bindValue (vars, '_' , node.target, context: node);
2965
2965
var sections = _visitList (node.cascadeSections) as List <JS .Expression >;
2966
2966
sections.add (_visit (_cascadeTarget));
@@ -3779,7 +3779,9 @@ JS.LiteralString _propertyName(String name) => js.string(name, "'");
3779
3779
/// variable. These objects use instance equality, and should be shared
3780
3780
/// everywhere in the tree where they are treated as the same variable.
3781
3781
class TemporaryVariableElement extends LocalVariableElementImpl {
3782
- TemporaryVariableElement .forNode (Identifier name) : super .forNode (name);
3782
+ final JS .Expression jsVariable;
3783
+ TemporaryVariableElement .forNode (Identifier name, this .jsVariable)
3784
+ : super .forNode (name);
3783
3785
3784
3786
int get hashCode => identityHashCode (this );
3785
3787
bool operator == (Object other) => identical (this , other);
0 commit comments