1 /********************************************************************************
2 *
3 * Copyright (c) 2008 Fujitsu Services Ltd.
4 *
5 * Author: Nick Battle
6 *
7 * This file is part of VDMJ.
8 *
9 * VDMJ is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * VDMJ is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with VDMJ. If not, see <http://www.gnu.org/licenses/>.
21 *
22 ******************************************************************************/
23
24 package org.overturetool.vdmj.expressions;
25
26 import org.overturetool.vdmj.definitions.Definition;
27 import org.overturetool.vdmj.definitions.ExplicitFunctionDefinition;
28 import org.overturetool.vdmj.definitions.ImplicitFunctionDefinition;
29 import org.overturetool.vdmj.definitions.InheritedDefinition;
30 import org.overturetool.vdmj.lex.LexNameList;
31 import org.overturetool.vdmj.pog.POContextStack;
32 import org.overturetool.vdmj.pog.ProofObligationList;
33 import org.overturetool.vdmj.runtime.Context;
34 import org.overturetool.vdmj.runtime.ValueException;
35 import org.overturetool.vdmj.typechecker.Environment;
36 import org.overturetool.vdmj.typechecker.NameScope;
37 import org.overturetool.vdmj.types.FunctionType;
38 import org.overturetool.vdmj.types.ParameterType;
39 import org.overturetool.vdmj.types.Type;
40 import org.overturetool.vdmj.types.TypeList;
41 import org.overturetool.vdmj.types.TypeSet;
42 import org.overturetool.vdmj.types.UnknownType;
43 import org.overturetool.vdmj.util.Utils;
44 import org.overturetool.vdmj.values.FunctionValue;
45 import org.overturetool.vdmj.values.ParameterValue;
46 import org.overturetool.vdmj.values.Value;
47
48 public class FuncInstantiationExpression extends Expression
49 {
50 private static final long serialVersionUID = 1L;
51 public final Expression function;
52 public TypeList actualTypes;
53 public FunctionType type;
54
55 private ExplicitFunctionDefinition expdef = null;
56 private ImplicitFunctionDefinition impdef = null;
57
58 public FuncInstantiationExpression(Expression function, TypeList types)
59 {
60 super(function);
61 this.function = function;
62 this.actualTypes = types;
63 }
64
65 @Override
66 public String toString()
67 {
68 return "(" + function + ")[" + Utils.listToString(actualTypes) + "]";
69 }
70
71 @Override
72 public Type typeCheck(Environment env, TypeList qualifiers, NameScope scope)
73 {
74
75
76
77
78
79
80
81
82
83
84 Type ftype = function.typeCheck(env, qualifiers, scope);
85
86 if (ftype.isUnknown())
87 {
88 return ftype;
89 }
90
91 if (ftype.isFunction())
92 {
93 FunctionType t = ftype.getFunction();
94 TypeSet set = new TypeSet();
95
96 if (t.definitions == null)
97 {
98 report(3098, "Function value is not polymorphic");
99 set.add(new UnknownType(location));
100 }
101 else
102 {
103 boolean serious = (t.definitions.size() == 1);
104
105 for (Definition def: t.definitions)
106 {
107 LexNameList typeParams = null;
108
109 while (def instanceof InheritedDefinition)
110 {
111 def = ((InheritedDefinition)def).superdef;
112 }
113
114 if (def instanceof ExplicitFunctionDefinition)
115 {
116 expdef = (ExplicitFunctionDefinition)def;
117 typeParams = expdef.typeParams;
118 }
119 else if (def instanceof ImplicitFunctionDefinition)
120 {
121 impdef = (ImplicitFunctionDefinition)def;
122 typeParams = impdef.typeParams;
123 }
124 else
125 {
126 report(3099, "Polymorphic function is not in scope");
127 }
128
129 if (typeParams == null)
130 {
131 concern(serious, 3100, "Function has no type parameters");
132 continue;
133 }
134
135 if (actualTypes.size() != typeParams.size())
136 {
137 concern(serious, 3101, "Expecting " + typeParams.size() + " type parameters");
138 continue;
139 }
140
141 TypeList fixed = new TypeList();
142
143 for (Type ptype: actualTypes)
144 {
145 if (ptype instanceof ParameterType)
146 {
147 ParameterType pt = (ParameterType)ptype;
148 Definition d = env.findName(pt.name, scope);
149
150 if (d == null)
151 {
152 concern(serious, 3102, "Parameter name " + pt + " not defined");
153 }
154
155 ptype = d.getType();
156 }
157
158 fixed.add(ptype.typeResolve(env, null));
159 }
160
161 actualTypes = fixed;
162
163 type = expdef == null ?
164 impdef.getType(actualTypes) : expdef.getType(actualTypes);
165
166 set.add(type);
167 }
168 }
169
170 if (!set.isEmpty())
171 {
172 return set.getType(location);
173 }
174 }
175 else
176 {
177 report(3103, "Function instantiation does not yield a function");
178 }
179
180 return new UnknownType(location);
181 }
182
183 @Override
184 public Value eval(Context ctxt)
185 {
186 breakpoint.check(location, ctxt);
187
188 try
189 {
190 FunctionValue fv = function.eval(ctxt).functionValue(ctxt);
191 TypeList fixed = new TypeList();
192
193 for (Type ptype: actualTypes)
194 {
195 if (ptype instanceof ParameterType)
196 {
197 ParameterType pname = (ParameterType)ptype;
198 Value t = ctxt.lookup(pname.name);
199
200 if (t == null)
201 {
202 abort(4008, "No such type parameter @" + pname + " in scope", ctxt);
203 }
204 else if (t instanceof ParameterValue)
205 {
206 ParameterValue tv = (ParameterValue)t;
207 fixed.add(tv.type);
208 }
209 else
210 {
211 abort(4009, "Type parameter/local variable name clash, @" + pname, ctxt);
212 }
213 }
214 else
215 {
216 fixed.add(ptype);
217 }
218 }
219
220 if (expdef == null)
221 {
222 FunctionValue prefv = null;
223 FunctionValue postfv = null;
224
225 if (impdef.predef != null)
226 {
227 prefv = impdef.predef.getPolymorphicValue(fixed);
228 }
229 else
230 {
231 prefv = null;
232 }
233
234 if (impdef.postdef != null)
235 {
236 postfv = impdef.postdef.getPolymorphicValue(fixed);
237 }
238 else
239 {
240 postfv = null;
241 }
242
243 FunctionValue rv = new FunctionValue(
244 impdef, fixed, prefv, postfv, null);
245
246 rv.setSelf(fv.self);
247 return rv;
248 }
249 else
250 {
251 FunctionValue prefv = null;
252 FunctionValue postfv = null;
253
254 if (expdef.predef != null)
255 {
256 prefv = expdef.predef.getPolymorphicValue(fixed);
257 }
258 else
259 {
260 prefv = null;
261 }
262
263 if (expdef.postdef != null)
264 {
265 postfv = expdef.postdef.getPolymorphicValue(fixed);
266 }
267 else
268 {
269 postfv = null;
270 }
271
272 FunctionValue rv = new FunctionValue(
273 expdef, fixed, prefv, postfv, null);
274
275 rv.setSelf(fv.self);
276 return rv;
277 }
278 }
279 catch (ValueException e)
280 {
281 return abort(e);
282 }
283 }
284
285 @Override
286 public Expression findExpression(int lineno)
287 {
288 Expression found = super.findExpression(lineno);
289 if (found != null) return found;
290
291 return function.findExpression(lineno);
292 }
293
294 @Override
295 public ProofObligationList getProofObligations(POContextStack ctxt)
296 {
297 return function.getProofObligations(ctxt);
298 }
299
300 @Override
301 public String kind()
302 {
303 return "instantiation";
304 }
305 }