Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of js; | 5 part of js; |
| 6 | 6 |
| 7 class TemplateManager { | 7 class TemplateManager { |
| 8 Map<String, Template> expressionTemplates = new Map<String, Template>(); | 8 Map<String, Template> expressionTemplates = new Map<String, Template>(); |
| 9 Map<String, Template> statementTemplates = new Map<String, Template>(); | 9 Map<String, Template> statementTemplates = new Map<String, Template>(); |
| 10 | 10 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 83 return generator.analysis.count == 0; | 83 return generator.analysis.count == 0; |
| 84 } | 84 } |
| 85 | 85 |
| 86 void _compile() { | 86 void _compile() { |
| 87 InstantiatorGeneratorVisitor generator = | 87 InstantiatorGeneratorVisitor generator = |
| 88 new InstantiatorGeneratorVisitor(forceCopy); | 88 new InstantiatorGeneratorVisitor(forceCopy); |
| 89 instantiator = generator.compile(ast); | 89 instantiator = generator.compile(ast); |
| 90 positionalArgumentCount = generator.analysis.count; | 90 positionalArgumentCount = generator.analysis.count; |
| 91 } | 91 } |
| 92 | 92 |
| 93 Node instantiate(List arguments) { | 93 /// Instantiates the template with the given [arguments]. |
| 94 /// | |
| 95 /// This method fills in the holes with the given arguments. The [arguments] | |
| 96 /// must be either a [List] or a [Map]. | |
| 97 Node instantiate(var arguments) { | |
| 94 if (arguments is List) { | 98 if (arguments is List) { |
| 95 if (arguments.length != positionalArgumentCount) { | 99 if (arguments.length != positionalArgumentCount) { |
| 96 throw 'Wrong number of template arguments, given ${arguments.length}, ' | 100 throw 'Wrong number of template arguments, given ${arguments.length}, ' |
| 97 'expected $positionalArgumentCount'; | 101 'expected $positionalArgumentCount'; |
| 98 } | 102 } |
| 99 return instantiator(arguments); | 103 return instantiator(arguments); |
| 100 } | 104 } |
| 101 // TODO(sra): Add named placeholders and a Map of arguments. | 105 assert(arguments is Map); |
|
sra1
2014/10/22 21:50:28
It might be nice to collect the set of names in th
floitsch
2014/11/03 18:12:58
Done.
| |
| 102 throw new UnimplementedError('Template arguments must be a list'); | 106 return instantiator(arguments); |
| 103 } | 107 } |
| 104 } | 108 } |
| 105 | 109 |
| 106 /** | 110 /** |
| 107 * An Instantiator is a Function that generates a JS AST tree or List of | 111 * An Instantiator is a Function that generates a JS AST tree or List of |
| 108 * trees. [arguments] is a List for positional templates, or (TODO) Map for | 112 * trees. [arguments] is a List for positional templates, or Map for |
| 109 * named templates. | 113 * named templates. |
| 110 */ | 114 */ |
| 111 typedef Node Instantiator(var arguments); | 115 typedef Node Instantiator(var arguments); |
| 112 | 116 |
| 113 | 117 |
| 114 /** | 118 /** |
| 115 * InstantiatorGeneratorVisitor compiles a template. This class compiles a tree | 119 * InstantiatorGeneratorVisitor compiles a template. This class compiles a tree |
| 116 * containing [InterpolatedNode]s into a function that will create a copy of the | 120 * containing [InterpolatedNode]s into a function that will create a copy of the |
| 117 * tree with the interpolated nodes substituted with provided values. | 121 * tree with the interpolated nodes substituted with provided values. |
| 118 */ | 122 */ |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 } | 166 } |
| 163 | 167 |
| 164 static RegExp identiferRE = new RegExp(r'^[A-Za-z_$][A-Za-z_$0-9]*$'); | 168 static RegExp identiferRE = new RegExp(r'^[A-Za-z_$][A-Za-z_$0-9]*$'); |
| 165 | 169 |
| 166 static Expression convertStringToVariableUse(String value) { | 170 static Expression convertStringToVariableUse(String value) { |
| 167 assert(identiferRE.hasMatch(value)); | 171 assert(identiferRE.hasMatch(value)); |
| 168 return new VariableUse(value); | 172 return new VariableUse(value); |
| 169 } | 173 } |
| 170 | 174 |
| 171 Instantiator visitInterpolatedExpression(InterpolatedExpression node) { | 175 Instantiator visitInterpolatedExpression(InterpolatedExpression node) { |
| 172 int position = node.name; | 176 var name = node.name; |
| 173 return (arguments) { | 177 return (arguments) { |
| 174 var value = arguments[position]; | 178 var value = arguments[name]; |
| 175 if (value is Expression) return value; | 179 if (value is Expression) return value; |
| 176 if (value is String) return convertStringToVariableUse(value);; | 180 if (value is String) return convertStringToVariableUse(value);; |
| 177 error('Interpolated value #$position is not an Expression: $value'); | 181 error('Interpolated value #$name is not an Expression: $value'); |
| 178 }; | 182 }; |
| 179 } | 183 } |
| 180 | 184 |
| 181 Instantiator visitSplayableExpression(Node node) { | 185 Instantiator visitSplayableExpression(Node node) { |
| 182 if (node is InterpolatedExpression) { | 186 if (node is InterpolatedExpression) { |
| 183 int position = node.name; | 187 var name = node.name; |
| 184 return (arguments) { | 188 return (arguments) { |
| 185 var value = arguments[position]; | 189 var value = arguments[name]; |
| 186 Expression toExpression(item) { | 190 Expression toExpression(item) { |
| 187 if (item is Expression) return item; | 191 if (item is Expression) return item; |
| 188 if (item is String) return convertStringToVariableUse(item); | 192 if (item is String) return convertStringToVariableUse(item); |
| 189 return error('Interpolated value #$position is not ' | 193 return error('Interpolated value #$name is not ' |
| 190 'an Expression or List of Expressions: $value'); | 194 'an Expression or List of Expressions: $value'); |
| 191 } | 195 } |
| 192 if (value is Iterable) return value.map(toExpression); | 196 if (value is Iterable) return value.map(toExpression); |
| 193 return toExpression(value); | 197 return toExpression(value); |
| 194 }; | 198 }; |
| 195 } | 199 } |
| 196 return visit(node); | 200 return visit(node); |
| 197 } | 201 } |
| 198 | 202 |
| 199 Instantiator visitInterpolatedLiteral(InterpolatedLiteral node) { | 203 Instantiator visitInterpolatedLiteral(InterpolatedLiteral node) { |
| 200 int position = node.name; | 204 var name = node.name; |
| 201 return (arguments) { | 205 return (arguments) { |
| 202 var value = arguments[position]; | 206 var value = arguments[name]; |
| 203 if (value is Literal) return value; | 207 if (value is Literal) return value; |
| 204 error('Interpolated value #$position is not a Literal: $value'); | 208 error('Interpolated value #$name is not a Literal: $value'); |
| 205 }; | 209 }; |
| 206 } | 210 } |
| 207 | 211 |
| 208 Instantiator visitInterpolatedParameter(InterpolatedParameter node) { | 212 Instantiator visitInterpolatedParameter(InterpolatedParameter node) { |
| 209 int position = node.name; | 213 var name = node.name; |
| 210 return (arguments) { | 214 return (arguments) { |
| 211 var value = arguments[position]; | 215 var value = arguments[name]; |
| 212 | 216 |
| 213 Parameter toParameter(item) { | 217 Parameter toParameter(item) { |
| 214 if (item is Parameter) return item; | 218 if (item is Parameter) return item; |
| 215 if (item is String) return new Parameter(item); | 219 if (item is String) return new Parameter(item); |
| 216 return error('Interpolated value #$position is not a Parameter or ' | 220 return error('Interpolated value #$name is not a Parameter or ' |
| 217 'List of Parameters: $value'); | 221 'List of Parameters: $value'); |
| 218 } | 222 } |
| 219 if (value is Iterable) return value.map(toParameter); | 223 if (value is Iterable) return value.map(toParameter); |
| 220 return toParameter(value); | 224 return toParameter(value); |
| 221 }; | 225 }; |
| 222 } | 226 } |
| 223 | 227 |
| 224 Instantiator visitInterpolatedSelector(InterpolatedSelector node) { | 228 Instantiator visitInterpolatedSelector(InterpolatedSelector node) { |
| 225 // A selector is an expression, as in `a[selector]`. | 229 // A selector is an expression, as in `a[selector]`. |
| 226 // A String argument converted into a LiteralString, so `a.#` with argument | 230 // A String argument converted into a LiteralString, so `a.#` with argument |
| 227 // 'foo' generates `a["foo"]` which prints as `a.foo`. | 231 // 'foo' generates `a["foo"]` which prints as `a.foo`. |
| 228 int position = node.name; | 232 var name = node.name; |
| 229 return (arguments) { | 233 return (arguments) { |
| 230 var value = arguments[position]; | 234 var value = arguments[name]; |
| 231 if (value is Expression) return value; | 235 if (value is Expression) return value; |
| 232 if (value is String) return new LiteralString('"$value"'); | 236 if (value is String) return new LiteralString('"$value"'); |
| 233 error('Interpolated value #$position is not a selector: $value'); | 237 error('Interpolated value #$name is not a selector: $value'); |
| 234 }; | 238 }; |
| 235 } | 239 } |
| 236 | 240 |
| 237 Instantiator visitInterpolatedStatement(InterpolatedStatement node) { | 241 Instantiator visitInterpolatedStatement(InterpolatedStatement node) { |
| 238 int position = node.name; | 242 var name = node.name; |
| 239 return (arguments) { | 243 return (arguments) { |
| 240 var value = arguments[position]; | 244 var value = arguments[name]; |
| 241 if (value is Node) return value.toStatement(); | 245 if (value is Node) return value.toStatement(); |
| 242 error('Interpolated value #$position is not a Statement: $value'); | 246 error('Interpolated value #$name is not a Statement: $value'); |
| 243 }; | 247 }; |
| 244 } | 248 } |
| 245 | 249 |
| 246 Instantiator visitSplayableStatement(Node node) { | 250 Instantiator visitSplayableStatement(Node node) { |
| 247 if (node is InterpolatedStatement) { | 251 if (node is InterpolatedStatement) { |
| 248 int position = node.name; | 252 var name = node.name; |
| 249 return (arguments) { | 253 return (arguments) { |
| 250 var value = arguments[position]; | 254 var value = arguments[name]; |
| 251 Statement toStatement(item) { | 255 Statement toStatement(item) { |
| 252 if (item is Statement) return item; | 256 if (item is Statement) return item; |
| 253 if (item is Expression) return item.toStatement();; | 257 if (item is Expression) return item.toStatement();; |
| 254 return error('Interpolated value #$position is not ' | 258 return error('Interpolated value #$name is not ' |
| 255 'a Statement or List of Statements: $value'); | 259 'a Statement or List of Statements: $value'); |
| 256 } | 260 } |
| 257 if (value is Iterable) return value.map(toStatement); | 261 if (value is Iterable) return value.map(toStatement); |
| 258 return toStatement(value); | 262 return toStatement(value); |
| 259 }; | 263 }; |
| 260 } | 264 } |
| 261 return visit(node); | 265 return visit(node); |
| 262 } | 266 } |
| 263 | 267 |
| 264 Instantiator visitProgram(Program node) { | 268 Instantiator visitProgram(Program node) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 315 if (node.condition is InterpolatedExpression) { | 319 if (node.condition is InterpolatedExpression) { |
| 316 return visitIfConditionalCompilation(node); | 320 return visitIfConditionalCompilation(node); |
| 317 } else { | 321 } else { |
| 318 return visitIfNormal(node); | 322 return visitIfNormal(node); |
| 319 } | 323 } |
| 320 } | 324 } |
| 321 | 325 |
| 322 Instantiator visitIfConditionalCompilation(If node) { | 326 Instantiator visitIfConditionalCompilation(If node) { |
| 323 // Special version of visitInterpolatedExpression that permits bools. | 327 // Special version of visitInterpolatedExpression that permits bools. |
| 324 compileCondition(InterpolatedExpression node) { | 328 compileCondition(InterpolatedExpression node) { |
| 325 int position = node.name; | 329 var name = node.name; |
| 326 return (arguments) { | 330 return (arguments) { |
| 327 var value = arguments[position]; | 331 var value = arguments[name]; |
| 328 if (value is bool) return value; | 332 if (value is bool) return value; |
| 329 if (value is Expression) return value; | 333 if (value is Expression) return value; |
| 330 if (value is String) return convertStringToVariableUse(value);; | 334 if (value is String) return convertStringToVariableUse(value);; |
| 331 error('Interpolated value #$position is not an Expression: $value'); | 335 error('Interpolated value #$name is not an Expression: $value'); |
| 332 }; | 336 }; |
| 333 } | 337 } |
| 334 var makeCondition = compileCondition(node.condition); | 338 var makeCondition = compileCondition(node.condition); |
| 335 Instantiator makeThen = visit(node.then); | 339 Instantiator makeThen = visit(node.then); |
| 336 Instantiator makeOtherwise = visit(node.otherwise); | 340 Instantiator makeOtherwise = visit(node.otherwise); |
| 337 return (arguments) { | 341 return (arguments) { |
| 338 var condition = makeCondition(arguments); | 342 var condition = makeCondition(arguments); |
| 339 if (condition is bool) { | 343 if (condition is bool) { |
| 340 if (condition == true) { | 344 if (condition == true) { |
| 341 return makeThen(arguments); | 345 return makeThen(arguments); |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 671 if (count != before) containsInterpolatedNode.add(node); | 675 if (count != before) containsInterpolatedNode.add(node); |
| 672 return null; | 676 return null; |
| 673 } | 677 } |
| 674 | 678 |
| 675 visitInterpolatedNode(InterpolatedNode node) { | 679 visitInterpolatedNode(InterpolatedNode node) { |
| 676 interpolatedNodes.add(node); | 680 interpolatedNodes.add(node); |
| 677 containsInterpolatedNode.add(node); | 681 containsInterpolatedNode.add(node); |
| 678 ++count; | 682 ++count; |
| 679 } | 683 } |
| 680 } | 684 } |
| OLD | NEW |