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;
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
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);
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;
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 }