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

Revision 3998, 12.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 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 static com.sun.fortress.exceptions.UnificationError.unificationError;
26import com.sun.fortress.interpreter.Driver;
27import com.sun.fortress.interpreter.evaluator.Environment;
28import com.sun.fortress.interpreter.evaluator.types.FType;
29import com.sun.fortress.interpreter.evaluator.types.FTypeRest;
30import com.sun.fortress.interpreter.glue.Glue;
31import com.sun.fortress.interpreter.glue.IndexedArrayWrapper;
32import com.sun.fortress.useful.HasAt;
33import com.sun.fortress.useful.Useful;
34
35import java.util.ArrayList;
36import java.util.Collections;
37import java.util.Iterator;
38import java.util.List;
39
40public abstract class NonPrimitive extends Simple_fcn {
41
42    static final List<FValue> VOID_ARG = Collections.singletonList((FValue) FVoid.V);
43
44    /*
45     * (non-Javadoc)
46     *
47     * @see com.sun.fortress.interpreter.evaluator.values.Simple_fcn#at()
48     */
49    @Override
50    public String at() {
51        return getAt().at();
52    }
53
54    protected abstract HasAt getAt();
55
56    NonPrimitive(Environment within) {
57        super(within);
58    }
59
60    private List<Parameter> params;
61
62    private boolean lastParamIsRest;
63
64    private volatile List<FType> cachedDomain;
65
66    protected boolean hasRest() {
67        return lastParamIsRest;
68    }
69
70    /**
71     * @param params The params to set.
72     */
73    public final void setParams(List<Parameter> original_params) {
74
75        List<Parameter> params = adjustParameterList(original_params);
76
77        if (this.params != null) {
78            if (!this.params.equals(params)) bug(this.getAt(), errorMsg(
79                    "Attempted second set of constructor/function/method params of ",
80                    this,
81                    " to ",
82                    Useful.listInParens(original_params)));
83            // be idempotent
84            return;
85        }
86
87        this.params = params;
88        lastParamIsRest = params.size() > 0 && (params.get(params.size() - 1).getType() instanceof FTypeRest);
89        setValueType();
90    }
91
92    protected List<Parameter> adjustParameterList(List<Parameter> params2) {
93        return params2;
94    }
95
96    abstract protected void setValueType();
97
98    /**
99     * @return Returns the params.
100     */
101    public List<Parameter> getParameters() {
102        if (params == null) return bug(getAt(), errorMsg("getParams of NonPrimitive ", this));
103        return params;
104    }
105
106    @Override
107    public List<FType> getDomain() {
108        if (cachedDomain == null) {
109            synchronized (this) {
110                if (cachedDomain == null) {
111                    //                    if (this instanceof FunctionalMethod
112                    //                            && ((FunctionalMethod) this).getSelfParameterType()
113                    //                                    .toString().contains("ParRange"))
114                    //                        System.err.println("getDomain of " + this);
115                    List<FType> l = typeListFromParameters(getParameters());
116                    cachedDomain = l;
117                }
118            }
119        }
120        return cachedDomain;
121    }
122
123    public static List<FValue> stripAsIf(List<FValue> args) {
124        List<FValue> res = new ArrayList<FValue>(args.size());
125        for (FValue v : args) {
126            if (v instanceof FAsIf) {
127                res.add(((FAsIf) v).getValue());
128            } else {
129                res.add(v);
130            }
131        }
132        return res;
133    }
134
135    /**
136     * Take passed-in parameters, type check them.
137     * Intended to be called from NativeApp.
138     * Do not bother calling this if you also call buildEnvFromParams.
139     */
140    public List<FValue> typecheckParams(List<FValue> args) {
141        args = fixupArgCount(args);
142        Iterator<FValue> argsIter = args.iterator();
143        Iterator<Parameter> paramsIter = params.iterator();
144        boolean asif = false;   // Need to strip asif?  Avoid if not.
145        for (int i = 1; paramsIter.hasNext(); i++) {
146            Parameter param = paramsIter.next();
147            FType paramType = param.getType();
148            if (paramType instanceof FTypeRest) {
149                FType restType = ((FTypeRest) paramType).getType();
150                for (; argsIter.hasNext(); i++) {
151                    FValue arg = argsIter.next();
152                    if (arg instanceof FAsIf) asif = true;
153                    if (!restType.typeMatch(arg)) {
154                        error(errorMsg("Closure/Constructor for ",
155                                       getAt().stringName(),
156                                       " rest parameter ",
157                                       i,
158                                       " (",
159                                       param.getName(),
160                                       ":",
161                                       restType,
162                                       "...) got type ",
163                                       arg.type()));
164                    }
165                }
166            } else {
167                // Usual case for the loop.
168                FValue arg = argsIter.next();
169                if (arg instanceof FAsIf) asif = true;
170                if (!paramType.typeMatch(arg)) {
171                    error(errorMsg("Closure/Constructor for ",
172                                   getAt().stringName(),
173                                   " parameter ",
174                                   i,
175                                   " (",
176                                   param.getName(),
177                                   ":",
178                                   param.getType(),
179                                   ") got type ",
180                                   arg.type()));
181                }
182            }
183        }
184        if (asif) return stripAsIf(args);
185        else return args;
186    }
187
188    /**
189     * Build environment for evaluation of closure.
190     * Intended to be called from Closure.
191     *
192     * @throws Error
193     */
194    public Environment buildEnvFromParams(List<FValue> args) throws Error {
195        Environment env = within.extendAt(getAt());
196        return buildEnvFromParams(args, env);
197    }
198
199    public Environment buildEnvFromEnvAndParams(Environment env, List<FValue> args) throws Error {
200        env = env.extendAt(getAt());
201        return buildEnvFromParams(args, env);
202    }
203
204    private Environment buildEnvFromParams(List<FValue> args, Environment env) throws Error {
205        // TODO Here is where we deal with rest parameters.
206        List<FValue> argsTemp = fixupArgCount(args);
207        if (argsTemp == null) return bug(
208                "The number of parameters (" + params.size() + ") does not match with the number of arguments (" +
209                args.size() + ").");
210        args = argsTemp;
211        Iterator<FValue> argsIter = args.iterator();
212        FValue arg = null;
213        int i = 0;
214        for (Parameter param : params) {
215            FType paramType = param.getType();
216            if (paramType instanceof FTypeRest) {
217                // Finish processing args in here (we just saw the last
218                // parameter)
219
220                // Find and invoke array1[\ T, size1 \] ()
221                String genericName = WellKnownNames.varargsFactoryName;
222                int[] natParams = new int[1];
223                natParams[0] = args.size() - i;
224
225                Environment wknInstantiationEnv = Driver.getFortressLibrary();
226
227                Simple_fcn f = Glue.instantiateGenericConstructor(wknInstantiationEnv,
228                                                                  genericName,
229                                                                  ((FTypeRest) paramType).getType(),
230                                                                  natParams);
231
232                FValue theArray = f.applyToArgs();
233                if (!(theArray instanceof FObject)) return bug(errorMsg(f, " returned non-FObject ", theArray));
234                // Use a wrapper to simplify our life
235                IndexedArrayWrapper iaw = new IndexedArrayWrapper(theArray);
236                int j = 0;
237                while (argsIter.hasNext()) {
238                    arg = argsIter.next();
239                    iaw.put(arg.getValue(), j);  // strip asif
240                    j++;
241                }
242                // Do the copy.
243                env.putValue(param.getName(), theArray);
244            } else {
245                // Usual case for the loop.
246                arg = argsIter.next();
247                i++;
248                if (!paramType.typeMatch(arg)) {
249                    unificationError(errorMsg("Closure/Constructor for ",
250                                              getAt().stringName(),
251                                              " param ",
252                                              i,
253                                              " (",
254                                              param.getName(),
255                                              ":",
256                                              paramType,
257                                              ") got arg ",
258                                              arg,
259                                              " of type ",
260                                              arg.type()));
261                }
262                arg = arg.getValue(); // Strip asif
263                try {
264                    if (param.getMutable()) {
265                        env.putValueRaw(param.getName(), arg, param.getType());
266                    } else {
267                        env.putValueRaw(param.getName(), arg);
268                    }
269                }
270                catch (FortressException ex) {
271                    throw ex.setWithin(env);
272                }
273            }
274
275        }
276        return env;
277    }
278
279    /**
280     * Return fixed up arguments; throws ProgramError if different lengths.
281     */
282    public List<FValue> fixupArgCount(List<FValue> args0, HasAt loc) {
283        List<FValue> args = fixupArgCount(args0);
284        if (args == null) {
285            error(loc, errorMsg("Incorrect number of arguments, expected ",
286                                Useful.listInParens(params),
287                                ", got ",
288                                Useful.listInParens(args0)));
289        }
290        return args;
291    }
292
293    /**
294     * @param args
295     * @return fixed up arguments, or null if different lengths.
296     */
297    public List<FValue> fixupArgCount(List<FValue> args) {
298        if (this.params == null) {
299            bug(this.getAt(), "Calling fixupArgCount on " + getAt().stringName() + " with null params");
300        }
301        if (args.size() == params.size()) return args;
302        if (hasRest() && args.size() + 1 >= params.size()) {
303            return args;
304        }
305        if (params.size() == 1) {
306            /* Obscure screw case: a type parameter was instantiated
307             * with void / tuple, or we declared a single parameter of
308             * void or tuple type ().  This is satisfied by a 0-ary
309             * application.  Rather than checking thoroughly, we
310             * return a singleton void and let the enclosing test
311             * catch it. */
312            if (args.size() == 0) return VOID_ARG;
313            return Collections.singletonList((FValue) FTuple.make(args));
314        }
315        return null;
316    }
317}
Note: See TracBrowser for help on using the browser.