01: package gnu.kawa.functions;
02:
03: import gnu.lists.*;
04: import gnu.mapping.*;
05:
06: /** Implement the standard Scheme function "apply".
07: * This has been generalized so that the last (list argument)
08: * can be any sequence, or any primitive array coercible to Object[]. */
09:
10: public class Apply extends ProcedureN {
11: public static final Apply apply = new Apply();
12: static {
13: apply.setName("apply");
14: }
15:
16: private Object[] getArguments(Object[] args, int skip) {
17: int count = args.length;
18: if (count < skip + 1)
19: throw new WrongArguments("apply", 2,
20: "(apply proc [args] args) [count:" + count
21: + " skip:" + skip + "]");
22: Object last = args[count - 1];
23: int last_count;
24: if (last instanceof Object[]) {
25: Object[] last_arr = (Object[]) last;
26: if (count == 2)
27: return last_arr;
28: last_count = last_arr.length;
29: } else if (last instanceof Sequence)
30: last_count = ((Sequence) last).size();
31: else
32: last_count = -1;
33: if (last_count < 0)
34: throw new WrongType(this , count, last, "sequence or array");
35: int numArgs = last_count + (count - skip - 1);
36: Object[] proc_args = new Object[numArgs];
37: int i;
38: for (i = 0; i < count - skip - 1; i++)
39: proc_args[i] = args[i + skip];
40: if (last instanceof Object[]) {
41: System.arraycopy((Object[]) last, 0, proc_args, i,
42: last_count);
43: } else {
44: while (last instanceof Pair) {
45: Pair pair = (Pair) last;
46: proc_args[i++] = pair.car;
47: last = pair.cdr;
48: last_count--;
49: }
50: if (last_count > 0) {
51: Sequence last_seq = (Sequence) last;
52: for (int j = 0; j < last_count; j++)
53: proc_args[i++] = last_seq.get(j);
54: }
55: }
56: return proc_args;
57: }
58:
59: public static Object doApply(Procedure proc, Object[] args)
60: throws Throwable {
61: return proc.applyN(apply.getArguments(args, 0));
62: }
63:
64: public Object applyN(Object[] args) throws Throwable {
65: return ((Procedure) args[0]).applyN(getArguments(args, 1));
66: }
67:
68: public void apply(CallContext ctx) throws Throwable {
69: Object[] args = ctx.getArgs();
70: ((Procedure) args[0]).checkN(getArguments(args, 1), ctx);
71: }
72: }
|