Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(683)

Side by Side Diff: frog/leg/ssa/builder.dart

Issue 9642001: Make string juxtaposition combine properly with string interpolations. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review comments. Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « frog/leg/scanner/scanner_task.dart ('k') | frog/leg/ssa/codegen.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 return builder.buildFactory(classElement, work.element); 161 return builder.buildFactory(classElement, work.element);
162 } 162 }
163 } 163 }
164 164
165 /** 165 /**
166 * Keeps track of locals (including parameters and phis) when building. The 166 * Keeps track of locals (including parameters and phis) when building. The
167 * 'this' reference is treated as parameter and hence handled by this class, 167 * 'this' reference is treated as parameter and hence handled by this class,
168 * too. 168 * too.
169 */ 169 */
170 class LocalsHandler { 170 class LocalsHandler {
171 // The values of locals that can be directly accessed (without redirections 171 /**
172 // to boxes or closure-fields). 172 * The values of locals that can be directly accessed (without redirections
173 * to boxes or closure-fields).
174 */
173 Map<Element, HInstruction> directLocals; 175 Map<Element, HInstruction> directLocals;
174 Map<Element, Element> redirectionMapping; 176 Map<Element, Element> redirectionMapping;
175 SsaBuilder builder; 177 SsaBuilder builder;
176 ClosureData closureData; 178 ClosureData closureData;
177 179
178 LocalsHandler(this.builder) 180 LocalsHandler(this.builder)
179 : directLocals = new Map<Element, HInstruction>(), 181 : directLocals = new Map<Element, HInstruction>(),
180 redirectionMapping = new Map<Element, Element>(); 182 redirectionMapping = new Map<Element, Element>();
181 183
182 /** 184 /**
(...skipping 1215 matching lines...) Expand 10 before | Expand all | Expand 10 after
1398 visit(node.receiver); 1400 visit(node.receiver);
1399 HNot not = new HNot(popBoolified()); 1401 HNot not = new HNot(popBoolified());
1400 push(not); 1402 push(not);
1401 } 1403 }
1402 1404
1403 void visitUnary(Send node, Operator op) { 1405 void visitUnary(Send node, Operator op) {
1404 assert(node.argumentsNode is Prefix); 1406 assert(node.argumentsNode is Prefix);
1405 visit(node.receiver); 1407 visit(node.receiver);
1406 assert(op.token.kind !== PLUS_TOKEN); 1408 assert(op.token.kind !== PLUS_TOKEN);
1407 HInstruction operand = pop(); 1409 HInstruction operand = pop();
1410
1408 HInstruction target = 1411 HInstruction target =
1409 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); 1412 new HStatic(interceptors.getPrefixOperatorInterceptor(op));
1410 add(target); 1413 add(target);
1411 HInvokeUnary result; 1414 HInvokeUnary result;
1412 switch (op.source.stringValue) { 1415 switch (op.source.stringValue) {
1413 case "-": result = new HNegate(target, operand); break; 1416 case "-": result = new HNegate(target, operand); break;
1414 case "~": result = new HBitNot(target, operand); break; 1417 case "~": result = new HBitNot(target, operand); break;
1415 default: unreachable(); 1418 default: unreachable();
1416 } 1419 }
1417 // See if we can constant-fold right away. This avoids rewrites later on. 1420 // See if we can constant-fold right away. This avoids rewrites later on.
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after
2073 } 2076 }
2074 2077
2075 void visitLiteralBool(LiteralBool node) { 2078 void visitLiteralBool(LiteralBool node) {
2076 stack.add(graph.addConstantBool(node.value)); 2079 stack.add(graph.addConstantBool(node.value));
2077 } 2080 }
2078 2081
2079 void visitLiteralString(LiteralString node) { 2082 void visitLiteralString(LiteralString node) {
2080 stack.add(graph.addConstantString(node.dartString)); 2083 stack.add(graph.addConstantString(node.dartString));
2081 } 2084 }
2082 2085
2083 void visitLiteralStringJuxtaposition(LiteralStringJuxtaposition node) { 2086 void visitStringJuxtaposition(StringJuxtaposition node) {
2084 visitLiteralString(node); 2087 if (!node.isInterpolation) {
2088 // This is a simple string with no interpolations.
2089 stack.add(graph.addConstantString(node.dartString));
2090 return;
2091 }
2092 int offset = node.getBeginToken().charOffset;
2093 StringBuilderVisitor stringBuilder =
2094 new StringBuilderVisitor(this, offset);
2095 stringBuilder.visit(node);
2096 stack.add(stringBuilder.result());
2085 } 2097 }
2086 2098
2087 void visitLiteralNull(LiteralNull node) { 2099 void visitLiteralNull(LiteralNull node) {
2088 stack.add(graph.addConstantNull()); 2100 stack.add(graph.addConstantNull());
2089 } 2101 }
2090 2102
2091 visitNodeList(NodeList node) { 2103 visitNodeList(NodeList node) {
2092 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { 2104 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) {
2093 if (isAborted()) { 2105 if (isAborted()) {
2094 compiler.reportWarning(link.head, 'dead code'); 2106 compiler.reportWarning(link.head, 'dead code');
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2197 open(joinBlock); 2209 open(joinBlock);
2198 2210
2199 localsHandler.mergeWith(thenLocals, joinBlock); 2211 localsHandler.mergeWith(thenLocals, joinBlock);
2200 HPhi phi = new HPhi.manyInputs(null, [thenInstruction, elseInstruction]); 2212 HPhi phi = new HPhi.manyInputs(null, [thenInstruction, elseInstruction]);
2201 joinBlock.addPhi(phi); 2213 joinBlock.addPhi(phi);
2202 stack.add(phi); 2214 stack.add(phi);
2203 } 2215 }
2204 2216
2205 visitStringInterpolation(StringInterpolation node) { 2217 visitStringInterpolation(StringInterpolation node) {
2206 int offset = node.getBeginToken().charOffset; 2218 int offset = node.getBeginToken().charOffset;
2207 Operator op = new Operator(new StringToken(PLUS_INFO, "+", offset)); 2219 StringBuilderVisitor stringBuilder =
2208 HInstruction target = new HStatic(interceptors.getOperatorInterceptor(op)); 2220 new StringBuilderVisitor(this, offset);
2209 add(target); 2221 stringBuilder.visit(node);
2210 visit(node.string); 2222 stack.add(stringBuilder.result());
2211 // Handle the parts here, to avoid recreating [target].
2212 for (StringInterpolationPart part in node.parts) {
2213 HInstruction prefix = pop();
2214 visit(part.expression);
2215 push(new HAdd(target, prefix, pop()));
2216 prefix = pop();
2217 visit(part.string);
2218 push(new HAdd(target, prefix, pop()));
2219 }
2220 } 2223 }
2221 2224
2222 visitStringInterpolationPart(StringInterpolationPart node) { 2225 visitStringInterpolationPart(StringInterpolationPart node) {
2223 // The parts are iterated in visitStringInterpolation. 2226 // The parts are iterated in visitStringInterpolation.
2224 unreachable(); 2227 unreachable();
2225 } 2228 }
2226 2229
2227 visitEmptyStatement(EmptyStatement node) { 2230 visitEmptyStatement(EmptyStatement node) {
2228 // Do nothing, empty statement. 2231 // Do nothing, empty statement.
2229 } 2232 }
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after
2701 buildBody() { 2704 buildBody() {
2702 // TODO(lrn): Make sure to take continue into account. 2705 // TODO(lrn): Make sure to take continue into account.
2703 visit(body); 2706 visit(body);
2704 if (isAborted()) { 2707 if (isAborted()) {
2705 compiler.reportWarning(body, "aborting loop body"); 2708 compiler.reportWarning(body, "aborting loop body");
2706 } 2709 }
2707 } 2710 }
2708 handleIf(buildBody, null); 2711 handleIf(buildBody, null);
2709 } 2712 }
2710 } 2713 }
2714
2715 /**
2716 * Visitor that handles generation of string literals (LiteralString,
2717 * StringInterpolation), and otherwise delegates to the given visitor for
2718 * non-literal subexpressions.
2719 * TODO(lrn): Consider whether to handle compile time constant int/boolean
2720 * expressions as well.
2721 */
2722 class StringBuilderVisitor extends AbstractVisitor {
2723 final SsaBuilder builder;
2724
2725 /**
2726 * Offset used for the synthetic operator token used by concat.
2727 * Can probably be removed when we stop using String.operator+.
2728 */
2729 final int offset;
2730
2731 /**
2732 * Used to collect concatenated string literals into a single literal
2733 * instead of introducing unnecessary concatenations.
2734 */
2735 DartString accumulator = const LiteralDartString("");
2736
2737 /**
2738 * The string value generated so far (not including that which is still
2739 * in [accumulator]).
2740 */
2741 HInstruction prefix = null;
2742
2743 StringBuilderVisitor(this.builder, this.offset);
2744
2745 void visit(Node node) {
2746 node.accept(this);
2747 }
2748
2749 visitNode(Node node) {
2750 compiler.internalError('unexpected node', node: node);
2751 }
2752
2753 void visitExpression(Node node) {
2754 flushAccumulator();
2755 node.accept(builder);
2756 prefix = concat(prefix, builder.pop());
2757 }
2758
2759 void visitStringInterpolation(StringInterpolation node) {
2760 node.visitChildren(this);
2761 }
2762
2763 void visitStringInterpolationPart(StringInterpolationPart node) {
2764 visit(node.expression);
2765 visit(node.string);
2766 }
2767
2768 void visitLiteralString(LiteralString node) {
2769 accumulator = new DartString.concat(accumulator, node.dartString);
2770 }
2771
2772 void visitStringJuxtaposition(StringJuxtaposition node) {
2773 node.visitChildren(this);
2774 }
2775
2776 void visitNodeList(NodeList node) {
2777 node.visitChildren(this);
2778 }
2779
2780 /**
2781 * Combine the strings in [accumulator] into the prefix instruction.
2782 * After this, the [accumulator] is empty and [prefix] is non-null.
2783 */
2784 void flushAccumulator() {
2785 if (accumulator.isEmpty()) {
2786 if (prefix === null) {
2787 prefix = builder.graph.addConstantString(accumulator);
2788 }
2789 return;
2790 }
2791 HInstruction string = builder.graph.addConstantString(accumulator);
2792 accumulator = new DartString.empty();
2793 if (prefix !== null) {
2794 prefix = concat(prefix, string);
2795 } else {
2796 prefix = string;
2797 }
2798 }
2799
2800 HInstruction concat(HInstruction left, HInstruction right) {
2801 Operator op = new Operator(new StringToken(PLUS_INFO, "+", offset));
2802 HStatic target =
2803 new HStatic(builder.interceptors.getOperatorInterceptor(op));
2804 builder.add(target);
2805 HInstruction concat = new HAdd(target, left, right);
2806 builder.add(concat);
2807 return concat;
2808 }
2809
2810 HInstruction result() {
2811 flushAccumulator();
2812 return prefix;
2813 }
2814 }
OLDNEW
« no previous file with comments | « frog/leg/scanner/scanner_task.dart ('k') | frog/leg/ssa/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698