| JStringConcatenationOp.java |
1 // Copyright 2012- Bill Campbell, Swami Iyer and Bahar Akbal-Delibas
2
3 package jminusminus;
4
5 import static jminusminus.CLConstants.*;
6
7 /**
8 * The AST node for a string concatenation operation. Nodes of this type are not produced by the
9 * parser, but by analysis of a + operation where the arguments are strings. Such operations are
10 * rewritten to be string concatenation operations.
11 */
12 class JStringConcatenationOp extends JBinaryExpression {
13 /**
14 * Constructs an AST node for a string concatenation expression.
15 *
16 * @param line line in which the expression occurs in the source file.
17 * @param lhs lhs operand.
18 * @param rhs rhs operand.
19 */
20 public JStringConcatenationOp(int line, JExpression lhs, JExpression rhs) {
21 super(line, "+", lhs, rhs);
22 }
23
24 /**
25 * {@inheritDoc}
26 */
27 public JExpression analyze(Context context) {
28 type = Type.STRING;
29 return this;
30 }
31
32 /**
33 * {@inheritDoc}
34 */
35 public void codegen(CLEmitter output) {
36 // Firstly, create a StringBuilder.
37 output.addReferenceInstruction(NEW, "java/lang/StringBuilder");
38 output.addNoArgInstruction(DUP);
39 output.addMemberAccessInstruction(INVOKESPECIAL, "java/lang/StringBuilder", "<init>",
40 "()V");
41
42 // Lhs and Rhs.
43 nestedCodegen(output);
44
45 // Finally, make into a String.
46 output.addMemberAccessInstruction(INVOKEVIRTUAL, "java/lang/StringBuilder", "toString",
47 "()Ljava/lang/String;");
48 }
49
50 // Like codegen() method, but we needn't (and shouldn't) create a StringBuilder nor convert
51 // the result to a String, as that will be done in a parent.
52 private void nestedCodegen(CLEmitter output) {
53 // Lhs.
54 if (lhs instanceof JStringConcatenationOp) {
55 // This appends lhs
56 ((JStringConcatenationOp) lhs).nestedCodegen(output);
57 } else {
58 lhs.codegen(output);
59 output.addMemberAccessInstruction(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
60 "(" + lhs.type().argumentTypeForAppend() + ")Ljava/lang/StringBuilder;");
61 }
62
63 // Rhs.
64 if (rhs instanceof JStringConcatenationOp) {
65 // This appends rhs.
66 ((JStringConcatenationOp) rhs).nestedCodegen(output);
67 } else {
68 rhs.codegen(output);
69 output.addMemberAccessInstruction(INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
70 "(" + rhs.type().argumentTypeForAppend() + ")Ljava/lang/StringBuilder;");
71 }
72 }
73 }
74