Source Code Cross Referenced for ClassGenerator.java in  » Scripting » Pnuts » pnuts » compiler » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » Pnuts » pnuts.compiler 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * ClassGenerator.java
003:         *
004:         * Copyright (c) 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
005:         *
006:         * See the file "LICENSE.txt" for information on usage and redistribution
007:         * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008:         */
009:        package pnuts.compiler;
010:
011:        import java.lang.reflect.Constructor;
012:        import java.lang.reflect.Method;
013:        import java.lang.reflect.Modifier;
014:        import java.util.ArrayList;
015:        import java.util.HashSet;
016:        import java.util.Iterator;
017:        import java.util.List;
018:        import java.util.Set;
019:        import org.pnuts.lang.ObjectDescFactory;
020:        import org.pnuts.lang.PropertyHandler;
021:        import org.pnuts.lang.ReflectionUtil;
022:        import org.pnuts.lang.Signature;
023:        import pnuts.lang.AbstractData;
024:        import pnuts.lang.Context;
025:        import pnuts.lang.PnutsParserTreeConstants;
026:        import pnuts.lang.SimpleNode;
027:        import pnuts.lang.Runtime;
028:
029:        public class ClassGenerator {
030:            public final static int THIS_BIT = 0x0001;
031:            public final static int SUPER_BIT = 0x0002;
032:            final static String SUPER_PROXY_NAME = "pnuts.compiler.ClassGenerator$SuperCallProxy";
033:
034:            public static ClassFile createClassFile(String className,
035:                    Class super Class, Class[] interfaceTypes,
036:                    Set super MethodNames) {
037:                ClassSpec[] interfaces = new ClassSpec[interfaceTypes.length];
038:                for (int i = 0; i < interfaces.length; i++) {
039:                    interfaces[i] = ClassSpec.create(interfaceTypes[i]);
040:                }
041:                return createClassFile(className, ClassSpec.create(super Class),
042:                        interfaces, super MethodNames);
043:            }
044:
045:            public static ClassFile createClassFile(String className,
046:                    ClassSpec super classSpec, ClassSpec[] interfaces,
047:                    Set super MethodNames) {
048:                Class super Class = super classSpec.compileTimeClass;
049:                if (super Class == null) {
050:                    super Class = Object.class;
051:                }
052:                ClassFile cf = new ClassFile(className,
053:                        super classSpec.className, null, Constants.ACC_PUBLIC);
054:                if (interfaces != null) {
055:                    for (int i = 0; i < interfaces.length; i++) {
056:                        cf.addInterface(interfaces[i].className);
057:                    }
058:                }
059:                cf.addField("_context", "Lpnuts/lang/Context;",
060:                        (short) (Constants.ACC_PRIVATE | Constants.ACC_STATIC));
061:
062:                super Call(cf, super Class, super MethodNames);
063:
064:                return cf;
065:
066:            }
067:
068:            public static void constructor(ClassFile cf,
069:                    ClassSpec super classSpec, Compiler compiler,
070:                    CompileContext cc, List/*<Signature>*/signatures) {
071:                String super className = super classSpec.className;
072:                Class super Class = super classSpec.compileTimeClass;
073:                Set/*<Constructor>*/protected_constructors = new HashSet();
074:                if (super Class == null) {
075:                    super Class = Object.class;
076:                }
077:
078:                getProtectedConstructors(super Class, new HashSet(),
079:                        protected_constructors);
080:                Constructor[] public_constructors = super Class
081:                        .getConstructors();
082:
083:                Set/*<Signature>*/generated_constructors = new HashSet();
084:                int num_constructors = 0;
085:                ;
086:
087:                for (int i = 0, n = signatures.size(); i < n; i++) {
088:                    Signature sig = (Signature) signatures.get(i);
089:                    //		    SimpleNode fnode = (SimpleNode)sig.nodeInfo;
090:
091:                    int modifiers = sig.getModifiers();
092:                    Class[] parameterTypes;
093:                    Class[] exceptionTypes;
094:
095:                    List constructors = new ArrayList();
096:                    if (sig.resolveAsConstructor(super Class, constructors)) {
097:                        for (int j = 0, n2 = constructors.size(); j < n2; j++) {
098:                            Constructor cons = (Constructor) constructors
099:                                    .get(j);
100:                            parameterTypes = cons.getParameterTypes();
101:                            exceptionTypes = cons.getExceptionTypes();
102:                            constructor(cf, cc, compiler, super classSpec,
103:                                    parameterTypes, exceptionTypes,
104:                                    Constants.ACC_PUBLIC);
105:                            generated_constructors
106:                                    .add(new Signature(null, void.class,
107:                                            parameterTypes, exceptionTypes));
108:                            num_constructors++;
109:                        }
110:                    } else {
111:                        parameterTypes = sig.getParameterTypes();
112:                        exceptionTypes = sig.getExceptionTypes();
113:                        constructor(cf, cc, compiler, super classSpec,
114:                                parameterTypes, exceptionTypes,
115:                                Constants.ACC_PUBLIC);
116:                        generated_constructors.add(new Signature(null,
117:                                void.class, parameterTypes, exceptionTypes));
118:                        num_constructors++;
119:
120:                    }
121:                }
122:                for (int i = 0; i < public_constructors.length; i++) {
123:                    Constructor cons = public_constructors[i];
124:                    Class[] parameterTypes = cons.getParameterTypes();
125:                    Class[] exceptionTypes = cons.getExceptionTypes();
126:                    Signature sig = new Signature(null, void.class,
127:                            parameterTypes, exceptionTypes);
128:                    if (!generated_constructors.contains(sig)) {
129:                        derivedConstructors(cf, cc, compiler, super Class,
130:                                super className, parameterTypes, exceptionTypes,
131:                                Constants.ACC_PUBLIC);
132:                        num_constructors++;
133:                    }
134:                }
135:                if (num_constructors == 0) {
136:                    cf.openMethod("<init>", "()V", Constants.ACC_PUBLIC);
137:                    cf.add(Opcode.ALOAD_0);
138:                    cf.add(Opcode.INVOKESPECIAL, super className, "<init>",
139:                            "()", "V");
140:                    cf.add(Opcode.ALOAD_0);
141:                    cf.add(Opcode.INVOKEVIRTUAL, cf.getClassName(),
142:                            "__initialize", "()", "V");
143:
144:                    cf.add(Opcode.RETURN);
145:                    cf.closeMethod();
146:                    generated_constructors.add(new Signature(null, void.class,
147:                            new Class[0], new Class[0]));
148:                }
149:                for (Iterator it = protected_constructors.iterator(); it
150:                        .hasNext();) {
151:                    Constructor cons = (Constructor) it.next();
152:                    Class[] parameterTypes = cons.getParameterTypes();
153:                    Class[] exceptionTypes = cons.getExceptionTypes();
154:                    Signature sig = new Signature(null, void.class,
155:                            parameterTypes, exceptionTypes);
156:                    if (!generated_constructors.contains(sig)) {
157:                        derivedConstructors(cf, cc, compiler, super Class,
158:                                super className, parameterTypes, exceptionTypes,
159:                                Constants.ACC_PROTECTED);
160:                    }
161:                }
162:            }
163:
164:            /*
165:             * derived constructors that just calls super(...)
166:             */
167:            static void derivedConstructors(ClassFile cf, CompileContext cc,
168:                    Compiler compiler, Class super Class, String super className,
169:                    Class[] parameterTypes, Class[] exceptionTypes,
170:                    short modifier) {
171:                String sig = ClassFile.signature(parameterTypes);
172:
173:                String[] exceptionTypeInfo = null;
174:                if (exceptionTypes != null && exceptionTypes.length > 0) {
175:                    exceptionTypeInfo = new String[exceptionTypes.length];
176:                    for (int j = 0; j < exceptionTypes.length; j++) {
177:                        exceptionTypeInfo[j] = exceptionTypes[j].getName();
178:                    }
179:                }
180:                cf.openMethod("<init>", sig + "V", modifier, exceptionTypeInfo);
181:                cf.add(Opcode.ALOAD_0);
182:                int pos = 1;
183:                for (int i = 0; i < parameterTypes.length; i++) {
184:                    Class type = parameterTypes[i];
185:                    if (type.isPrimitive()) {
186:                        if (type == long.class) {
187:                            cf.lloadLocal(pos);
188:                            pos += 2;
189:                        } else if (type == double.class) {
190:                            cf.dloadLocal(pos);
191:                            pos += 2;
192:                        } else if (type == float.class) {
193:                            cf.floadLocal(pos++);
194:                        } else if (type == int.class || type == byte.class
195:                                || type == short.class || type == char.class
196:                                || type == boolean.class) {
197:                            cf.iloadLocal(pos++);
198:                        }
199:                    } else {
200:                        cf.loadLocal(pos++);
201:                    }
202:                }
203:                cf
204:                        .add(Opcode.INVOKESPECIAL, super className, "<init>",
205:                                sig, "V");
206:
207:                /*
208:                 * __initialize(this);
209:                 */
210:                cf.add(Opcode.ALOAD_0);
211:                cf.add(Opcode.INVOKEVIRTUAL, cf.getClassName(), "__initialize",
212:                        "()", "V");
213:
214:                cf.add(Opcode.RETURN);
215:                cf.closeMethod();
216:            }
217:
218:            /*
219:             * user defined constructors
220:             */
221:            static void constructor(ClassFile cf, Context cc,
222:                    Compiler compiler, ClassSpec super classSpec,
223:                    Class[] parameterTypes, Class[] exceptionTypes,
224:                    short modifier) {
225:                String className = cf.getClassName();
226:                for (int i = 0; i < parameterTypes.length; i++) {
227:                    if (parameterTypes[i] == null) {
228:                        parameterTypes[i] = Object.class;
229:                    }
230:                }
231:                String sig = ClassFile.signature(parameterTypes);
232:                String methodID = Signature.toJavaIdentifier(sig);
233:
234:                String[] exceptionTypeInfo = null;
235:                if (exceptionTypes != null && exceptionTypes.length > 0) {
236:                    exceptionTypeInfo = new String[exceptionTypes.length];
237:                    for (int j = 0; j < exceptionTypes.length; j++) {
238:                        exceptionTypeInfo[j] = exceptionTypes[j].getName();
239:                    }
240:                }
241:
242:                cf.openMethod("<init>", sig + "V", modifier, exceptionTypeInfo);
243:
244:                cf.add(Opcode.ALOAD_0);
245:                cf.add(Opcode.INVOKESPECIAL, super classSpec.className,
246:                        "<init>", "()", "V");
247:
248:                cf.add(Opcode.ALOAD_0);
249:                cf.add(Opcode.INVOKEVIRTUAL, cf.getClassName(), "__initialize",
250:                        "()", "V");
251:
252:                cf.add(Opcode.ALOAD_0);
253:                cf.add(Opcode.GETFIELD, className, methodID,
254:                        "Lpnuts/lang/PnutsFunction;");
255:                int f = cf.getLocal();
256:
257:                cf.storeLocal(f);
258:                cf.loadLocal(f);
259:                Label nonnull = cf.getLabel();
260:                cf.add(Opcode.IFNONNULL, nonnull);
261:                cf.add(Opcode.RETURN);
262:
263:                nonnull.fix();
264:                cf.loadLocal(f);
265:                cf.add(Opcode.CHECKCAST, "pnuts.lang.PnutsFunction");
266:
267:                int nargs = parameterTypes.length;
268:                if (nargs <= -0x8000 || nargs >= 0x8000) {
269:                    throw new RuntimeException("too many parameters");
270:                }
271:
272:                Label catchStart = cf.getLabel(true);
273:
274:                int k = 0;
275:
276:                cf.pushInteger(nargs);
277:                cf.add(Opcode.ANEWARRAY, "java.lang.Object");
278:
279:                for (int j = 0; j < nargs; j++) {
280:                    cf.add(Opcode.DUP);
281:                    cf.pushInteger(j + k);
282:                    Class paramType = parameterTypes[j];
283:                    if (paramType != null && paramType.isPrimitive()) {
284:                        loadPrimitive(cf, paramType, j + 1);
285:                        if (paramType.equals(long.class)
286:                                || paramType.equals(double.class)) {
287:                            j++;
288:                        }
289:                    } else {
290:                        cf.loadLocal(j + 1);
291:                    }
292:                    cf.add(Opcode.AASTORE);
293:                }
294:                k = 0;
295:
296:                cf.add(Opcode.GETSTATIC, className, "_context",
297:                        "Lpnuts/lang/Context;");
298:                cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.PnutsFunction",
299:                        "call", "([Ljava/lang/Object;Lpnuts/lang/Context;)",
300:                        "Ljava/lang/Object;");
301:
302:                cf.add(Opcode.POP);
303:                cf.add(Opcode.RETURN);
304:
305:                Label catchEnd = cf.getLabel(true);
306:                Label catchTarget = cf.getLabel(true);
307:                cf.reserveStack(1);
308:                int pex = cf.getLocal();
309:                cf.storeLocal(pex);
310:
311:                cf.loadLocal(pex);
312:                cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.PnutsException",
313:                        "getThrowable", "()", "Ljava/lang/Throwable;");
314:                int ex = cf.getLocal();
315:                cf.storeLocal(ex);
316:                Label next;
317:                if (exceptionTypeInfo != null) {
318:                    for (int i = 0; i < exceptionTypeInfo.length; i++) {
319:                        next = cf.getLabel();
320:                        cf.loadLocal(ex);
321:                        cf.add(Opcode.INSTANCEOF, exceptionTypeInfo[i]);
322:                        cf.add(Opcode.IFEQ, next);
323:                        cf.loadLocal(ex);
324:                        cf.add(Opcode.ATHROW);
325:                        next.fix();
326:                    }
327:                }
328:
329:                cf.loadLocal(pex);
330:                cf.add(Opcode.ATHROW);
331:                cf.addExceptionHandler(catchStart, catchEnd, catchTarget,
332:                        "pnuts.lang.PnutsException");
333:                cf.closeMethod();
334:            }
335:
336:            /*
337:             * this._superCallProxy = new SuperCallProxy(this);
338:             */
339:            static void assignSuperCallProxy(ClassFile cf, String className) {
340:                cf.add(Opcode.ALOAD_0);
341:                cf.add(Opcode.NEW, SUPER_PROXY_NAME);
342:                cf.add(Opcode.DUP);
343:                cf.add(Opcode.ALOAD_0);
344:                cf.add(Opcode.INVOKESPECIAL, SUPER_PROXY_NAME, "<init>",
345:                        "(Ljava/lang/Object;)", "V");
346:                cf.add(Opcode.PUTFIELD, className, "_superCallProxy",
347:                        "Lpnuts/lang/AbstractData;");
348:            }
349:
350:            /*
351:             * private AbstractData _superCallProxy;
352:             *
353:             * public <Type> $super$<MethodName>(...){ super. <MethodName>(...); } ...
354:             */
355:            private static void super Call(ClassFile cf, Class super Class,
356:                    Set super MethodNames) {
357:                Method[] methods = ReflectionUtil
358:                        .getInheritableMethods(super Class);
359:                for (int i = 0; i < methods.length; i++) {
360:                    Method m = methods[i];
361:
362:                    int modifiers = m.getModifiers();
363:                    if (!Modifier.isStatic(modifiers)
364:                            && !Modifier.isFinal(modifiers)
365:                            && (Modifier.isPublic(modifiers) || Modifier
366:                                    .isProtected(modifiers))) {
367:                        String methodName = m.getName();
368:                        if (super MethodNames != null
369:                                && !super MethodNames.contains(methodName)) {
370:                            continue;
371:                        }
372:                        Class[] parameterTypes = m.getParameterTypes();
373:                        Class returnType = m.getReturnType();
374:
375:                        cf.openMethod("$super$" + methodName, ClassFile
376:                                .signature(parameterTypes)
377:                                + ClassFile.signature(returnType),
378:                                Constants.ACC_PUBLIC);
379:                        cf.add(Opcode.ALOAD_0);
380:                        int nparams = parameterTypes.length;
381:                        for (int j = 0, k = 0; j < nparams; j++) {
382:                            Class type = parameterTypes[j];
383:                            if (type.isPrimitive()) {
384:                                if (type == int.class || type == byte.class
385:                                        || type == short.class
386:                                        || type == boolean.class
387:                                        || type == char.class) {
388:                                    cf.iloadLocal(j + k + 1);
389:                                } else if (type == long.class) {
390:                                    cf.lloadLocal(j + k + 1);
391:                                    k++;
392:                                } else if (type == float.class) {
393:                                    cf.floadLocal(j + k + 1);
394:                                } else if (type == double.class) {
395:                                    cf.dloadLocal(j + k + 1);
396:                                    k++;
397:                                }
398:                            } else {
399:                                cf.loadLocal(j + k + 1);
400:                            }
401:                        }
402:
403:                        cf.add(Opcode.INVOKESPECIAL, m.getDeclaringClass()
404:                                .getName(), methodName, ClassFile
405:                                .signature(parameterTypes), ClassFile
406:                                .signature(returnType));
407:                        if (returnType.isPrimitive()) {
408:                            if (returnType == int.class
409:                                    || returnType == byte.class
410:                                    || returnType == short.class
411:                                    || returnType == boolean.class
412:                                    || returnType == char.class) {
413:                                cf.add(Opcode.IRETURN);
414:                            } else if (returnType == long.class) {
415:                                cf.add(Opcode.LRETURN);
416:                            } else if (returnType == float.class) {
417:                                cf.add(Opcode.FRETURN);
418:                            } else if (returnType == double.class) {
419:                                cf.add(Opcode.DRETURN);
420:                            } else if (returnType == Void.TYPE) {
421:                                cf.add(Opcode.RETURN);
422:                            }
423:                        } else {
424:                            cf.add(Opcode.ARETURN);
425:                        }
426:                        cf.closeMethod();
427:                    }
428:                }
429:            }
430:
431:            private static void getImplicitInterfaces(Class cls, List list) {
432:                Class[] interfaces = cls.getInterfaces();
433:                for (int i = 0; i < interfaces.length; i++) {
434:                    list.add(interfaces[i]);
435:                }
436:            }
437:
438:            static Constructor[] getProtectedConstructors(Class cls) {
439:                Set/*<Signature>*/s = new HashSet(); // signatures
440:                Set/*<Constructor>*/cons = new HashSet(); // constructors
441:                Class c = cls;
442:                while (c != null) {
443:                    getProtectedConstructors(c, s, cons);
444:                    c = c.getSuperclass();
445:                }
446:                return (Constructor[]) cons
447:                        .toArray(new Constructor[cons.size()]);
448:            }
449:
450:            static void getProtectedConstructors(Class cls, Set signatures,
451:                    Set constructors) {
452:                Constructor _constructors[] = cls.getDeclaredConstructors();
453:                for (int j = 0; j < _constructors.length; j++) {
454:                    Constructor c = _constructors[j];
455:                    int modifiers = c.getModifiers();
456:                    if (!Modifier.isProtected(modifiers)
457:                            || Modifier.isFinal(modifiers)) {
458:                        continue;
459:                    }
460:                    String sig = ClassFile.signature(c.getParameterTypes());
461:                    if (signatures.add(sig)) {
462:                        constructors.add(c);
463:                    }
464:                }
465:            }
466:
467:            public static void defineMethod(ClassFile cf,
468:                    Class[] parameterTypes, Class returnType,
469:                    Class[] exceptionTypes, int modifiers, String methodName,
470:                    String sig, int mode) {
471:                String className = cf.getClassName();
472:                String[] exceptionTypeInfo = null;
473:                if (exceptionTypes != null && exceptionTypes.length > 0) {
474:                    exceptionTypeInfo = new String[exceptionTypes.length];
475:                    for (int i = 0; i < exceptionTypes.length; i++) {
476:                        exceptionTypeInfo[i] = exceptionTypes[i].getName();
477:                    }
478:                }
479:                cf
480:                        .openMethod(
481:                                methodName,
482:                                ClassFile.signature(parameterTypes)
483:                                        + ClassFile.signature(returnType),
484:                                (short) (modifiers & (Constants.ACC_PUBLIC | Constants.ACC_PROTECTED)),
485:                                exceptionTypeInfo);
486:
487:                cf.add(Opcode.GETSTATIC, className, "_package",
488:                        "Lpnuts/lang/Package;");
489:                cf.add(Opcode.LDC, cf.addConstant(sig));
490:                cf.add(Opcode.INVOKEVIRTUAL, "java.lang.String", "intern",
491:                        "()", "Ljava/lang/String;");
492:                cf.add(Opcode.GETSTATIC, className, "_context",
493:                        "Lpnuts/lang/Context;");
494:                cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.Package", "get",
495:                        "(Ljava/lang/String;Lpnuts/lang/Context;)",
496:                        "Ljava/lang/Object;");
497:                //                int f = cf.getLocal();
498:                cf.add(Opcode.CHECKCAST, "pnuts.lang.PnutsFunction");
499:
500:                int nargs = parameterTypes.length;
501:                if (nargs <= -0x8000 || nargs >= 0x8000) {
502:                    throw new RuntimeException("too many parameters");
503:                }
504:                boolean hasThis = ((mode & THIS_BIT) == THIS_BIT);
505:                boolean hasSuper = ((mode & SUPER_BIT) == SUPER_BIT);
506:                int i = 0;
507:
508:                Label catchStart = cf.getLabel(true);
509:
510:                int nargs2 = nargs;
511:                if (hasThis) {
512:                    nargs2++;
513:                    i++;
514:                }
515:                if (hasSuper) {
516:                    nargs2++;
517:                    i++;
518:                }
519:
520:                cf.pushInteger(nargs2);
521:                cf.add(Opcode.ANEWARRAY, "java.lang.Object");
522:
523:                int k = 0;
524:                for (int j = 0; k < nargs; j++, k++) {
525:                    cf.add(Opcode.DUP);
526:                    cf.pushInteger(k/* + i*/);
527:                    Class paramType = parameterTypes[k];
528:                    if (paramType.isPrimitive()) {
529:                        loadPrimitive(cf, paramType, j + 1);
530:                        if (paramType.equals(long.class)
531:                                || paramType.equals(double.class)) {
532:                            j++;
533:                        }
534:                    } else {
535:                        cf.loadLocal(j + 1);
536:                    }
537:                    cf.add(Opcode.AASTORE);
538:                }
539:                i = 0;
540:                if (hasThis) {
541:                    cf.add(Opcode.DUP);
542:                    cf.pushInteger(i++);
543:                    cf.loadLocal(0);
544:                    cf.add(Opcode.AASTORE);
545:                }
546:                if (hasSuper) {
547:                    cf.add(Opcode.DUP);
548:                    cf.pushInteger(i++);
549:                    cf.loadLocal(0);
550:                    cf.add(Opcode.GETFIELD, className, "_superCallProxy",
551:                            "Lpnuts/lang/AbstractData;");
552:                    cf.add(Opcode.AASTORE);
553:                }
554:
555:                cf.add(Opcode.GETSTATIC, className, "_context",
556:                        "Lpnuts/lang/Context;");
557:                cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.PnutsFunction",
558:                        "call", "([Ljava/lang/Object;Lpnuts/lang/Context;)",
559:                        "Ljava/lang/Object;");
560:
561:                if (returnType == void.class) {
562:                    cf.add(Opcode.POP);
563:                    cf.add(Opcode.RETURN);
564:                } else if (returnType.isPrimitive()) {
565:                    returnPrimitive(cf, returnType);
566:                } else {
567:                    if (returnType != Object.class) {
568:                        // TODO: transform array <-> list?
569:                        cf.add(Opcode.CHECKCAST, returnType.getName());
570:                    }
571:                    cf.add(Opcode.ARETURN);
572:                }
573:
574:                Label catchEnd = cf.getLabel(true);
575:                Label catchTarget = cf.getLabel(true);
576:                cf.reserveStack(1);
577:                int pex = cf.getLocal();
578:                cf.storeLocal(pex);
579:
580:                cf.loadLocal(pex);
581:                cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.PnutsException",
582:                        "getThrowable", "()", "Ljava/lang/Throwable;");
583:                int ex = cf.getLocal();
584:                cf.storeLocal(ex);
585:                Label next;
586:                if (exceptionTypeInfo != null) {
587:                    for (i = 0; i < exceptionTypeInfo.length; i++) {
588:                        next = cf.getLabel();
589:                        cf.loadLocal(ex);
590:                        cf.add(Opcode.INSTANCEOF, exceptionTypeInfo[i]);
591:                        cf.add(Opcode.IFEQ, next);
592:                        cf.loadLocal(ex);
593:                        cf.add(Opcode.ATHROW);
594:                        next.fix();
595:                    }
596:                }
597:
598:                cf.loadLocal(pex);
599:                cf.add(Opcode.ATHROW);
600:                cf.addExceptionHandler(catchStart, catchEnd, catchTarget,
601:                        "pnuts.lang.PnutsException");
602:
603:                cf.closeMethod();
604:            }
605:
606:            public static void defineMethod(ClassFile cf,
607:                    Class[] parameterTypes, Class returnType,
608:                    Class[] exceptionTypes, int modifiers, String methodName,
609:                    String sig, String functionFieldName) {
610:                String className = cf.getClassName();
611:                String[] exceptionTypeInfo = null;
612:                if (exceptionTypes != null && exceptionTypes.length > 0) {
613:                    exceptionTypeInfo = new String[exceptionTypes.length];
614:                    for (int i = 0; i < exceptionTypes.length; i++) {
615:                        exceptionTypeInfo[i] = exceptionTypes[i].getName();
616:                    }
617:                }
618:                cf
619:                        .openMethod(
620:                                methodName,
621:                                ClassFile.signature(parameterTypes)
622:                                        + ClassFile.signature(returnType),
623:                                (short) (modifiers & (Constants.ACC_PUBLIC | Constants.ACC_PROTECTED)),
624:                                exceptionTypeInfo);
625:                cf.add(Opcode.ALOAD_0);
626:                cf.add(Opcode.GETFIELD, className, functionFieldName,
627:                        "Lpnuts/lang/PnutsFunction;");
628:
629:                int nargs = parameterTypes.length;
630:                if (nargs <= -0x8000 || nargs >= 0x8000) {
631:                    throw new RuntimeException("too many parameters");
632:                }
633:
634:                Label catchStart = cf.getLabel(true);
635:
636:                cf.pushInteger(nargs);
637:                cf.add(Opcode.ANEWARRAY, "java.lang.Object");
638:
639:                int k = 0;
640:                for (int j = 0; k < nargs; j++, k++) {
641:                    cf.add(Opcode.DUP);
642:                    cf.pushInteger(k/* + i*/);
643:                    Class paramType = parameterTypes[k];
644:                    if (paramType.isPrimitive()) {
645:                        loadPrimitive(cf, paramType, j + 1);
646:                        if (paramType.equals(long.class)
647:                                || paramType.equals(double.class)) {
648:                            j++;
649:                        }
650:                    } else {
651:                        cf.loadLocal(j + 1);
652:                    }
653:                    cf.add(Opcode.AASTORE);
654:                }
655:
656:                cf.add(Opcode.GETSTATIC, className, "_context",
657:                        "Lpnuts/lang/Context;");
658:                cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.PnutsFunction",
659:                        "call", "([Ljava/lang/Object;Lpnuts/lang/Context;)",
660:                        "Ljava/lang/Object;");
661:
662:                if (returnType == void.class) {
663:                    cf.add(Opcode.POP);
664:                    cf.add(Opcode.RETURN);
665:                } else if (returnType.isPrimitive()) {
666:                    returnPrimitive(cf, returnType);
667:                } else {
668:                    if (returnType != Object.class) {
669:                        // TODO: transform array <-> list?
670:                        cf.add(Opcode.CHECKCAST, returnType.getName());
671:                    }
672:                    cf.add(Opcode.ARETURN);
673:                }
674:
675:                Label catchEnd = cf.getLabel(true);
676:                Label catchTarget = cf.getLabel(true);
677:                cf.reserveStack(1);
678:                int pex = cf.getLocal();
679:                cf.storeLocal(pex);
680:
681:                cf.loadLocal(pex);
682:                cf.add(Opcode.INVOKEVIRTUAL, "pnuts.lang.PnutsException",
683:                        "getThrowable", "()", "Ljava/lang/Throwable;");
684:                int ex = cf.getLocal();
685:                cf.storeLocal(ex);
686:                Label next;
687:                if (exceptionTypeInfo != null) {
688:                    for (int i = 0; i < exceptionTypeInfo.length; i++) {
689:                        next = cf.getLabel();
690:                        cf.loadLocal(ex);
691:                        cf.add(Opcode.INSTANCEOF, exceptionTypeInfo[i]);
692:                        cf.add(Opcode.IFEQ, next);
693:                        cf.loadLocal(ex);
694:                        cf.add(Opcode.ATHROW);
695:                        next.fix();
696:                    }
697:                }
698:
699:                cf.loadLocal(pex);
700:                cf.add(Opcode.ATHROW);
701:                cf.addExceptionHandler(catchStart, catchEnd, catchTarget,
702:                        "pnuts.lang.PnutsException");
703:
704:                cf.closeMethod();
705:            }
706:
707:            private static void loadPrimitive(ClassFile cf, Class primitive,
708:                    int index) {
709:                if (primitive == int.class) {
710:                    cf.add(Opcode.NEW, "java.lang.Integer");
711:                    cf.add(Opcode.DUP);
712:                    cf.iloadLocal(index);
713:                    cf.add(Opcode.INVOKESPECIAL, "java.lang.Integer", "<init>",
714:                            "(I)", "V");
715:                } else if (primitive == byte.class) {
716:                    cf.add(Opcode.NEW, "java.lang.Byte");
717:                    cf.add(Opcode.DUP);
718:                    cf.iloadLocal(index);
719:                    cf.add(Opcode.INVOKESPECIAL, "java.lang.Byte", "<init>",
720:                            "(B)", "V");
721:                } else if (primitive == short.class) {
722:                    cf.add(Opcode.NEW, "java.lang.Short");
723:                    cf.add(Opcode.DUP);
724:                    cf.iloadLocal(index);
725:                    cf.add(Opcode.INVOKESPECIAL, "java.lang.Short", "<init>",
726:                            "(S)", "V");
727:                } else if (primitive == char.class) {
728:                    cf.add(Opcode.NEW, "java.lang.Character");
729:                    cf.add(Opcode.DUP);
730:                    cf.iloadLocal(index);
731:                    cf.add(Opcode.INVOKESPECIAL, "java.lang.Character",
732:                            "<init>", "(C)", "V");
733:                } else if (primitive == long.class) {
734:                    cf.add(Opcode.NEW, "java.lang.Long");
735:                    cf.add(Opcode.DUP);
736:                    cf.lloadLocal(index);
737:                    cf.add(Opcode.INVOKESPECIAL, "java.lang.Long", "<init>",
738:                            "(J)", "V");
739:                } else if (primitive == float.class) {
740:                    cf.add(Opcode.NEW, "java.lang.Float");
741:                    cf.add(Opcode.DUP);
742:                    cf.floadLocal(index);
743:                    cf.add(Opcode.INVOKESPECIAL, "java.lang.Float", "<init>",
744:                            "(F)", "V");
745:                } else if (primitive == double.class) {
746:                    cf.add(Opcode.NEW, "java.lang.Double");
747:                    cf.add(Opcode.DUP);
748:                    cf.dloadLocal(index);
749:                    cf.add(Opcode.INVOKESPECIAL, "java.lang.Double", "<init>",
750:                            "(D)", "V");
751:                } else if (primitive == boolean.class) {
752:                    cf.add(Opcode.NEW, "java.lang.Boolean");
753:                    cf.add(Opcode.DUP);
754:                    cf.iloadLocal(index);
755:                    cf.add(Opcode.INVOKESPECIAL, "java.lang.Boolean", "<init>",
756:                            "(Z)", "V");
757:                }
758:            }
759:
760:            private static void returnPrimitive(ClassFile cf, Class type) {
761:                if (type == int.class) {
762:                    cf.add(Opcode.CHECKCAST, "java.lang.Integer");
763:                    cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Integer",
764:                            "intValue", "()", "I");
765:                    cf.add(Opcode.IRETURN);
766:                } else if (type == byte.class) {
767:                    cf.add(Opcode.CHECKCAST, "java.lang.Byte");
768:                    cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Byte", "byteValue",
769:                            "()", "B");
770:                    cf.add(Opcode.IRETURN);
771:                } else if (type == short.class) {
772:                    cf.add(Opcode.CHECKCAST, "java.lang.Short");
773:                    cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Short",
774:                            "shortValue", "()", "S");
775:                    cf.add(Opcode.IRETURN);
776:                } else if (type == char.class) {
777:                    cf.add(Opcode.CHECKCAST, "java.lang.Character");
778:                    cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Character",
779:                            "charValue", "()", "C");
780:                    cf.add(Opcode.IRETURN);
781:                } else if (type == long.class) {
782:                    cf.add(Opcode.CHECKCAST, "java.lang.Long");
783:                    cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Long", "longValue",
784:                            "()", "L");
785:                    cf.add(Opcode.LRETURN);
786:                } else if (type == float.class) {
787:                    cf.add(Opcode.CHECKCAST, "java.lang.Float");
788:                    cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Float",
789:                            "floatValue", "()", "F");
790:                    cf.add(Opcode.FRETURN);
791:                } else if (type == double.class) {
792:                    cf.add(Opcode.CHECKCAST, "java.lang.Double");
793:                    cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Double",
794:                            "doubleValue", "()", "D");
795:                    cf.add(Opcode.DRETURN);
796:                } else if (type == boolean.class) {
797:                    cf.add(Opcode.CHECKCAST, "java.lang.Boolean");
798:                    cf.add(Opcode.INVOKEVIRTUAL, "java.lang.Boolean",
799:                            "booleanValue", "()", "Z");
800:                    cf.add(Opcode.IRETURN);
801:                } else {
802:                    throw new InternalError();
803:                }
804:            }
805:
806:            static class MethodArity {
807:                String name;
808:                int nargs;
809:
810:                MethodArity(String name, int nargs) {
811:                    this .name = name;
812:                    this .nargs = nargs;
813:                }
814:
815:                public int hashCode() {
816:                    return name.hashCode() * nargs;
817:                }
818:
819:                public boolean equals(Object obj) {
820:                    if (obj instanceof  MethodArity) {
821:                        MethodArity a = (MethodArity) obj;
822:                        return a.nargs == nargs && a.name.equals(name);
823:                    }
824:                    return false;
825:                }
826:            }
827:
828:            private static class ThisTransformer extends ScopeAnalyzer {
829:
830:                private Set methods;
831:                private Set fields;
832:                private Set nodesNeedTransformation;
833:
834:                ThisTransformer(Set methods, Set fields,
835:                        Set nodesNeedTransformation) {
836:                    this .methods = methods;
837:                    this .fields = fields;
838:                    this .nodesNeedTransformation = nodesNeedTransformation;
839:                }
840:
841:                protected void handleFreeVariable(SimpleNode node,
842:                        Context context) {
843:                    SimpleNode parent = node.jjtGetParent();
844:                    if (parent != null
845:                            && parent.id == PnutsParserTreeConstants.JJTAPPLICATIONNODE) {
846:                        String symbol = node.str;
847:                        SimpleNode argNode = parent.jjtGetChild(1);
848:                        int n = argNode.jjtGetNumChildren();
849:
850:                        MethodArity arity = new MethodArity(symbol, n);
851:                        if (methods.contains(arity)) {
852:                            nodesNeedTransformation.add(parent);
853:                        }
854:                    } else if (parent != null
855:                            && parent.id != PnutsParserTreeConstants.JJTMEMBERNODE) {
856:                        if (fields.contains(node.str)) {
857:                            nodesNeedTransformation.add(node);
858:                        }
859:                    }
860:                }
861:
862:                protected void declared(SimpleNode node, Context context,
863:                        String symbol) {
864:                    if (fields.contains(node.str)) {
865:                        nodesNeedTransformation.add(node);
866:                    }
867:                }
868:            }
869:
870:            private static void populateMembers(SimpleNode classDefBody,
871:                    Set methods, Set fields) {
872:                for (int i = 0, n = classDefBody.jjtGetNumChildren(); i < n; i++) {
873:                    SimpleNode c = classDefBody.jjtGetChild(i);
874:                    String name;
875:                    int arity;
876:                    if (c.id == PnutsParserTreeConstants.JJTMETHODDEF) {
877:                        name = c.str;
878:                        int num = c.jjtGetNumChildren();
879:                        if (num == 2) {
880:                            SimpleNode typedParamList = c.jjtGetChild(0);
881:                            arity = typedParamList.jjtGetNumChildren();
882:                        } else if (num == 3) {
883:                            SimpleNode typedParamList = c.jjtGetChild(1);
884:                            arity = typedParamList.jjtGetNumChildren();
885:                        } else {
886:                            throw new InternalError();
887:                        }
888:                        methods.add(new MethodArity(name, arity));
889:                    } else if (c.id == PnutsParserTreeConstants.JJTFIELDDEF) {
890:                        fields.add(c.str);
891:                    }
892:                }
893:            }
894:
895:            private static void populateMethodArities(Class cls, Set methods) {
896:                Method m[] = cls.getMethods();
897:                for (int i = 0; i < m.length; i++) {
898:                    MethodArity a = new MethodArity(m[i].getName(), m[i]
899:                            .getParameterTypes().length);
900:                    methods.add(a);
901:                }
902:            }
903:
904:            private static void populateFieldNames(Class cls, final Set fields) {
905:                ObjectDescFactory.getDefault().create(cls).handleProperties(
906:                        new PropertyHandler() {
907:                            public void handle(String propertyName, Class type,
908:                                    Method readMethod, Method writeMethod) {
909:                                fields.add(propertyName);
910:                            }
911:                        });
912:            }
913:
914:            private static void transformApplicationNode(SimpleNode node) {
915:                node.id = PnutsParserTreeConstants.JJTMETHODNODE;
916:                SimpleNode n0 = node.jjtGetChild(0);
917:                node.str = n0.str;
918:                n0.str = Compiler.THIS;
919:            }
920:
921:            private static void transformApplicationNode(SimpleNode node,
922:                    Set methods, Set fields) {
923:                Set nodes = new HashSet();
924:                new ThisTransformer(methods, fields, nodes).analyze(node);
925:                for (Iterator it = nodes.iterator(); it.hasNext();) {
926:                    SimpleNode n = (SimpleNode) it.next();
927:                    if (n.id == PnutsParserTreeConstants.JJTAPPLICATIONNODE) {
928:                        transformApplicationNode(n);
929:                    }
930:                }
931:            }
932:
933:            public static void transformClassDefBody(SimpleNode classDefBody,
934:                    Class super class) {
935:                Set methods = new HashSet();
936:                Set fields = new HashSet();
937:                populateMethodArities(super class, methods);
938:                populateFieldNames(super class, fields);
939:                populateMembers(classDefBody, methods, fields);
940:                transformApplicationNode(classDefBody, methods, fields);
941:            }
942:
943:            public static class SuperCallProxy implements  AbstractData {
944:                private Object target;
945:
946:                public SuperCallProxy(Object target) {
947:                    this .target = target;
948:                }
949:
950:                public Object get(String name, Context context) {
951:                    throw new UnsupportedOperationException();
952:                }
953:
954:                public void set(String name, Object value, Context context) {
955:                    throw new UnsupportedOperationException();
956:                }
957:
958:                public Object invoke(String name, Object[] args, Context context) {
959:                    return Runtime.callMethod(context, target.getClass(),
960:                            "$super$" + name, args, null, target);
961:                }
962:            }
963:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.