root/trunk/ProjectFortress/src/com/sun/fortress/interpreter/evaluator/values/MethodClosure.java

Revision 3998, 8.0 KB (checked in by EricAllen, 4 months ago)

Cleaned up some code formatting.

Line 
1/*******************************************************************************
2 Copyright 2009 Sun Microsystems, Inc.,
3 4150 Network Circle, Santa Clara, California 95054, U.S.A.
4 All rights reserved.
5
6 U.S. Government Rights - Commercial software.
7 Government users are subject to the Sun Microsystems, Inc. standard
8 license agreement and applicable provisions of the FAR and its supplements.
9
10 Use is subject to license terms.
11
12 This distribution may include materials developed by third parties.
13
14 Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered
15 trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
16 ******************************************************************************/
17
18package com.sun.fortress.interpreter.evaluator.values;
19
20import com.sun.fortress.compiler.WellKnownNames;
21import static com.sun.fortress.exceptions.InterpreterBug.bug;
22import static com.sun.fortress.exceptions.ProgramError.errorMsg;
23import com.sun.fortress.interpreter.evaluator.Environment;
24import com.sun.fortress.interpreter.evaluator.Evaluator;
25import com.sun.fortress.interpreter.evaluator.types.FType;
26import com.sun.fortress.nodes.Applicable;
27import com.sun.fortress.nodes.Expr;
28import com.sun.fortress.nodes_util.NodeUtil;
29import com.sun.fortress.useful.Hasher;
30import com.sun.fortress.useful.Useful;
31
32import java.util.Collections;
33import java.util.List;
34
35public class MethodClosure extends FunctionClosure implements Method {
36
37    final int selfParameterIndex;
38
39    final FType definer;
40
41    public MethodClosure(Environment within, Applicable fndef, FType definer) {
42        super(within, fndef);
43        this.definer = definer;
44        selfParameterIndex = NodeUtil.selfParameterIndex(getDef());
45
46    }
47
48    public MethodClosure(Environment within, Applicable fndef, FType definer, List<FType> args) {
49        super(within, fndef, args);
50        this.definer = definer;
51        selfParameterIndex = NodeUtil.selfParameterIndex(getDef());
52
53        // TODO this is really not figured out yet.
54    }
55
56    /**
57     * Method values have this filtering applied to them.
58     * This is necessary to create proper fm$whatever methods
59     * to be called by the functional method wrapper.
60     */
61    protected List<Parameter> adjustParameterList(List<Parameter> params2) {
62        return selfParameterIndex == -1 ? params2 : Useful.removeIndex(selfParameterIndex, params2);
63    }
64
65    // The choice of evaluation environment is the only difference between applying
66    // a MethodClosure and applying its subclass, a PartiallyDefinedMethod (which
67    // appears to actually represent some piece of a functional method in practice).
68    protected Environment envForApplication(FObject selfValue) {
69        return selfValue.getLexicalEnv();
70    }
71
72    public FValue applyMethod(FObject selfValue, List<FValue> args) {
73        args = conditionallyUnwrapTupledArgs(args);
74        Expr body = getBodyNull();
75
76        if (body != null) {
77            // This is a little over-tricky. In theory, all instances of
78            // objectExpr
79            // from the same
80            // "place" are environment-free, and instead they snag their
81            // environments from self.
82            // This might be wrong; what about the case where the surrounding
83            // environment is the
84            // instantiation of some generic? It seems like signatures etc will
85            // depend on this.
86            Evaluator eval = new Evaluator(buildEnvFromEnvAndParams(envForApplication(selfValue), args));
87            // selfName() was rewritten to our special "$self", and
88            // we don't care about shadowing here.
89            eval.e.putValueRaw(selfName(), selfValue);
90            return eval.eval(body);
91        } else if (def instanceof Method) {
92            return ((Method) def).applyMethod(selfValue, args);
93        } else {
94            return bug(errorMsg("MethodClosure ", this, " has neither body nor def instanceof Method"));
95
96        }
97    }
98
99    public FValue applyMethod(FObject self) {
100        return applyMethod(self, Collections.<FValue>emptyList());
101    }
102
103    // Remaining applyMethod work like a functional method invocation
104    // if applicable, otherwise they work like a method invocation with self first.
105
106    public FValue applyMethod(FObject self, FValue a) {
107        return applyMethod(self, Collections.singletonList(a));
108    }
109
110    public FValue applyMethod(FObject self, FValue a, FValue b) {
111        return applyMethod(self, Useful.list(a, b));
112    }
113
114    public FValue applyMethod(FObject self, FValue a, FValue b, FValue c) {
115        return applyMethod(self, Useful.list(a, b, c));
116    }
117
118    /* A MethodClosure should be invoked via applyInnerPossiblyGeneric iff:
119     *   The corresponding FunctionalMethod closure is an overloading at top level.
120     *   We're obtaining the MethodClosure from the overloading table,
121     *      where it was cached during a previous call.
122     *   In that case we can strip "AsIf" information from self, as
123     *      we've already dealt with the type information.
124     */
125    public FValue applyInnerPossiblyGeneric(List<FValue> args) {
126        if (selfParameterIndex == -1) {
127            return bug(errorMsg("MethodClosure for dotted method ",
128                                this,
129                                " was invoked as if it were a functional method."));
130        }
131        // We're a functional method instance, so fish out self and
132        // chain to applyMethod.
133        FObject self = (FObject) args.get(selfParameterIndex).getValue();
134        args = Useful.removeIndex(selfParameterIndex, args);
135        return applyMethod(self, args);
136    }
137
138    public FValue applyToArgs() {
139        return bug(errorMsg("No recipient object for method ", this));
140    }
141
142    public FValue applyToArgs(FValue a) {
143        return applyToArgs(toSelf(a), Collections.<FValue>emptyList());
144    }
145
146    // Remaining applyToArgs work like a functional method invocation
147    // if applicable, otherwise they work like a method invocation with self first.
148
149    public FValue applyToArgs(FValue a, FValue b) {
150        if (selfParameterIndex <= 0) {
151            return applyToArgs(toSelf(a), Collections.singletonList(b));
152        }
153        return applyToArgs(toSelf(b), Collections.singletonList(a));
154    }
155
156    public FValue applyToArgs(FValue a, FValue b, FValue c) {
157        if (selfParameterIndex <= 0) {
158            return applyToArgs(toSelf(a), Useful.list(b, c));
159        } else if (selfParameterIndex == 1) {
160            return applyToArgs(toSelf(b), Useful.list(a, c));
161        } else {
162            return applyToArgs(toSelf(c), Useful.list(a, b));
163        }
164    }
165
166    public FValue applyToArgs(FValue a, FValue b, FValue c, FValue d) {
167        if (selfParameterIndex <= 0) {
168            return applyToArgs(toSelf(a), Useful.list(b, c, d));
169        } else if (selfParameterIndex == 1) {
170            return applyToArgs(toSelf(b), Useful.list(a, c, d));
171        } else if (selfParameterIndex == 2) {
172            return applyToArgs(toSelf(c), Useful.list(a, b, d));
173        } else {
174            return applyToArgs(toSelf(d), Useful.list(a, b, c));
175        }
176    }
177
178    protected FObject toSelf(FValue a) {
179        if (a instanceof FObject) return (FObject) a;
180        return bug(errorMsg("Non-object recipient ", a, " for method ", this));
181    }
182
183    public String selfName() {
184        return WellKnownNames.secretSelfName;
185    }
186
187    public static Hasher<MethodClosure> signatureEquivalence = new Hasher<MethodClosure>() {
188
189        @Override
190        public long hash(MethodClosure x) {
191            return Simple_fcn.signatureEquivalence.hash(x);
192        }
193
194        @Override
195        public boolean equiv(MethodClosure x, MethodClosure y) {
196            return Simple_fcn.signatureEquivalence.equiv(x, y);
197        }
198
199    };
200
201    /* (non-Javadoc)
202     * @see com.sun.fortress.interpreter.evaluator.values.Fcn#asMethodName()
203     */
204    @Override
205    public String asMethodName() {
206        // TODO Auto-generated method stub
207        return NodeUtil.nameAsMethod(getDef());
208    }
209
210    public FType getDefiner() {
211        return definer;
212    }
213
214}
Note: See TracBrowser for help on using the browser.