]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/m2/gm2-compiler/M2Check.mod
Update copyright years.
[thirdparty/gcc.git] / gcc / m2 / gm2-compiler / M2Check.mod
1 (* M2Check.mod perform rigerous type checking for fully declared symbols.
2
3 Copyright (C) 2020-2024 Free Software Foundation, Inc.
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 M2Check ;
23
24 (*
25 Title : M2Check
26 Author : Gaius Mulley
27 System : GNU Modula-2
28 Date : Fri Mar 6 15:32:10 2020
29 Revision : $Version$
30 Description: provides a module to check the symbol type compatibility.
31 It assumes that the declaration of all dependants
32 is complete.
33 *)
34
35 FROM M2System IMPORT IsSystemType, IsGenericSystemType, IsSameSize, IsComplexN ;
36 FROM M2Base IMPORT IsParameterCompatible, IsAssignmentCompatible, IsExpressionCompatible, IsComparisonCompatible, IsBaseType, IsMathType, ZType, CType, RType, IsComplexType ;
37 FROM Indexing IMPORT Index, InitIndex, GetIndice, PutIndice, KillIndex, HighIndice, LowIndice, IncludeIndiceIntoIndex ;
38 FROM M2Error IMPORT Error, InternalError, NewError, ErrorString, ChainError ;
39 FROM M2MetaError IMPORT MetaErrorStringT2, MetaErrorStringT3, MetaErrorStringT4, MetaString2, MetaString3, MetaString4 ;
40 FROM StrLib IMPORT StrEqual ;
41 FROM M2Debug IMPORT Assert ;
42 FROM SymbolTable IMPORT NulSym, IsRecord, IsSet, GetDType, GetSType, IsType, SkipType, IsProcedure, NoOfParam, IsVarParam, GetNth, GetNthParam, IsProcType, IsVar, IsEnumeration, IsArray, GetDeclaredMod, IsSubrange, GetArraySubscript, IsConst, IsReallyPointer, IsPointer, IsParameter, ModeOfAddr, GetMode, GetType, IsUnbounded, IsComposite, IsConstructor, IsParameter, IsConstString ;
43 FROM M2GCCDeclare IMPORT GetTypeMin, GetTypeMax ;
44 FROM M2System IMPORT Address ;
45 FROM M2ALU IMPORT Equ, PushIntegerTree ;
46 FROM m2expr IMPORT AreConstantsEqual ;
47 FROM SymbolConversion IMPORT Mod2Gcc ;
48 FROM DynamicStrings IMPORT String, InitString, KillString ;
49 FROM M2LexBuf IMPORT GetTokenNo ;
50 FROM Storage IMPORT ALLOCATE ;
51 FROM libc IMPORT printf ;
52
53
54 CONST
55 debugging = FALSE ;
56
57 TYPE
58 errorSig = POINTER TO RECORD
59 token: CARDINAL ;
60 left,
61 right: CARDINAL ;
62 END ;
63
64 pair = POINTER TO RECORD
65 left, right: CARDINAL ;
66 pairStatus : status ;
67 next : pair ;
68 END ;
69
70 typeCheckFunction = PROCEDURE (status, tInfo, CARDINAL, CARDINAL) : status ;
71
72 checkType = (parameter, assignment, expression) ;
73
74 tInfo = POINTER TO RECORD
75 format : String ;
76 kind : checkType ;
77 token,
78 actual,
79 formal,
80 left,
81 right,
82 procedure,
83 nth : CARDINAL ;
84 isvar : BOOLEAN ;
85 strict : BOOLEAN ; (* Comparison expression. *)
86 isin : BOOLEAN ; (* Expression created by IN? *)
87 error : Error ;
88 checkFunc : typeCheckFunction ;
89 visited,
90 resolved,
91 unresolved: Index ;
92 next : tInfo ;
93 END ;
94
95 status = (true, false, unknown, visited, unused) ;
96
97
98 VAR
99 pairFreeList : pair ;
100 tinfoFreeList: tInfo ;
101 errors : Index ;
102
103
104 (*
105 isKnown - returns BOOLEAN:TRUE if result is status:true or status:false.
106 *)
107
108 PROCEDURE isKnown (result: status) : BOOLEAN ;
109 BEGIN
110 RETURN (result = true) OR (result = false) OR (result = visited)
111 END isKnown ;
112
113
114 (*
115 isTrue - returns BOOLEAN:TRUE if result is status:true
116
117 PROCEDURE isTrue (result: status) : BOOLEAN ;
118 BEGIN
119 RETURN result = true
120 END isTrue ;
121 *)
122
123
124 (*
125 isFalse - returns BOOLEAN:TRUE if result is status:false
126 *)
127
128 PROCEDURE isFalse (result: status) : BOOLEAN ;
129 BEGIN
130 RETURN result = false
131 END isFalse ;
132
133
134 (*
135 checkTypeEquivalence - returns TRUE if left and right can be skipped and found to be equal.
136 *)
137
138 PROCEDURE checkTypeEquivalence (result: status; left, right: CARDINAL) : status ;
139 VAR
140 leftT, rightT: CARDINAL ;
141 BEGIN
142 (* firstly check to see if we already have resolved this as false. *)
143 IF isFalse (result)
144 THEN
145 RETURN result
146 ELSE
147 (* check to see if we dont care about left or right. *)
148 IF (left = NulSym) OR (right = NulSym)
149 THEN
150 RETURN true
151 ELSE
152 leftT := SkipType (left) ;
153 rightT := SkipType (right) ;
154 IF leftT = rightT
155 THEN
156 RETURN true
157 ELSIF IsType (leftT) AND IsType (rightT)
158 THEN
159 (* the fundamental types are definitely different. *)
160 RETURN false
161 END
162 END
163 END ;
164 RETURN result
165 END checkTypeEquivalence ;
166
167
168 (*
169 checkSubrange - check to see if subrange types left and right have the same limits.
170 *)
171
172 PROCEDURE checkSubrange (result: status; tinfo: tInfo; left, right: CARDINAL) : status ;
173 VAR
174 lLow, rLow,
175 lHigh, rHigh: CARDINAL ;
176 BEGIN
177 (* firstly check to see if we already have resolved this as false. *)
178 IF isFalse (result)
179 THEN
180 RETURN result
181 ELSE
182 Assert (IsSubrange (left)) ;
183 Assert (IsSubrange (right)) ;
184 lLow := GetTypeMin (left) ;
185 lHigh := GetTypeMax (left) ;
186 rLow := GetTypeMin (right) ;
187 rHigh := GetTypeMax (right) ;
188 PushIntegerTree (Mod2Gcc (lLow)) ;
189 PushIntegerTree (Mod2Gcc (rLow)) ;
190 IF NOT Equ (tinfo^.token)
191 THEN
192 RETURN false
193 END ;
194 PushIntegerTree (Mod2Gcc (lHigh)) ;
195 PushIntegerTree (Mod2Gcc (rHigh)) ;
196 IF NOT Equ (tinfo^.token)
197 THEN
198 RETURN false
199 END
200 END ;
201 RETURN true
202 END checkSubrange ;
203
204
205 (*
206 checkArrayTypeEquivalence -
207 *)
208
209 PROCEDURE checkArrayTypeEquivalence (result: status; tinfo: tInfo;
210 left, right: CARDINAL) : status ;
211 VAR
212 lSub , rSub: CARDINAL ;
213 BEGIN
214 IF isFalse (result)
215 THEN
216 RETURN result
217 ELSIF IsArray (left) AND IsArray (right)
218 THEN
219 lSub := GetArraySubscript (left) ;
220 rSub := GetArraySubscript (right) ;
221 result := checkPair (result, tinfo, GetType (left), GetType (right)) ;
222 IF (lSub # NulSym) AND (rSub # NulSym)
223 THEN
224 result := checkSubrange (result, tinfo, getSType (lSub), getSType (rSub))
225 END
226 ELSIF IsUnbounded (left) AND (IsArray (right) OR IsUnbounded (right))
227 THEN
228 IF IsGenericSystemType (getSType (left)) OR IsGenericSystemType (getSType (right))
229 THEN
230 RETURN true
231 ELSE
232 result := checkPair (result, tinfo, GetType (left), GetType (right))
233 END
234 END ;
235 RETURN result
236 END checkArrayTypeEquivalence ;
237
238
239 (*
240 checkGenericTypeEquivalence - check left and right for generic equivalence.
241 *)
242
243 PROCEDURE checkGenericTypeEquivalence (result: status; left, right: CARDINAL) : status ;
244 BEGIN
245 IF isFalse (result)
246 THEN
247 RETURN result
248 ELSIF left = right
249 THEN
250 RETURN true
251 ELSE
252 RETURN result
253 END
254 END checkGenericTypeEquivalence ;
255
256
257 (*
258 firstTime - returns TRUE if the triple (token, left, right) has not been seen before.
259 *)
260
261 PROCEDURE firstTime (token: CARDINAL; left, right: CARDINAL) : BOOLEAN ;
262 VAR
263 p : errorSig ;
264 i, n: CARDINAL ;
265 BEGIN
266 i := 1 ;
267 n := HighIndice (errors) ;
268 WHILE i <= n DO
269 p := GetIndice (errors, i) ;
270 IF (p^.token = token) AND (p^.left = left) AND (p^.right = right)
271 THEN
272 RETURN FALSE
273 END ;
274 INC (i)
275 END ;
276 NEW (p) ;
277 p^.token := token ;
278 p^.left := left ;
279 p^.right := right ;
280 IncludeIndiceIntoIndex (errors, p) ;
281 RETURN TRUE
282 END firstTime ;
283
284
285 (*
286 buildError4 -
287 *)
288
289 PROCEDURE buildError4 (tinfo: tInfo; left, right: CARDINAL) ;
290 VAR
291 s: String ;
292 BEGIN
293 IF firstTime (tinfo^.token, left, right)
294 THEN
295 IF tinfo^.error = NIL
296 THEN
297 (* need to create top level error message first. *)
298 tinfo^.error := NewError (tinfo^.token) ;
299 (* The parameters to MetaString4 in buildError4 must match the order
300 of paramters passed to ParameterTypeCompatible. *)
301 s := MetaString4 (tinfo^.format,
302 tinfo^.procedure,
303 tinfo^.left, tinfo^.right,
304 tinfo^.nth) ;
305 ErrorString (tinfo^.error, s)
306 END ;
307 (* and also generate a sub error containing detail. *)
308 IF (left # tinfo^.left) OR (right # tinfo^.right)
309 THEN
310 tinfo^.error := ChainError (tinfo^.token, tinfo^.error) ;
311 s := MetaString2 (InitString ("{%1Ead} and {%2ad} are incompatible in this context"), left, right) ;
312 ErrorString (tinfo^.error, s)
313 END
314 END
315 END buildError4 ;
316
317
318 (*
319 buildError2 -
320 *)
321
322 PROCEDURE buildError2 (tinfo: tInfo; left, right: CARDINAL) ;
323 VAR
324 s: String ;
325 BEGIN
326 IF firstTime (tinfo^.token, left, right)
327 THEN
328 IF tinfo^.error = NIL
329 THEN
330 (* need to create top level error message first. *)
331 tinfo^.error := NewError (tinfo^.token) ;
332 s := MetaString2 (tinfo^.format,
333 tinfo^.left, tinfo^.right) ;
334 ErrorString (tinfo^.error, s)
335 END ;
336 (* and also generate a sub error containing detail. *)
337 IF (left # tinfo^.left) OR (right # tinfo^.right)
338 THEN
339 tinfo^.error := ChainError (tinfo^.token, tinfo^.error) ;
340 s := MetaString2 (InitString ("{%1Ead} and {%2ad} are incompatible in this context"), left, right) ;
341 ErrorString (tinfo^.error, s)
342 END
343 END
344 END buildError2 ;
345
346
347 (*
348 issueError -
349 *)
350
351 PROCEDURE issueError (result: BOOLEAN; tinfo: tInfo; left, right: CARDINAL) : status ;
352 BEGIN
353 IF result
354 THEN
355 RETURN true
356 ELSE
357 (* check whether errors are required. *)
358 IF tinfo^.format # NIL
359 THEN
360 CASE tinfo^.kind OF
361
362 parameter : buildError4 (tinfo, left, right) |
363 assignment: buildError2 (tinfo, left, right) |
364 expression: buildError2 (tinfo, left, right)
365
366 END ;
367 tinfo^.format := NIL (* string is used by MetaError now. *)
368 END ;
369 RETURN false
370 END
371 END issueError ;
372
373
374 (*
375 checkBaseEquivalence - the catch all check for types not specifically
376 handled by this module.
377 *)
378
379 PROCEDURE checkBaseEquivalence (result: status; tinfo: tInfo;
380 left, right: CARDINAL) : status ;
381 BEGIN
382 IF isKnown (result)
383 THEN
384 RETURN result
385 ELSE
386 CASE tinfo^.kind OF
387
388 parameter : IF tinfo^.isvar
389 THEN
390 RETURN issueError (IsExpressionCompatible (left, right),
391 tinfo, left, right)
392 ELSE
393 RETURN issueError (IsAssignmentCompatible (left, right),
394 tinfo, left, right)
395 END |
396 assignment: RETURN issueError (IsAssignmentCompatible (left, right),
397 tinfo, left, right) |
398 expression: IF tinfo^.isin
399 THEN
400 IF IsVar (right) OR IsConst (right)
401 THEN
402 right := getSType (right)
403 END
404 END ;
405 IF tinfo^.strict
406 THEN
407 RETURN issueError (IsComparisonCompatible (left, right),
408 tinfo, left, right)
409 ELSE
410 RETURN issueError (IsExpressionCompatible (left, right),
411 tinfo, left, right)
412 END
413
414 ELSE
415 InternalError ('unexpected kind value')
416 END
417 END
418 (* should never reach here. *)
419 END checkBaseEquivalence ;
420
421
422 (*
423 checkPair -
424 *)
425
426 PROCEDURE checkPair (result: status; tinfo: tInfo;
427 left, right: CARDINAL) : status ;
428 BEGIN
429 IF isFalse (result)
430 THEN
431 exclude (tinfo^.visited, left, right) ;
432 RETURN result
433 ELSE
434 IF in (tinfo^.resolved, left, right)
435 THEN
436 exclude (tinfo^.visited, left, right) ;
437 RETURN getStatus (tinfo^.resolved, left, right)
438 ELSIF in (tinfo^.visited, left, right)
439 THEN
440 RETURN visited
441 ELSE
442 IF debugging
443 THEN
444 printf (" marked as visited (%d, %d)\n", left, right)
445 END ;
446 include (tinfo^.visited, left, right, unknown) ;
447 include (tinfo^.unresolved, left, right, unknown)
448 END ;
449 RETURN doCheckPair (result, tinfo, left, right)
450 END
451 END checkPair ;
452
453
454 (*
455 useBaseCheck -
456 *)
457
458 PROCEDURE useBaseCheck (sym: CARDINAL) : BOOLEAN ;
459 BEGIN
460 RETURN IsBaseType (sym) OR IsSystemType (sym) OR IsMathType (sym) OR IsComplexType (sym)
461 END useBaseCheck ;
462
463
464 (*
465 checkBaseTypeEquivalence -
466 *)
467
468 PROCEDURE checkBaseTypeEquivalence (result: status; tinfo: tInfo;
469 left, right: CARDINAL) : status ;
470 BEGIN
471 IF isFalse (result)
472 THEN
473 RETURN result
474 ELSIF useBaseCheck (left) AND useBaseCheck (right)
475 THEN
476 RETURN checkBaseEquivalence (result, tinfo, left, right)
477 ELSE
478 RETURN result
479 END
480 END checkBaseTypeEquivalence ;
481
482
483 (*
484 IsTyped -
485 *)
486
487 PROCEDURE IsTyped (sym: CARDINAL) : BOOLEAN ;
488 BEGIN
489 RETURN IsVar (sym) OR IsVar (sym) OR IsParameter (sym) OR
490 (IsConst (sym) AND IsConstructor (sym)) OR IsParameter (sym) OR
491 (IsConst (sym) AND (GetType (sym) # NulSym))
492 END IsTyped ;
493
494
495 (*
496 isLValue -
497 *)
498
499 PROCEDURE isLValue (sym: CARDINAL) : BOOLEAN ;
500 BEGIN
501 RETURN IsVar (sym) AND (GetMode (sym) = LeftValue)
502 END isLValue ;
503
504
505 (*
506 checkVarEquivalence - this test must be done early as it checks the symbol mode.
507 An LValue is treated as a pointer during assignment and the
508 LValue is attached to a variable. This function skips the variable
509 and checks the types - after it has considered a possible LValue.
510 *)
511
512 PROCEDURE checkVarEquivalence (result: status; tinfo: tInfo;
513 left, right: CARDINAL) : status ;
514 BEGIN
515 IF isFalse (result)
516 THEN
517 RETURN result
518 ELSIF IsTyped (left) OR IsTyped (right)
519 THEN
520 IF tinfo^.kind = assignment
521 THEN
522 (* LValues are only relevant during assignment. *)
523 IF isLValue (left) AND (NOT isLValue (right))
524 THEN
525 IF SkipType (getType (right)) = Address
526 THEN
527 RETURN true
528 ELSIF IsPointer (SkipType (getType (right)))
529 THEN
530 right := GetDType (SkipType (getType (right)))
531 END
532 ELSIF isLValue (right) AND (NOT isLValue (left))
533 THEN
534 IF SkipType (getType (left)) = Address
535 THEN
536 RETURN true
537 ELSIF IsPointer (SkipType (getType (left)))
538 THEN
539 left := GetDType (SkipType (getType (left)))
540 END
541 END
542 END ;
543 RETURN doCheckPair (result, tinfo, getType (left), getType (right))
544 ELSE
545 RETURN result
546 END
547 END checkVarEquivalence ;
548
549
550 (*
551 checkConstMeta -
552 *)
553
554 PROCEDURE checkConstMeta (result: status;
555 left, right: CARDINAL) : status ;
556 VAR
557 typeRight: CARDINAL ;
558 BEGIN
559 Assert (IsConst (left)) ;
560 IF isFalse (result)
561 THEN
562 RETURN result
563 ELSIF IsConstString (left)
564 THEN
565 typeRight := GetDType (right) ;
566 IF typeRight = NulSym
567 THEN
568 RETURN result
569 ELSIF IsSet (typeRight) OR IsEnumeration (typeRight)
570 THEN
571 RETURN false
572 END
573 END ;
574 RETURN result
575 END checkConstMeta ;
576
577
578 (*
579 checkConstEquivalence - this check can be done first as it checks symbols which
580 may have no type. Ie constant strings. These constants
581 will likely have their type set during quadruple folding.
582 But we can check the meta type for obvious mismatches
583 early on. For example adding a string to an enum or set.
584 *)
585
586 PROCEDURE checkConstEquivalence (result: status;
587 left, right: CARDINAL) : status ;
588 BEGIN
589 IF isFalse (result)
590 THEN
591 RETURN result
592 ELSIF (left = NulSym) OR (right = NulSym)
593 THEN
594 (* No option but to return true. *)
595 RETURN true
596 ELSIF IsConst (left)
597 THEN
598 RETURN checkConstMeta (result, left, right)
599 ELSIF IsConst (right)
600 THEN
601 RETURN checkConstMeta (result, right, left)
602 END ;
603 RETURN result
604 END checkConstEquivalence ;
605
606
607 (*
608 checkSubrangeTypeEquivalence -
609 *)
610
611 PROCEDURE checkSubrangeTypeEquivalence (result: status; tinfo: tInfo;
612 left, right: CARDINAL) : status ;
613 BEGIN
614 IF isFalse (result)
615 THEN
616 RETURN result
617 ELSE
618 IF IsSubrange (left)
619 THEN
620 RETURN doCheckPair (result, tinfo, GetDType (left), right)
621 END ;
622 IF IsSubrange (right)
623 THEN
624 RETURN doCheckPair (result, tinfo, left, GetDType (right))
625 END ;
626 IF left = right
627 THEN
628 RETURN true
629 ELSE
630 RETURN result
631 END
632 END
633 END checkSubrangeTypeEquivalence ;
634
635
636 (*
637 isZRC -
638 *)
639
640 PROCEDURE isZRC (zrc, sym: CARDINAL) : BOOLEAN ;
641 BEGIN
642 IF IsConst (sym)
643 THEN
644 sym := SkipType (GetType (sym))
645 END ;
646 IF (zrc = CType) AND (IsComplexN (sym) OR IsComplexType (sym))
647 THEN
648 RETURN TRUE
649 END ;
650 RETURN (zrc = sym) OR ((zrc = ZType) OR (zrc = RType) AND (NOT IsComposite (sym)))
651 END isZRC ;
652
653
654 (*
655 isSameSizeConst -
656
657 *)
658
659 PROCEDURE isSameSizeConst (a, b: CARDINAL) : BOOLEAN ;
660 BEGIN
661 IF IsConst (a)
662 THEN
663 a := SkipType (GetType (a)) ;
664 RETURN isZRC (a, b) OR (a = b) OR ((a # NulSym) AND isSameSize (a, b))
665 ELSIF IsConst (b)
666 THEN
667 b := SkipType (GetType (b)) ;
668 RETURN isZRC (b, a) OR (a = b) OR ((b # NulSym) AND isSameSize (a, b))
669 END ;
670 RETURN FALSE
671 END isSameSizeConst ;
672
673
674 (*
675 isSameSize - should only be called if either a or b are WORD, BYTE, etc.
676 *)
677
678 PROCEDURE isSameSize (a, b: CARDINAL) : BOOLEAN ;
679 BEGIN
680 RETURN isSameSizeConst (a, b) OR IsSameSize (a, b)
681 END isSameSize ;
682
683
684 (*
685 checkSystemEquivalence - check whether left and right are system types and whether they have the same size.
686 *)
687
688 PROCEDURE checkSystemEquivalence (result: status; left, right: CARDINAL) : status ;
689 BEGIN
690 IF isFalse (result) OR (result = visited)
691 THEN
692 RETURN result
693 ELSE
694 IF (IsGenericSystemType (left) OR IsGenericSystemType (right)) AND
695 isSameSize (left, right)
696 THEN
697 RETURN true
698 END
699 END ;
700 RETURN result
701 END checkSystemEquivalence ;
702
703
704 (*
705 doCheckPair -
706 *)
707
708 PROCEDURE doCheckPair (result: status; tinfo: tInfo;
709 left, right: CARDINAL) : status ;
710 BEGIN
711 IF isFalse (result) OR (result = visited)
712 THEN
713 RETURN return (result, tinfo, left, right)
714 ELSIF left = right
715 THEN
716 RETURN return (true, tinfo, left, right)
717 ELSE
718 result := checkConstEquivalence (unknown, left, right) ;
719 IF NOT isKnown (result)
720 THEN
721 result := checkVarEquivalence (unknown, tinfo, left, right) ;
722 IF NOT isKnown (result)
723 THEN
724 result := checkSystemEquivalence (unknown, left, right) ;
725 IF NOT isKnown (result)
726 THEN
727 result := checkSubrangeTypeEquivalence (unknown, tinfo, left, right) ;
728 IF NOT isKnown (result)
729 THEN
730 result := checkBaseTypeEquivalence (unknown, tinfo, left, right) ;
731 IF NOT isKnown (result)
732 THEN
733 result := checkTypeEquivalence (unknown, left, right) ;
734 IF NOT isKnown (result)
735 THEN
736 result := checkArrayTypeEquivalence (result, tinfo, left, right) ;
737 IF NOT isKnown (result)
738 THEN
739 result := checkGenericTypeEquivalence (result, left, right) ;
740 IF NOT isKnown (result)
741 THEN
742 result := checkTypeKindEquivalence (result, tinfo, left, right)
743 END
744 END
745 END
746 END
747 END
748 END
749 END
750 END
751 END ;
752 RETURN return (result, tinfo, left, right)
753 END doCheckPair ;
754
755
756 (*
757 checkProcType -
758 *)
759
760 PROCEDURE checkProcType (result: status; tinfo: tInfo;
761 left, right: CARDINAL) : status ;
762 VAR
763 i, n : CARDINAL ;
764 lt, rt: CARDINAL ;
765 BEGIN
766 Assert (IsProcType (right)) ;
767 Assert (IsProcType (left)) ;
768 IF isFalse (result)
769 THEN
770 RETURN result
771 ELSE
772 lt := GetDType (left) ;
773 rt := GetDType (right) ;
774 IF (lt = NulSym) AND (rt = NulSym)
775 THEN
776 result := unknown
777 ELSIF lt = NulSym
778 THEN
779 IF tinfo^.format # NIL
780 THEN
781 MetaErrorStringT3 (tinfo^.token, InitString ("procedure type {%1a} does not have a {%kRETURN} type whereas procedure type {%2ad} has a {%kRETURN} type {%3ad}"), left, right, rt)
782 END ;
783 RETURN return (false, tinfo, left, right)
784 ELSIF rt = NulSym
785 THEN
786 IF tinfo^.format # NIL
787 THEN
788 MetaErrorStringT3 (tinfo^.token, InitString ("procedure type {%1a} does not have a {%kRETURN} type whereas procedure type {%2ad} has a {%kRETURN} type {%3ad}"), right, left, lt)
789 END ;
790 RETURN return (false, tinfo, left, right)
791 ELSE
792 (* two return type seen so we check them. *)
793 result := checkPair (unknown, tinfo, lt, rt)
794 END ;
795
796 IF NoOfParam (left) # NoOfParam (right)
797 THEN
798 IF tinfo^.format # NIL
799 THEN
800 MetaErrorStringT2 (tinfo^.token, InitString ("procedure type {%1a} has a different number of parameters from procedure type {%2ad}"), right, left)
801 END ;
802 RETURN return (false, tinfo, left, right)
803 END ;
804 i := 1 ;
805 n := NoOfParam (left) ;
806 WHILE i <= n DO
807 IF IsVarParam (left, i) # IsVarParam (right, i)
808 THEN
809 IF IsVarParam (left, i)
810 THEN
811 IF tinfo^.format # NIL
812 THEN
813 MetaErrorStringT3 (tinfo^.token, InitString ("procedure type {%2a} {%3n} parameter was declared as a {%kVAR} whereas procedure type {%1ad} {%3n} parameter was not"), right, left, i)
814 END
815 ELSE
816 IF tinfo^.format # NIL
817 THEN
818 MetaErrorStringT3 (tinfo^.token, InitString ("procedure type {%1a} {%3n} parameter was declared as a {%kVAR} whereas procedure type {%2ad} {%3n} parameter was not"), right, left, i)
819 END
820 END ;
821 RETURN return (false, tinfo, left, right)
822 END ;
823 result := checkPair (result, tinfo, GetDType (GetNthParam (left, i)), GetDType (GetNthParam (right, i))) ;
824 INC (i)
825 END
826 END ;
827 RETURN return (result, tinfo, left, right)
828 END checkProcType ;
829
830
831 (*
832 checkProcedureProcType -
833 *)
834
835 PROCEDURE checkProcedureProcType (result: status; tinfo: tInfo;
836 left, right: CARDINAL) : status ;
837 VAR
838 i, n : CARDINAL ;
839 lt, rt: CARDINAL ;
840 BEGIN
841 Assert (IsProcedure (right)) ;
842 Assert (IsProcType (left)) ;
843 IF NOT isFalse (result)
844 THEN
845 lt := GetDType (left) ;
846 rt := GetDType (right) ;
847 IF (lt = NulSym) AND (rt = NulSym)
848 THEN
849 (* nothing. *)
850 ELSIF lt = NulSym
851 THEN
852 IF tinfo^.format # NIL
853 THEN
854 MetaErrorStringT3 (tinfo^.token, InitString ("procedure type {%1a} does not have a {%kRETURN} type whereas procedure {%2ad} has a {%kRETURN} type {%3ad}"), left, right, rt)
855 END ;
856 RETURN return (false, tinfo, left, right)
857 ELSIF rt = NulSym
858 THEN
859 IF tinfo^.format # NIL
860 THEN
861 MetaErrorStringT3 (tinfo^.token, InitString ("procedure {%1a} does not have a {%kRETURN} type whereas procedure type {%2ad} has a {%kRETURN} type {%3ad}"), right, left, lt)
862 END ;
863 RETURN return (false, tinfo, left, right)
864 ELSE
865 (* two return type seen so we check them. *)
866 result := checkPair (result, tinfo, lt, rt)
867 END ;
868
869 IF NoOfParam (left) # NoOfParam (right)
870 THEN
871 IF tinfo^.format # NIL
872 THEN
873 MetaErrorStringT2 (tinfo^.token, InitString ("procedure {%1a} has a different number of parameters from procedure type {%2ad}"), right, left)
874 END ;
875 RETURN return (false, tinfo, left, right)
876 END ;
877 i := 1 ;
878 n := NoOfParam (left) ;
879 WHILE i <= n DO
880 IF IsVarParam (left, i) # IsVarParam (right, i)
881 THEN
882 IF IsVarParam (left, i)
883 THEN
884 IF tinfo^.format # NIL
885 THEN
886 MetaErrorStringT3 (tinfo^.token, InitString ("procedure type {%2a} {%3n} parameter was declared as a {%kVAR} whereas procedure {%1ad} {%3n} parameter was not"), right, left, i)
887 END
888 ELSE
889 IF tinfo^.format # NIL
890 THEN
891 MetaErrorStringT3 (tinfo^.token, InitString ("procedure {%1a} {%3n} parameter was declared as a {%kVAR} whereas procedure type {%2ad} {%3n} parameter was not"), right, left, i)
892 END
893 END ;
894 RETURN return (false, tinfo, left, right)
895 END ;
896 result := checkPair (result, tinfo, GetDType (GetNthParam (left, i)), GetDType (GetNthParam (right, i))) ;
897 INC (i)
898 END
899 END ;
900 RETURN return (result, tinfo, left, right)
901 END checkProcedureProcType ;
902
903
904 (*
905 checkProcedure -
906 *)
907
908 PROCEDURE checkProcedure (result: status; tinfo: tInfo;
909 left, right: CARDINAL) : status ;
910 BEGIN
911 Assert (IsProcedure (right)) ;
912 IF isFalse (result)
913 THEN
914 RETURN result
915 ELSIF IsVar (left)
916 THEN
917 RETURN checkProcedure (result, tinfo,
918 GetDType (left), right)
919 ELSIF left = Address
920 THEN
921 RETURN true
922 ELSIF IsProcType (left)
923 THEN
924 RETURN checkProcedureProcType (result, tinfo, left, right)
925 ELSE
926 RETURN result
927 END
928 END checkProcedure ;
929
930
931 (*
932 checkEnumerationEquivalence -
933 *)
934
935 PROCEDURE checkEnumerationEquivalence (result: status;
936 left, right: CARDINAL) : status ;
937 BEGIN
938 IF isFalse (result)
939 THEN
940 RETURN result
941 ELSIF left = right
942 THEN
943 RETURN true
944 ELSE
945 RETURN false
946 END
947 END checkEnumerationEquivalence ;
948
949
950 (*
951 checkPointerType - check whether left and right are equal or are of type ADDRESS.
952 *)
953
954 PROCEDURE checkPointerType (result: status; left, right: CARDINAL) : status ;
955 BEGIN
956 IF isFalse (result)
957 THEN
958 RETURN result
959 ELSIF (left = right) OR (left = Address) OR (right = Address)
960 THEN
961 RETURN true
962 ELSE
963 RETURN false
964 END
965 END checkPointerType ;
966
967
968 (*
969 checkProcTypeEquivalence - allow proctype to be compared against another
970 proctype or procedure. It is legal to be compared
971 against an address.
972 *)
973
974 PROCEDURE checkProcTypeEquivalence (result: status; tinfo: tInfo;
975 left, right: CARDINAL) : status ;
976 BEGIN
977 IF isFalse (result)
978 THEN
979 RETURN result
980 ELSIF IsProcedure (left) AND IsProcType (right)
981 THEN
982 RETURN checkProcedure (result, tinfo, right, left)
983 ELSIF IsProcType (left) AND IsProcedure (right)
984 THEN
985 RETURN checkProcedure (result, tinfo, left, right)
986 ELSIF IsProcType (left) AND IsProcType (right)
987 THEN
988 RETURN checkProcType (result, tinfo, left, right)
989 ELSIF (left = Address) OR (right = Address)
990 THEN
991 RETURN true
992 ELSE
993 RETURN false
994 END
995 END checkProcTypeEquivalence ;
996
997
998
999 (*
1000 checkTypeKindEquivalence -
1001 *)
1002
1003 PROCEDURE checkTypeKindEquivalence (result: status; tinfo: tInfo;
1004 left, right: CARDINAL) : status ;
1005 BEGIN
1006 IF isFalse (result)
1007 THEN
1008 RETURN result
1009 ELSIF (left = NulSym) OR (right = NulSym)
1010 THEN
1011 RETURN true
1012 ELSE
1013 (* Long cascade of all type kinds. *)
1014 IF IsSet (left) AND IsSet (right)
1015 THEN
1016 RETURN checkSetEquivalent (result, tinfo, left, right)
1017 ELSIF IsArray (left) AND IsArray (right)
1018 THEN
1019 RETURN checkArrayTypeEquivalence (result, tinfo, left, right)
1020 ELSIF IsRecord (left) AND IsRecord (right)
1021 THEN
1022 RETURN checkRecordEquivalence (result, left, right)
1023 ELSIF IsEnumeration (left) AND IsEnumeration (right)
1024 THEN
1025 RETURN checkEnumerationEquivalence (result, left, right)
1026 ELSIF IsProcType (left) OR IsProcType (right)
1027 THEN
1028 RETURN checkProcTypeEquivalence (result, tinfo, right, left)
1029 ELSIF IsReallyPointer (left) AND IsReallyPointer (right)
1030 THEN
1031 RETURN checkPointerType (result, left, right)
1032 ELSE
1033 RETURN result
1034 END
1035 END
1036 END checkTypeKindEquivalence ;
1037
1038
1039 (*
1040 isSkipEquivalence -
1041 *)
1042
1043 PROCEDURE isSkipEquivalence (left, right: CARDINAL) : BOOLEAN ;
1044 BEGIN
1045 RETURN SkipType (left) = SkipType (right)
1046 END isSkipEquivalence ;
1047
1048
1049 (*
1050 checkValueEquivalence - check to see if left and right values are the same.
1051 *)
1052
1053 PROCEDURE checkValueEquivalence (result: status; left, right: CARDINAL) : status ;
1054 BEGIN
1055 IF isKnown (result)
1056 THEN
1057 RETURN result
1058 ELSIF left = right
1059 THEN
1060 RETURN true
1061 ELSE
1062 IF AreConstantsEqual (Mod2Gcc (left), Mod2Gcc (right))
1063 THEN
1064 RETURN true
1065 ELSE
1066 RETURN false
1067 END
1068 END
1069 END checkValueEquivalence ;
1070
1071
1072 (*
1073 and -
1074 *)
1075
1076 PROCEDURE and (left, right: status) : status ;
1077 BEGIN
1078 IF (left = true) AND (right = true)
1079 THEN
1080 RETURN true
1081 ELSE
1082 RETURN false
1083 END
1084 END and ;
1085
1086
1087 (*
1088 checkTypeRangeEquivalence -
1089 *)
1090
1091 PROCEDURE checkTypeRangeEquivalence (result: status; tinfo: tInfo;
1092 left, right: CARDINAL) : status ;
1093 VAR
1094 result2, result3: status ;
1095 BEGIN
1096 result := checkSkipEquivalence (result, left, right) ;
1097 result2 := checkValueEquivalence (result, GetTypeMin (left), GetTypeMin (right)) ;
1098 result3 := checkValueEquivalence (result, GetTypeMax (left), GetTypeMax (right)) ;
1099 RETURN return (and (result2, result3), tinfo, left, right)
1100 END checkTypeRangeEquivalence ;
1101
1102
1103 (*
1104 include - include pair left:right into pairs with status, s.
1105 *)
1106
1107 PROCEDURE include (pairs: Index; left, right: CARDINAL; s: status) ;
1108 VAR
1109 p: pair ;
1110 BEGIN
1111 p := newPair () ;
1112 p^.left := left ;
1113 p^.right := right ;
1114 p^.pairStatus := s ;
1115 p^.next := NIL ;
1116 IncludeIndiceIntoIndex (pairs, p)
1117 END include ;
1118
1119
1120 (*
1121 exclude - exclude pair left:right from pairs.
1122 *)
1123
1124 PROCEDURE exclude (pairs: Index; left, right: CARDINAL) ;
1125 VAR
1126 p : pair ;
1127 i, n: CARDINAL ;
1128 BEGIN
1129 i := 1 ;
1130 n := HighIndice (pairs) ;
1131 WHILE i <= n DO
1132 p := GetIndice (pairs, i) ;
1133 IF (p # NIL) AND (p^.left = left) AND (p^.right = right)
1134 THEN
1135 PutIndice (pairs, i, NIL) ;
1136 disposePair (p) ;
1137 RETURN
1138 END ;
1139 INC (i)
1140 END
1141 END exclude ;
1142
1143
1144 (*
1145 getStatus -
1146 *)
1147
1148 PROCEDURE getStatus (pairs: Index; left, right: CARDINAL) : status ;
1149 VAR
1150 p : pair ;
1151 i, n: CARDINAL ;
1152 BEGIN
1153 i := 1 ;
1154 n := HighIndice (pairs) ;
1155 WHILE i <= n DO
1156 p := GetIndice (pairs, i) ;
1157 IF (p # NIL) AND (p^.left = left) AND (p^.right = right)
1158 THEN
1159 RETURN p^.pairStatus
1160 END ;
1161 INC (i)
1162 END ;
1163 RETURN unknown
1164 END getStatus ;
1165
1166
1167 (*
1168 return -
1169 *)
1170
1171 PROCEDURE return (result: status; tinfo: tInfo; left, right: CARDINAL) : status ;
1172 BEGIN
1173 IF result # unknown
1174 THEN
1175 IF isKnown (result)
1176 THEN
1177 include (tinfo^.resolved, left, right, result) ;
1178 exclude (tinfo^.unresolved, left, right) ;
1179 exclude (tinfo^.visited, left, right) (* no longer visiting as it is resolved. *)
1180 END
1181 END ;
1182 IF result = false
1183 THEN
1184 RETURN issueError (FALSE, tinfo, left, right)
1185 END ;
1186 RETURN result
1187 END return ;
1188
1189
1190 (*
1191 checkSkipEquivalence - return true if left right are equivalent.
1192 *)
1193
1194 PROCEDURE checkSkipEquivalence (result: status; left, right: CARDINAL) : status ;
1195 BEGIN
1196 IF isKnown (result)
1197 THEN
1198 RETURN result
1199 ELSIF isSkipEquivalence (left, right)
1200 THEN
1201 RETURN true
1202 ELSE
1203 RETURN result
1204 END
1205 END checkSkipEquivalence ;
1206
1207
1208 (*
1209 checkSetEquivalent - compares set types, left and right.
1210 *)
1211
1212 PROCEDURE checkSetEquivalent (result: status; tinfo: tInfo;
1213 left, right: CARDINAL) : status ;
1214 BEGIN
1215 result := checkSkipEquivalence (result, left, right) ;
1216 result := checkTypeKindEquivalence (result, tinfo, GetDType (left), GetDType (right)) ;
1217 result := checkTypeRangeEquivalence (result, tinfo, GetDType (left), GetDType (right)) ;
1218 RETURN return (result, tinfo, left, right)
1219 END checkSetEquivalent ;
1220
1221
1222 (*
1223 checkRecordEquivalence - compares record types, left and right.
1224 *)
1225
1226 PROCEDURE checkRecordEquivalence (result: status; left, right: CARDINAL) : status ;
1227 BEGIN
1228 IF isFalse (result)
1229 THEN
1230 RETURN result
1231 ELSIF left = right
1232 THEN
1233 RETURN true
1234 ELSE
1235 RETURN false
1236 END
1237 END checkRecordEquivalence ;
1238
1239
1240 (*
1241 getType - only returns the type of symbol providing it is not a procedure.
1242 *)
1243
1244 PROCEDURE getType (sym: CARDINAL) : CARDINAL ;
1245 BEGIN
1246 IF (sym # NulSym) AND IsProcedure (sym)
1247 THEN
1248 RETURN Address
1249 ELSIF IsTyped (sym)
1250 THEN
1251 RETURN GetDType (sym)
1252 ELSE
1253 RETURN sym
1254 END
1255 END getType ;
1256
1257
1258 (*
1259 getSType -
1260 *)
1261
1262 PROCEDURE getSType (sym: CARDINAL) : CARDINAL ;
1263 BEGIN
1264 IF IsProcedure (sym)
1265 THEN
1266 RETURN Address
1267 ELSE
1268 RETURN GetSType (sym)
1269 END
1270 END getSType ;
1271
1272
1273 (*
1274 determineCompatible - check for compatibility by checking
1275 equivalence, array, generic and type kind.
1276 *)
1277
1278 PROCEDURE determineCompatible (result: status; tinfo: tInfo; left, right: CARDINAL) : status ;
1279 BEGIN
1280 result := checkPair (result, tinfo, left, right) ;
1281 RETURN return (result, tinfo, left, right)
1282 END determineCompatible ;
1283
1284
1285 (*
1286 get -
1287 *)
1288
1289 PROCEDURE get (pairs: Index; VAR left, right: CARDINAL; s: status) : BOOLEAN ;
1290 VAR
1291 i, n: CARDINAL ;
1292 p : pair ;
1293 BEGIN
1294 i := 1 ;
1295 n := HighIndice (pairs) ;
1296 WHILE i <= n DO
1297 p := GetIndice (pairs, i) ;
1298 IF (p # NIL) AND (p^.pairStatus = s)
1299 THEN
1300 left := p^.left ;
1301 right := p^.right ;
1302 RETURN TRUE
1303 END ;
1304 INC (i)
1305 END ;
1306 RETURN FALSE
1307 END get ;
1308
1309
1310 (*
1311 doCheck - keep obtaining an unresolved pair and check for the
1312 type compatibility. This is the main check routine used by
1313 parameter, assignment and expression compatibility.
1314 It tests all unknown pairs and calls the appropriate
1315 check function
1316 *)
1317
1318 PROCEDURE doCheck (tinfo: tInfo) : BOOLEAN ;
1319 VAR
1320 result : status ;
1321 left, right: CARDINAL ;
1322 BEGIN
1323 WHILE get (tinfo^.unresolved, left, right, unknown) DO
1324 IF debugging
1325 THEN
1326 printf ("doCheck (%d, %d)\n", left, right)
1327 END ;
1328 (*
1329 IF in (tinfo^.visited, left, right)
1330 THEN
1331 IF debugging
1332 THEN
1333 printf (" already visited (%d, %d)\n", left, right)
1334 END ;
1335 ELSE
1336 IF debugging
1337 THEN
1338 printf (" not visited (%d, %d)\n", left, right)
1339 END ;
1340 *)
1341 result := tinfo^.checkFunc (unknown, tinfo, left, right) ;
1342 IF isKnown (result)
1343 THEN
1344 (* remove this pair from the unresolved list. *)
1345 exclude (tinfo^.unresolved, left, right) ;
1346 (* add it to the resolved list. *)
1347 include (tinfo^.resolved, left, right, result) ;
1348 IF result = false
1349 THEN
1350 IF debugging
1351 THEN
1352 printf (" known (%d, %d) false\n", left, right)
1353 END ;
1354 RETURN FALSE
1355 ELSE
1356 IF debugging
1357 THEN
1358 printf (" known (%d, %d) true\n", left, right)
1359 END
1360 END
1361 END
1362 END ;
1363 RETURN TRUE
1364 END doCheck ;
1365
1366
1367 (*
1368 in - returns TRUE if the pair is in the list.
1369 *)
1370
1371 PROCEDURE in (pairs: Index; left, right: CARDINAL) : BOOLEAN ;
1372 VAR
1373 i, n: CARDINAL ;
1374 p : pair ;
1375 BEGIN
1376 i := 1 ;
1377 n := HighIndice (pairs) ;
1378 WHILE i <= n DO
1379 p := GetIndice (pairs, i) ;
1380 IF (p # NIL) AND (p^.left = left) AND (p^.right = right)
1381 THEN
1382 RETURN TRUE
1383 END ;
1384 INC (i)
1385 END ;
1386 RETURN FALSE
1387 END in ;
1388
1389
1390 (*
1391 newPair -
1392 *)
1393
1394 PROCEDURE newPair () : pair ;
1395 VAR
1396 p: pair ;
1397 BEGIN
1398 IF pairFreeList = NIL
1399 THEN
1400 NEW (p)
1401 ELSE
1402 p := pairFreeList ;
1403 pairFreeList := p^.next
1404 END ;
1405 Assert (p # NIL) ;
1406 RETURN p
1407 END newPair ;
1408
1409
1410 (*
1411 disposePair - adds pair, p, to the free list.
1412 *)
1413
1414 PROCEDURE disposePair (p: pair) ;
1415 BEGIN
1416 p^.next := pairFreeList ;
1417 pairFreeList := p
1418 END disposePair ;
1419
1420
1421 (*
1422 deconstructIndex -
1423 *)
1424
1425 PROCEDURE deconstructIndex (pairs: Index) : Index ;
1426 VAR
1427 p : pair ;
1428 i, n: CARDINAL ;
1429 BEGIN
1430 i := 1 ;
1431 n := HighIndice (pairs) ;
1432 WHILE i <= n DO
1433 p := GetIndice (pairs, i) ;
1434 IF p # NIL
1435 THEN
1436 disposePair (p)
1437 END ;
1438 INC (i)
1439 END ;
1440 RETURN KillIndex (pairs)
1441 END deconstructIndex ;
1442
1443
1444 (*
1445 deconstruct - deallocate the List data structure.
1446 *)
1447
1448 PROCEDURE deconstruct (tinfo: tInfo) ;
1449 BEGIN
1450 tinfo^.format := KillString (tinfo^.format) ;
1451 tinfo^.visited := deconstructIndex (tinfo^.visited) ;
1452 tinfo^.resolved := deconstructIndex (tinfo^.resolved) ;
1453 tinfo^.unresolved := deconstructIndex (tinfo^.unresolved)
1454 END deconstruct ;
1455
1456
1457 (*
1458 newtInfo -
1459 *)
1460
1461 PROCEDURE newtInfo () : tInfo ;
1462 VAR
1463 tinfo: tInfo ;
1464 BEGIN
1465 IF tinfoFreeList = NIL
1466 THEN
1467 NEW (tinfo)
1468 ELSE
1469 tinfo := tinfoFreeList ;
1470 tinfoFreeList := tinfoFreeList^.next
1471 END ;
1472 RETURN tinfo
1473 END newtInfo ;
1474
1475
1476 (*
1477 collapseString - if the string, a, is "" then return NIL otherwise create
1478 and return a dynamic string.
1479 *)
1480
1481 PROCEDURE collapseString (a: ARRAY OF CHAR) : String ;
1482 BEGIN
1483 IF StrEqual (a, "")
1484 THEN
1485 RETURN NIL
1486 ELSE
1487 RETURN InitString (a)
1488 END
1489 END collapseString ;
1490
1491
1492 (*
1493 AssignmentTypeCompatible - returns TRUE if the des and the expr are assignment compatible.
1494 *)
1495
1496 PROCEDURE AssignmentTypeCompatible (token: CARDINAL; format: ARRAY OF CHAR;
1497 des, expr: CARDINAL) : BOOLEAN ;
1498 VAR
1499 tinfo: tInfo ;
1500 BEGIN
1501 tinfo := newtInfo () ;
1502 tinfo^.format := collapseString (format) ;
1503 tinfo^.token := token ;
1504 tinfo^.kind := assignment ;
1505 tinfo^.actual := NulSym ;
1506 tinfo^.formal := NulSym ;
1507 tinfo^.procedure := NulSym ;
1508 tinfo^.nth := 0 ;
1509 tinfo^.isvar := FALSE ;
1510 tinfo^.error := NIL ;
1511 tinfo^.left := des ;
1512 tinfo^.right := expr ;
1513 tinfo^.checkFunc := determineCompatible ;
1514 tinfo^.visited := InitIndex (1) ;
1515 tinfo^.resolved := InitIndex (1) ;
1516 tinfo^.unresolved := InitIndex (1) ;
1517 include (tinfo^.unresolved, des, expr, unknown) ;
1518 tinfo^.strict := FALSE ;
1519 tinfo^.isin := FALSE ;
1520 IF doCheck (tinfo)
1521 THEN
1522 deconstruct (tinfo) ;
1523 RETURN TRUE
1524 ELSE
1525 deconstruct (tinfo) ;
1526 RETURN FALSE
1527 END
1528 END AssignmentTypeCompatible ;
1529
1530
1531 (*
1532 ParameterTypeCompatible - returns TRUE if the nth procedure parameter formal
1533 is compatible with actual.
1534 *)
1535
1536 PROCEDURE ParameterTypeCompatible (token: CARDINAL; format: ARRAY OF CHAR;
1537 procedure, formal, actual, nth: CARDINAL;
1538 isvar: BOOLEAN) : BOOLEAN ;
1539 VAR
1540 formalT, actualT: CARDINAL ;
1541 tinfo : tInfo ;
1542 BEGIN
1543 tinfo := newtInfo () ;
1544 formalT := getSType (formal) ;
1545 actualT := getSType (actual) ;
1546 tinfo^.format := collapseString (format) ;
1547 tinfo^.token := token ;
1548 tinfo^.kind := parameter ;
1549 tinfo^.actual := actual ;
1550 tinfo^.formal := formal ;
1551 tinfo^.procedure := procedure ;
1552 tinfo^.nth := nth ;
1553 tinfo^.isvar := isvar ;
1554 tinfo^.error := NIL ;
1555 tinfo^.left := formalT ;
1556 tinfo^.right := actualT ;
1557 tinfo^.checkFunc := determineCompatible ;
1558 tinfo^.visited := InitIndex (1) ;
1559 tinfo^.resolved := InitIndex (1) ;
1560 tinfo^.unresolved := InitIndex (1) ;
1561 tinfo^.strict := FALSE ;
1562 tinfo^.isin := FALSE ;
1563 include (tinfo^.unresolved, actual, formal, unknown) ;
1564 IF doCheck (tinfo)
1565 THEN
1566 deconstruct (tinfo) ;
1567 RETURN TRUE
1568 ELSE
1569 deconstruct (tinfo) ;
1570 RETURN FALSE
1571 END
1572 END ParameterTypeCompatible ;
1573
1574
1575 (*
1576 doExpressionTypeCompatible -
1577 *)
1578
1579 PROCEDURE doExpressionTypeCompatible (token: CARDINAL; format: ARRAY OF CHAR;
1580 left, right: CARDINAL;
1581 strict: BOOLEAN) : BOOLEAN ;
1582 VAR
1583 tinfo: tInfo ;
1584 BEGIN
1585 tinfo := newtInfo () ;
1586 tinfo^.format := collapseString (format) ;
1587 tinfo^.token := token ;
1588 tinfo^.kind := expression ;
1589 tinfo^.actual := NulSym ;
1590 tinfo^.formal := NulSym ;
1591 tinfo^.procedure := NulSym ;
1592 tinfo^.nth := 0 ;
1593 tinfo^.isvar := FALSE ;
1594 tinfo^.error := NIL ;
1595 tinfo^.left := left ;
1596 tinfo^.right := right ;
1597 tinfo^.checkFunc := determineCompatible ;
1598 tinfo^.visited := InitIndex (1) ;
1599 tinfo^.resolved := InitIndex (1) ;
1600 tinfo^.unresolved := InitIndex (1) ;
1601 tinfo^.strict := strict ;
1602 tinfo^.isin := FALSE ;
1603 include (tinfo^.unresolved, left, right, unknown) ;
1604 IF doCheck (tinfo)
1605 THEN
1606 deconstruct (tinfo) ;
1607 RETURN TRUE
1608 ELSE
1609 deconstruct (tinfo) ;
1610 RETURN FALSE
1611 END
1612 END doExpressionTypeCompatible ;
1613
1614
1615 (*
1616 ExpressionTypeCompatible - returns TRUE if the expressions, left and right,
1617 are expression compatible.
1618 *)
1619
1620 PROCEDURE ExpressionTypeCompatible (token: CARDINAL; format: ARRAY OF CHAR;
1621 left, right: CARDINAL;
1622 strict, isin: BOOLEAN) : BOOLEAN ;
1623 BEGIN
1624 IF (left#NulSym) AND (right#NulSym)
1625 THEN
1626 IF isin
1627 THEN
1628 IF IsConst (right) OR IsVar (right)
1629 THEN
1630 right := getSType (right)
1631 END ;
1632 IF IsSet (right)
1633 THEN
1634 right := getSType (right)
1635 END
1636 END
1637 END ;
1638 RETURN doExpressionTypeCompatible (token, format, left, right, strict)
1639 END ExpressionTypeCompatible ;
1640
1641
1642 (*
1643 init - initialise all global data structures for this module.
1644 *)
1645
1646 PROCEDURE init ;
1647 BEGIN
1648 pairFreeList := NIL ;
1649 tinfoFreeList := NIL ;
1650 errors := InitIndex (1)
1651 END init ;
1652
1653
1654 BEGIN
1655 init
1656 END M2Check.