1   // Copyright 2013 Bill Campbell, Swami Iyer and Bahar Akbal-Delibas
2   
3   package jminusminus;
4   
5   import java.util.ArrayList;
6   import static jminusminus.CLConstants.*;
7   
8   /**
9    * The AST node for a this(...) constructor.
10   */
11  
12  class JThisConstruction extends JExpression {
13  
14      /** Arguments to the constructor. */
15      private ArrayList<JExpression> arguments;
16  
17      /** Constructor representation of the constructor. */
18      private Constructor constructor;
19  
20      /** Types of arguments. */
21      private Type[] argTypes;
22  
23      /**
24       * Whether this constructor is used properly, ie, as the first statement
25       * within a constructor.
26       */
27      private boolean properUseOfConstructor = false;
28  
29      /**
30       * Construct the AST node for a this(...) constructor given its line number
31       * and arguments.
32       * 
33       * @param line
34       *            line in which the constructor occurs in the source file.
35       * @param arguments
36       *            the constructor's arguments.
37       */
38  
39      protected JThisConstruction(int line, ArrayList<JExpression> arguments) {
40          super(line);
41          this.arguments = arguments;
42      }
43  
44      /**
45       * Used in JConstructorDeclaration to mark this(...) as being properly
46       * placed, ie, as the first statement in its body.
47       */
48  
49      public void markProperUseOfConstructor() {
50          properUseOfConstructor = true;
51      }
52  
53      /**
54       * Analyzing a this constructor statement involves (1) setting the type, (2)
55       * analyzing the actual arguments, (3) checking that this construction
56       * statement is properly invoked (as the first statement in another
57       * constructor), and (4) finding the appropriate Constructor
58       * 
59       * @param context
60       *            context in which names are resolved.
61       * @return the analyzed (and possibly rewritten) AST subtree.
62       */
63  
64      public JExpression analyze(Context context) {
65          type = Type.VOID;
66  
67          // Analyze the arguments, collecting
68          // their types (in Class form) as argTypes.
69          argTypes = new Type[arguments.size()];
70          for (int i = 0; i < arguments.size(); i++) {
71              arguments.set(i, (JExpression) arguments.get(i).analyze(context));
72              argTypes[i] = arguments.get(i).type();
73          }
74  
75          if (!properUseOfConstructor) {
76              JAST.compilationUnit.reportSemanticError(line(), "this"
77                      + Type.argTypesAsString(argTypes)
78                      + " must be first statement in the constructor's body.");
79              return this;
80          }
81  
82          // Get the constructor this(...) refers to.
83          constructor = ((JTypeDecl) context.classContext.definition())
84                  .thisType().constructorFor(argTypes);
85  
86          if (constructor == null) {
87              JAST.compilationUnit.reportSemanticError(line(),
88                      "No such constructor: this"
89                              + Type.argTypesAsString(argTypes));
90  
91          }
92          return this;
93      }
94  
95      /**
96       * Code generation involves generating the code for loading the actual
97       * arguments onto the stack, and then for invoking this constructor.
98       * 
99       * @param output
100      *            the code emitter (basically an abstraction for producing the
101      *            .class file).
102      */
103 
104     public void codegen(CLEmitter output) {
105         output.addNoArgInstruction(ALOAD_0); // this
106         for (JExpression argument : arguments) {
107             argument.codegen(output);
108         }
109         output.addMemberAccessInstruction(INVOKESPECIAL, constructor
110                 .declaringType().jvmName(), "<init>", constructor
111                 .toDescriptor());
112     }
113 
114     /**
115      * @inheritDoc
116      */
117 
118     public void writeToStdOut(PrettyPrinter p) {
119         p.printf("<JThisConstruction line=\"%d\"/>\n", line());
120         p.indentRight();
121         if (arguments != null) {
122             p.println("<Arguments>");
123             for (JExpression argument : arguments) {
124                 p.indentRight();
125                 p.println("<Argument>");
126                 p.indentRight();
127                 argument.writeToStdOut(p);
128                 p.indentLeft();
129                 p.println("</Argument>");
130                 p.indentLeft();
131             }
132             p.println("</Arguments>");
133         }
134         p.indentLeft();
135         p.println("</JThisConstruction>");
136     }
137 
138 }
139