Index: lib/src/codegen/js_metalet.dart |
diff --git a/lib/src/codegen/js_metalet.dart b/lib/src/codegen/js_metalet.dart |
index ae239ed1de8831b1b5adb542218e0b1528a24152..8fcda050e1357f1b36d72e192453c4eb5b8579a2 100644 |
--- a/lib/src/codegen/js_metalet.dart |
+++ b/lib/src/codegen/js_metalet.dart |
@@ -41,7 +41,7 @@ class MetaLet extends Expression { |
final Map<String, Expression> variables; |
/// A list of expressions in the body. |
- /// Conceptually this is like a comma expression: the last value is returned. |
+ /// The last value should represent the returned value. |
final List<Expression> body; |
/// True if the final expression in [body] can be skipped in [toStatement]. |
@@ -120,15 +120,45 @@ class MetaLet extends Expression { |
return _finishStatement(statements); |
} |
- accept(NodeVisitor visitor) => toExpression().accept(visitor); |
+ accept(NodeVisitor visitor) { |
+ // TODO(jmesserly): we special case vistors from js_ast.Template, because it |
+ // doesn't know about MetaLet. Should we integrate directly? |
+ if (visitor is InstantiatorGeneratorVisitor) { |
+ return _templateVisitMetaLet(visitor); |
+ } else if (visitor is InterpolatedNodeAnalysis) { |
+ return visitor.visitNode(this); |
+ } else { |
+ return toExpression().accept(visitor); |
+ } |
+ } |
void visitChildren(NodeVisitor visitor) { |
- toExpression().visitChildren(visitor); |
+ // TODO(jmesserly): we special case vistors from js_ast.Template, because it |
+ // doesn't know about MetaLet. Should we integrate directly? |
+ if (visitor is InterpolatedNodeAnalysis || |
+ visitor is InstantiatorGeneratorVisitor) { |
+ variables.values.forEach((v) => v.accept(visitor)); |
+ body.forEach((v) => v.accept(visitor)); |
+ } else { |
+ toExpression().visitChildren(visitor); |
+ } |
} |
/// This generates as either a comma expression or a call. |
int get precedenceLevel => variables.isEmpty ? EXPRESSION : CALL; |
+ /// Patch to pretend [Template] supports visitMetaLet. |
+ Instantiator _templateVisitMetaLet(InstantiatorGeneratorVisitor visitor) { |
+ var valueInstantiators = variables.values.map(visitor.visit); |
+ var bodyInstantiators = body.map(visitor.visit); |
+ |
+ return (args) => new MetaLet( |
+ new Map.fromIterables( |
+ variables.keys, valueInstantiators.map((i) => i(args))), |
+ bodyInstantiators.map((i) => i(args)).toList(), |
+ statelessResult: statelessResult); |
+ } |
+ |
Expression _toInvokedFunction(Statement block) { |
var finder = new _YieldFinder(); |
block.accept(finder); |
@@ -209,7 +239,10 @@ class MetaLet extends Expression { |
String name = last.nameOrPosition; |
if (!variables.containsKey(name)) return null; |
- // Variables declared can't be used inside their initializer. |
+ // Variables declared can't be used inside their initializer, so make |
+ // sure we don't transform an assignment into an initializer. |
+ // If this already was a declaration, then we know it's legal, so we can |
+ // skip the check. |
if (!isDeclaration) { |
var finder = new _IdentFinder(left.name); |
for (var expr in body) { |