1   // Copyright 2012- 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 by its analyze()
9    * method, which also re-writes any initializations as assignment statements, in turn generated
10   * by its codegen() method.
11   */
12  class JVariableDeclaration extends JStatement {
13      // Variable declarators.
14      private ArrayList<JVariableDeclarator> decls;
15  
16      // Variable initializers.
17      private ArrayList<JStatement> initializations;
18  
19      /**
20       * Constructs an AST node for a variable declaration.
21       *
22       * @param line  line in which the variable declaration occurs in the source file.
23       * @param decls variable declarators.
24       */
25      public JVariableDeclaration(int line, ArrayList<JVariableDeclarator> decls) {
26          super(line);
27          this.decls = decls;
28          initializations = new ArrayList<JStatement>();
29      }
30  
31      /**
32       * {@inheritDoc}
33       */
34      public JStatement analyze(Context context) {
35          for (JVariableDeclarator decl : decls) {
36              // Local variables are declared here (fields are declared in preAnalyze()).
37              int offset = ((LocalContext) context).nextOffset();
38              LocalVariableDefn defn = new LocalVariableDefn(decl.type().resolve(context), offset);
39  
40              // First, check for shadowing.
41              IDefn previousDefn = context.lookup(decl.name());
42              if (previousDefn != null && previousDefn instanceof LocalVariableDefn) {
43                  JAST.compilationUnit.reportSemanticError(decl.line(),
44                          "The name " + decl.name() + " overshadows another local variable");
45              }
46  
47              // Then declare it in the local context.
48              context.addEntry(decl.line(), decl.name(), defn);
49  
50              // All initializations must be turned into assignment statements and analyzed.
51              if (decl.initializer() != null) {
52                  defn.initialize();
53                  JAssignOp assignOp = new JAssignOp(decl.line(), new JVariable(decl.line(),
54                          decl.name()), decl.initializer());
55                  assignOp.isStatementExpression = true;
56                  initializations.add(new JStatementExpression(decl.line(),
57                          assignOp).analyze(context));
58              }
59          }
60          return this;
61      }
62  
63      /**
64       * {@inheritDoc}
65       */
66      public void codegen(CLEmitter output) {
67          for (JStatement initialization : initializations) {
68              initialization.codegen(output);
69          }
70      }
71  
72      /**
73       * {@inheritDoc}
74       */
75      public void toJSON(JSONElement json) {
76          JSONElement e = new JSONElement();
77          json.addChild("JVariableDeclaration:" + line, e);
78          if (decls != null) {
79              for (JVariableDeclarator decl : decls) {
80                  decl.toJSON(e);
81              }
82          }
83      }
84  }
85