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.definitions;
25  
26  import java.util.List;
27  import java.util.Vector;
28  
29  import org.overturetool.vdmj.expressions.Expression;
30  import org.overturetool.vdmj.lex.LexLocation;
31  import org.overturetool.vdmj.lex.LexNameList;
32  import org.overturetool.vdmj.lex.LexNameToken;
33  import org.overturetool.vdmj.patterns.Pattern;
34  import org.overturetool.vdmj.patterns.PatternList;
35  import org.overturetool.vdmj.pog.POContextStack;
36  import org.overturetool.vdmj.pog.ProofObligationList;
37  import org.overturetool.vdmj.runtime.Context;
38  import org.overturetool.vdmj.typechecker.Environment;
39  import org.overturetool.vdmj.typechecker.NameScope;
40  import org.overturetool.vdmj.typechecker.Pass;
41  import org.overturetool.vdmj.typechecker.TypeCheckException;
42  import org.overturetool.vdmj.types.BooleanType;
43  import org.overturetool.vdmj.types.FunctionType;
44  import org.overturetool.vdmj.types.InvariantType;
45  import org.overturetool.vdmj.types.NamedType;
46  import org.overturetool.vdmj.types.RecordType;
47  import org.overturetool.vdmj.types.Type;
48  import org.overturetool.vdmj.types.TypeList;
49  import org.overturetool.vdmj.types.UnresolvedType;
50  import org.overturetool.vdmj.values.FunctionValue;
51  import org.overturetool.vdmj.values.NameValuePair;
52  import org.overturetool.vdmj.values.NameValuePairList;
53  
54  
55  /***
56   * A class to hold a type definition.
57   */
58  
59  public class TypeDefinition extends Definition
60  {
61  	private static final long serialVersionUID = 1L;
62  	public Type type;
63  	public final Pattern invPattern;
64  	public final Expression invExpression;
65  	public ExplicitFunctionDefinition invdef;
66  	public boolean infinite = false;
67  
68  	public TypeDefinition(LexNameToken name, InvariantType type, Pattern invPattern,
69  		Expression invExpression)
70  	{
71  		super(Pass.TYPES, name.location, name, NameScope.TYPENAME);
72  
73  		this.type = type;
74  		this.invPattern = invPattern;
75  		this.invExpression = invExpression;
76  	}
77  
78  	@Override
79  	public String toString()
80  	{
81  		return accessSpecifier.ifSet(" ") +
82  				name.name + " = " + type.toDetailedString() +
83  				(invPattern == null ? "" :
84  					"\n\tinv " + invPattern + " == " + invExpression);
85  	}
86  
87  	@Override
88  	public void implicitDefinitions(Environment base)
89  	{
90  		if (invPattern != null)
91  		{
92      		invdef = getInvDefinition();
93      		invdef.setAccessSpecifier(accessSpecifier);
94      		((InvariantType)type).setInvariant(invdef);
95  		}
96  		else
97  		{
98  			invdef = null;
99  		}
100 	}
101 
102 	@Override
103 	public void typeResolve(Environment base)
104 	{
105 		try
106 		{
107 			infinite = false;
108 			type = type.typeResolve(base, this);
109 
110 			if (infinite)
111 			{
112 				report(3050, "Type '" + name + "' is infinite");
113 			}
114 
115 			if (invdef != null)
116 			{
117 				invdef.typeResolve(base);
118 				invPattern.typeResolve(base);
119 			}
120 		}
121 		catch (TypeCheckException e)
122 		{
123 			type.unResolve();
124 			throw e;
125 		}
126 	}
127 
128 	@Override
129 	public void typeCheck(Environment base, NameScope scope)
130 	{
131 		if (invdef != null)
132 		{
133 			invdef.typeCheck(base, scope);
134 		}
135 	}
136 
137 	@Override
138 	public Type getType()
139 	{
140 		if (type instanceof NamedType)
141 		{
142 			return type;
143 		}
144 		else
145 		{
146 			return new NamedType(name, type);
147 		}
148 	}
149 
150 	@Override
151 	public Definition findName(LexNameToken sought, NameScope incState)
152 	{
153 		if (invdef != null && invdef.findName(sought, incState) != null)
154 		{
155 			return invdef;
156 		}
157 
158 		return null;
159 	}
160 
161 	@Override
162 	public Definition findType(LexNameToken sought)
163 	{
164 		if (type instanceof NamedType)
165 		{
166 			NamedType nt = (NamedType)type;
167 
168 			if (nt.type instanceof RecordType)
169 			{
170 				RecordType rt = (RecordType)nt.type;
171 
172 				if (rt.name.equals(sought))
173 				{
174 					return this;	// T1 = compose T2 x:int end;
175 				}
176 			}
177 		}
178 
179 		return super.findName(sought, NameScope.TYPENAME);
180 	}
181 
182 	@Override
183 	public Expression findExpression(int lineno)
184 	{
185 		if (invdef != null)
186 		{
187 			Expression found = invdef.findExpression(lineno);
188 			if (found != null) return found;
189 		}
190 
191 		return null;
192 	}
193 
194 	@Override
195 	public DefinitionList getDefinitions()
196 	{
197 		DefinitionList defs = new DefinitionList(this);
198 
199 		if (invdef != null)
200 		{
201 			defs.add(invdef);
202 		}
203 
204 		return defs;
205 	}
206 
207 	@Override
208 	public LexNameList getVariableNames()
209 	{
210 		// This is only used in VDM++ type inheritance
211 		return new LexNameList(name);
212 	}
213 
214 	@Override
215 	public NameValuePairList getNamedValues(Context ctxt)
216 	{
217 		NameValuePairList nvl = new NameValuePairList();
218 
219 		if (invdef != null)
220 		{
221 			FunctionValue invfunc =	new FunctionValue(invdef, null, null, ctxt);
222 			nvl.add(new NameValuePair(invdef.name, invfunc));
223 		}
224 
225 		return nvl;
226 	}
227 
228 	private ExplicitFunctionDefinition getInvDefinition()
229 	{
230 		LexLocation loc = invPattern.location;
231 		PatternList params = new PatternList();
232 		params.add(invPattern);
233 
234 		List<PatternList> parameters = new Vector<PatternList>();
235 		parameters.add(params);
236 
237 		TypeList ptypes = new TypeList();
238 		ptypes.add(new UnresolvedType(name));
239 		FunctionType ftype =
240 			new FunctionType(loc, false, ptypes, new BooleanType(loc));
241 
242 		ExplicitFunctionDefinition def = new ExplicitFunctionDefinition(
243 			name.getInvName(loc),
244 			NameScope.GLOBAL, null, ftype, parameters, invExpression,
245 			null, null, true, false, null);
246 
247 		def.setAccessSpecifier(accessSpecifier);	// Same as type's
248 		def.classDefinition = classDefinition;
249 		ftype.definitions = new DefinitionList(def);
250 		return def;
251 	}
252 
253 	@Override
254 	public boolean isRuntime()
255 	{
256 		return false;	// Though the inv definition is, of course
257 	}
258 
259 	@Override
260 	public boolean isTypeDefinition()
261 	{
262 		return true;
263 	}
264 
265 	@Override
266 	public ProofObligationList getProofObligations(POContextStack ctxt)
267 	{
268 		ProofObligationList list = new ProofObligationList();
269 
270 		if (invdef != null)
271 		{
272 			list.addAll(invdef.getProofObligations(ctxt));
273 		}
274 
275 		return list;
276 	}
277 
278 	@Override
279 	public String kind()
280 	{
281 		return "type";
282 	}
283 }