⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 invoke.java

📁 A framework written in Java for implementing high-level and dynamic languages, compiling them into J
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package gnu.kawa.reflect;import gnu.mapping.*;import gnu.expr.*;import gnu.bytecode.*;import gnu.lists.FString;import java.lang.reflect.Array;import gnu.kawa.lispexpr.ClassNamespace; // FIXMEpublic class Invoke extends ProcedureN implements CanInline{  /** The kind on invoke operation.   *  'N' - make (new).   *  'S' - invoke-static (static or non-static):   *        The first operand is a Class or Type, the second is the name,   *        and if the is non-static the 3rd is the receiver.   *  's' - Like 'S' but only allow static methods. [not used]   *  'V' - non-static invoke, only allow non-static methods. [not used]   *  '*' - non-static invoke, can match static methods also.   *        This is Java's 'Primary.MethodName(args)' - if the selected method   *        is static, we only use Primary's type for method select,   *        but ignore its value.   */  char kind;  Language language;  public static final Invoke invoke = new Invoke("invoke", '*');  public static final Invoke invokeStatic = new Invoke("invoke-static", 'S');  public static final Invoke invokeSpecial = new Invoke("invoke-special", 'P');  public static final Invoke make = new Invoke("make", 'N');  public Invoke(String name, char kind)  {    super(name);    this.kind = kind;    this.language = Language.getDefaultLanguage();  }  public Invoke(String name, char kind, Language language)  {    super(name);    this.kind = kind;    this.language = language;  }  public static Object invoke$V(Object[] args) throws Throwable  {    return invoke.applyN(args);  }  public static Object invokeStatic$V(Object[] args) throws Throwable  {    return invokeStatic.applyN(args);  }  public static Object make$V(Object[] args) throws Throwable  {    return make.applyN(args);  }  private static ObjectType typeFrom (Object arg, Invoke thisProc)  {    if (arg instanceof Class)      arg = Type.make((Class) arg);    if (arg instanceof ObjectType)      return (ObjectType) arg;    if (arg instanceof String || arg instanceof FString)      return ClassType.make(arg.toString());    if (arg instanceof Symbol)      return ClassType.make(((Symbol) arg).getName());    if (arg instanceof ClassNamespace)      return ((ClassNamespace) arg).getClassType();    throw new WrongType(thisProc, 0, arg, "class-specifier");  }  public void apply (CallContext ctx) throws Throwable  {    Object[] args = ctx.getArgs();    if (kind=='S' || kind=='V' || kind=='s' || kind=='*')      {        // The following is an optimization, so that output from the        // method is sent directly to ctx.consumer, rather than reified.        int nargs = args.length;        Procedure.checkArgCount(this, nargs);        Object arg0 = args[0];        ObjectType dtype = (ObjectType)          ((kind == 'S' || kind == 's') ? typeFrom(arg0, this)           : Type.make(arg0.getClass()));        Procedure proc = lookupMethods(dtype, args[1]);        Object[] margs = new Object[nargs-(kind == 'S' ? 2 : 1)];        int i = 0;        if (kind == 'V' || kind == '*')          margs[i++] = args[0];        System.arraycopy(args, 2, margs, i, nargs - 2);        proc.checkN(margs, ctx);      }    else      ctx.writeValue(this.applyN(args));  }  public Object applyN (Object[] args) throws Throwable  {    if (kind == 'P')      throw new RuntimeException(getName()                                  + ": invoke-special not allowed at run time");        int nargs = args.length;    Procedure.checkArgCount(this, nargs);    Object arg0 = args[0];    ObjectType dtype = (kind != 'V' && kind != '*' ? typeFrom(arg0, this)                       : (ObjectType) Type.make(arg0.getClass()));    Object mname;    if (kind == 'N')      {	mname = null;        if (dtype instanceof TypeValue)          {            Procedure constructor = ((TypeValue) dtype).getConstructor();            if (constructor != null)              {                nargs--;                Object[] xargs = new Object[nargs];                System.arraycopy(args, 1, xargs, 0, nargs);                return constructor.applyN(xargs);              }          }	if (dtype instanceof PairClassType)	  {	    PairClassType ptype = (PairClassType) dtype;	    dtype = ptype.instanceType;	  }        if (dtype instanceof ArrayType)          {            Type elementType = ((ArrayType) dtype).getComponentType();            int len;            len = args.length-1;            String name;            int length;            int i;            boolean lengthSpecified;            if (len >= 2 && args[1] instanceof Keyword                && ("length".equals(name = ((Keyword) args[1]).getName())                    || "size".equals(name)))              {                length = ((Number) args[2]).intValue();                i = 3;                lengthSpecified = true;              }            else              {                length = len;                i = 1;                lengthSpecified = false;              }            Object arr = Array.newInstance(elementType.getReflectClass(),                                           length);            int index = 0;            for (; i <= len;  i++)              {                Object arg = args[i];                if (lengthSpecified && arg instanceof Keyword && i < len)                  {                    String kname = ((Keyword) arg).getName();                    try                      {                        index =  Integer.parseInt(kname);                      }                    catch (Throwable ex)                      {                        throw new RuntimeException("non-integer keyword '"+kname+"' in array constructor");                      }                    arg = args[++i];                  }                Array.set(arr, index, elementType.coerceFromObject(arg));                index++;              }            return arr;          }      }    else      {        mname = args[1];      }    MethodProc proc = lookupMethods((ObjectType) dtype, mname);    if (kind != 'N')      {        Object[] margs = new Object[nargs-(kind == 'S' || kind == 's' ? 2 : 1)];        int i = 0;        if (kind == 'V' || kind == '*')          margs[i++] = args[0];        System.arraycopy(args, 2, margs, i, nargs - 2);        return proc.applyN(margs);      }    else      {        CallContext vars = CallContext.getInstance();        int err = proc.matchN(args, vars);        if (err == 0)          return vars.runUntilValue();        if ((nargs & 1) == 1)          {            // Check if args is a set of (keyword,value)-pairs.            for (int i = 1;  ;  i += 2)              {                if (i == nargs)                  {                    Object result;                    result = proc.apply1(args[0]);                    for (i = 1;  i < nargs;  i += 2)                      {                        Keyword key = (Keyword) args[i];                        Object arg = args[i+1];                        SlotSet.apply(false, result, key.getName(), arg);                      }                    return result;                  }                if (! (args[i] instanceof Keyword))                  break;              }          }        MethodProc vproc = ClassMethods.apply((ClassType) dtype, "valueOf",                                              '\0', language);        if (vproc != null)          {            Object[] margs = new Object[nargs-1];            System.arraycopy(args, 1, margs, 0, nargs-1);            err = vproc.matchN(margs, vars);            if (err == 0)              return vars.runUntilValue();          }        throw MethodProc.matchFailAsException(err, proc, args);      }  }  public int numArgs()  {    return (-1 << 12) | (kind == 'N' ? 1 : 2);  }  protected MethodProc lookupMethods(ObjectType dtype, Object name)  {    String mname;    if (kind == 'N')      mname = "<init>";    else      {        if (name instanceof String || name instanceof FString)          mname = name.toString();	else if (name instanceof Symbol)	  mname = ((Symbol) name).getName();        else          throw new WrongType(this, 1, null);        mname = Compilation.mangleName(mname);      }    MethodProc proc = ClassMethods.apply(dtype, mname,                                         kind == 'P' ? 'P'                                         : kind == '*' || kind == 'V' ? 'V'                                         : '\0',                                         language);    if (proc == null)      throw new RuntimeException(getName() + ": no method named `"                                 + mname + "' in class " + dtype.getName());    return proc;  }  protected PrimProcedure[] getMethods(ObjectType ctype, String mname,                                        ClassType caller)  {    return ClassMethods.getMethods(ctype, mname,                                   kind == 'P' ? 'P'                                   : kind == '*' || kind == 'V' ? 'V'                                   : '\0',                                   caller, language);  }  private static long selectApplicable(PrimProcedure[] methods,                                       ObjectType ctype,                                       Expression[] args, int margsLength,                                        int argsStartIndex, int objIndex)  {    Type[] atypes = new Type[margsLength];    int dst = 0;    if (objIndex >= 0)      atypes[dst++] = ctype;    for (int src = argsStartIndex;          src < args.length && dst < atypes.length;          src++, dst++)      atypes[dst] = args[src].getType();    return ClassMethods.selectApplicable(methods, atypes);  }  /** Return an array if args (starting with start) is a set of   * (keyword, value)-value pairs. */  static Object[] checkKeywords(Type type, Expression[] args,                                int start, ClassType caller)  {    int len = args.length;    if (((len - start) & 1) != 0)      return null;    Object[] fields = new Object[(len-start) >> 1];    for (int i = fields.length;  -- i>= 0; )      {        Expression arg = args[start + 2 * i];        if (! (arg instanceof QuoteExp))          return null;        Object value = ((QuoteExp) arg).getValue();        if (! (value instanceof Keyword))          return null;        String name = ((Keyword) value).getName();        Member slot = SlotSet.lookupMember((ClassType) type, name, caller);        fields[i] = slot != null ? (Object) slot : (Object) name;      }    return fields;  }  /** Check if class exists.   * @return 1 if class actually exists;   * -1 is class should exist, but doesn't;   * and 0 otherwise.   */  public static int checkKnownClass (Type type, Compilation comp)  {    if (type instanceof ClassType && ((ClassType) type).isExisting())      {        try          {            type.getReflectClass();            return 1;          }        catch (Exception ex)          {            comp.error('e', "unknown class: " + type.getName());            return -1;          }      }    return 0;  }  /** Resolve class specifier to ClassType at inline time.   * This is an optimization to avoid having a module-level binding   * created for the class name. */  public static ApplyExp inlineClassName (ApplyExp exp, int carg,                                          InlineCalls walker)  {    Compilation comp = walker.getCompilation();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -