KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > python > core > PyTableCode


1 // Copyright (c) Corporation for National Research Initiatives
2
package org.python.core;
3
4 /**
5  * An implementation of PyCode where the actual executable content
6  * is stored as a PyFunctionTable instance and an integer index.
7  */

8
9 public class PyTableCode extends PyCode
10 {
11     public int co_argcount;
12     int nargs;
13     public int co_firstlineno = -1;
14     public String JavaDoc co_varnames[];
15     public String JavaDoc co_cellvars[];
16     public int jy_npurecell; // internal: jython specific
17
public String JavaDoc co_freevars[];
18     public String JavaDoc co_filename;
19     public int co_flags;
20     public int co_nlocals;
21     public boolean args, keywords;
22     PyFunctionTable funcs;
23     int func_id;
24
25     final public static int CO_OPTIMIZED = 0x0001;
26     //final public static int CO_NEWLOCALS = 0x0002
27
final public static int CO_VARARGS = 0x0004;
28     final public static int CO_VARKEYWORDS = 0x0008;
29     final public static int CO_GENERATOR = 0x0020;
30     
31     final public static int CO_NESTED = 0x0010;
32     final public static int CO_GENERATOR_ALLOWED = 0x1000;
33     final public static int CO_FUTUREDIVISION = 0x2000;
34     final public static int CO_ALL_FEATURES = CO_NESTED|CO_GENERATOR_ALLOWED|CO_FUTUREDIVISION;
35
36
37     public PyTableCode(int argcount, String JavaDoc varnames[],
38                        String JavaDoc filename, String JavaDoc name,
39                        int firstlineno,
40                        boolean args, boolean keywords,
41                        PyFunctionTable funcs, int func_id)
42     {
43         this(argcount, varnames, filename, name, firstlineno, args,
44              keywords, funcs, func_id, null, null, 0, 0);
45     }
46
47     public PyTableCode(int argcount, String JavaDoc varnames[],
48                        String JavaDoc filename, String JavaDoc name,
49                        int firstlineno,
50                        boolean args, boolean keywords,
51                        PyFunctionTable funcs, int func_id,
52                        String JavaDoc[] cellvars, String JavaDoc[] freevars, int npurecell,
53                        int moreflags) // may change
54
{
55         co_argcount = nargs = argcount;
56         co_varnames = varnames;
57         co_nlocals = varnames.length;
58         co_filename = filename;
59         co_firstlineno = firstlineno;
60         co_cellvars = cellvars;
61         co_freevars = freevars;
62         this.jy_npurecell = npurecell;
63         this.args = args;
64         co_name = name;
65         if (args) {
66             co_argcount -= 1;
67             co_flags |= CO_VARARGS;
68         }
69         this.keywords = keywords;
70         if (keywords) {
71             co_argcount -= 1;
72             co_flags |= CO_VARKEYWORDS;
73         }
74         co_flags |= moreflags;
75         this.funcs = funcs;
76         this.func_id = func_id;
77     }
78
79     private static final String JavaDoc[] __members__ = {
80         "co_name", "co_argcount",
81         "co_varnames", "co_filename", "co_firstlineno",
82         "co_flags","co_cellvars","co_freevars","co_nlocals"
83         // not supported: co_code, co_consts, co_names,
84
// co_lnotab, co_stacksize
85
};
86
87     public PyObject __dir__() {
88         PyString members[] = new PyString[__members__.length];
89         for (int i = 0; i < __members__.length; i++)
90             members[i] = new PyString(__members__[i]);
91         return new PyList(members);
92     }
93
94     private void throwReadonly(String JavaDoc name) {
95         for (int i = 0; i < __members__.length; i++)
96             if (__members__[i] == name)
97                 throw Py.TypeError("readonly attribute");
98         throw Py.AttributeError(name);
99     }
100
101     public void __setattr__(String JavaDoc name, PyObject value) {
102         // no writable attributes
103
throwReadonly(name);
104     }
105
106     public void __delattr__(String JavaDoc name) {
107         throwReadonly(name);
108     }
109
110     private static PyTuple toPyStringTuple(String JavaDoc[] ar) {
111         if (ar == null) return Py.EmptyTuple;
112         int sz = ar.length;
113         PyString[] pystr = new PyString[sz];
114         for (int i = 0; i < sz; i++) {
115             pystr[i] = new PyString(ar[i]);
116         }
117         return new PyTuple(pystr);
118     }
119
120     public PyObject __findattr__(String JavaDoc name) {
121         // have to craft co_varnames specially
122
if (name == "co_varnames") return toPyStringTuple(co_varnames);
123         if (name == "co_cellvars") return toPyStringTuple(co_cellvars);
124         if (name == "co_freevars") return toPyStringTuple(co_freevars);
125         return super.__findattr__(name);
126     }
127
128     public PyObject call(PyFrame frame, PyObject closure) {
129 // System.err.println("tablecode call: "+co_name);
130
ThreadState ts = Py.getThreadState();
131         if (ts.systemState == null) {
132             ts.systemState = Py.defaultSystemState;
133         }
134         //System.err.println("got ts: "+ts+", "+ts.systemState);
135

136         // Cache previously defined exception
137
PyException previous_exception = ts.exception;
138
139         // Push frame
140
frame.f_back = ts.frame;
141         if (frame.f_builtins == null) {
142             if (frame.f_back != null) {
143                 frame.f_builtins = frame.f_back.f_builtins;
144             } else {
145                 //System.err.println("ts: "+ts);
146
//System.err.println("ss: "+ts.systemState);
147
frame.f_builtins = ts.systemState.builtins;
148             }
149         }
150         // nested scopes: setup env with closure
151
int env_j = 0;
152         int ncells = frame.f_ncells;
153         int nfreevars = frame.f_nfreevars;
154         PyCell[] env = frame.f_env;
155         PyTuple freevars = (PyTuple)closure;
156         for (int i = 0; i < ncells; i++,env_j++) {
157             env[env_j] = new PyCell();
158         }
159         for (int i=0; i<nfreevars; i++,env_j++) {
160             env[env_j] = (PyCell)freevars.pyget(i);
161         }
162
163         ts.frame = frame;
164
165         // Handle trace function for debugging
166
PySystemState ss = ts.systemState;
167         if (ss.tracefunc != null) {
168             // JPython and CPython differ here. CPython actually lays down
169
// an extra SET_LINENO bytecode for function definition line.
170
// This is ostensibly so that a tuple unpacking failure in
171
// argument passing gets the right line number in the
172
// traceback. It also means that when tracing a function,
173
// you'll see two 'line' events, one for the def line and then
174
// immediately after, one for the first line of the function.
175
//
176
// JPython on the other hand only lays down a call in the
177
// generated Java function to set the line number for the first
178
// line of the function (i.e. not the def line). This
179
// difference in behavior doesn't seem to affect arg tuple
180
// unpacking tracebacks, but it does mean that function tracing
181
// gives slightly different behavior. Is this bad? Until
182
// someone complains... no.
183
//
184
// The second commented out line fixes this but it is probably
185
// not the right solution. Better would be to fix the code
186
// generator to lay down two calls to setline() in the
187
// classfile. This would allow that call to be optimized out
188
// when using the -O option. I suppose on the other hand we
189
// could test that flag here and not call the setline below.
190
// In either case, it probably doesn't make sense to slow down
191
// function calling even by this miniscule amount until it's
192
// shown to have a detrimental effect.
193
//
194
// Note also that if you were to print out frame.f_lineno in
195
// the `call' event handler of your trace function, you'd see
196
// zero instead of the line of the def. That's what the first
197
// commented line fixes.
198
//
199
// 9-Sep-1999 baw
200
//
201
// frame.f_lineno = co_firstlineno;
202
frame.tracefunc = ss.tracefunc.traceCall(frame);
203             frame.setline(co_firstlineno);
204         }
205
206         // Handle trace function for profiling
207
if (ss.profilefunc != null) {
208             ss.profilefunc.traceCall(frame);
209         }
210
211         PyObject ret;
212         try {
213             ret = funcs.call_function(func_id, frame);
214         } catch (Throwable JavaDoc t) {
215             //t.printStackTrace();
216
//Convert exceptions that occured in Java code to PyExceptions
217
PyException e = Py.JavaError(t);
218
219             //Add another traceback object to the exception if needed
220
if (e.traceback.tb_frame != frame) {
221                 PyTraceback tb = new PyTraceback(e.traceback.tb_frame.f_back);
222                 tb.tb_next = e.traceback;
223                 e.traceback = tb;
224             }
225
226             frame.f_lasti = -1;
227
228             if (frame.tracefunc != null) {
229                 frame.tracefunc.traceException(frame, e);
230             }
231             if (ss.profilefunc != null) {
232                 ss.profilefunc.traceException(frame, e);
233             }
234
235             //Rethrow the exception to the next stack frame
236
ts.exception = previous_exception;
237             ts.frame = ts.frame.f_back;
238             throw e;
239         }
240
241         if (frame.tracefunc != null) {
242             frame.tracefunc.traceReturn(frame, ret);
243         }
244         // Handle trace function for profiling
245
if (ss.profilefunc != null) {
246             ss.profilefunc.traceReturn(frame, ret);
247         }
248
249         // Restore previously defined exception
250
ts.exception = previous_exception;
251
252         ts.frame = ts.frame.f_back;
253         return ret;
254     }
255
256     public PyObject call(PyObject globals, PyObject[] defaults,
257                          PyObject closure)
258     {
259         if (co_argcount != 0 || args || keywords)
260             return call(Py.EmptyObjects, Py.NoKeywords, globals, defaults,
261                         closure);
262         PyFrame frame = new PyFrame(this, globals);
263         if ((co_flags & CO_GENERATOR) != 0) {
264             return new PyGenerator(frame, closure);
265         }
266         return call(frame, closure);
267     }
268
269     public PyObject call(PyObject arg1, PyObject globals, PyObject[] defaults,
270                          PyObject closure)
271     {
272         if (co_argcount != 1 || args || keywords)
273             return call(new PyObject[] {arg1},
274                         Py.NoKeywords, globals, defaults, closure);
275         PyFrame frame = new PyFrame(this, globals);
276         frame.f_fastlocals[0] = arg1;
277         if ((co_flags & CO_GENERATOR) != 0) {
278             return new PyGenerator(frame, closure);
279         }
280         return call(frame, closure);
281     }
282
283     public PyObject call(PyObject arg1, PyObject arg2, PyObject globals,
284                          PyObject[] defaults, PyObject closure)
285     {
286         if (co_argcount != 2 || args || keywords)
287             return call(new PyObject[] {arg1, arg2},
288                         Py.NoKeywords, globals, defaults, closure);
289         PyFrame frame = new PyFrame(this, globals);
290         frame.f_fastlocals[0] = arg1;
291         frame.f_fastlocals[1] = arg2;
292         if ((co_flags & CO_GENERATOR) != 0) {
293             return new PyGenerator(frame, closure);
294         }
295         return call(frame, closure);
296     }
297
298     public PyObject call(PyObject arg1, PyObject arg2, PyObject arg3,
299                          PyObject globals, PyObject[] defaults,
300                          PyObject closure)
301     {
302         if (co_argcount != 3 || args || keywords)
303             return call(new PyObject[] {arg1, arg2, arg3},
304                         Py.NoKeywords, globals, defaults, closure);
305         PyFrame frame = new PyFrame(this, globals);
306         frame.f_fastlocals[0] = arg1;
307         frame.f_fastlocals[1] = arg2;
308         frame.f_fastlocals[2] = arg3;
309         if ((co_flags & CO_GENERATOR) != 0) {
310             return new PyGenerator(frame, closure);
311         }
312         return call(frame, closure);
313     }
314
315     public PyObject call(PyObject self, PyObject call_args[],
316                          String JavaDoc call_keywords[], PyObject globals,
317                          PyObject[] defaults, PyObject closure)
318     {
319         PyObject[] os = new PyObject[call_args.length+1];
320         os[0] = (PyObject)self;
321         System.arraycopy(call_args, 0, os, 1, call_args.length);
322         return call(os, call_keywords, globals, defaults, closure);
323     }
324
325     private String JavaDoc prefix() {
326         return co_name.toString()+"() ";
327     }
328
329     public PyObject call(PyObject call_args[], String JavaDoc call_keywords[],
330                          PyObject globals, PyObject[] defaults,
331                          PyObject closure)
332     {
333         //Needs try except finally blocks
334
PyFrame my_frame = new PyFrame(this, globals);
335
336         PyObject actual_args[], extra_args[] = null;
337         PyDictionary extra_keywords = null;
338         int plain_args = call_args.length - call_keywords.length;
339         int i;
340
341         if (plain_args > co_argcount)
342             plain_args = co_argcount;
343
344         actual_args = my_frame.f_fastlocals;
345         if (plain_args > 0)
346             System.arraycopy(call_args, 0, actual_args, 0, plain_args);
347
348         if (!((call_keywords == null || call_keywords.length == 0) &&
349               call_args.length == co_argcount && !keywords && !args))
350         {
351             if (keywords)
352                 extra_keywords = new PyDictionary();
353
354             for (i=0; i<call_keywords.length; i++) {
355                 int index=0;
356                 while (index<co_argcount) {
357                     if (co_varnames[index].equals(call_keywords[i]))
358                         break;
359                     index++;
360                 }
361                 if (index < co_argcount) {
362                     if (actual_args[index] != null) {
363                         throw Py.TypeError(prefix()+
364                                            "got multiple values for " +
365                                            "keyword argument '"+
366                                            call_keywords[i] + "'");
367                     }
368                     actual_args[index] =
369                         call_args[i+(call_args.length-call_keywords.length)];
370                 }
371                 else {
372                     if (extra_keywords == null) {
373                         throw Py.TypeError(prefix()+
374                                            "got an unexpected keyword " +
375                                            "argument '"+ call_keywords[i] +
376                                            "'");
377                     }
378                     extra_keywords.__setitem__(
379                         call_keywords[i],
380                         call_args[i+(call_args.length-call_keywords.length)]);
381                 }
382             }
383             if (call_args.length-call_keywords.length > co_argcount) {
384                 if (!args)
385                     throw Py.TypeError(
386                         prefix()+
387                         "too many arguments; expected "+
388                         co_argcount+" got "+
389                         (call_args.length-call_keywords.length));
390                 extra_args = new PyObject[call_args.length-
391                                          call_keywords.length-
392                                          co_argcount];
393
394                 for (i=0; i<extra_args.length; i++) {
395                     extra_args[i] = call_args[i+co_argcount];
396                 }
397             }
398             for (i=plain_args; i<co_argcount; i++) {
399                 if (actual_args[i] == null) {
400                     if (co_argcount-i > defaults.length) {
401                         int min = co_argcount-defaults.length;
402                         throw Py.TypeError(
403                             prefix()+
404                             "takes at least " + min +
405                             (min == 1 ? " argument (" : " arguments (") +
406                             (call_args.length-call_keywords.length)+
407                             " given)");
408                     }
409                     actual_args[i] =
410                           defaults[defaults.length-(co_argcount-i)];
411                 }
412             }
413             if (args) {
414                 if (extra_args == null)
415                     actual_args[co_argcount] = Py.EmptyTuple;
416                 else
417                     actual_args[co_argcount] = new PyTuple(extra_args);
418             }
419             if (extra_keywords != null) {
420                 actual_args[nargs-1] = extra_keywords;
421             }
422         }
423         if ((co_flags & CO_GENERATOR) != 0) {
424             return new PyGenerator(my_frame, closure);
425         }
426         return call(my_frame, closure);
427     }
428
429     public String JavaDoc toString() {
430         return "<code object " + co_name + " "+Py.idstr(this) +
431             ", file \"" + co_filename + "\", line " +
432             co_firstlineno + ">";
433     }
434 }
435
Popular Tags