parser-moids-equivalence.c
1 //! @file parser-moids-equivalence.c
2 //! @author J. Marcel van der Veer
3
4 //! @section Copyright
5 //!
6 //! This file is part of Algol68G - an Algol 68 compiler-interpreter.
7 //! Copyright 2001-2024 J. Marcel van der Veer [algol68g@xs4all.nl].
8
9 //! @section License
10 //!
11 //! This program is free software; you can redistribute it and/or modify it
12 //! under the terms of the GNU General Public License as published by the
13 //! Free Software Foundation; either version 3 of the License, or
14 //! (at your option) any later version.
15 //!
16 //! This program is distributed in the hope that it will be useful, but
17 //! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 //! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 //! more details. You should have received a copy of the GNU General Public
20 //! License along with this program. If not, see [http://www.gnu.org/licenses/].
21
22 //! @section Synopsis
23 //!
24 //! Prove equivalence of modes.
25
26 #include "a68g.h"
27 #include "a68g-postulates.h"
28 #include "a68g-parser.h"
29
30 // Routines for establishing equivalence of modes.
31 // After I made this mode equivalencer (in 1993), I found:
32 //
33 // Algol Bulletin 30.3.3 C.H.A. Koster: On infinite modes, 86-89 [1969],
34 //
35 // which essentially concurs with this test on mode equivalence I wrote.
36 // It is elementary logic anyway: prove equivalence, assuming equivalence.
37
38 //! @brief Whether packs are equivalent, same sequence of equivalence modes.
39
40 BOOL_T are_packs_equivalent (PACK_T * s, PACK_T * t)
41 {
42 for (; s != NO_PACK && t != NO_PACK; FORWARD (s), FORWARD (t)) {
43 if (!are_modes_equivalent (MOID (s), MOID (t))) {
44 return A68_FALSE;
45 }
46 if (TEXT (s) != TEXT (t)) {
47 return A68_FALSE;
48 }
49 }
50 return (BOOL_T) (s == NO_PACK && t == NO_PACK);
51 }
52
53 //! @brief Whether packs are subsets.
54
55 BOOL_T is_united_subset (PACK_T * s, PACK_T * t)
56 {
57 // For all modes in 's' there must be an equivalent in 't'.
58 for (PACK_T *p = s; p != NO_PACK; FORWARD (p)) {
59 BOOL_T f = A68_FALSE;
60 for (PACK_T *q = t; q != NO_PACK && !f; FORWARD (q)) {
61 f = are_modes_equivalent (MOID (p), MOID (q));
62 }
63 if (!f) {
64 return A68_FALSE;
65 }
66 }
67 return A68_TRUE;
68 }
69
70 //! @brief Whether packs are subsets.
71
72 BOOL_T are_united_packs_equivalent (PACK_T * s, PACK_T * t)
73 {
74 return is_united_subset (s, t) && is_united_subset (t, s);
75 }
76
77 //! @brief Whether moids a and b are structurally equivalent.
78
79 BOOL_T are_modes_equivalent (MOID_T * a, MOID_T * b)
80 {
81 // Heuristics.
82 if (a == NO_MOID || b == NO_MOID) {
83 // Modes can be NO_MOID in partial argument lists.
84 return A68_FALSE;
85 } else if (a == M_ERROR || b == M_ERROR) {
86 return A68_FALSE;
87 } else if (a == b) {
88 return A68_TRUE;
89 } else if (ATTRIBUTE (a) != ATTRIBUTE (b)) {
90 return A68_FALSE;
91 } else if (DIM (a) != DIM (b)) {
92 return A68_FALSE;
93 } else if (IS (a, STANDARD)) {
94 return (BOOL_T) (a == b);
95 } else if (EQUIVALENT (a) == b || EQUIVALENT (b) == a) {
96 return A68_TRUE;
97 } else if (is_postulated_pair (A68 (top_postulate), a, b) || is_postulated_pair (A68 (top_postulate), b, a)) {
98 return A68_TRUE;
99 } else if (IS (a, INDICANT)) {
100 if (NODE (a) == NO_NODE || NODE (b) == NO_NODE) {
101 return A68_FALSE;
102 } else {
103 return NODE (a) == NODE (b);
104 }
105 }
106 // Investigate structure.
107 // We now know that 'a' and 'b' have same attribute, dimension, ...
108 if (IS (a, REF_SYMBOL)) {
109 // REF MODE
110 return are_modes_equivalent (SUB (a), SUB (b));
111 } else if (IS (a, ROW_SYMBOL)) {
112 // [] MODE
113 return are_modes_equivalent (SUB (a), SUB (b));
114 } else if (IS (a, FLEX_SYMBOL)) {
115 // FLEX [...] MODE
116 return are_modes_equivalent (SUB (a), SUB (b));
117 } else if (IS (a, STRUCT_SYMBOL)) {
118 // STRUCT (...)
119 POSTULATE_T *save = A68 (top_postulate);
120 make_postulate (&A68 (top_postulate), a, b);
121 BOOL_T z = are_packs_equivalent (PACK (a), PACK (b));
122 free_postulate_list (A68 (top_postulate), save);
123 A68 (top_postulate) = save;
124 return z;
125 } else if (IS (a, UNION_SYMBOL)) {
126 // UNION (...)
127 return are_united_packs_equivalent (PACK (a), PACK (b));
128 } else if (IS (a, PROC_SYMBOL) && PACK (a) == NO_PACK && PACK (b) == NO_PACK) {
129 // PROC MOID
130 return are_modes_equivalent (SUB (a), SUB (b));
131 } else if (IS (a, PROC_SYMBOL) && PACK (a) != NO_PACK && PACK (b) != NO_PACK) {
132 // PROC (...) MOID
133 POSTULATE_T *save = A68 (top_postulate);
134 make_postulate (&A68 (top_postulate), a, b);
135 BOOL_T z = are_modes_equivalent (SUB (a), SUB (b));
136 if (z) {
137 z = are_packs_equivalent (PACK (a), PACK (b));
138 }
139 free_postulate_list (A68 (top_postulate), save);
140 A68 (top_postulate) = save;
141 return z;
142 } else if (IS (a, SERIES_MODE) || IS (a, STOWED_MODE)) {
143 // Modes occurring in displays.
144 return are_packs_equivalent (PACK (a), PACK (b));
145 }
146 return A68_FALSE;
147 }
148
149 //! @brief Whether two modes are structurally equivalent.
150
151 BOOL_T prove_moid_equivalence (MOID_T * p, MOID_T * q)
152 {
153 // Prove two modes to be equivalent under assumption that they indeed are.
154 POSTULATE_T *save = A68 (top_postulate);
155 BOOL_T z = are_modes_equivalent (p, q);
156 free_postulate_list (A68 (top_postulate), save);
157 A68 (top_postulate) = save;
158 return z;
159 }
© 2002-2024 J.M. van der Veer (jmvdveer@xs4all.nl)
|