OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 class Interceptors { | 5 class Interceptors { |
6 Compiler compiler; | 6 Compiler compiler; |
7 Interceptors(Compiler this.compiler); | 7 Interceptors(Compiler this.compiler); |
8 | 8 |
9 SourceString mapOperatorToMethodName(Operator op) { | 9 SourceString mapOperatorToMethodName(Operator op) { |
10 String name = op.source.stringValue; | 10 String name = op.source.stringValue; |
(...skipping 2572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2583 void visitLiteralString(LiteralString node) { | 2583 void visitLiteralString(LiteralString node) { |
2584 stack.add(graph.addConstantString(node.dartString, node)); | 2584 stack.add(graph.addConstantString(node.dartString, node)); |
2585 } | 2585 } |
2586 | 2586 |
2587 void visitStringJuxtaposition(StringJuxtaposition node) { | 2587 void visitStringJuxtaposition(StringJuxtaposition node) { |
2588 if (!node.isInterpolation) { | 2588 if (!node.isInterpolation) { |
2589 // This is a simple string with no interpolations. | 2589 // This is a simple string with no interpolations. |
2590 stack.add(graph.addConstantString(node.dartString, node)); | 2590 stack.add(graph.addConstantString(node.dartString, node)); |
2591 return; | 2591 return; |
2592 } | 2592 } |
2593 int offset = node.getBeginToken().charOffset; | 2593 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this); |
2594 StringBuilderVisitor stringBuilder = | |
2595 new StringBuilderVisitor(this, offset); | |
2596 stringBuilder.visit(node); | 2594 stringBuilder.visit(node); |
2597 stack.add(stringBuilder.result(node)); | 2595 stack.add(stringBuilder.result(node)); |
2598 } | 2596 } |
2599 | 2597 |
2600 void visitLiteralNull(LiteralNull node) { | 2598 void visitLiteralNull(LiteralNull node) { |
2601 stack.add(graph.addConstantNull()); | 2599 stack.add(graph.addConstantNull()); |
2602 } | 2600 } |
2603 | 2601 |
2604 visitNodeList(NodeList node) { | 2602 visitNodeList(NodeList node) { |
2605 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { | 2603 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2737 open(joinBlock); | 2735 open(joinBlock); |
2738 | 2736 |
2739 localsHandler.mergeWith(thenLocals, joinBlock); | 2737 localsHandler.mergeWith(thenLocals, joinBlock); |
2740 HPhi phi = new HPhi.manyInputs(null, | 2738 HPhi phi = new HPhi.manyInputs(null, |
2741 <HInstruction>[thenInstruction, elseInstruction]); | 2739 <HInstruction>[thenInstruction, elseInstruction]); |
2742 joinBlock.addPhi(phi); | 2740 joinBlock.addPhi(phi); |
2743 stack.add(phi); | 2741 stack.add(phi); |
2744 } | 2742 } |
2745 | 2743 |
2746 visitStringInterpolation(StringInterpolation node) { | 2744 visitStringInterpolation(StringInterpolation node) { |
2747 int offset = node.getBeginToken().charOffset; | 2745 StringBuilderVisitor stringBuilder = new StringBuilderVisitor(this); |
2748 StringBuilderVisitor stringBuilder = | |
2749 new StringBuilderVisitor(this, offset); | |
2750 stringBuilder.visit(node); | 2746 stringBuilder.visit(node); |
2751 stack.add(stringBuilder.result(node)); | 2747 stack.add(stringBuilder.result(node)); |
2752 } | 2748 } |
2753 | 2749 |
2754 visitStringInterpolationPart(StringInterpolationPart node) { | 2750 visitStringInterpolationPart(StringInterpolationPart node) { |
2755 // The parts are iterated in visitStringInterpolation. | 2751 // The parts are iterated in visitStringInterpolation. |
2756 compiler.internalError('visitStringInterpolation should not be called', | 2752 compiler.internalError('visitStringInterpolation should not be called', |
2757 node: node); | 2753 node: node); |
2758 } | 2754 } |
2759 | 2755 |
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3283 | 3279 |
3284 /** | 3280 /** |
3285 * Visitor that handles generation of string literals (LiteralString, | 3281 * Visitor that handles generation of string literals (LiteralString, |
3286 * StringInterpolation), and otherwise delegates to the given visitor for | 3282 * StringInterpolation), and otherwise delegates to the given visitor for |
3287 * non-literal subexpressions. | 3283 * non-literal subexpressions. |
3288 * TODO(lrn): Consider whether to handle compile time constant int/boolean | 3284 * TODO(lrn): Consider whether to handle compile time constant int/boolean |
3289 * expressions as well. | 3285 * expressions as well. |
3290 */ | 3286 */ |
3291 class StringBuilderVisitor extends AbstractVisitor { | 3287 class StringBuilderVisitor extends AbstractVisitor { |
3292 final SsaBuilder builder; | 3288 final SsaBuilder builder; |
3293 final Element stringConcat; | |
3294 final Element stringToString; | |
3295 | 3289 |
3296 /** | 3290 /** |
3297 * Offset used for the synthetic operator token used by concat. | 3291 * The string value generated so far. |
3298 * Can probably be removed when we stop using String.operator+. | |
3299 */ | |
3300 final int offset; | |
3301 | |
3302 /** | |
3303 * Used to collect concatenated string literals into a single literal | |
3304 * instead of introducing unnecessary concatenations. | |
3305 */ | |
3306 DartString literalAccumulator = const LiteralDartString(""); | |
3307 | |
3308 /** | |
3309 * The string value generated so far (not including that which is still | |
3310 * in [literalAccumulator]). | |
3311 */ | 3292 */ |
3312 HInstruction prefix = null; | 3293 HInstruction prefix = null; |
floitsch
2012/06/06 12:13:34
Maybe rename to 'result' and remove result-method?
kasperl
2012/06/06 13:31:03
Done.
| |
3313 | 3294 |
3314 StringBuilderVisitor(builder, this.offset) | 3295 StringBuilderVisitor(this.builder); |
3315 : this.builder = builder, | |
3316 stringConcat = builder.compiler.findHelper( | |
3317 const SourceString("stringConcat")), | |
3318 stringToString = builder.compiler.findHelper( | |
3319 const SourceString("stringToString")); | |
3320 | 3296 |
3321 void visit(Node node) { | 3297 void visit(Node node) { |
3322 node.accept(this); | 3298 node.accept(this); |
3323 } | 3299 } |
3324 | 3300 |
3325 visitNode(Node node) { | 3301 visitNode(Node node) { |
3326 builder.compiler.internalError('unexpected node', node: node); | 3302 builder.compiler.internalError('unexpected node', node: node); |
3327 } | 3303 } |
3328 | 3304 |
3329 void visitExpression(Node node) { | 3305 void visitExpression(Node node) { |
3330 flushLiterals(node); | |
3331 node.accept(builder); | 3306 node.accept(builder); |
3332 HInstruction asString = buildToString(node, builder.pop()); | 3307 HInstruction expression = builder.pop(); |
3333 prefix = buildConcat(prefix, asString); | 3308 prefix = (prefix === null) ? expression : concat(prefix, expression); |
3334 } | |
3335 | |
3336 void visitLiteralNull(LiteralNull node) { | |
3337 addLiteral(const LiteralDartString("null")); | |
3338 } | |
3339 | |
3340 void visitLiteralInt(LiteralInt node) { | |
3341 addLiteral(new DartString.literal(node.value.toString())); | |
3342 } | |
3343 | |
3344 void visitLiteralDouble(LiteralDouble node) { | |
3345 addLiteral(new DartString.literal(node.value.toString())); | |
3346 } | |
3347 | |
3348 void visitLiteralBool(LiteralBool node) { | |
3349 addLiteral(node.value ? const LiteralDartString("true") | |
3350 : const LiteralDartString("false")); | |
3351 } | 3309 } |
3352 | 3310 |
3353 void visitStringInterpolation(StringInterpolation node) { | 3311 void visitStringInterpolation(StringInterpolation node) { |
3354 node.visitChildren(this); | 3312 node.visitChildren(this); |
3355 } | 3313 } |
3356 | 3314 |
3357 void visitStringInterpolationPart(StringInterpolationPart node) { | 3315 void visitStringInterpolationPart(StringInterpolationPart node) { |
3358 visit(node.expression); | 3316 visit(node.expression); |
3359 visit(node.string); | 3317 visit(node.string); |
3360 } | 3318 } |
3361 | 3319 |
3362 void visitLiteralString(LiteralString node) { | |
3363 addLiteral(node.dartString); | |
3364 } | |
3365 | |
3366 void visitStringJuxtaposition(StringJuxtaposition node) { | 3320 void visitStringJuxtaposition(StringJuxtaposition node) { |
3367 node.visitChildren(this); | 3321 node.visitChildren(this); |
3368 } | 3322 } |
3369 | 3323 |
3370 void visitNodeList(NodeList node) { | 3324 void visitNodeList(NodeList node) { |
3371 node.visitChildren(this); | 3325 node.visitChildren(this); |
3372 } | 3326 } |
3373 | 3327 |
3374 /** | 3328 HInstruction concat(HInstruction left, HInstruction right) { |
3375 * Add another literal string to the literalAccumulator. | 3329 HInstruction result = new HStringConcat([left, right]); |
3376 */ | 3330 builder.add(result); |
3377 void addLiteral(DartString dartString) { | 3331 return result; |
3378 literalAccumulator = new DartString.concat(literalAccumulator, dartString); | |
3379 } | |
3380 | |
3381 /** | |
3382 * Combine the strings in [literalAccumulator] into the prefix instruction. | |
3383 * After this, the [literalAccumulator] is empty and [prefix] is non-null. | |
3384 */ | |
3385 void flushLiterals(Node node) { | |
3386 if (literalAccumulator.isEmpty()) { | |
3387 if (prefix === null) { | |
3388 prefix = builder.graph.addConstantString(literalAccumulator, node); | |
3389 } | |
3390 return; | |
3391 } | |
3392 HInstruction string = | |
3393 builder.graph.addConstantString(literalAccumulator, node); | |
3394 literalAccumulator = new DartString.empty(); | |
3395 if (prefix !== null) { | |
3396 prefix = buildConcat(prefix, string); | |
3397 } else { | |
3398 prefix = string; | |
3399 } | |
3400 } | |
3401 | |
3402 HInstruction buildConcat(HInstruction left, HInstruction right) { | |
3403 HStatic target = new HStatic(stringConcat); | |
3404 builder.add(target); | |
3405 builder.push(new HAdd(target, left, right)); | |
3406 return builder.pop(); | |
3407 } | |
3408 | |
3409 HInstruction buildToString(Node node, HInstruction input) { | |
3410 HStatic target = new HStatic(stringToString); | |
3411 builder.add(target); | |
3412 builder.push(new HInvokeStatic(Selector.INVOCATION_1, | |
3413 <HInstruction>[target, input], | |
3414 HType.STRING)); | |
3415 return builder.pop(); | |
3416 } | 3332 } |
3417 | 3333 |
3418 HInstruction result(Node node) { | 3334 HInstruction result(Node node) { |
floitsch
2012/06/06 12:13:34
If you keep the result-method, remove the argument
| |
3419 flushLiterals(node); | |
3420 return prefix; | 3335 return prefix; |
3421 } | 3336 } |
3422 } | 3337 } |
OLD | NEW |