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

Revision 2828, 11.4 kB (checked in by jmaessen, 4 weeks ago)

Fix to type signature in Set.fss and Set.fsi, plus minor doc fixes to FortressLibrary

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