Source Code Cross Referenced for PrimProcedure.java in  » Scripting » Kawa » gnu » expr » 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 » Kawa » gnu.expr 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        // Copyright (c) 1999, 2000  Per M.A. Bothner.
002:        // This is free software;  for terms and warranty disclaimer see ./COPYING.
003:
004:        package gnu.expr;
005:
006:        import gnu.bytecode.*;
007:        import gnu.mapping.*;
008:
009:        /** A primitive Procedure implemented by a plain Java method. */
010:
011:        public class PrimProcedure extends MethodProc implements 
012:                gnu.expr.Inlineable {
013:            Type retType;
014:            /** The types of the method parameters.
015:             * If known, the types have been coerced to Language-specific parameters.
016:             * Does not include the implicit static link argument of some constructors.
017:             */
018:            Type[] argTypes;
019:            Method method;
020:            int op_code;
021:            /** 'P' means use invokespecial;
022:             * 'V' means expect a target (this) argument, even if method is static;
023:             * '\0' means don't expect a target. */
024:            char mode;
025:
026:            /** If non-null, the LambdaExp that this PrimProcedure implements. */
027:            LambdaExp source;
028:
029:            java.lang.reflect.Member member;
030:
031:            public final int opcode() {
032:                return op_code;
033:            }
034:
035:            public Type getReturnType() {
036:                return retType;
037:            }
038:
039:            public void setReturnType(Type retType) {
040:                this .retType = retType;
041:            }
042:
043:            public boolean isSpecial() {
044:                return mode == 'P';
045:            }
046:
047:            public Type getReturnType(Expression[] args) {
048:                return retType;
049:            }
050:
051:            public Method getMethod() {
052:                return method;
053:            }
054:
055:            /** Return true iff the last parameter is a "rest" argument. */
056:            public boolean takesVarArgs() {
057:                if (method != null) {
058:                    String name = method.getName();
059:                    return name.endsWith("$V") || name.endsWith("$V$X");
060:                }
061:                return false;
062:            }
063:
064:            public boolean takesContext() {
065:                return method != null && takesContext(method);
066:            }
067:
068:            public static boolean takesContext(Method method) {
069:                return method.getName().endsWith("$X");
070:            }
071:
072:            public final boolean isConstructor() {
073:                // invokespecial == primitive-constructor
074:                return opcode() == 183 && mode != 'P';
075:            }
076:
077:            /** Whether we are passed an argument for the 'target' / 'receiver' / 'this'.
078:             * Normally this is false for static methods and true for non-static
079:             * methods.  However, we may need to be able to call a static method using
080:             * {@code object.name(args...)} (Java syntax) or
081:             * {@code (invoke object 'name args...)} (Scheme syntax).
082:             * This includes when the {@code object} is implied.
083:             * In this case we need to ignore the first argument's value.
084:             */
085:            public boolean takesTarget() {
086:                return mode != '\0';
087:            }
088:
089:            /** The (minimum, number) of arguments.
090:             * Doesn't not count implicit CallContext argument.
091:             * Does count 'this' argument for non-static methods.
092:             * Does count an implicit staticLink argument for constructor.
093:             */
094:            public int numArgs() {
095:                int num = argTypes.length;
096:                if (takesTarget())
097:                    num++;
098:                if (takesContext())
099:                    num--;
100:                return takesVarArgs() ? (num - 1) + (-1 << 12) : num
101:                        + (num << 12);
102:            }
103:
104:            public int match0(CallContext ctx) {
105:                return matchN(ProcedureN.noArgs, ctx);
106:            }
107:
108:            public int match1(Object arg1, CallContext ctx) {
109:                Object[] args = { arg1 };
110:                return matchN(args, ctx);
111:            }
112:
113:            public int match2(Object arg1, Object arg2, CallContext ctx) {
114:                Object[] args = { arg1, arg2 };
115:                return matchN(args, ctx);
116:            }
117:
118:            public int match3(Object arg1, Object arg2, Object arg3,
119:                    CallContext ctx) {
120:                Object[] args = { arg1, arg2, arg3 };
121:                return matchN(args, ctx);
122:            }
123:
124:            public int match4(Object arg1, Object arg2, Object arg3,
125:                    Object arg4, CallContext ctx) {
126:                Object[] args = { arg1, arg2, arg3, arg4 };
127:                return matchN(args, ctx);
128:            }
129:
130:            public int matchN(Object[] args, CallContext ctx) {
131:                int nargs = args.length;
132:                boolean takesVarArgs = takesVarArgs();
133:                int fixArgs = minArgs();
134:                if (nargs < fixArgs)
135:                    return NO_MATCH_TOO_FEW_ARGS | fixArgs;
136:                if (!takesVarArgs && nargs > fixArgs)
137:                    return NO_MATCH_TOO_MANY_ARGS | fixArgs;
138:                int paramCount = argTypes.length;
139:                Type elementType = null;
140:                Object[] restArray = null;
141:                int extraCount = (takesTarget() || isConstructor()) ? 1 : 0;
142:                boolean takesContext = takesContext();
143:                Object[] rargs = new Object[paramCount];
144:                if (takesContext)
145:                    rargs[--paramCount] = ctx;
146:                Object extraArg;
147:                if (takesVarArgs) {
148:                    Type restType = argTypes[paramCount - 1];
149:                    if (restType == Compilation.scmListType) { // FIXME
150:                        rargs[paramCount - 1] = gnu.lists.LList.makeList(args,
151:                                fixArgs);
152:                        nargs = fixArgs;
153:                        elementType = Type.pointer_type;
154:                    } else {
155:                        ArrayType restArrayType = (ArrayType) restType;
156:                        elementType = restArrayType.getComponentType();
157:                        Class elementClass = elementType.getReflectClass();
158:                        restArray = (Object[]) java.lang.reflect.Array
159:                                .newInstance(elementClass, nargs - fixArgs);
160:                        rargs[paramCount - 1] = restArray;
161:                    }
162:                }
163:                if (isConstructor())
164:                    extraArg = args[0];
165:                else if (extraCount != 0) {
166:                    try {
167:                        extraArg = method.getDeclaringClass().coerceFromObject(
168:                                args[0]);
169:                    } catch (ClassCastException ex) {
170:                        return NO_MATCH_BAD_TYPE | 1;
171:                    }
172:                } else
173:                    extraArg = null;
174:                for (int i = extraCount; i < args.length; i++) {
175:                    Object arg = args[i];
176:                    Type type = i < fixArgs ? argTypes[i - extraCount]
177:                            : elementType;
178:                    if (type != Type.pointer_type) {
179:                        try {
180:                            arg = type.coerceFromObject(arg);
181:                        } catch (ClassCastException ex) {
182:                            return NO_MATCH_BAD_TYPE | (i + 1);
183:                        }
184:                    }
185:                    if (i < fixArgs)
186:                        rargs[i - extraCount] = arg;
187:                    else if (restArray != null) // I.e. using array rather than LList.
188:                        restArray[i - fixArgs] = arg;
189:                }
190:                ctx.value1 = extraArg;
191:                ctx.values = rargs;
192:                ctx.proc = this ;
193:                return 0;
194:            }
195:
196:            public void apply(CallContext ctx) throws Throwable {
197:                int arg_count = argTypes.length;
198:                boolean is_constructor = isConstructor();
199:                boolean slink = is_constructor
200:                        && method.getDeclaringClass().hasOuterLink();
201:
202:                try {
203:                    if (member == null) {
204:                        Class clas = method.getDeclaringClass()
205:                                .getReflectClass();
206:                        Class[] paramTypes = new Class[arg_count
207:                                + (slink ? 1 : 0)];
208:                        for (int i = arg_count; --i >= 0;)
209:                            paramTypes[i + (slink ? 1 : 0)] = argTypes[i]
210:                                    .getReflectClass();
211:                        if (slink)
212:                            paramTypes[0] = method.getDeclaringClass()
213:                                    .getOuterLinkType().getReflectClass();
214:                        if (is_constructor)
215:                            member = clas.getConstructor(paramTypes);
216:                        else if (method != Type.clone_method)
217:                            member = clas.getMethod(method.getName(),
218:                                    paramTypes);
219:                    }
220:                    Object result;
221:                    if (is_constructor) {
222:                        Object[] args = ctx.values;
223:                        if (slink) {
224:                            int nargs = args.length + 1;
225:                            Object[] xargs = new Object[nargs];
226:                            System.arraycopy(args, 0, xargs, 1, nargs - 1);
227:                            xargs[0] = ((PairClassType) ctx.value1).staticLink;
228:                            args = xargs;
229:                        }
230:
231:                        result = (((java.lang.reflect.Constructor) member)
232:                                .newInstance(args));
233:                    } else if (method == Type.clone_method) {
234:                        // The special Type.clone_method is only used for array types.
235:                        Object arr = ctx.value1;
236:                        Class elClass = arr.getClass().getComponentType();
237:                        int n = java.lang.reflect.Array.getLength(arr);
238:                        result = java.lang.reflect.Array
239:                                .newInstance(elClass, n);
240:                        System.arraycopy(arr, 0, result, 0, n);
241:                    } else
242:                        result = retType
243:                                .coerceToObject(((java.lang.reflect.Method) member)
244:                                        .invoke(ctx.value1, ctx.values));
245:                    if (!takesContext())
246:                        ctx.consumer.writeObject(result);
247:                } catch (java.lang.reflect.InvocationTargetException ex) {
248:                    throw ex.getTargetException();
249:                }
250:            }
251:
252:            public PrimProcedure(String className, String methodName,
253:                    int numArgs) {
254:                this (ClassType.make(className).getDeclaredMethod(methodName,
255:                        numArgs));
256:            }
257:
258:            public PrimProcedure(java.lang.reflect.Method method,
259:                    Language language) {
260:                this (((ClassType) language.getTypeFor(method
261:                        .getDeclaringClass())).getMethod(method), language);
262:            }
263:
264:            public PrimProcedure(Method method) {
265:                init(method);
266:                this .retType = method.getName().endsWith("$X") ? Type.pointer_type
267:                        : method.getReturnType();
268:            }
269:
270:            public PrimProcedure(Method method, Language language) {
271:                this (method, '\0', language);
272:            }
273:
274:            public PrimProcedure(Method method, char mode, Language language) {
275:                this .mode = mode;
276:
277:                init(method);
278:
279:                // This stuff deals with that a language may have its own mapping
280:                // from Java types to language types, for coercions and other reasons.
281:                Type[] pTypes = this .argTypes;
282:                int nTypes = pTypes.length;
283:                argTypes = null;
284:                for (int i = nTypes; --i >= 0;) {
285:                    Type javaType = pTypes[i];
286:                    if (javaType instanceof  ClassType
287:                            && !((ClassType) javaType).isExisting())
288:                        continue;
289:                    Type langType = language.getLangTypeFor(javaType);
290:                    if (javaType != langType) {
291:                        if (argTypes == null) {
292:                            argTypes = new Type[nTypes];
293:                            System.arraycopy(pTypes, 0, argTypes, 0, nTypes);
294:                        }
295:                        argTypes[i] = langType;
296:                    }
297:                }
298:                if (argTypes == null)
299:                    argTypes = pTypes;
300:                if (isConstructor())
301:                    retType = method.getDeclaringClass();
302:                else if (method.getName().endsWith("$X"))
303:                    retType = Type.pointer_type;
304:                else {
305:                    retType = language.getLangTypeFor(method.getReturnType());
306:
307:                    // Kludge - tostring_type doesn't have methods.
308:                    // It shouldn't be used as the "type" of anything -
309:                    // it's just a type with a coercion.  FIXME.
310:                    if (retType == Type.tostring_type)
311:                        retType = Type.string_type;
312:                }
313:            }
314:
315:            private void init(Method method) {
316:                this .method = method;
317:                int flags = method.getModifiers();
318:                if ((flags & Access.STATIC) != 0)
319:                    this .op_code = 184; // invokestatic
320:                else {
321:                    ClassType mclass = method.getDeclaringClass();
322:                    if (mode == 'P')
323:                        this .op_code = 183; // invokespecial
324:                    else {
325:                        mode = 'V';
326:                        if ("<init>".equals(method.getName()))
327:                            this .op_code = 183; // invokespecial
328:                        else if ((mclass.getModifiers() & Access.INTERFACE) != 0)
329:                            this .op_code = 185; // invokeinterface
330:                        else
331:                            this .op_code = 182; // invokevirtual
332:                    }
333:                }
334:                Type[] mtypes = method.getParameterTypes();
335:                if (isConstructor()
336:                        && method.getDeclaringClass().hasOuterLink()) {
337:                    int len = mtypes.length - 1;
338:                    Type[] types = new Type[len];
339:                    System.arraycopy(mtypes, 1, types, 0, len);
340:                    mtypes = types;
341:                }
342:                this .argTypes = mtypes;
343:            }
344:
345:            public PrimProcedure(Method method, LambdaExp source) {
346:                this (method);
347:                this .retType = source.getReturnType();
348:                this .source = source;
349:            }
350:
351:            public PrimProcedure(int opcode, Type retType, Type[] argTypes) {
352:                this .op_code = opcode;
353:                this .retType = retType;
354:                this .argTypes = argTypes;
355:            }
356:
357:            public static PrimProcedure makeBuiltinUnary(int opcode, Type type) {
358:                // FIXME - should cache!
359:                Type[] args = new Type[1];
360:                args[0] = type;
361:                return new PrimProcedure(opcode, type, args);
362:            }
363:
364:            public static PrimProcedure makeBuiltinBinary(int opcode, Type type) {
365:                // FIXME - should cache!
366:                Type[] args = new Type[2];
367:                args[0] = type;
368:                args[1] = type;
369:                return new PrimProcedure(opcode, type, args);
370:            }
371:
372:            public PrimProcedure(int op_code, ClassType classtype, String name,
373:                    Type retType, Type[] argTypes) {
374:                this .op_code = op_code;
375:                method = classtype.addMethod(name,
376:                        op_code == 184 ? Access.STATIC : 0, argTypes, retType);
377:                this .retType = retType;
378:                this .argTypes = argTypes;
379:                mode = op_code == 184 ? '\0' : 'V';
380:            }
381:
382:            /** True if there is no 'this' parameter. */
383:            public final boolean getStaticFlag() {
384:                return method == null || method.getStaticFlag()
385:                        || isConstructor();
386:            }
387:
388:            public final Type[] getParameterTypes() {
389:                return argTypes;
390:            }
391:
392:            /** Compile arguments and push unto stack.
393:             * @param args arguments to evaluate and push.
394:             * @param thisType If we are calling a non-static function,
395:             *   then args[0] is the receiver and thisType is its expected class.
396:             *   If thisType==Type.void_type, ignore argTypes[0].  (It is used to to
397:             *   pass a link to a closure environment, which was pushed by our caller.)
398:             *   If thisType==null, no special handling of args[0] or argTypes[0].
399:             */
400:            private void compileArgs(Expression[] args, int startArg,
401:                    Type this Type, Compilation comp) {
402:                boolean variable = takesVarArgs();
403:                String name = getName();
404:                Type arg_type = null;
405:                gnu.bytecode.CodeAttr code = comp.getCode();
406:                int skipArg = this Type == Type.void_type ? 1 : 0;
407:                int arg_count = argTypes.length - skipArg;
408:                if (takesContext())
409:                    arg_count--;
410:                boolean is_static = this Type == null || skipArg != 0;
411:                int fix_arg_count = variable ? arg_count - 1 : args.length
412:                        - startArg;
413:                Declaration argDecl = source == null ? null : source
414:                        .firstDecl();
415:                if (argDecl != null && argDecl.isThisParameter())
416:                    argDecl = argDecl.nextDecl();
417:                for (int i = 0;; ++i) {
418:                    if (variable && i == fix_arg_count) {
419:                        arg_type = argTypes[arg_count - 1 + skipArg];
420:                        if (arg_type == Compilation.scmListType) {
421:                            gnu.kawa.functions.MakeList.compile(args, startArg
422:                                    + i, comp);
423:                            break;
424:                        }
425:                        code
426:                                .emitPushInt(args.length - startArg
427:                                        - fix_arg_count);
428:                        arg_type = ((ArrayType) arg_type).getComponentType();
429:                        code.emitNewArray(arg_type);
430:                    }
431:                    if (i + startArg >= args.length)
432:                        break;
433:                    if (i >= fix_arg_count) {
434:                        code.emitDup(1); // dup array.
435:                        code.emitPushInt(i - fix_arg_count);
436:                    } else
437:                        arg_type = argDecl != null && (is_static || i > 0) ? argDecl
438:                                .getType()
439:                                : is_static ? argTypes[i + skipArg]
440:                                        : i == 0 ? this Type : argTypes[i - 1];
441:                    comp.usedClass(arg_type);
442:                    Target target = source == null ? CheckedTarget.getInstance(
443:                            arg_type, name, i + 1) : CheckedTarget.getInstance(
444:                            arg_type, source, i);
445:                    args[startArg + i].compileNotePosition(comp, target,
446:                            args[startArg + i]);
447:                    if (i >= fix_arg_count)
448:                        code.emitArrayStore(arg_type);
449:                    if (argDecl != null && (is_static || i > 0))
450:                        argDecl = argDecl.nextDecl();
451:                }
452:            }
453:
454:            public void compile(ApplyExp exp, Compilation comp, Target target) {
455:                gnu.bytecode.CodeAttr code = comp.getCode();
456:                ClassType mclass = method == null ? null : method
457:                        .getDeclaringClass();
458:                Expression[] args = exp.getArgs();
459:                if (isConstructor()) {
460:                    code.emitNew(mclass);
461:                    code.emitDup(mclass);
462:                }
463:                String arg_error = WrongArguments.checkArgCount(this ,
464:                        args.length);
465:                if (arg_error != null)
466:                    comp.error('e', arg_error);
467:
468:                compile(getStaticFlag() ? null : mclass, exp, comp, target);
469:            }
470:
471:            void compile(Type this Type, ApplyExp exp, Compilation comp,
472:                    Target target) {
473:                Expression[] args = exp.getArgs();
474:                gnu.bytecode.CodeAttr code = comp.getCode();
475:                Type stackType = retType;
476:                int startArg = 0;
477:                if (isConstructor()) {
478:                    ClassType mclass = method == null ? null : method
479:                            .getDeclaringClass();
480:                    if (mclass.hasOuterLink()) {
481:                        // This can be optimized in most cases. FIXME.
482:                        args[0].compile(comp, Target
483:                                .pushValue(Compilation.typeClassType));
484:                        code.emitInvokeStatic(ClassType.make(
485:                                "gnu.expr.PairClassType").getDeclaredMethod(
486:                                "extractStaticLink", 1));
487:                        code.emitCheckcast(mclass.getOuterLinkType());
488:                        this Type = Type.void_type;
489:                    } else
490:                        this Type = null;
491:                    startArg = 1;
492:                } else if (takesTarget() && method.getStaticFlag())
493:                    startArg = 1;
494:
495:                compileArgs(args, startArg, this Type, comp);
496:
497:                if (method == null) {
498:                    code.emitPrimop(opcode(), args.length, retType);
499:                    target.compileFromStack(comp, stackType);
500:                } else {
501:                    compileInvoke(comp, method, target, exp.isTailCall(),
502:                            op_code, stackType);
503:                }
504:            }
505:
506:            /** Emit the actual invoke operation, after arguments have been pushed.
507:             * Does whatever magic is needed to pass the result to target,
508:             * including passing CallContext or special handling of ConsumerTarget.
509:             */
510:            public static void compileInvoke(Compilation comp, Method method,
511:                    Target target, boolean isTailCall, int op_code,
512:                    Type stackType) {
513:                CodeAttr code = comp.getCode();
514:                comp.usedClass(method.getDeclaringClass());
515:                comp.usedClass(method.getReturnType());
516:                if (!takesContext(method)) {
517:                    code.emitInvokeMethod(method, op_code);
518:                } else if (target instanceof  IgnoreTarget
519:                        || (target instanceof  ConsumerTarget && ((ConsumerTarget) target)
520:                                .isContextTarget())) {
521:                    Field consumerFld = null;
522:                    Variable saveCallContext = null;
523:                    comp.loadCallContext();
524:                    if (target instanceof  IgnoreTarget) {
525:                        ClassType typeCallContext = Compilation.typeCallContext;
526:                        consumerFld = typeCallContext
527:                                .getDeclaredField("consumer");
528:
529:                        // Consumer saveConsumer = ctx.consumer;
530:                        // ctx.consumer = VoidConsumer.instance:
531:                        code.pushScope();
532:                        saveCallContext = code.addLocal(typeCallContext);
533:                        code.emitDup();
534:                        code.emitGetField(consumerFld);
535:                        code.emitStore(saveCallContext);
536:                        code.emitDup();
537:                        code.emitGetStatic(ClassType.make(
538:                                "gnu.lists.VoidConsumer").getDeclaredField(
539:                                "instance"));
540:                        code.emitPutField(consumerFld);
541:                    }
542:                    code.emitInvokeMethod(method, op_code);
543:                    if (isTailCall) {
544:                        comp.loadCallContext();
545:                        code.emitInvoke(Compilation.typeCallContext
546:                                .getDeclaredMethod("runUntilDone", 0));
547:                    }
548:                    if (target instanceof  IgnoreTarget) {
549:                        // ctx.consumer = saveConsumer
550:                        comp.loadCallContext();
551:                        code.emitLoad(saveCallContext);
552:                        code.emitPutField(consumerFld);
553:                        code.popScope();
554:                    }
555:                    return;
556:                } else {
557:                    comp.loadCallContext();
558:                    stackType = Type.pointer_type;
559:                    code.pushScope();
560:                    Variable saveIndex = code.addLocal(Type.int_type);
561:                    comp.loadCallContext();
562:                    code.emitInvokeVirtual(Compilation.typeCallContext
563:                            .getDeclaredMethod("startFromContext", 0));
564:                    code.emitStore(saveIndex);
565:                    code.emitWithCleanupStart();
566:                    code.emitInvokeMethod(method, op_code);
567:                    code.emitWithCleanupCatch(null);
568:                    comp.loadCallContext();
569:                    code.emitLoad(saveIndex);
570:                    code.emitInvokeVirtual(Compilation.typeCallContext
571:                            .getDeclaredMethod("cleanupFromContext", 1));
572:                    code.emitWithCleanupDone();
573:                    comp.loadCallContext();
574:                    code.emitLoad(saveIndex);
575:                    code.emitInvokeVirtual(Compilation.typeCallContext
576:                            .getDeclaredMethod("getFromContext", 1));
577:                    code.popScope();
578:                }
579:                target.compileFromStack(comp, stackType);
580:            }
581:
582:            public Type getParameterType(int index) {
583:                if (takesTarget()) {
584:                    if (index == 0)
585:                        return isConstructor() ? Type.pointer_type : method
586:                                .getDeclaringClass();
587:                    index--;
588:                }
589:                int lenTypes = argTypes.length;
590:                if (index < lenTypes - 1)
591:                    return argTypes[index];
592:                boolean varArgs = takesVarArgs();
593:                if (index < lenTypes && !varArgs)
594:                    return argTypes[index];
595:                // if (! varArgs) ERROR;
596:                Type restType = argTypes[lenTypes - 1];
597:                if (restType instanceof  ArrayType)
598:                    return ((ArrayType) restType).getComponentType();
599:                else
600:                    // Should be LList or some other Sequence class.
601:                    return Type.pointer_type;
602:            }
603:
604:            // This is null in JDK 1.1 and something else in JDK 1.2.
605:            private static ClassLoader systemClassLoader = PrimProcedure.class
606:                    .getClassLoader();
607:
608:            public static PrimProcedure getMethodFor(Procedure pproc,
609:                    Expression[] args) {
610:                return getMethodFor(pproc, null, args, Language
611:                        .getDefaultLanguage());
612:            }
613:
614:            /** Search for a matching static method in a procedure's class.
615:             * @return a PrimProcedure that is suitable, or null. */
616:            public static PrimProcedure getMethodFor(Procedure pproc,
617:                    Declaration decl, Expression[] args, Language language) {
618:                int nargs = args.length;
619:                Type[] atypes = new Type[nargs];
620:                for (int i = nargs; --i >= 0;)
621:                    atypes[i] = args[i].getType();
622:                return getMethodFor(pproc, decl, atypes, language);
623:            }
624:
625:            public static PrimProcedure getMethodFor(Procedure pproc,
626:                    Declaration decl, Type[] atypes, Language language) {
627:                if (pproc instanceof  GenericProc) {
628:                    GenericProc gproc = (GenericProc) pproc;
629:                    MethodProc[] methods = gproc.methods;
630:                    pproc = null;
631:                    for (int i = gproc.count; --i >= 0;) {
632:                        int applic = methods[i].isApplicable(atypes);
633:                        if (applic < 0)
634:                            continue;
635:                        if (pproc != null)
636:                            return null; // Ambiguous.
637:                        pproc = methods[i];
638:                    }
639:                    if (pproc == null)
640:                        return null;
641:                }
642:                if (pproc instanceof  PrimProcedure) {
643:                    PrimProcedure prproc = (PrimProcedure) pproc;
644:                    if (prproc.isApplicable(atypes) >= 0)
645:                        return prproc;
646:                }
647:                Class pclass = getProcedureClass(pproc);
648:                if (pclass == null)
649:                    return null;
650:                return getMethodFor((ClassType) Type.make(pclass), pproc
651:                        .getName(), decl, atypes, language);
652:            }
653:
654:            public static Class getProcedureClass(Object pproc) {
655:                Class procClass;
656:                if (pproc instanceof  ModuleMethod)
657:                    procClass = ((ModuleMethod) pproc).module.getClass();
658:                else
659:                    procClass = pproc.getClass();
660:                try {
661:                    if (procClass.getClassLoader() == systemClassLoader)
662:                        return procClass;
663:                } catch (SecurityException ex) {
664:                }
665:                return null;
666:            }
667:
668:            /** Get PrimProcedure for matching method in given class. */
669:            public static PrimProcedure getMethodFor(Class procClass,
670:                    String name, Declaration decl, Expression[] args,
671:                    Language language) {
672:                return getMethodFor((ClassType) Type.make(procClass), name,
673:                        decl, args, language);
674:            }
675:
676:            public static PrimProcedure getMethodFor(ClassType procClass,
677:                    String name, Declaration decl, Expression[] args,
678:                    Language language) {
679:                int nargs = args.length;
680:                Type[] atypes = new Type[nargs];
681:                for (int i = nargs; --i >= 0;)
682:                    atypes[i] = args[i].getType();
683:                return getMethodFor(procClass, name, decl, atypes, language);
684:            }
685:
686:            public static PrimProcedure getMethodFor(ClassType procClass,
687:                    String name, Declaration decl, Type[] atypes,
688:                    Language language) {
689:                PrimProcedure best = null;
690:                int bestCode = -1;
691:                boolean bestIsApply = false;
692:                try {
693:                    if (name == null)
694:                        return null;
695:                    String mangledName = Compilation.mangleName(name);
696:                    String mangledNameV = mangledName + "$V";
697:                    String mangledNameVX = mangledName + "$V$X";
698:                    String mangledNameX = mangledName + "$X";
699:                    boolean applyOk = true; // Also look for "apply" and "apply$V".
700:                    for (Method meth = procClass.getDeclaredMethods(); meth != null; meth = meth
701:                            .getNext()) {
702:                        int mods = meth.getModifiers();
703:                        if ((mods & (Access.STATIC | Access.PUBLIC)) != (Access.STATIC | Access.PUBLIC)) {
704:                            if (decl == null || decl.base == null)
705:                                continue;
706:                        }
707:                        String mname = meth.getName();
708:                        boolean isApply;
709:                        if (mname.equals(mangledName)
710:                                || mname.equals(mangledNameV)
711:                                || mname.equals(mangledNameX)
712:                                || mname.equals(mangledNameVX)) {
713:                            isApply = false;
714:                        } else if (applyOk
715:                                && (mname.equals("apply") || mname
716:                                        .equals("apply$V"))) {
717:                            isApply = true;
718:                        } else
719:                            continue;
720:                        if (!isApply) {
721:                            // If we saw a real match, ignore "apply".
722:                            applyOk = false;
723:                            if (bestIsApply) {
724:                                best = null;
725:                                bestCode = -1;
726:                                bestIsApply = false;
727:                            }
728:                        }
729:                        PrimProcedure prproc = new PrimProcedure(meth, language);
730:                        prproc.setName(name);
731:                        int code = prproc.isApplicable(atypes);
732:                        if (code < 0 || code < bestCode)
733:                            continue;
734:                        if (code > bestCode) {
735:                            best = prproc;
736:                        } else if (best != null) {
737:                            best = (PrimProcedure) MethodProc.mostSpecific(
738:                                    best, prproc);
739:                            if (best == null) { // Ambiguous.
740:                                if (bestCode > 0)
741:                                    return null;
742:                            }
743:                        }
744:                        bestCode = code;
745:                        bestIsApply = isApply;
746:                    }
747:                } catch (SecurityException ex) {
748:                }
749:                return best;
750:            }
751:
752:            public String getName() {
753:                String name = super .getName();
754:                if (name != null)
755:                    return name;
756:                name = getVerboseName();
757:                setName(name);
758:                return name;
759:            }
760:
761:            public String getVerboseName() {
762:                StringBuffer buf = new StringBuffer(100);
763:                if (method == null) {
764:                    buf.append("<op ");
765:                    buf.append(op_code);
766:                    buf.append('>');
767:                } else {
768:                    buf.append(method.getDeclaringClass().getName());
769:                    buf.append('.');
770:                    buf.append(method.getName());
771:                }
772:                buf.append('(');
773:                for (int i = 0; i < argTypes.length; i++) {
774:                    if (i > 0)
775:                        buf.append(',');
776:                    buf.append(argTypes[i].getName());
777:                }
778:                buf.append(')');
779:                return buf.toString();
780:            }
781:
782:            public String toString() {
783:                StringBuffer buf = new StringBuffer(100);
784:                buf.append(retType.getName());
785:                buf.append(' ');
786:                buf.append(getVerboseName());
787:                return buf.toString();
788:            }
789:
790:            public void print(java.io.PrintWriter ps) {
791:                ps.print("#<primitive procedure ");
792:                ps.print(toString());
793:                ps.print('>');
794:            }
795:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.