1   // Copyright 2013 Bill Campbell, Swami Iyer and Bahar Akbal-Delibas
2   
3   package jminusminus;
4   
5   import java.util.ArrayList;
6   
7   /**
8    * The AST node for a local variable declaration. Local variables are declared
9    * by analyze(), which also re-writes any initializations as assignment
10   * statements, in turn generated by codegen().
11   */
12  
13  class JVariableDeclaration extends JStatement {
14  
15      /** Modifiers. */
16      private ArrayList<String> mods;
17  
18      /** Variable declarators. */
19      private ArrayList<JVariableDeclarator> decls;
20  
21      /** Variable initializers. */
22      private ArrayList<JStatement> initializations;
23  
24      /**
25       * Construct an AST node for a variable declaration given the line number,
26       * modifiers, and the variable declarators.
27       * 
28       * @param line
29       *            line in which the variable declaration occurs in the source
30       *            file.
31       * @param mods
32       *            modifiers.
33       * @param decls
34       *            variable declarators.
35       */
36  
37      public JVariableDeclaration(int line, ArrayList<String> mods,
38              ArrayList<JVariableDeclarator> decls) {
39          super(line);
40          this.mods = mods;
41          this.decls = decls;
42          initializations = new ArrayList<JStatement>();
43      }
44  
45      /**
46       * Return the list of modifiers.
47       * 
48       * @return list of modifiers.
49       */
50  
51      public ArrayList<String> mods() {
52          return mods;
53      }
54  
55      /**
56       * We declare the variable(s). Initializations are rewritten as assignment
57       * statements.
58       * 
59       * @param context
60       *            context in which names are resolved.
61       * @return the analyzed (and possibly rewritten) AST subtree.
62       */
63  
64      public JStatement analyze(Context context) {
65          for (JVariableDeclarator decl : decls) {
66              // Local variables are declared here (fields are
67              // declared
68              // in preAnalyze())
69              int offset = ((LocalContext) context).nextOffset();
70              LocalVariableDefn defn = new LocalVariableDefn(decl.type().resolve(
71                      context), offset);
72  
73              // First, check for shadowing
74              IDefn previousDefn = context.lookup(decl.name());
75              if (previousDefn != null
76                      && previousDefn instanceof LocalVariableDefn) {
77                  JAST.compilationUnit.reportSemanticError(decl.line(),
78                          "The name " + decl.name()
79                                  + " overshadows another local variable.");
80              }
81  
82              // Then declare it in the local context
83              context.addEntry(decl.line(), decl.name(), defn);
84  
85              // All initializations must be turned into assignment
86              // statements and analyzed
87              if (decl.initializer() != null) {
88                  defn.initialize();
89                  JAssignOp assignOp = new JAssignOp(decl.line(), new JVariable(
90                          decl.line(), decl.name()), decl.initializer());
91                  assignOp.isStatementExpression = true;
92                  initializations.add(new JStatementExpression(decl.line(),
93                          assignOp).analyze(context));
94              }
95          }
96          return this;
97      }
98  
99      /**
100      * Local variable initializations (rewritten as assignments in analyze())
101      * are generated here.
102      * 
103      * @param output
104      *            the code emitter (basically an abstraction for producing the
105      *            .class file).
106      */
107 
108     public void codegen(CLEmitter output) {
109         for (JStatement initialization : initializations) {
110             initialization.codegen(output);
111         }
112     }
113 
114     /**
115      * @inheritDoc
116      */
117 
118     public void writeToStdOut(PrettyPrinter p) {
119         p.println("<JVariableDeclaration>");
120         p.indentRight();
121         if (mods != null) {
122             p.println("<Modifiers>");
123             p.indentRight();
124             for (String mod : mods) {
125                 p.printf("<Modifier name=\"%s\"/>\n", mod);
126             }
127             p.indentLeft();
128             p.println("</Modifiers>");
129         }
130         if (decls != null) {
131             p.println("<VariableDeclarators>");
132             for (JVariableDeclarator decl : decls) {
133                 p.indentRight();
134                 decl.writeToStdOut(p);
135                 p.indentLeft();
136             }
137             p.println("</VariableDeclarators>");
138         }
139         p.indentLeft();
140         p.println("</JVariableDeclaration>");
141     }
142 
143 }
144