View Javadoc

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  		// If there are no type qualifiers passed because the poly function value
75  		// is being accessed alone (not applied). In this case, the null qualifier
76  		// will cause VariableExpression to search for anything that matches the
77  		// name alone. If there is precisely one, it is selected; if there are
78  		// several, this is an ambiguity error.
79  		//
80  		// Note that a poly function is hard to identify from the actual types
81  		// passed here because the number of parameters may not equal the number
82  		// of type parameters.
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)		// Possibly a union of several
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)		// Recursive polymorphism
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 }