]>
Commit | Line | Data |
---|---|---|
1eee94d3 GM |
1 | (* M2Const.mod maintain and resolve the types of constants. |
2 | ||
a945c346 | 3 | Copyright (C) 2010-2024 Free Software Foundation, Inc. |
1eee94d3 GM |
4 | Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>. |
5 | ||
6 | This file is part of GNU Modula-2. | |
7 | ||
8 | GNU Modula-2 is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 3, or (at your option) | |
11 | any later version. | |
12 | ||
13 | GNU Modula-2 is distributed in the hope that it will be useful, but | |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with GNU Modula-2; see the file COPYING3. If not see | |
20 | <http://www.gnu.org/licenses/>. *) | |
21 | ||
22 | IMPLEMENTATION MODULE M2Const ; | |
23 | ||
24 | (* | |
25 | CONST | |
26 | Debugging = FALSE ; | |
27 | DebugConsts = FALSE ; | |
28 | ||
29 | TYPE | |
30 | constList = POINTER TO cList ; | |
31 | cList = RECORD | |
32 | constsym : CARDINAL ; | |
33 | constmeta: constType ; | |
34 | expr : CARDINAL ; | |
35 | type : CARDINAL ; | |
36 | next : constList ; | |
37 | END ; | |
38 | ||
39 | ||
40 | VAR | |
41 | headOfConsts: constList ; | |
42 | ||
43 | ||
44 | PROCEDURE stop ; BEGIN END stop ; | |
45 | ||
46 | ||
47 | (* | |
48 | addToConstList - add a constant, sym, to the head of the constants list. | |
49 | *) | |
50 | ||
51 | PROCEDURE addToConstList (sym: CARDINAL) ; | |
52 | VAR | |
53 | h: constList ; | |
54 | BEGIN | |
55 | h := headOfConsts ; | |
56 | WHILE h#NIL DO | |
57 | IF h^.constsym=sym | |
58 | THEN | |
59 | InternalError ('should never see the same symbol id declared twice') | |
60 | END ; | |
61 | h := h^.next | |
62 | END ; | |
63 | NEW(h) ; | |
64 | WITH h^ DO | |
65 | constsym := sym ; | |
66 | constmeta := unknown ; | |
67 | expr := NulSym ; | |
68 | type := NulSym ; | |
69 | next := headOfConsts | |
70 | END ; | |
71 | headOfConsts := h | |
72 | END addToConstList ; | |
73 | ||
74 | ||
75 | (* | |
76 | FixupConstAsString - fixes up a constant, sym, which will have the string type. | |
77 | *) | |
78 | ||
79 | PROCEDURE FixupConstAsString (sym: CARDINAL) ; | |
80 | BEGIN | |
81 | fixupConstMeta(sym, str) | |
82 | END FixupConstAsString ; | |
83 | ||
84 | ||
85 | (* | |
86 | FixupConstType - fixes up a constant, sym, which will have the type, consttype. | |
87 | *) | |
88 | ||
89 | PROCEDURE FixupConstType (sym: CARDINAL; consttype: CARDINAL) ; | |
90 | VAR | |
91 | h: constList ; | |
92 | BEGIN | |
93 | h := headOfConsts ; | |
94 | WHILE h#NIL DO | |
95 | WITH h^ DO | |
96 | IF constsym=sym | |
97 | THEN | |
98 | IF constmeta=str | |
99 | THEN | |
100 | InternalError ('cannot fix up a constant to have a type if it is already known as a string') | |
101 | END ; | |
102 | type := consttype ; | |
103 | PutConst(sym, consttype) ; | |
104 | RETURN | |
105 | END | |
106 | END ; | |
107 | h := h^.next | |
108 | END | |
109 | END FixupConstType ; | |
110 | ||
111 | ||
112 | (* | |
113 | FixupProcedureType - creates a proctype from a procedure. | |
114 | *) | |
115 | ||
116 | PROCEDURE FixupProcedureType (p: CARDINAL) : CARDINAL ; | |
117 | VAR | |
118 | par, | |
119 | t : CARDINAL ; | |
120 | n, i: CARDINAL ; | |
121 | BEGIN | |
122 | IF IsProcedure(p) | |
123 | THEN | |
124 | t := MakeProcType(CheckAnonymous(NulName)) ; | |
125 | i := 1 ; | |
126 | n := NoOfParam(p) ; | |
127 | WHILE i<=n DO | |
128 | par := GetParam(p, i) ; | |
129 | IF IsParameterVar(par) | |
130 | THEN | |
131 | PutProcTypeVarParam(t, GetType(par), IsParameterUnbounded(par)) | |
132 | ELSE | |
133 | PutProcTypeParam(t, GetType(par), IsParameterUnbounded(par)) | |
134 | END ; | |
135 | INC(i) | |
136 | END ; | |
137 | IF GetType(p)#NulSym | |
138 | THEN | |
139 | PutFunction(t, GetType(p)) | |
140 | END ; | |
141 | RETURN( t ) | |
142 | ELSE | |
143 | InternalError ('expecting a procedure') | |
144 | END ; | |
145 | RETURN( NulSym ) | |
146 | END FixupProcedureType ; | |
147 | ||
148 | ||
149 | (* | |
150 | FixupConstProcedure - fixes up a constant, sym, which will be equivalent to e. | |
151 | *) | |
152 | ||
153 | PROCEDURE FixupConstProcedure (sym: CARDINAL; e: CARDINAL) ; | |
154 | VAR | |
155 | h: constList ; | |
156 | BEGIN | |
157 | h := headOfConsts ; | |
158 | WHILE h#NIL DO | |
159 | WITH h^ DO | |
160 | IF constsym=sym | |
161 | THEN | |
162 | expr := e ; | |
163 | type := FixupProcedureType(e) ; | |
164 | PutConst(sym, type) ; | |
165 | RETURN | |
166 | END | |
167 | END ; | |
168 | h := h^.next | |
169 | END | |
170 | END FixupConstProcedure ; | |
171 | ||
172 | ||
173 | (* | |
174 | FixupConstExpr - fixes up a constant, sym, which will be equivalent to e. | |
175 | *) | |
176 | ||
177 | PROCEDURE FixupConstExpr (sym: CARDINAL; e: CARDINAL) ; | |
178 | VAR | |
179 | h: constList ; | |
180 | BEGIN | |
181 | h := headOfConsts ; | |
182 | WHILE h#NIL DO | |
183 | WITH h^ DO | |
184 | IF constsym=sym | |
185 | THEN | |
186 | expr := e ; | |
187 | RETURN | |
188 | END | |
189 | END ; | |
190 | h := h^.next | |
191 | END | |
192 | END FixupConstExpr ; | |
193 | ||
194 | ||
195 | (* | |
196 | fixupConstMeta - fixes up symbol, sym, to have the, meta, constType. | |
197 | *) | |
198 | ||
199 | PROCEDURE FixupConstMeta (sym: CARDINAL; meta: constType) ; | |
200 | VAR | |
201 | h: constList ; | |
202 | BEGIN | |
203 | h := headOfConsts ; | |
204 | WHILE h#NIL DO | |
205 | WITH h^ DO | |
206 | IF constsym=sym | |
207 | THEN | |
208 | constmeta := meta ; | |
209 | RETURN | |
210 | END | |
211 | END ; | |
212 | h := h^.next | |
213 | END | |
214 | END FixupConstMeta ; | |
215 | ||
216 | ||
217 | (* | |
218 | fixupConstCast - | |
219 | *) | |
220 | ||
221 | PROCEDURE fixupConstCast (sym: CARDINAL; castType: CARDINAL) ; | |
222 | VAR | |
223 | h: constList ; | |
224 | BEGIN | |
225 | h := headOfConsts ; | |
226 | WHILE h#NIL DO | |
227 | WITH h^ DO | |
228 | IF constsym=sym | |
229 | THEN | |
230 | type := castType ; | |
231 | RETURN | |
232 | END | |
233 | END ; | |
234 | h := h^.next | |
235 | END | |
236 | END fixupConstCast ; | |
237 | ||
238 | ||
239 | (* | |
240 | findConstType - | |
241 | *) | |
242 | ||
243 | PROCEDURE findConstType (sym: CARDINAL) : CARDINAL ; | |
244 | VAR | |
245 | h: constList ; | |
246 | t: CARDINAL ; | |
247 | BEGIN | |
248 | h := headOfConsts ; | |
249 | WHILE h#NIL DO | |
250 | WITH h^ DO | |
251 | IF constsym=sym | |
252 | THEN | |
253 | t := GetType(sym) ; | |
254 | IF t=NulSym | |
255 | THEN | |
256 | RETURN( NulSym ) | |
257 | ELSE | |
258 | RETURN( t ) | |
259 | END | |
260 | END | |
261 | END ; | |
262 | h := h^.next | |
263 | END ; | |
264 | RETURN( NulSym ) | |
265 | END findConstType ; | |
266 | ||
267 | ||
268 | (* | |
269 | findConstMeta - | |
270 | *) | |
271 | ||
272 | PROCEDURE findConstMeta (sym: CARDINAL) : constType ; | |
273 | VAR | |
274 | h: constList ; | |
275 | BEGIN | |
276 | h := headOfConsts ; | |
277 | WHILE h#NIL DO | |
278 | WITH h^ DO | |
279 | IF constsym=sym | |
280 | THEN | |
281 | RETURN( constmeta ) | |
282 | END | |
283 | END ; | |
284 | h := h^.next | |
285 | END ; | |
286 | RETURN( unknown ) | |
287 | END findConstMeta ; | |
288 | ||
289 | ||
290 | (* | |
291 | ReportUnresolvedConstTypes - emits an error message for any unresolved constant type. | |
292 | *) | |
293 | ||
294 | PROCEDURE ReportUnresolvedConstTypes ; | |
295 | VAR | |
296 | h: constList ; | |
297 | BEGIN | |
298 | h := headOfConsts ; | |
299 | WHILE h#NIL DO | |
300 | WITH h^ DO | |
301 | IF (constmeta#unknown) AND (constmeta#str) AND (type=NulSym) | |
302 | THEN | |
303 | MetaError1('unable to resolve the type of the constant {%1Dad}', h^.constsym) | |
304 | END | |
305 | END ; | |
306 | h := h^.next | |
307 | END | |
308 | END ReportUnresolvedConstTypes ; | |
309 | ||
310 | ||
311 | (* | |
312 | DebugMeta - | |
313 | *) | |
314 | ||
315 | PROCEDURE DebugMeta (h: constList) ; | |
316 | VAR | |
317 | n: Name ; | |
318 | BEGIN | |
319 | IF DebugConsts | |
320 | THEN | |
321 | WITH h^ DO | |
322 | n := GetSymName(constsym) ; | |
323 | printf1('constant %a ', n) ; | |
324 | IF type=NulSym | |
325 | THEN | |
326 | printf0('type is unknown\n') | |
327 | ELSE | |
328 | printf0('type is known\n') | |
329 | END | |
330 | END | |
331 | END | |
332 | END DebugMeta ; | |
333 | ||
334 | ||
335 | (* | |
336 | constTypeResolved - | |
337 | *) | |
338 | ||
339 | PROCEDURE constTypeResolved (h: constList) : BOOLEAN ; | |
340 | BEGIN | |
341 | RETURN( h^.type#NulSym ) | |
342 | END constTypeResolved ; | |
343 | ||
344 | ||
345 | (* | |
346 | constExprResolved - | |
347 | *) | |
348 | ||
349 | PROCEDURE constExprResolved (h: constList) : BOOLEAN ; | |
350 | BEGIN | |
351 | RETURN( h^.expr#NulSym ) | |
352 | END constExprResolved ; | |
353 | ||
354 | ||
355 | (* | |
356 | findConstMetaExpr - | |
357 | *) | |
358 | ||
359 | PROCEDURE findConstMetaExpr (h: constList) : constType ; | |
360 | BEGIN | |
361 | RETURN( h^.constmeta ) | |
362 | END findConstMetaExpr ; | |
363 | ||
364 | ||
365 | (* | |
366 | constResolveViaMeta - | |
367 | *) | |
368 | ||
369 | PROCEDURE constResolveViaMeta (h: constList) : BOOLEAN ; | |
370 | VAR | |
371 | n: Name ; | |
372 | BEGIN | |
373 | WITH h^ DO | |
374 | IF findConstMetaExpr(h)=str | |
375 | THEN | |
376 | PutConstString(constsym, MakeKey('')) ; | |
377 | IF DebugConsts | |
378 | THEN | |
379 | n := GetSymName(constsym) ; | |
380 | printf1('resolved constant %a as a string\n', n) | |
381 | END ; | |
382 | RETURN( TRUE ) | |
383 | END | |
384 | END ; | |
385 | RETURN( FALSE ) | |
386 | END constResolveViaMeta ; | |
387 | ||
388 | ||
389 | (* | |
390 | constResolvedViaType - | |
391 | *) | |
392 | ||
393 | PROCEDURE constResolvedViaType (h: constList) : BOOLEAN ; | |
394 | VAR | |
395 | n: Name ; | |
396 | BEGIN | |
397 | WITH h^ DO | |
398 | type := findConstType(expr) ; | |
399 | IF type#NulSym | |
400 | THEN | |
401 | PutConst(constsym, type) ; | |
402 | IF DebugConsts | |
403 | THEN | |
404 | n := GetSymName(constsym) ; | |
405 | printf1('resolved type of constant %a\n', n) | |
406 | END ; | |
407 | RETURN( TRUE ) | |
408 | END | |
409 | END ; | |
410 | RETURN( FALSE ) | |
411 | END constResolvedViaType ; | |
412 | ||
413 | ||
414 | (* | |
415 | resolveConstType - | |
416 | *) | |
417 | ||
418 | PROCEDURE resolveConstType (h: constList) : BOOLEAN ; | |
419 | BEGIN | |
420 | WITH h^ DO | |
421 | IF (constmeta=unknown) OR (constmeta=str) | |
422 | THEN | |
423 | (* do nothing *) | |
424 | ELSE | |
425 | DebugMeta(h) ; | |
426 | IF constTypeResolved(h) | |
427 | THEN | |
428 | (* nothing to do *) | |
429 | ELSE | |
430 | IF constExprResolved(h) | |
431 | THEN | |
432 | IF constResolveViaMeta(h) | |
433 | THEN | |
434 | RETURN( TRUE ) | |
435 | ELSIF constResolvedViaType(h) | |
436 | THEN | |
437 | RETURN( TRUE ) | |
438 | END | |
439 | END | |
440 | END | |
441 | END | |
442 | END ; | |
443 | RETURN( FALSE ) | |
444 | END resolveConstType ; | |
445 | ||
446 | ||
447 | (* | |
448 | ResolveConstTypes - resolves the types of all aggegrate constants. | |
449 | *) | |
450 | ||
451 | PROCEDURE ResolveConstTypes ; | |
452 | VAR | |
453 | h : constList ; | |
454 | changed: BOOLEAN ; | |
455 | BEGIN | |
456 | REPEAT | |
457 | changed := FALSE ; | |
458 | h := headOfConsts ; | |
459 | WHILE h#NIL DO | |
460 | changed := resolveConstType(h) ; | |
461 | h := h^.next | |
462 | END | |
463 | UNTIL NOT changed ; | |
464 | ReportUnresolvedConstTypes | |
465 | END ResolveConstTypes ; | |
466 | ||
467 | ||
468 | (* | |
469 | SkipConst - returns the symbol which is a pseudonum of, sym. | |
470 | *) | |
471 | ||
472 | PROCEDURE SkipConst (sym: CARDINAL) : CARDINAL ; | |
473 | VAR | |
474 | init: CARDINAL ; | |
475 | h : constList ; | |
476 | BEGIN | |
477 | init := sym ; | |
478 | h := headOfConsts ; | |
479 | WHILE h#NIL DO | |
480 | IF (h^.constsym=sym) AND (h^.expr#NulSym) | |
481 | THEN | |
482 | sym := h^.expr ; | |
483 | IF sym=init | |
484 | THEN | |
485 | (* circular definition found *) | |
486 | RETURN( sym ) | |
487 | END ; | |
488 | h := headOfConsts | |
489 | ELSE | |
490 | h := h^.next | |
491 | END | |
492 | END ; | |
493 | RETURN( sym ) | |
494 | END SkipConst ; | |
495 | ||
496 | ||
497 | BEGIN | |
498 | headOfConsts := NIL | |
499 | *) | |
500 | BEGIN | |
501 | END M2Const. |