001: // Copyright (c) 1999 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.mapping.*;
007: import java.lang.reflect.*;
008:
009: /** Call a specified method in in a ModuleBody.
010: * We use an extra level of indirection, but we save by having
011: * to create fewer classes than in the one-class-per-procedure
012: * scheme, without having to use (slow) reflection.
013: *
014: * ModuleMethod is redundant, since it could be replaced by ApplyMethodProc.
015: * However, ModuleMethod uses virtual method calls, while ApplyMethodProc
016: * uses the possibly much slower interface method calls.
017: */
018: // NICE: Avoid being dependant of gnu.mapping.MethodProc.
019: // NICE: This is bad because this class is needed at runtime.
020: public class ModuleMethod extends ProcedureN {
021: ModuleBody module;
022: public final int selector;
023: private int numArgs;
024:
025: public ModuleMethod(ModuleBody module, int selector, String name,
026: int numArgs) {
027: this .module = module;
028: this .selector = selector;
029: this .numArgs = numArgs;
030: if (name != null)
031: setName(name);
032: }
033:
034: /** Figure out parameter types.
035: * Uses reflection to get method parameter types.
036: * INCOMPLETE - does not handle procedures with optional or rest args. */
037: /*
038: protected void resolveParameterTypes()
039: {
040: Method method = null;
041: try
042: {
043: Class moduleClass = module.getClass();
044: Method[] methods = moduleClass.getDeclaredMethods();
045: String mangledName = Compilation.mangleNameIfNeeded(getName());
046: for (int i = methods.length; --i >= 0; )
047: {
048: if (methods[i].getName().equals(mangledName))
049: {
050: if (method != null)
051: {
052: method = null;
053: break;
054: }
055: method = methods[i];
056: }
057: }
058: if (method != null)
059: {
060: Interpreter interp = Interpreter.getInterpreter();
061: Class[] parameterClasses = method.getParameterTypes();
062: int numParamTypes = parameterClasses.length;
063: gnu.bytecode.Type[] atypes = new gnu.bytecode.Type[numParamTypes];
064: for (int i = numParamTypes; --i >= 0; )
065: {
066: atypes[i] = interp.getTypeFor(parameterClasses[i]);
067: }
068: this.argTypes = atypes;
069: }
070: }
071: catch (Throwable ex)
072: {
073: }
074: if (argTypes == null)
075: super.resolveParameterTypes();
076: }
077: */
078:
079: public int numArgs() {
080: return numArgs;
081: }
082:
083: public Object apply0() {
084: return module.apply0(this );
085: }
086:
087: public Object apply1(Object arg1) {
088: return module.apply1(this , arg1);
089: }
090:
091: public Object apply2(Object arg1, Object arg2) {
092: return module.apply2(this , arg1, arg2);
093: }
094:
095: public Object apply3(Object arg1, Object arg2, Object arg3) {
096: return module.apply3(this , arg1, arg2, arg3);
097: }
098:
099: public Object apply4(Object arg1, Object arg2, Object arg3,
100: Object arg4) {
101: return module.apply4(this , arg1, arg2, arg3, arg4);
102: }
103:
104: public Object applyN(Object[] args) {
105: return module.applyN(this , args);
106: }
107:
108: /*
109: public int match (CallContext ctx, Object[] args)
110: {
111: int argCount = args.length;
112: int num = numArgs();
113: int min = num & 0xFFF;
114: if (argCount < min)
115: return NO_MATCH_TOO_FEW_ARGS|min;
116: if (num >= 0)
117: {
118: int max = num >> 12;
119: if (argCount > max)
120: return NO_MATCH_TOO_MANY_ARGS|max;
121: }
122: for (int i = 0; i < args.length; i++)
123: {
124: Object argi = args[i];
125: if (argi != null && ! getParameterType(i).isInstance(argi))
126: return NO_MATCH_BAD_TYPE|i;
127: }
128: ctx.value1 = args;
129: return 0;
130: }
131:
132: public Object applyV(CallContext ctx)
133: {
134: return applyN((Object[]) ctx.value1);
135: }
136: */
137: }
|