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 field declaration.
9    */
10  class JFieldDeclaration extends JAST implements JMember {
11      // Field modifiers.
12      private ArrayList<String> mods;
13  
14      // Variable declarators.
15      private ArrayList<JVariableDeclarator> decls;
16  
17      // Variable initializations.
18      private ArrayList<JStatement> initializations;
19  
20      /**
21       * Constructs an AST node for a field declaration.
22       *
23       * @param line  line in which the variable declaration occurs in the source file.
24       * @param mods  field modifiers.
25       * @param decls variable declarators.
26       */
27      public JFieldDeclaration(int line, ArrayList<String> mods,
28                               ArrayList<JVariableDeclarator> decls) {
29          super(line);
30          this.mods = mods;
31          this.decls = decls;
32          initializations = new ArrayList<JStatement>();
33      }
34  
35      /**
36       * Returns the list of modifiers.
37       *
38       * @return the list of modifiers.
39       */
40      public ArrayList<String> mods() {
41          return mods;
42      }
43  
44      /**
45       * {@inheritDoc}
46       */
47      public void preAnalyze(Context context, CLEmitter partial) {
48          if (mods.contains("abstract")) {
49              JAST.compilationUnit.reportSemanticError(line(), "Field cannot be declared abstract");
50          }
51          for (JVariableDeclarator decl : decls) {
52              decl.setType(decl.type().resolve(context));
53              partial.addField(mods, decl.name(), decl.type().toDescriptor(), false);
54          }
55      }
56  
57      /**
58       * {@inheritDoc}
59       */
60      public JFieldDeclaration analyze(Context context) {
61          for (JVariableDeclarator decl : decls) {
62              if (decl.initializer() != null) {
63                  JAssignOp assignOp = new JAssignOp(decl.line(), new JVariable(decl.line(),
64                          decl.name()), decl.initializer());
65                  assignOp.isStatementExpression = true;
66                  initializations.add(new JStatementExpression(decl.line(),
67                          assignOp).analyze(context));
68              }
69          }
70          return this;
71      }
72  
73      /**
74       * {@inheritDoc}
75       */
76      public void codegen(CLEmitter output) {
77          for (JVariableDeclarator decl : decls) {
78              output.addField(mods, decl.name(), decl.type().toDescriptor(), false);
79          }
80      }
81  
82      /**
83       * Generates code for the field initializations.
84       *
85       * @param output the code emitter.
86       */
87      public void codegenInitializations(CLEmitter output) {
88          for (JStatement initialization : initializations) {
89              initialization.codegen(output);
90          }
91      }
92  
93      /**
94       * {@inheritDoc}
95       */
96      public void toJSON(JSONElement json) {
97          JSONElement e = new JSONElement();
98          json.addChild("JFieldDeclaration", e);
99          e.addAttribute("line", String.valueOf(line()));
100         if (mods != null) {
101             ArrayList<String> value = new ArrayList<String>();
102             for (String mod : mods) {
103                 value.add(String.format("\"%s\"", mod));
104             }
105             e.addAttribute("modifiers", value);
106         }
107         if (decls != null) {
108             JSONElement e1 = new JSONElement();
109             e.addChild("VariableDeclarators", e1);
110             for (JVariableDeclarator decl : decls) {
111                 decl.toJSON(e1);
112             }
113         }
114     }
115 }
116