123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- package kawa.standard;
- import kawa.lang.*;
- import gnu.lists.*;
- import gnu.mapping.*;
- import gnu.mapping.Location; // As opposed to gnu.bytecode.Location.
- import gnu.expr.*;
- import gnu.bytecode.*;
- import gnu.kawa.functions.GetNamedPart;
- import gnu.kawa.lispexpr.LispLanguage;
- import gnu.kawa.reflect.Invoke;
- import gnu.kawa.reflect.SlotGet;
- import gnu.kawa.reflect.StaticFieldLocation;
- /**
- * The Syntax transformer that re-writes the Kawa "location" primitive.
- * @author Per Bothner
- */
- public class location extends Syntax
- {
- public static final location location = new location();
- static { location.setName("location"); }
- public Expression rewrite (Object obj, Translator tr)
- {
- if (! (obj instanceof Pair))
- return tr.syntaxError ("missing argument to location");
- Pair pair = (Pair) obj;
- if (pair.getCdr() != LList.Empty)
- return tr.syntaxError ("extra arguments to location");
- Expression[] args = { location.rewrite(tr.rewrite(pair.getCar()), tr) };
- return Invoke.makeInvokeStatic(thisType, "makeLocationProc", args);
- }
- private static ClassType thisType = ClassType.make("kawa.standard.location");
- public static Expression rewrite (Expression arg, Translator tr)
- {
- if (arg instanceof ReferenceExp)
- {
- ReferenceExp rexp = (ReferenceExp) arg;
- rexp.setDontDereference(true);
- Declaration decl = rexp.getBinding();
- if (decl != null)
- {
- decl.maybeIndirectBinding(tr);
- decl = Declaration.followAliases(decl);
- decl.setCanRead(true);
- decl.setCanWrite(true);
- }
- return rexp;
- }
- if (arg instanceof ApplyExp)
- {
- ApplyExp aexp = (ApplyExp) arg;
- Expression afunc = aexp.getFunction();
- Expression[] aargs = aexp.getArgs();
- int aalen = aargs.length;
- Object aproc = afunc.valueIfConstant();
- StaticFieldLocation sloc = null;
- if (aproc == GetNamedPart.getNamedPart && aalen == 2) {
- Expression exp = rewriteApply(aargs[0], aargs[1], tr);
- if (exp != null)
- return exp;
- }
- if (aproc == Scheme.applyToArgs && aalen == 3
- && aargs[0].valueIfConstant() == SlotGet.staticField) {
- Expression exp = rewriteApply(aargs[1], aargs[2], tr);
- if (exp != null)
- return exp;
- }
- Expression[] args = new Expression[aalen + 1];
- args[0] = afunc;
- System.arraycopy(aargs, 0, args, 1, aalen);
- return new ApplyExp(getMakeProcLocProc(), args);
- }
- return tr.syntaxError("invalid argument to location");
- }
- /** Helper for handling special cases to take locations of ApplyExp.
- * Specifically for static fields and static member classes.
- */
- static Expression rewriteApply(Expression classExp, Expression nameExp,
- Compilation comp) {
- ClassType caller = comp.curClass;
- Object cls = classExp.valueIfConstant();
- if (cls instanceof Class)
- cls = Type.make((Class) cls);
- Object nam = nameExp.valueIfConstant();
- if (cls instanceof ClassType && nam instanceof SimpleSymbol) {
- String name = nam.toString();
- ClassType ctype = (ClassType) cls;
- Member member = SlotGet.lookupMember(ctype, name, caller);
- if (member != null && member.getStaticFlag()) {
- if (member instanceof Field) {
- StaticFieldLocation sloc =
- new StaticFieldLocation(ctype, Mangling.mangleNameIfNeeded(name));
- ReferenceExp rexp = new ReferenceExp(sloc.getDeclaration());
- rexp.setDontDereference(true);
- return rexp;
- }
- else if (member instanceof ClassType) {
- ClassType cltype = (ClassType) member;
- if (cltype.isExisting()) {
- try {
- Class clas = cltype.getReflectClass();
- if (clas != null)
- return new QuoteExp(clas);
- } catch (Exception ex) {
- // silenty ignored
- }
- }
- }
- }
- }
- return null;
- }
- private static PrimProcedure makeProcLocProc;
- public static synchronized PrimProcedure getMakeProcLocProc() {
- if (makeProcLocProc == null) {
- makeProcLocProc = new PrimProcedure(ClassType.make("kawa.standard.location").getDeclaredMethod("makeProcLocation$V", 2));
- }
- return makeProcLocProc;
- }
- public static Location
- makeProcLocation$V (Procedure proc, Object[] args)
- {
- int nargs = args.length;
- if (proc instanceof gnu.kawa.functions.ApplyToArgs
- && nargs > 0
- && args[0] instanceof Procedure) // FIXME
- {
- proc = (Procedure) args[0];
- if (proc instanceof LocationProc && nargs == 1)
- return ((LocationProc) proc).getLocation();
- Object[] rargs = new Object[nargs-1];
- System.arraycopy(args, 1, rargs, 0, rargs.length);
- return new ProcLocation(proc, rargs);
- }
- if (proc instanceof LocationProc && nargs == 0)
- return ((LocationProc) proc).getLocation();
- return new ProcLocation(proc, args);
- }
- public static LocationProc
- makeLocationProc (Location loc)
- {
- return new LocationProc(loc);
- }
- }
|