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

Revision 3998, 6.9 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.FortressClosure;
21import com.sun.fortress.exceptions.FortressException;
22import static com.sun.fortress.exceptions.InterpreterBug.bug;
23import static com.sun.fortress.exceptions.ProgramError.error;
24import static com.sun.fortress.exceptions.ProgramError.errorMsg;
25import com.sun.fortress.exceptions.UnificationError;
26import com.sun.fortress.interpreter.evaluator.Environment;
27import com.sun.fortress.interpreter.evaluator.types.FType;
28import com.sun.fortress.nodes.IdOrOpOrAnonymousName;
29import com.sun.fortress.nodes_util.NodeUtil;
30import com.sun.fortress.useful.HasAt;
31import com.sun.fortress.useful.Useful;
32
33import java.util.ArrayList;
34import java.util.Collections;
35import java.util.List;
36
37abstract public class Fcn extends FValue implements FortressClosure {
38    /**
39     * Need to know the environment so we can resolve
40     * overloading/shadowing properly.
41     */
42    Environment within;
43
44    /**
45     * Need to make type information mutable due to
46     * multi-phase initialization protocol.
47     */
48    private volatile FType ftype;
49
50    protected Fcn(Environment within) {
51        this.within = within;
52        within.bless();
53    }
54
55    public Environment getWithin() {
56        return within;
57    }
58
59    public boolean needsInference() {
60        return false;
61    }
62
63    /**
64     * Getter for ftype.  Should always be non-null, but right now
65     * FGenericFunction never calls setFtype and this returns null in
66     * that case.  This leads to extensive bugs particularly when a
67     * generic function is overloaded along with non-generic siblings,
68     * or when a generic function is passed as an argument to an
69     * overloaded function without providing an explicit type
70     * instantiation.  Delete "&& false" to enable checking if you're
71     * trying to fix this bug.
72     */
73    public FType type() {
74        if (ftype == null && false) {
75            throw new NullPointerException(errorMsg("No type information for ", this, " ", this.getClass()));
76        }
77        return ftype;
78    }
79
80    /**
81     * Finish initializing Fcn, if necessary.
82     * <p/>
83     * There used to be a HasFinishInitializing interface for this,
84     * but after cleaning up the code a bit it became clear that we
85     * should just let it apply to any Fcn.
86     */
87    public void finishInitializing() {
88        // By default, nothing need be done.
89    }
90
91    public void setFtype(FType ftype) {
92        if (this.ftype != null) throw new IllegalStateException("Cannot set twice");
93        setFtypeUnconditionally(ftype);
94    }
95
96    public void setFtypeUnconditionally(FType ftype) {
97        this.ftype = ftype;
98    }
99
100    protected FValue check(FValue x) {
101        return x;
102    }
103
104    public FValue applyToArgs(List<FValue> args) {
105        List<FValue> unwrapped = conditionallyUnwrapTupledArgs(args);
106        try {
107            return check(applyInnerPossiblyGeneric(unwrapped));
108        }
109        catch (UnificationError u) {
110            if (unwrapped != args) {
111                try {
112                    return check(applyInnerPossiblyGeneric(args));
113                }
114                catch (UnificationError u1) {
115                    throw u;
116                }
117            }
118            throw u;
119        }
120    }
121
122    public FValue applyToArgs(FObject self, List<FValue> args) {
123        List<FValue> actuals = new ArrayList(args.size() + 1);
124        actuals.add(self);
125        actuals.addAll(args);
126        return applyToArgs(actuals);
127    }
128
129    public FValue applyToArgs() {
130        return check(applyInnerPossiblyGeneric(Collections.<FValue>emptyList()));
131    }
132
133    public FValue applyToArgs(FValue a) {
134        return applyToArgs(Collections.singletonList(a));
135    }
136
137    public FValue applyToArgs(FValue a, FValue b) {
138        return applyToArgs(Useful.list(a, b));
139    }
140
141    public FValue applyToArgs(FValue a, FValue b, FValue c) {
142        return applyToArgs(Useful.list(a, b, c));
143    }
144
145    public FValue applyToArgs(FValue a, FValue b, FValue c, FValue d) {
146        return applyToArgs(Useful.list(a, b, c, d));
147    }
148
149    protected List<FValue> conditionallyUnwrapTupledArgs(List<FValue> args) {
150        // TODO This ought not be necessary.
151        if (args.size() == 1 && (args.get(0) instanceof FTuple)) {
152            args = ((FTuple) args.get(0)).getVals();
153        }
154        return args;
155    }
156
157    abstract public FValue applyInnerPossiblyGeneric(List<FValue> args);
158
159    public boolean hasSelfDotMethodInvocation() {
160        return false;
161    }
162
163    abstract public IdOrOpOrAnonymousName getFnName();
164
165    /**
166     * Returns the name if this "function" is regarded as a method.
167     * For functions, just returns the name.
168     */
169    public String asMethodName() {
170        return NodeUtil.nameString(getFnName());
171    }
172
173
174    public static FValue functionInvocation(FValue arg, FValue foo, HasAt loc) {
175        return functionInvocation(Useful.list(arg), foo, loc);
176    }
177
178    public FValue functionInvocation(FValue arg, HasAt loc) {
179        return this.functionInvocation(Useful.list(arg), loc);
180    }
181
182    public static FValue functionInvocation(List<FValue> args, FValue foo, HasAt loc) {
183        if (foo instanceof Fcn) {
184            return ((Fcn) foo).functionInvocation(args, loc);
185        } else {
186            return bug(loc, errorMsg("Not a Fcn: ", foo));
187        }
188    }
189
190    public FValue functionInvocation(List<FValue> args, HasAt site) {
191        try {
192            // We used to do redundant checks for genericity here, but
193            // now we reply on foo.apply to do type inference if necessary.
194            return this.applyToArgs(args);
195        }
196        catch (UnificationError ue) {
197            // If we propagate these, they get misinterpreted by enclosing calls,
198            // and we lose calling context information.  This leads to really confusing
199            // failures!
200            // So we need to wrap them instead.
201            // cf Evaluator.invokeGenericMethod and Evaluator.invokeMethod.
202            return error(site, errorMsg("Unification error: ", ue.getMessage()), ue);
203        }
204        catch (FortressException ex) {
205            throw ex.setWhere(site);
206        }
207        catch (StackOverflowError soe) {
208            return error(site, errorMsg("Stack overflow on ", site));
209        }
210    }
211
212}
Note: See TracBrowser for help on using the browser.