001: package gnu.kawa.functions;
002:
003: import gnu.bytecode.*;
004: import gnu.mapping.*;
005: import gnu.kawa.reflect.*;
006: import gnu.expr.*;
007: import java.io.*;
008:
009: /** The value of the Kawa Scehem expression '*:PART-NAME'.
010: * This function invokes a method or accesses a field,
011: * if the PART-NAME starts with a '.'.
012: *
013: * This syntax is semi-depecated, since instead of
014: * (*:method-name instance args ...) you can now write
015: * (instance:method-name args ...), and
016: * instead of (*:.field-name instance) you can write
017: * instance:field-name (without the parentheses).
018: */
019:
020: public class GetNamedInstancePart extends ProcedureN implements
021: Externalizable, CanInline, HasSetter {
022: String pname;
023: boolean isField;
024:
025: public static Expression makeExp(Expression member) {
026: String name;
027: if (member instanceof QuoteExp) {
028: Object val = ((QuoteExp) member).getValue();
029: if (val instanceof String)
030: return QuoteExp.getInstance(new GetNamedInstancePart(
031: val.toString()));
032: }
033: Expression[] args = new Expression[2];
034: args[0] = new QuoteExp(ClassType
035: .make("gnu.kawa.functions.GetNamedInstancePart"));
036: args[1] = member;
037: return new ApplyExp(Invoke.make, args);
038: }
039:
040: public GetNamedInstancePart() {
041: }
042:
043: public GetNamedInstancePart(String name) {
044: setPartName(name);
045: }
046:
047: public void setPartName(String name) {
048: setName("get-instance-part:" + name);
049: if (name.length() > 1 && name.charAt(0) == '.') {
050: isField = true;
051: pname = name.substring(1);
052: } else {
053: isField = false;
054: pname = name;
055: }
056: }
057:
058: public int numArgs() {
059: return isField ? 0x1001 : 0xfffff001;
060: }
061:
062: public Expression inline(ApplyExp exp, ExpWalker walker) {
063: Expression[] args = exp.getArgs();
064: Expression[] xargs;
065: Procedure proc;
066: if (isField) {
067: xargs = new Expression[] { args[0], new QuoteExp(pname) };
068: proc = SlotGet.field;
069: } else {
070: int nargs = args.length;
071: xargs = new Expression[nargs + 1];
072: xargs[0] = args[0];
073: xargs[1] = new QuoteExp(pname);
074: System.arraycopy(args, 1, xargs, 2, nargs - 1);
075: proc = Invoke.invoke;
076: }
077: return ((InlineCalls) walker).walkApplyOnly(new ApplyExp(proc,
078: xargs));
079: }
080:
081: public Object applyN(Object[] args) throws Throwable {
082: checkArgCount(this , args.length);
083: if (isField)
084: return SlotGet.field(args[0], pname);
085: else {
086: Object[] xargs = new Object[args.length + 1];
087: xargs[0] = args[0];
088: xargs[1] = pname;
089: System.arraycopy(args, 1, xargs, 2, args.length - 1);
090: return Invoke.invoke.applyN(xargs);
091: }
092: }
093:
094: public Procedure getSetter() {
095: if (!isField)
096: throw new RuntimeException(
097: "no setter for instance method call");
098: return new SetNamedInstancePart(pname);
099: }
100:
101: public void writeExternal(ObjectOutput out) throws IOException {
102: out.writeObject(isField ? ("." + pname) : pname);
103: }
104:
105: public void readExternal(ObjectInput in) throws IOException,
106: ClassNotFoundException {
107: setPartName((String) in.readObject());
108: }
109: }
110:
111: class SetNamedInstancePart extends Procedure2 implements
112: Externalizable, CanInline {
113: String pname;
114:
115: public SetNamedInstancePart() {
116: }
117:
118: public SetNamedInstancePart(String name) {
119: setPartName(name);
120: }
121:
122: public void setPartName(String name) {
123: setName("set-instance-part:." + name);
124: pname = name;
125: }
126:
127: public Expression inline(ApplyExp exp, ExpWalker walker) {
128: Expression[] args = exp.getArgs();
129: Expression[] xargs = new Expression[] { args[0],
130: new QuoteExp(pname), args[1] };
131: Procedure proc = SlotSet.set$Mnfield$Ex;
132: return ((InlineCalls) walker).walkApplyOnly(new ApplyExp(proc,
133: xargs));
134: }
135:
136: public Object apply2(Object instance, Object value)
137: throws Throwable {
138: SlotSet.setField(instance, pname, value);
139: return Values.empty;
140: }
141:
142: public void writeExternal(ObjectOutput out) throws IOException {
143: out.writeObject(pname);
144: }
145:
146: public void readExternal(ObjectInput in) throws IOException,
147: ClassNotFoundException {
148: setPartName((String) in.readObject());
149: }
150: }
|