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

📄 getnamedpart.java

📁 A framework written in Java for implementing high-level and dynamic languages, compiling them into J
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package gnu.kawa.functions;import gnu.bytecode.*;import gnu.mapping.*;import gnu.kawa.reflect.*;import gnu.expr.*;import java.io.*;import kawa.lang.Translator;/** Procedure to get the value of a named component of an object. */public class GetNamedPart extends Procedure2 implements HasSetter, CanInline{  public static final GetNamedPart getNamedPart = new GetNamedPart();  /** PREFIX:<> is equivalent to the ClassType bound to PREFIX. */  public static final String CLASSTYPE_FOR = "<>";  /** Pseudo-method-name for the cast operation. */  public static final String CAST_METHOD_NAME = "@";  /** Pseudo-method-name for class-membership-test (instanceof) operation. */  public static final String INSTANCEOF_METHOD_NAME = "instance?";  public static String combineName (Expression part1, Expression part2)  {    String name1;    Object name2;    if (part2 instanceof QuoteExp        && (name2 = ((QuoteExp) part2).getValue()) instanceof String        && ((part1 instanceof ReferenceExp             && (name1 = ((ReferenceExp) part1).getSimpleName()) != null)            || (part1 instanceof GetNamedExp                && (name1 = ((GetNamedExp) part1).combinedName) != null)))      return (name1+':'+name2).intern();    return null;  }  public static Expression makeExp (Expression clas, Expression member)  {    ReferenceExp rexp;    String combinedName = combineName(clas, member);    Environment env = Environment.getCurrent();    if (combinedName != null)      {        Translator tr = (Translator) Compilation.getCurrent();        Declaration decl = tr.lexical.lookup(combinedName, false/*FIXME*/);        if (! Declaration.isUnknown(decl))          return new ReferenceExp(decl);        Symbol symbol = env.defaultNamespace().lookup(combinedName);        Object property = null; // FIXME?        if (symbol != null && env.isBound(symbol, property))          return new ReferenceExp(combinedName);      }    if (clas instanceof ReferenceExp        && (rexp = (ReferenceExp) clas).isUnknown())      {        Object rsym = rexp.getSymbol();        Symbol sym = rsym instanceof Symbol ? (Symbol) rsym          : env.getSymbol(rsym.toString());        if (env.get(sym, null) == null)          {            String name = rexp.getName();            try              {                Class cl = ClassType.getContextClass(name);                clas = QuoteExp.getInstance(Type.make(cl));              }            catch (Throwable ex)              {              }          }      }    Expression[] args = { clas, member };    GetNamedExp exp = new GetNamedExp(args);    exp.combinedName = combinedName;    return exp;  }  public static Expression makeExp (Expression clas, String member)  {    return makeExp(clas, new QuoteExp(member));  }  public static Expression makeExp (Type type, String member)  {    return makeExp(new QuoteExp(type), new QuoteExp(member));  }  public Expression inline (ApplyExp exp, ExpWalker walker)  {    Expression[] args = exp.getArgs();    if (args.length != 2 || ! (args[1] instanceof QuoteExp)        || ! (exp instanceof GetNamedExp))      return exp;    Expression context = args[0];    Declaration decl = null;    if (context instanceof ReferenceExp)      {        ReferenceExp rexp = (ReferenceExp) context;        if ("*".equals(rexp.getName()))          return GetNamedInstancePart.makeExp(args[1]);        decl = rexp.getBinding();      }    String mname = ((QuoteExp) args[1]).getValue().toString();    Type type = context.getType();    boolean isInstanceOperator = context == QuoteExp.nullExp;    Compilation comp = walker.getCompilation();    Language language = comp.getLanguage();    Type typeval = language.getTypeFor(context, false);    ClassType caller = comp == null ? null      : comp.curClass != null ? comp.curClass      : comp.mainClass;    GetNamedExp nexp = (GetNamedExp) exp;    if (typeval instanceof Type)      {        if (mname.equals(CLASSTYPE_FOR))          return new QuoteExp(typeval);        if (typeval instanceof ObjectType)          {            if (mname.equals("new"))              return nexp.setProcedureKind('N');            if (mname.equals(INSTANCEOF_METHOD_NAME))              return nexp.setProcedureKind('I');            if (mname.equals(CAST_METHOD_NAME))              return nexp.setProcedureKind('C');          }      }    if (typeval instanceof ClassType)      {        if (mname.length() > 1 && mname.charAt(0) == '.')          {            // The following would also work:            // return nexp.setProcedureKind('D');            // However, it makes optimzing the 'setter' case harder.            return new QuoteExp(new NamedPart(typeval, mname, 'D'));          }        if (Invoke.checkKnownClass(typeval, comp) < 0)          return exp;        PrimProcedure[] methods          = ClassMethods.getMethods((ClassType) typeval,                                    Compilation.mangleName(mname),                                    '\0', caller, language);        if (methods != null && methods.length > 0)          {            nexp.methods = methods;            return nexp.setProcedureKind('S');          }        ApplyExp aexp = new ApplyExp(SlotGet.staticField, args);        aexp.setLine(exp);        return ((InlineCalls) walker).walkApplyOnly(aexp);                                  }    if (typeval != null)      {              }    /*    if (type.isSubtype(Compilation.typeValues))      {        // FIXME      }    */    if (type.isSubtype(Compilation.typeClassType)        || type.isSubtype(Type.java_lang_Class_type))      // The container evaluates to a class (so we should look for a static      // field or method), but we don't know which class at compile-time.      // However, we should still optimize it somewhat, above.  FIXME.      return exp;    if (type instanceof ObjectType)      {        ObjectType otype = (ObjectType) type;        ClassType ctype          = type instanceof ClassType ? (ClassType) type : Type.pointer_type;        PrimProcedure[] methods          = ClassMethods.getMethods(otype, Compilation.mangleName(mname),                                    'V', caller, language);        if (methods != null && methods.length > 0)          {            nexp.methods = methods;            return nexp.setProcedureKind('M');          }        Member part = SlotGet.lookupMember(ctype, mname, caller);        if (part != null            || (mname.equals("length") && type instanceof ArrayType))          {            // FIXME: future kludge to avoid re-doing SlotGet.getField.            // args = new Expression[] { context, new QuoteExp(part) });            ApplyExp aexp = new ApplyExp(SlotGet.field, args);            aexp.setLine(exp);            return ((InlineCalls) walker).walkApplyOnly(aexp);          }        if (type.isSubtype(typeHasNamedParts))          {            Object val;            if (decl != null                && (val = Declaration.followAliases(decl).getConstantValue()) != null)              {                HasNamedParts value = (HasNamedParts) val;                if (value.isConstant(mname))                  {                    val = value.get(mname);                    return QuoteExp.getInstance(val);                  }              }            return new ApplyExp(typeHasNamedParts.getDeclaredMethod("get", 1),                                args).setLine(exp);          }      }    if (comp.getBooleanOption("warn-invoke-unknown-method", ! comp.immediate))      comp.error('w', "no known slot '"+mname+"' in "+type.getName());    return exp;  }  static final ClassType typeHasNamedParts  = ClassType.make("gnu.mapping.HasNamedParts");  public Object apply2 (Object container, Object part)    throws Throwable  {    if (container instanceof Values)      {        Object[] values = ((Values) container).getValues();        Values result = new Values();        for (int i = 0;  i < values.length;  i++)          {            Values.writeValues(apply2(values[i], part), result);          }        return result.canonicalize();      }    Symbol sym;    if (part instanceof Symbol)      sym = (Symbol) part;    else      sym = Namespace.EmptyNamespace.getSymbol(part.toString().intern());    return getNamedPart(container, sym);  }  public static Object getTypePart (Type type, String name)    throws Throwable  {    if (name.equals(CLASSTYPE_FOR))      return type;    if (type instanceof ObjectType)      {        if (name.equals(INSTANCEOF_METHOD_NAME))          return new NamedPart(type, name, 'I');        if (name.equals(CAST_METHOD_NAME))          return new NamedPart(type, name, 'C');        if (name.equals("new"))          return new NamedPart(type, name, 'N');        if (name.equals(".length")            || (name.length() > 1 && name.charAt(0) == '.'                && type instanceof ClassType))          return new NamedPart(type, name, 'D');      }    if (type instanceof ClassType)      {        try          {            return gnu.kawa.reflect.SlotGet.staticField(type, name);          }        catch (Throwable ex)          {            // FIXME!          }        return ClassMethods.apply(ClassMethods.classMethods, type, name);      }    return getMemberPart(type, name);  }  public static Object getNamedPart (Object container, Symbol part)    throws Throwable  {    String name = part.getName();    if (container instanceof HasNamedParts)      return ((HasNamedParts) container).get(name);    if (container instanceof Class)      container = (ClassType) Type.make((Class) container);    if (container instanceof Type)      return getTypePart((Type) container, name);    return getMemberPart(container, part.toString());  }  public static Object getMemberPart(Object container, String name)    throws Throwable  {    try      {        return gnu.kawa.reflect.SlotGet.field(container, name);      }    catch (Throwable ex)      {        // FIXME!      }    MethodProc methods = ClassMethods.apply((ClassType) ClassType.make(container.getClass()),                                            Compilation.mangleName(name), '\0',                                            Language.getDefaultLanguage());    if (methods != null)      return new NamedPart(container, name, 'M', methods);    throw new RuntimeException("no part '"+name+"' in "+container);  }  public Procedure getSetter()  {    return SetNamedPart.setNamedPart;  }}class GetNamedExp extends ApplyExp{  /*   * 'N' - new (make) - if methodName is "new".   * 'I' - instance of - if methodName is INSTANCEOF_METHOD_NAME.   * 'C' - cast - if methodName is CAST_METHOD_NAME.   * 'T' - type - if methodName is CLASSTYPE_FOR   * 'M' - non-static method   * 'S' - static method   * 'D' - if methodname starts with '.'   */  char kind;  PrimProcedure[] methods;  public String combinedName;  public void apply (CallContext ctx) throws Throwable  {    if (combinedName != null)      {

⌨️ 快捷键说明

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