KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > polyglot > visit > Translator


1 package polyglot.visit;
2
3 import java.io.File JavaDoc;
4 import java.io.IOException JavaDoc;
5 import java.io.Writer JavaDoc;
6 import java.util.Collection JavaDoc;
7 import java.util.Iterator JavaDoc;
8 import java.util.LinkedList JavaDoc;
9 import java.util.List JavaDoc;
10
11 import polyglot.ast.Import;
12 import polyglot.ast.Node;
13 import polyglot.ast.NodeFactory;
14 import polyglot.ast.SourceCollection;
15 import polyglot.ast.SourceFile;
16 import polyglot.ast.TopLevelDecl;
17 import polyglot.frontend.Job;
18 import polyglot.frontend.TargetFactory;
19 import polyglot.types.ClassType;
20 import polyglot.types.Context;
21 import polyglot.types.Package;
22 import polyglot.types.TypeSystem;
23 import polyglot.util.CodeWriter;
24 import polyglot.util.Copy;
25 import polyglot.util.ErrorInfo;
26 import polyglot.util.InternalCompilerError;
27
28 /**
29  * A Translator generates output code from the processed AST.
30  * Output is sent to one or more java file in the directory
31  * <code>Options.output_directory</code>. Each SourceFile in the AST
32  * is output to exactly one java file. The name of that file is
33  * determined as follows:
34  * <ul>
35  * <li> If the SourceFile has a declaration of a public top-level class "C",
36  * file name is "C.java". It is an error for there to be more than one
37  * top-level public declaration.
38  * <li> If the SourceFile has no public declarations, the file name
39  * is the input file name (e.g., "X.jl") with the suffix replaced with ".java"
40  * (thus, "X.java").
41  * </ul>
42  *
43  * To use:
44  * <pre>
45  * new Translator(job, ts, nf, tf).translate(ast);
46  * </pre>
47  * The <code>ast</code> must be either a SourceFile or a SourceCollection.
48  */

49 public class Translator extends PrettyPrinter implements Copy
50 {
51     protected Job job;
52     protected NodeFactory nf;
53     protected TargetFactory tf;
54     protected TypeSystem ts;
55     protected Context context;
56     protected ClassType outerClass = null;
57
58     /**
59      * Create a Translator. The output of the visitor is a collection of files
60      * whose names are added to the collection <code>outputFiles</code>.
61      */

62     public Translator(Job job, TypeSystem ts, NodeFactory nf, TargetFactory tf) {
63         super();
64
65         this.job = job;
66         this.nf = nf;
67         this.tf = tf;
68         this.ts = ts;
69         this.context = job.context();
70
71         if (this.context == null) {
72             this.context = ts.createContext();
73         }
74     }
75
76     /**
77      * Return the job associated with this Translator.
78      */

79     public Job job() {
80         return job;
81     }
82     
83     /** Create a new <code>Translator</code> identical to <code>this</code> but
84      * with new context <code>c</code> */

85     public Translator context(Context c) {
86         if (c == this.context) {
87             return this;
88         }
89         Translator tr = (Translator) copy();
90         tr.context = c;
91         return tr;
92     }
93
94     /** Copy the translator. */
95     public Object JavaDoc copy() {
96         try {
97             return super.clone();
98         }
99         catch (CloneNotSupportedException JavaDoc e) {
100             throw new InternalCompilerError("Java clone() weirdness.");
101         }
102     }
103
104     /** Set the outer class context of the translator. This class is used when
105      * translating "new" expressions for nested classes. For the expression
106      * "e.new C()", the name "C" needs to be looked up in the context of the
107      * static type of expression "e" (i.e., <code>outerClass</code>), rather
108      * than in the current context returned by <code>context()</code>.
109      */

110     public ClassType outerClass() {
111         return outerClass;
112     }
113
114     /** Destructively set the outer class context of the translator. */
115     public void setOuterClass(ClassType ct) {
116         this.outerClass = ct;
117     }
118
119     /** Get the extension's type system. */
120     public TypeSystem typeSystem() {
121         return ts;
122     }
123
124     /** Get the current context in which we are translating. */
125     public Context context() {
126         return context;
127     }
128
129     /** Get the extension's node factory. */
130     public NodeFactory nodeFactory() {
131         return nf;
132     }
133
134     /** Print an ast node using the given code writer. This method should not
135      * be called directly to translate a source file AST; use
136      * <code>translate(Node)</code> instead. This method should only be called
137      * by nodes to print their children.
138      */

139     public void print(Node parent, Node child, CodeWriter w) {
140         Translator tr;
141
142         if (parent != null) {
143             Context c = parent.del().enterScope(child, context);
144             tr = this.context(c);
145         }
146         else {
147             Context c = child.del().enterScope(context);
148             tr = this.context(c);
149         }
150
151         child.del().translate(w, tr);
152
153         if (parent != null) {
154             parent.addDecls(context);
155         }
156     }
157
158     /** Translate the entire AST. */
159     public boolean translate(Node ast) {
160         if (ast instanceof SourceFile) {
161             SourceFile sfn = (SourceFile) ast;
162             return translateSource(sfn);
163         }
164         else if (ast instanceof SourceCollection) {
165             SourceCollection sc = (SourceCollection) ast;
166
167             boolean okay = true;
168
169             for (Iterator JavaDoc i = sc.sources().iterator(); i.hasNext(); ) {
170                 SourceFile sfn = (SourceFile) i.next();
171                 okay &= translateSource(sfn);
172             }
173
174             return okay;
175         }
176         else {
177             throw new InternalCompilerError("AST root must be a SourceFile; " +
178                                             "found a " + ast.getClass().getName());
179         }
180     }
181
182     /** Transate a single SourceFile node */
183     protected boolean translateSource(SourceFile sfn) {
184         TypeSystem ts = typeSystem();
185         NodeFactory nf = nodeFactory();
186     TargetFactory tf = this.tf;
187     int outputWidth = job.compiler().outputWidth();
188     Collection JavaDoc outputFiles = job.compiler().outputFiles();
189
190         // Find the public declarations in the file. We'll use these to
191
// derive the names of the target files. There will be one
192
// target file per public declaration. If there are no public
193
// declarations, we'll use the source file name to derive the
194
// target file name.
195
List JavaDoc exports = exports(sfn);
196
197         try {
198             File JavaDoc of;
199             Writer JavaDoc ofw;
200             CodeWriter w;
201
202             String JavaDoc pkg = "";
203
204             if (sfn.package_() != null) {
205                 Package JavaDoc p = sfn.package_().package_();
206                 pkg = p.toString();
207             }
208
209             Context c = sfn.del().enterScope(context);
210
211             TopLevelDecl first = null;
212
213             if (exports.size() == 0) {
214                 // Use the source name to derive a default output file name.
215
of = tf.outputFile(pkg, sfn.source());
216             }
217             else {
218                 first = (TopLevelDecl) exports.get(0);
219                 of = tf.outputFile(pkg, first.name(), sfn.source());
220             }
221
222             String JavaDoc opfPath = of.getPath();
223             if (!opfPath.endsWith("$")) outputFiles.add(of.getPath());
224             ofw = tf.outputWriter(of);
225             w = new CodeWriter(ofw, outputWidth);
226
227             writeHeader(sfn, w);
228
229             for (Iterator JavaDoc i = sfn.decls().iterator(); i.hasNext(); ) {
230                 TopLevelDecl decl = (TopLevelDecl) i.next();
231
232                 if (decl.flags().isPublic() && decl != first) {
233                     // We hit a new exported declaration, open a new file.
234
// But, first close the old file.
235
w.flush();
236                     ofw.close();
237
238                     of = tf.outputFile(pkg, decl.name(), sfn.source());
239                     outputFiles.add(of.getPath());
240                     ofw = tf.outputWriter(of);
241                     w = new CodeWriter(ofw, outputWidth);
242
243                     writeHeader(sfn, w);
244                 }
245
246                 decl.del().translate(w, this.context(c));
247
248                 if (i.hasNext()) {
249                     w.newline(0);
250                 }
251             }
252
253             w.flush();
254             ofw.close();
255             return true;
256         }
257         catch (IOException JavaDoc e) {
258             job.compiler().errorQueue().enqueue(ErrorInfo.IO_ERROR,
259                       "I/O error while translating: " + e.getMessage());
260             return false;
261         }
262     }
263
264     /** Write the package and import declarations for a source file. */
265     protected void writeHeader(SourceFile sfn, CodeWriter w) {
266     if (sfn.package_() != null) {
267         w.write("package ");
268         sfn.package_().del().translate(w, this);
269         w.write(";");
270         w.newline(0);
271         w.newline(0);
272     }
273
274     boolean newline = false;
275
276     for (Iterator JavaDoc i = sfn.imports().iterator(); i.hasNext(); ) {
277         Import imp = (Import) i.next();
278         imp.del().translate(w, this);
279         newline = true;
280     }
281
282     if (newline) {
283         w.newline(0);
284     }
285     }
286
287     /** Get the list of public top-level classes declared in the source file. */
288     protected List JavaDoc exports(SourceFile sfn) {
289     List JavaDoc exports = new LinkedList JavaDoc();
290
291     for (Iterator JavaDoc i = sfn.decls().iterator(); i.hasNext(); ) {
292         TopLevelDecl decl = (TopLevelDecl) i.next();
293
294         if (decl.flags().isPublic()) {
295         exports.add(decl);
296         }
297     }
298
299     return exports;
300     }
301
302     public String JavaDoc toString() {
303     return "Translator";
304     }
305 }
306
Popular Tags