001: package jsint;
002:
003: /**
004: A generic function.
005:
006: * @author Ken R. Anderson, Copyright 2000, kanderso@bbn.com, <a href="license.txt">license</a>
007: * subsequently modified by Jscheme project members
008: * licensed under zlib licence (see license.txt)
009: */
010:
011: public class Generic extends StaticReflector {
012:
013: private Object[] methodTable;
014:
015: public Object[] getMethodTable() {
016: return methodTable;
017: }
018:
019: public Generic(String name) {
020: this .name = name;
021: }
022:
023: private void addMethod(Class[] types, Procedure p) {
024: if (methodTable == null) {
025: methodTable = new Object[Invoke.BUCKET_SIZE];
026: install(0, types, p);
027: } else {
028: for (int i = 0; i < methodTable.length; i = i
029: + Invoke.BUCKET_SIZE)
030: if (Invoke.parameterTypesMatch(
031: ((Class[]) methodTable[i]), types)) {
032: install(i, types, p);
033: return;
034: }
035: grow();
036: install(methodTable.length - Invoke.BUCKET_SIZE, types, p);
037: }
038: }
039:
040: private void install(int i, Class[] types, Procedure p) {
041: methodTable[i] = types;
042: methodTable[i + 1] = p;
043: }
044:
045: private void grow() {
046: Object[] ms = new Object[methodTable.length
047: + Invoke.BUCKET_SIZE];
048: System.arraycopy(methodTable, 0, ms, 0, methodTable.length);
049: methodTable = ms;
050: }
051:
052: private static Generic ensureGeneric(Symbol name) {
053: if (name.isDefined()) {
054: Object v = name.getGlobalValue();
055: if (!(v instanceof Generic)) {
056: E.warn(name + " was bound to " + v
057: + " it is now a Generic.");
058: Generic g = new Generic(name.toString());
059: name.setGlobalValue(g);
060: return g;
061: } else
062: return ((Generic) v);
063: } else {
064: Generic g = new Generic(name.toString());
065: name.setGlobalValue(g);
066: return g;
067: }
068: }
069:
070: public static synchronized Generic defineMethod(Symbol name,
071: Pair types, Procedure p) {
072: Generic g = ensureGeneric(name);
073: g.addMethod(Invoke.toClassArray(types, 0), p);
074: return g;
075: }
076:
077: public Closure findMethod(Object[] args) {
078: return ((Closure) Invoke.findMethodNoOpt(methodTable, args));
079: }
080:
081: public Object apply(Object[] args) {
082: Procedure m = ((Procedure) Invoke.findMethodNoOpt(methodTable,
083: args));
084: // return ((Procedure)m).apply(args);
085: // KRA 11FEB02: Quick hack to get compiling working again.
086: if (m.minArgs == 0 && m.maxArgs == Integer.MAX_VALUE)
087: return m.apply(new Object[] { U.vectorToList(args) });
088: else
089: return m.apply(args);
090: }
091:
092: protected synchronized void reset() {
093: for (int i = 0; i < methodTable.length; i = i
094: + Invoke.BUCKET_SIZE)
095: methodTable[i] = resetParameters((Class[]) methodTable[i]);
096: }
097:
098: private Object[] resetParameters(Class[] parameters) {
099: Class[] parameters2 = new Class[parameters.length];
100: for (int i = 0; i < parameters2.length; i++)
101: parameters2[i] = Import.forName(parameters[i].getName());
102: return parameters2;
103: }
104: }
|