KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > python > compiler > Module


1 // Copyright (c) Corporation for National Research Initiatives
2

3 package org.python.compiler;
4
5 import java.io.*;
6 import java.util.*;
7 import org.python.parser.*;
8 import org.python.parser.ast.*;
9 import org.python.core.Py;
10 import org.python.core.PyException;
11
12 class PyIntegerConstant extends Constant implements ClassConstants
13 {
14     int value;
15
16     public PyIntegerConstant(int value) {
17         this.value = value;
18     }
19
20     public void get(Code c) throws IOException {
21         c.getstatic(module.classfile.name, name, $pyInteger);
22     }
23
24     public void put(Code c) throws IOException {
25         module.classfile.addField(name, $pyInteger, access);
26         c.iconst(value);
27         int mref_newInteger = c.pool.Methodref(
28             "org/python/core/Py",
29             "newInteger",
30             "(I)" + $pyInteger);
31         c.invokestatic(mref_newInteger);
32         c.putstatic(module.classfile.name, name, $pyInteger);
33     }
34
35     public int hashCode() {
36         return value;
37     }
38
39     public boolean equals(Object JavaDoc o) {
40         if (o instanceof PyIntegerConstant)
41             return ((PyIntegerConstant)o).value == value;
42         else
43             return false;
44     }
45 }
46
47 class PyFloatConstant extends Constant implements ClassConstants
48 {
49     double value;
50
51     public PyFloatConstant(double value) {
52         this.value = value;
53     }
54
55     public void get(Code c) throws IOException {
56         c.getstatic(module.classfile.name, name, $pyFloat);
57     }
58
59     public void put(Code c) throws IOException {
60         module.classfile.addField(name, $pyFloat, access);
61         c.ldc(c.pool.Double(value));
62         int mref_newFloat = c.pool.Methodref("org/python/core/Py",
63                                              "newFloat",
64                                              "(D)" + $pyFloat);
65         c.invokestatic(mref_newFloat);
66         c.putstatic(module.classfile.name, name, $pyFloat);
67     }
68
69     public int hashCode() {
70         return (int)value;
71     }
72
73     public boolean equals(Object JavaDoc o) {
74         if (o instanceof PyFloatConstant)
75             return ((PyFloatConstant)o).value == value;
76         else
77             return false;
78     }
79 }
80
81 class PyComplexConstant extends Constant implements ClassConstants
82 {
83     double value;
84
85     public PyComplexConstant(double value) {
86         this.value = value;
87     }
88
89     public void get(Code c) throws IOException {
90         c.getstatic(module.classfile.name, name, $pyComplex);
91     }
92
93     public void put(Code c) throws IOException {
94         module.classfile.addField(name, $pyComplex, access);
95         c.ldc(c.pool.Double(value));
96         int mref_newImaginary = c.pool.Methodref(
97             "org/python/core/Py",
98             "newImaginary",
99             "(D)" + $pyComplex);
100         c.invokestatic(mref_newImaginary);
101         c.putstatic(module.classfile.name, name, $pyComplex);
102     }
103
104     public int hashCode() {
105         return (int)value;
106     }
107
108     public boolean equals(Object JavaDoc o) {
109         if (o instanceof PyComplexConstant)
110             return ((PyComplexConstant)o).value == value;
111         else
112             return false;
113     }
114 }
115
116 class PyStringConstant extends Constant implements ClassConstants
117 {
118     String JavaDoc value;
119
120     public PyStringConstant(String JavaDoc value) {
121         this.value = value;
122     }
123
124     public void get(Code c) throws IOException {
125         c.getstatic(module.classfile.name, name, $pyStr);
126     }
127
128     public void put(Code c) throws IOException {
129         module.classfile.addField(name, $pyStr, access);
130         c.ldc(value);
131         int mref_newString = c.pool.Methodref(
132             "org/python/core/Py",
133             "newString",
134             "(" + $str + ")" + $pyStr);
135         c.invokestatic(mref_newString);
136         c.putstatic(module.classfile.name, name, $pyStr);
137     }
138
139     public int hashCode() {
140         return value.hashCode();
141     }
142
143     public boolean equals(Object JavaDoc o) {
144         if (o instanceof PyStringConstant)
145             return ((PyStringConstant)o).value.equals(value);
146         else
147             return false;
148     }
149 }
150
151 class PyLongConstant extends Constant implements ClassConstants
152 {
153     String JavaDoc value;
154
155     public PyLongConstant(String JavaDoc value) {
156         this.value = value;
157     }
158
159     public void get(Code c) throws IOException {
160         c.getstatic(module.classfile.name, name, $pyLong);
161     }
162
163     public void put(Code c) throws IOException {
164         module.classfile.addField(name, $pyLong, access);
165         c.ldc(value);
166         int mref_newLong = c.pool.Methodref(
167             "org/python/core/Py",
168             "newLong",
169             "(" + $str + ")" + $pyLong);
170         c.invokestatic(mref_newLong);
171         c.putstatic(module.classfile.name, name, $pyLong);
172     }
173
174     public int hashCode() {
175         return value.hashCode();
176     }
177
178     public boolean equals(Object JavaDoc o) {
179         if (o instanceof PyLongConstant)
180             return ((PyLongConstant)o).value.equals(value);
181         else return false;
182     }
183 }
184
185 class PyCodeConstant extends Constant implements ClassConstants
186 {
187     public String JavaDoc co_name;
188     public int argcount;
189     public String JavaDoc[] names;
190     public int id;
191     public int co_firstlineno;
192     public boolean arglist, keywordlist;
193     String JavaDoc fname;
194
195     // for nested scopes
196
public String JavaDoc[] cellvars;
197     public String JavaDoc[] freevars;
198     public int jy_npurecell;
199
200     public int moreflags;
201
202     public PyCodeConstant() { ;
203     }
204
205     public void get(Code c) throws IOException {
206         c.getstatic(module.classfile.name, name, $pyCode);
207     }
208
209     public void put(Code c) throws IOException {
210         module.classfile.addField(name, $pyCode, access);
211         c.iconst(argcount);
212
213         //Make all names
214
if (names != null) {
215             CodeCompiler.makeStrings(c, names, names.length);
216         } else { // classdef
217
CodeCompiler.makeStrings(c, null, 0);
218         }
219
220         c.ldc(((PyStringConstant)module.filename).value);
221         c.ldc(co_name);
222         c.iconst(co_firstlineno);
223
224         c.iconst(arglist ? 1 : 0);
225         c.iconst(keywordlist ? 1 : 0);
226
227         int mref_self = c.pool.Fieldref(module.classfile.name,
228                                         "self",
229                                         "L"+module.classfile.name+";");
230         c.getstatic(mref_self);
231         //c.aconst_null();
232

233         c.iconst(id);
234
235         if (cellvars != null)
236             CodeCompiler.makeStrings(c, cellvars, cellvars.length);
237         else
238             c.aconst_null();
239         if (freevars != null)
240             CodeCompiler.makeStrings(c, freevars, freevars.length);
241         else
242             c.aconst_null();
243
244         c.iconst(jy_npurecell);
245
246         c.iconst(moreflags);
247
248         int mref_newCode = c.pool.Methodref(
249             "org/python/core/Py",
250             "newCode",
251             "(I" + $strArr + $str + $str + "IZZ" + $pyFuncTbl + "I" +
252                 $strArr + $strArr + "II)" + $pyCode);
253
254         c.invokestatic(mref_newCode);
255         //c.aconst_null();
256
c.putstatic(module.classfile.name, name, $pyCode);
257     }
258 }
259
260 public class Module implements ClassConstants, CompilationContext
261 {
262     ClassFile classfile;
263     Constant filename;
264     String JavaDoc sfilename;
265     public Constant mainCode;
266     public boolean linenumbers;
267     public boolean setFile=true;
268     Future futures;
269     Hashtable scopes;
270
271     public Module(String JavaDoc name, String JavaDoc filename, boolean linenumbers) {
272         this.linenumbers = linenumbers;
273         classfile = new ClassFile(name, "org/python/core/PyFunctionTable",
274                                   ClassFile.SYNCHRONIZED | ClassFile.PUBLIC);
275         constants = new Hashtable();
276         sfilename = filename;
277         if (filename != null)
278             this.filename = PyString(filename);
279         else
280             this.filename = null;
281         codes = new Vector();
282         futures = new Future();
283         scopes = new Hashtable();
284     }
285
286     public Module(String JavaDoc name) {
287         this(name, name+".py", true);
288     }
289
290     // This block of code handles the pool of Python Constants
291
Hashtable constants;
292
293     private Constant findConstant(Constant c) {
294         Constant ret = (Constant)constants.get(c);
295         if (ret != null)
296             return ret;
297         ret = c;
298         c.module = this;
299         //More sophisticated name mappings might be nice
300
c.name = "_"+constants.size();
301         constants.put(ret, ret);
302         return ret;
303     }
304
305     public Constant PyInteger(int value) {
306         return findConstant(new PyIntegerConstant(value));
307     }
308
309     public Constant PyFloat(double value) {
310         return findConstant(new PyFloatConstant(value));
311     }
312
313     public Constant PyComplex(double value) {
314         return findConstant(new PyComplexConstant(value));
315     }
316
317     public Constant PyString(String JavaDoc value) {
318         return findConstant(new PyStringConstant(value));
319     }
320     public Constant PyLong(String JavaDoc value) {
321         return findConstant(new PyLongConstant(value));
322     }
323
324     /*public PyCodeConstant PyCode(SimpleNode tree, String name,
325       ArgListCompiler ac,
326       boolean fast_locals, boolean class_body)
327       throws Exception {
328       return PyCode(tree, name, ac, fast_locals, class_body, false, 0);
329       }
330       public PyCodeConstant PyCode(SimpleNode tree, String name,
331       ArgListCompiler ac,
332       boolean fast_locals, boolean class_body,
333       int firstlineno)
334       throws Exception {
335       return PyCode(tree, name, ac, fast_locals, class_body, false,
336                     firstlineno);
337       }
338       public PyCodeConstant PyCode(SimpleNode tree, String name,
339       ArgListCompiler ac,
340       boolean fast_locals, boolean class_body,
341       boolean printResults)
342       throws Exception {
343       return PyCode(tree, name, ac, fast_locals, class_body, printResults, 0);
344       }*/

345
346     Vector codes;
347     private boolean isJavaIdentifier(String JavaDoc s) {
348         char[] chars = s.toCharArray();
349         if (chars.length == 0)
350             return false;
351         if (!Character.isJavaIdentifierStart(chars[0]))
352             return false;
353
354         for(int i=1; i<chars.length; i++) {
355             if (!Character.isJavaIdentifierPart(chars[i]))
356                 return false;
357         }
358         return true;
359     }
360
361     private static final String JavaDoc[] emptyStringAr = new String JavaDoc[0];
362
363     private String JavaDoc[] toNameAr(Vector names,boolean nullok) {
364         int sz = names.size();
365         if (sz ==0 && nullok) return null;
366         String JavaDoc[] nameArray = new String JavaDoc[sz];
367         names.copyInto(nameArray);
368         return nameArray;
369     }
370
371
372     private int to_cell;
373
374     public PyCodeConstant PyCode(modType tree, String JavaDoc name,
375                                  boolean fast_locals, String JavaDoc className,
376                                  boolean classBody, boolean printResults,
377                                  int firstlineno, ScopeInfo scope)
378         throws Exception JavaDoc
379     {
380         return PyCode(tree,name,fast_locals,className,classBody,
381                       printResults,firstlineno,scope,null);
382     }
383
384
385     public PyCodeConstant PyCode(modType tree, String JavaDoc name,
386                                  boolean fast_locals, String JavaDoc className,
387                                  boolean classBody, boolean printResults,
388                                  int firstlineno,
389                                  ScopeInfo scope,
390                                  org.python.core.CompilerFlags cflags)
391         throws Exception JavaDoc
392     {
393         PyCodeConstant code = new PyCodeConstant();
394         ArgListCompiler ac = (scope != null)?scope.ac:null;
395
396         if (ac != null) {
397             code.arglist = ac.arglist;
398             code.keywordlist = ac.keywordlist;
399             code.argcount = ac.names.size();
400         }
401
402         code.co_name = name;
403         code.co_firstlineno = firstlineno;
404         code.id = codes.size();
405
406         //Better names in the future?
407
if (isJavaIdentifier(name))
408             code.fname = name+"$"+code.id;
409         else
410             code.fname = "f$"+code.id;
411
412         codes.addElement(code);
413
414         Code c = classfile.addMethod(
415             code.fname,
416             "(" + $pyFrame + ")" + $pyObj,
417             ClassFile.PUBLIC);
418
419         CodeCompiler compiler = new CodeCompiler(this, printResults);
420
421         Label genswitch = c.getLabel();
422         if (scope.generator) {
423             c.goto_(genswitch);
424         }
425         Label start = c.getLabel();
426         start.setPosition();
427
428         //Do something to add init_code to tree
429
if (ac != null && ac.init_code.size() > 0) {
430             ac.appendInitCode((Suite) tree);
431         }
432
433         if (scope != null) {
434           int nparamcell = scope.jy_paramcells.size();
435           if (nparamcell > 0) {
436             if (to_cell == 0) {
437                 to_cell = classfile.pool.Methodref("org/python/core/PyFrame",
438                     "to_cell","(II)V");
439             }
440             Hashtable tbl = scope.tbl;
441             Vector paramcells = scope.jy_paramcells;
442             for (int i = 0; i < nparamcell; i++) {
443                 c.aload(1);
444                 SymInfo syminf = (SymInfo)tbl.get(paramcells.elementAt(i));
445                 c.iconst(syminf.locals_index);
446                 c.iconst(syminf.env_index);
447                 c.invokevirtual(to_cell);
448             }
449           }
450         }
451
452         compiler.parse(tree, c, fast_locals, className, classBody,
453                        scope, cflags);
454
455         if (scope.generator) {
456             genswitch.setPosition();
457             c.aload(1);
458             if (compiler.f_lasti == 0) {
459                 compiler.f_lasti = c.pool.Fieldref(
460                         "org/python/core/PyFrame", "f_lasti", "I");
461             }
462             c.getfield(compiler.f_lasti);
463
464             Label[] yields = new Label[compiler.yields.size()+1];
465
466             yields[0] = start;
467             for (int i = 1; i < yields.length; i++) {
468                 yields[i] = (Label) compiler.yields.elementAt(i-1);
469             }
470             c.tableswitch(start, 0, yields);
471             // XXX: Generate an error
472
}
473
474         // !classdef only
475
if (!classBody) code.names = toNameAr(compiler.names,false);
476
477         if (scope != null) {
478             code.cellvars = toNameAr(scope.cellvars,true);
479             code.freevars = toNameAr(scope.freevars,true);
480             code.jy_npurecell = scope.jy_npurecell;
481         }
482
483         if (compiler.optimizeGlobals) {
484             code.moreflags |= org.python.core.PyTableCode.CO_OPTIMIZED;
485         }
486         if (compiler.my_scope.generator) {
487             code.moreflags |= org.python.core.PyTableCode.CO_GENERATOR;
488         }
489         if (cflags != null) {
490             if (cflags.generator_allowed) {
491                 code.moreflags |= org.python.core.PyTableCode.CO_GENERATOR_ALLOWED;
492             }
493             if (cflags.division) {
494                 code.moreflags |= org.python.core.PyTableCode.CO_FUTUREDIVISION;
495             }
496         }
497
498         code.module = this;
499         code.name = code.fname;
500         return code;
501     }
502
503     //This block of code writes out the various standard methods
504
public void addInit() throws IOException {
505         Code c = classfile.addMethod("<init>", "()V", ClassFile.PUBLIC);
506         c.aload(0);
507         c.invokespecial(c.pool.Methodref("org/python/core/PyFunctionTable",
508                                          "<init>",
509                                          "()V"));
510         c.return_();
511     }
512
513     public void addRunnable() throws IOException {
514         Code c = classfile.addMethod("getMain",
515                                      "()" + $pyCode,
516                                      ClassFile.PUBLIC);
517         mainCode.get(c);
518         c.areturn();
519     }
520
521     public void addMain() throws IOException {
522         Code c = classfile.addMethod("main", "(" + $str + ")V",
523                                      ClassFile.PUBLIC | ClassFile.STATIC);
524
525
526         int mref_self = c.pool.Fieldref(classfile.name,
527                                         "self",
528                                         "L"+classfile.name+";");
529         c.getstatic(mref_self);
530         c.aload(0);
531         c.invokestatic(c.pool.Methodref(
532             "org/python/core/Py",
533             "do_main",
534             "(" + $pyRunnable + $strArr + ")V"));
535         c.return_();
536     }
537
538     public void addConstants() throws IOException {
539         Code c = classfile.addMethod("<clinit>", "()V", ClassFile.STATIC);
540
541         classfile.addField("self", "L"+classfile.name+";",
542                            ClassFile.STATIC|ClassFile.FINAL);
543         c.new_(c.pool.Class(classfile.name));
544         c.dup();
545         c.invokespecial(c.pool.Methodref(classfile.name, "<init>", "()V"));
546         c.putstatic(c.pool.Fieldref(classfile.name,
547                                     "self",
548                                     "L"+classfile.name+";"));
549
550         Enumeration e = constants.elements();
551
552         while (e.hasMoreElements()) {
553             Constant constant = (Constant)e.nextElement();
554             constant.put(c);
555         }
556
557         for(int i=0; i<codes.size(); i++) {
558             PyCodeConstant pyc = (PyCodeConstant)codes.elementAt(i);
559             pyc.put(c);
560         }
561
562         c.return_();
563     }
564
565     public void addFunctions() throws IOException {
566         Code code = classfile.addMethod(
567             "call_function",
568             "(I" + $pyFrame + ")" + $pyObj,
569             ClassFile.PUBLIC);
570
571         Label def = code.getLabel();
572         Label[] labels = new Label[codes.size()];
573         int i;
574         for(i=0; i<labels.length; i++)
575             labels[i] = code.getLabel();
576
577         //Get index for function to call
578
code.iload(1);
579
580         code.tableswitch(def, 0, labels);
581         for(i=0; i<labels.length; i++) {
582             labels[i].setPosition();
583             code.aload(0);
584             code.aload(2);
585             code.invokevirtual(
586                 classfile.name,
587                 ((PyCodeConstant)codes.elementAt(i)).fname,
588                 "(" + $pyFrame + ")" + $pyObj);
589             code.areturn();
590         }
591         def.setPosition();
592
593         //Should probably throw internal exception here
594
code.aconst_null();
595         code.areturn();
596
597     }
598
599     public void write(OutputStream stream) throws IOException {
600         addInit();
601         addRunnable();
602         //addMain();
603

604         addConstants();
605         addFunctions();
606
607         classfile.addInterface("org/python/core/PyRunnable");
608         if (sfilename != null) {
609             classfile.addAttribute(new SourceFile(sfilename, classfile.pool));
610         }
611         classfile.addAttribute(new APIVersion(org.python.core.imp.APIVersion,
612                                               classfile.pool));
613         classfile.write(stream);
614     }
615
616     // Implementation of CompilationContext
617
public Future getFutures() { return futures; }
618
619     public String JavaDoc getFilename() { return sfilename; }
620
621     public ScopeInfo getScopeInfo(SimpleNode node) {
622         return (ScopeInfo) scopes.get(node);
623     }
624
625     public void error(String JavaDoc msg,boolean err,SimpleNode node)
626         throws Exception JavaDoc
627     {
628         if (!err) {
629             try {
630                 Py.warning(Py.SyntaxWarning, msg,
631                            (sfilename != null) ? sfilename : "?",
632                            node.beginLine ,null, Py.None);
633                 return;
634             } catch(PyException e) {
635                 if (!Py.matchException(e, Py.SyntaxWarning))
636                     throw e;
637             }
638         }
639         throw new ParseException(msg,node);
640     }
641
642     public static void compile(modType node, OutputStream ostream,
643                                String JavaDoc name, String JavaDoc filename,
644                                boolean linenumbers, boolean printResults,
645                                boolean setFile,
646                                org.python.core.CompilerFlags cflags)
647         throws Exception JavaDoc
648     {
649         Module module = new Module(name, filename, linenumbers);
650         module.setFile = setFile;
651         module.futures.preprocessFutures(node, cflags);
652         new ScopesCompiler(module, module.scopes).parse(node);
653
654         //Add __doc__ if it exists
655
//Add __file__ for filename (if it exists?)
656

657         Constant main = module.PyCode(node, "?", false, null, false,
658                                       printResults, 0,
659                                       module.getScopeInfo(node),
660                                       cflags);
661         module.mainCode = main;
662         module.write(ostream);
663     }
664 }
665
Popular Tags