expr.c
1 //! @file expr.c
2 //! @author J. Marcel van der Veer
3 //
4 //! @section Copyright
5 //
6 // This file is part of VIF - vintage FORTRAN compiler.
7 // Copyright 2020-2025 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 //! Compile Fortran expressions.
25
26 #include <vif.h>
27
28 int_4 lhs_factor;
29
30 #define OP_ERROR(num, s) {\
31 RECORD _str_;\
32 _srecordf (_str_, "%s %s %s",\
33 qtype (&lhs->mode), op, qtype (&rhs->mode));\
34 ERROR ((num), (s), _str_);\
35 return;\
36 }
37
38 int_4 valid_expr (EXPR *reg)
39 {
40 if (strlen (reg->str) == 0) {
41 return FALSE;
42 }
43 if (reg->mode.type == ETYPE) {
44 return FALSE;
45 }
46 return TRUE;
47 }
48
49 char *const_1 (MODE * m)
50 {
51 if (m->type == INTEGER) {
52 return "1";
53 } else if (m->type == REAL) {
54 if (m->len == 8) {
55 return "1.0";
56 } else if (m->len == 16) {
57 return "1.0q";
58 }
59 } else if (m->type == COMPLEX) {
60 if (m->len == 16) {
61 return "1.0";
62 } else if (m->len == 32) {
63 return "1.0q";
64 }
65 }
66 return "1";
67 }
68
69 int_4 optimise_exp (char *str, EXPR * lhs, EXPR * rhs)
70 {
71 RECORD tmp;
72 if (lhs->mode.type == INTEGER && lhs->variant == EXPR_CONST && rhs->mode.type == INTEGER && rhs->variant == EXPR_CONST) {
73 int_4 a, n;
74 sscanf (lhs->str, "%d", &a);
75 sscanf (rhs->str, "%d", &n);
76 _srecordf (str, "%d", _up_int_4 (a, n));
77 return TRUE;
78 }
79 int_4 simple = lhs->variant != EXPR_OTHER;
80 if (EQUAL (rhs->str, "2")) {
81 if (simple) {
82 _srecordf (str, "(%s * %s)", lhs->str, lhs->str);
83 } else {
84 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
85 add_local (tmp, lhs->mode.type, lhs->mode.len, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
86 _srecordf (str, "(%s = %s, %s * %s)", tmp, lhs->str, tmp, tmp);
87 }
88 return TRUE;
89 } else if (simple && EQUAL (rhs->str, "-2")) {
90 _srecordf (str, "%s / (%s * %s)", const_1 (&lhs->mode), lhs->str, lhs->str);
91 return TRUE;
92 } else if (simple && EQUAL (rhs->str, "3")) {
93 _srecordf (str, "(%s * %s * %s)", lhs->str, lhs->str, lhs->str);
94 return TRUE;
95 } else if (simple && EQUAL (rhs->str, "-3")) {
96 _srecordf (str, "%s / (%s * %s * %s)", const_1 (&lhs->mode), lhs->str, lhs->str, lhs->str);
97 return TRUE;
98 } else if (simple && EQUAL (rhs->str, "4")) {
99 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
100 add_local (tmp, lhs->mode.type, lhs->mode.len, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
101 _srecordf (str, "(%s = %s * %s, %s * %s)", tmp, lhs->str, lhs->str, tmp, tmp);
102 return TRUE;
103 } else if (simple && EQUAL (rhs->str, "-4")) {
104 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
105 add_local (tmp, lhs->mode.type, lhs->mode.len, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
106 _srecordf (str, "(%s = %s * %s, %s / (%s * %s))", tmp, lhs->str, lhs->str, const_1 (&lhs->mode), tmp, tmp);
107 return TRUE;
108 } else if (simple && EQUAL (rhs->str, "5")) {
109 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
110 add_local (tmp, lhs->mode.type, lhs->mode.len, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
111 _srecordf (str, "(%s = %s * %s, %s * %s * %s)", tmp, lhs->str, lhs->str, lhs->str, tmp, tmp);
112 return TRUE;
113 } else if (simple && EQUAL (rhs->str, "-5")) {
114 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
115 add_local (tmp, lhs->mode.type, lhs->mode.len, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
116 _srecordf (str, "(%s = %s * %s, %s / (%s * %s * %s))", tmp, lhs->str, lhs->str, const_1 (&lhs->mode), lhs->str, tmp, tmp);
117 return TRUE;
118 } else if (simple && EQUAL (rhs->str, "6")) {
119 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
120 add_local (tmp, lhs->mode.type, lhs->mode.len, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
121 _srecordf (str, "(%s = %s * %s, %s * %s * %s)", tmp, lhs->str, lhs->str, tmp, tmp, tmp);
122 return TRUE;
123 } else if (simple && EQUAL (rhs->str, "-6")) {
124 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
125 add_local (tmp, lhs->mode.type, lhs->mode.len, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
126 _srecordf (str, "(%s = %s * %s, %s / (%s * %s * %s))", tmp, lhs->str, lhs->str, const_1 (&lhs->mode), tmp, tmp, tmp);
127 return TRUE;
128 } else {
129 return FALSE;
130 }
131 }
132
133 static void oper_char (EXPR * lhs, EXPR * rhs, char *op)
134 {
135 if (lhs->mode.type != rhs->mode.type) {
136 OP_ERROR (1301, "mixed mode expression");
137 } else {
138 if (EQUAL (op, "+") || EQUAL (op, "//")) {
139 int len;
140 if (lhs->mode.len == 0 || rhs->mode.len == 0) {
141 len = MAX_STRLEN;
142 } else {
143 len = lhs->mode.len + rhs->mode.len;
144 }
145 MODE m = {.type = CHARACTER, .len = (len > MAX_STRLEN ? MAX_STRLEN : len)};
146 norm_mode (&m);
147 RECORD tmp;
148 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
149 add_local (tmp, CHARACTER, m.len, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
150 _srecordf (lhs->str, "concat (%s, %s, %s)", tmp, lhs->str, rhs->str);
151 lhs->mode = (MODE) {.type = CHARACTER, .len = m.len, .dim = 0};
152 } else if (EQUAL (op, ".eq.") || EQUAL (op, "==")) {
153 _srecordf (lhs->str, "(strcmp (%s, %s) == 0)", lhs->str, rhs->str);
154 lhs->mode = (MODE) {.type = LOGICAL, .len = 4, .dim = 0};
155 } else if (EQUAL (op, ".ne.") || EQUAL (op, "!=")) {
156 _srecordf (lhs->str, "(strcmp (%s, %s) != 0)", lhs->str, rhs->str);
157 lhs->mode = (MODE) {.type = LOGICAL, .len = 4, .dim = 0};
158 } else if (EQUAL (op, ".le.") || EQUAL (op, ".lle.") || EQUAL (op, "<=")) {
159 _srecordf (lhs->str, "(strcmp (%s, %s) <= 0)", lhs->str, rhs->str);
160 lhs->mode = (MODE) {.type = LOGICAL, .len = 4, .dim = 0};
161 } else if (EQUAL (op, ".ge.") || EQUAL (op, ".lge.") || EQUAL (op, ">=")) {
162 _srecordf (lhs->str, "(strcmp (%s, %s) >= 0)", lhs->str, rhs->str);
163 lhs->mode = (MODE) {.type = LOGICAL, .len = 4, .dim = 0};
164 } else if (EQUAL (op, ".lt.") || EQUAL (op, ".llt.") || EQUAL (op, "<")) {
165 _srecordf (lhs->str, "(strcmp (%s, %s) < 0)", lhs->str, rhs->str);
166 lhs->mode = (MODE) {.type = LOGICAL, .len = 4, .dim = 0};
167 } else if (EQUAL (op, ".gt.") || EQUAL (op, ".lgt.") || EQUAL (op, ">")) {
168 _srecordf (lhs->str, "(strcmp (%s, %s) > 0)", lhs->str, rhs->str);
169 lhs->mode = (MODE) {.type = LOGICAL, .len = 4, .dim = 0};
170 } else {
171 OP_ERROR (1302, "undefined operator");
172 }
173 }
174 }
175
176 static void oper_real_32 (EXPR * lhs, EXPR * rhs, char *op)
177 {
178 if (TYPE (lhs, REAL, 32)) {
179 if (TYPE (rhs, REAL, 32)) {
180 /* Ok */;
181 } else if (rhs->mode.type == REAL || rhs->mode.type == INTEGER) {
182 RECORD tmp;
183 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
184 add_local (tmp, REAL, 32, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
185 _srecordf (rhs->str, "_quadtop (&%s, %s)", tmp, rhs->str);
186 rhs->mode = (MODE) {.type = REAL, .len = 32, .dim = 0};
187 }
188 } else if (TYPE (rhs, REAL, 32)) {
189 if (TYPE (lhs, REAL, 32)) {
190 /* Ok */;
191 } else if (lhs->mode.type == REAL || lhs->mode.type == INTEGER) {
192 RECORD tmp;
193 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
194 add_local (tmp, REAL, 32, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
195 _srecordf (lhs->str, "_quadtop (&%s, %s)", tmp, lhs->str);
196 lhs->mode = (MODE) {.type = REAL, .len = 32, .dim = 0};
197 }
198 }
199 if (lhs->mode.type != rhs->mode.type) {
200 OP_ERROR (1303, "undefined operator");
201 } else if (lhs->mode.len != rhs->mode.len) {
202 OP_ERROR (1304, "undefined operator");
203 } else if (EQUAL (op, "+")) {
204 _srecordf (lhs->str, "xsum (%s, %s)", lhs->str, rhs->str);
205 } else if (EQUAL (op, "-")) {
206 _srecordf (lhs->str, "xsub (%s, %s)", lhs->str, rhs->str);
207 } else if (EQUAL (op, "*")) {
208 _srecordf (lhs->str, "xmul (%s, %s)", lhs->str, rhs->str);
209 } else if (EQUAL (op, "/")) {
210 _srecordf (lhs->str, "xdiv (%s, %s)", lhs->str, rhs->str);
211 } else if (EQUAL (op, ".eq.") || EQUAL (op, "==")) {
212 _srecordf (lhs->str, "xeq (%s, %s)", lhs->str, rhs->str);
213 lhs->mode = (MODE) {.type = LOGICAL,.len = 4,.dim = 0};
214 } else if (EQUAL (op, ".ne.") || EQUAL (op, "!=")) {
215 _srecordf (lhs->str, "xneq (%s, %s)", lhs->str, rhs->str);
216 lhs->mode = (MODE) {.type = LOGICAL,.len = 4,.dim = 0};
217 } else if (EQUAL (op, ".le.") || EQUAL (op, "<=")) {
218 _srecordf (lhs->str, "xle (%s, %s)", lhs->str, rhs->str);
219 lhs->mode = (MODE) {.type = LOGICAL,.len = 4,.dim = 0};
220 } else if (EQUAL (op, ".lt.") || EQUAL (op, "<")) {
221 _srecordf (lhs->str, "xlt (%s, %s)", lhs->str, rhs->str);
222 lhs->mode = (MODE) {.type = LOGICAL,.len = 4,.dim = 0};
223 } else if (EQUAL (op, ".ge.") || EQUAL (op, ">=")) {
224 _srecordf (lhs->str, "xge (%s, %s)", lhs->str, rhs->str);
225 lhs->mode = (MODE) {.type = LOGICAL,.len = 4,.dim = 0};
226 } else if (EQUAL (op, ".gt.") || EQUAL (op, ">")) {
227 _srecordf (lhs->str, "xgt (%s, %s)", lhs->str, rhs->str);
228 lhs->mode = (MODE) {.type = LOGICAL,.len = 4,.dim = 0};
229 } else {
230 OP_ERROR (1305, "undefined operator");
231 }
232 }
233
234 static void oper_complex_64 (EXPR * lhs, EXPR * rhs, char *op)
235 {
236 if (TYPE (lhs, COMPLEX, 64)) {
237 if (TYPE (rhs, COMPLEX, 64)) {
238 /* Ok */;
239 } else if (TYPE (rhs, REAL, 32)) {
240 RECORD tmp;
241 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
242 add_local (tmp, COMPLEX, 64, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
243 _srecordf (rhs->str, "_coctotop (&%s, %s)", tmp, rhs->str);
244 rhs->mode = (MODE) {.type = COMPLEX, .len = 64, .dim = 0};
245 } else if (rhs->mode.type == INTEGER || rhs->mode.type == REAL) {
246 RECORD tmp;
247 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
248 add_local (tmp, COMPLEX, 64, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
249 _srecordf (rhs->str, "_cquadtop (&%s, %s)", tmp, rhs->str);
250 rhs->mode = (MODE) {.type = COMPLEX, .len = 64, .dim = 0};
251 }
252 } else if (TYPE (rhs, COMPLEX, 64)) {
253 if (TYPE (lhs, REAL, 32)) {
254 RECORD tmp;
255 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
256 add_local (tmp, COMPLEX, 64, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
257 _srecordf (lhs->str, "_coctotop (&%s, %s)", tmp, lhs->str);
258 lhs->mode = (MODE) {.type = COMPLEX, .len = 64, .dim = 0};
259 } else if (lhs->mode.type == INTEGER || lhs->mode.type == REAL) {
260 RECORD tmp;
261 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
262 add_local (tmp, COMPLEX, 64, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
263 _srecordf (lhs->str, "_cquadtop (&%s, %s)", tmp, lhs->str);
264 lhs->mode = (MODE) {.type = COMPLEX, .len = 64, .dim = 0};
265 }
266 }
267 if (lhs->mode.type != rhs->mode.type) {
268 OP_ERROR (1306, "undefined operator");
269 } else if (lhs->mode.len != rhs->mode.len) {
270 OP_ERROR (1307, "undefined operator");
271 } else if (EQUAL (op, "+")) {
272 _srecordf (lhs->str, "cxsum (%s, %s)", lhs->str, rhs->str);
273 } else if (EQUAL (op, "-")) {
274 _srecordf (lhs->str, "cxsub (%s, %s)", lhs->str, rhs->str);
275 } else if (EQUAL (op, "*")) {
276 _srecordf (lhs->str, "cxmul (%s, %s)", lhs->str, rhs->str);
277 } else if (EQUAL (op, "/")) {
278 _srecordf (lhs->str, "cxdiv (%s, %s)", lhs->str, rhs->str);
279 } else if (EQUAL (op, ".eq.")) {
280 _srecordf (lhs->str, "cxeq (%s, %s)", lhs->str, rhs->str);
281 } else if (EQUAL (op, ".ne.")) {
282 _srecordf (lhs->str, "cxneq (%s, %s)", lhs->str, rhs->str);
283 } else {
284 OP_ERROR (1308, "undefined operator");
285 }
286 }
287
288 int_4 mix_len (EXPR * lhs, EXPR * rhs)
289 {
290 return _max (lhs->mode.len, rhs->mode.len);
291 }
292
293 void power (EXPR * lhs, EXPR * rhs, char *op)
294 {
295 RECORD str;
296 RECCLR (str);
297 if (rhs->mode.type != INTEGER) {
298 if (TYPE (lhs, REAL, 4) && TYPE (rhs, REAL, 4)) {
299 _srecordf (lhs->str, "powl (%s, %s)", lhs->str, rhs->str);
300 } else if (TYPE (lhs, REAL, 4) && TYPE (rhs, REAL, 8)) {
301 _srecordf (lhs->str, "powl (%s, (real_4) %s)", lhs->str, rhs->str);
302 } else if (TYPE (lhs, REAL, 8) && TYPE (rhs, REAL, 8)) {
303 _srecordf (lhs->str, "pow (%s, %s)", lhs->str, rhs->str);
304 } else if (TYPE (lhs, REAL, 8) && TYPE (rhs, REAL, 4)) {
305 _srecordf (lhs->str, "pow (%s, (real_8) %s)", lhs->str, rhs->str);
306 } else if (TYPE (lhs, REAL, 16) && TYPE (rhs, REAL, 16)) {
307 _srecordf (lhs->str, "powq (%s, %s)", lhs->str, rhs->str);
308 } else if (TYPE (lhs, REAL, 32) && TYPE (rhs, REAL, 32)) {
309 _srecordf (lhs->str, "xpow (%s, %s)", lhs->str, rhs->str);
310 } else {
311 OP_ERROR (1309, "undefined operator");
312 }
313 } else if (TYPE (lhs, COMPLEX, 64)) {
314 _srecordf (lhs->str, "cxpwr (%s, %s)", lhs->str, rhs->str);
315 } else if (TYPE (lhs, REAL, 32)) {
316 _srecordf (lhs->str, "xpwr (%s, %s)", lhs->str, rhs->str);
317 } else {
318 if (optimise_exp (str, lhs, rhs)) {
319 strcpy (lhs->str, str);
320 return;
321 } else {
322 RECORD proc;
323 RECCLR (proc);
324 if (lhs->mode.type == INTEGER) {
325 if (lhs->mode.len == 4) {
326 strcpy (proc, "_up_int_4");
327 } else if (lhs->mode.len == 8) {
328 strcpy (proc, "_up_int_8");
329 }
330 } else if (lhs->mode.type == REAL) {
331 if (lhs->mode.len == 4) {
332 strcpy (proc, "_up_real_4");
333 } else if (lhs->mode.len == 8) {
334 strcpy (proc, "_up_real_8");
335 } else if (lhs->mode.len == 16) {
336 strcpy (proc, "_up_real_16");
337 }
338 } else if (lhs->mode.type == COMPLEX) {
339 if (lhs->mode.len == 8) {
340 strcpy (proc, "_up_complex_8");
341 } else if (lhs->mode.len == 16) {
342 strcpy (proc, "_up_complex");
343 } else if (lhs->mode.len == 32) {
344 strcpy (proc, "_up_complex_32");
345 }
346 } else {
347 OP_ERROR (1310, "not an arithmetic operand");
348 }
349 _srecordf (lhs->str, "%s (%s, %s)", proc, lhs->str, rhs->str);
350 return;
351 }
352 }
353 }
354
355 void oper (EXPR * lhs, EXPR * rhs, char *op)
356 {
357 //
358 if (lhs->mode.type == ETYPE || rhs->mode.type == ETYPE) {
359 lhs->mode.type = ETYPE;
360 return;
361 }
362 //
363 if (EQUAL (op, ".not.") || EQUAL (op, "!")) {
364 _srecordf (lhs->str, "! (%s)", rhs->str);\
365 lhs->mode = (MODE) {.type = LOGICAL, .len = 4, .dim = 0};\
366 return;
367 }
368 //
369 #define MIXED(p, f_op, q, r, c_op) {\
370 if ((lhs->mode.type == (p) && rhs->mode.type == (q)) ||\
371 (lhs->mode.type == (q) && rhs->mode.type == (p))) {\
372 if (EQUAL (op, f_op)) {\
373 _srecordf (lhs->str, "%s %s %s", lhs->str, c_op, rhs->str);\
374 lhs->mode = (MODE) {.type = r, .len = mix_len (lhs, rhs), .dim = 0};\
375 return;\
376 }\
377 }}
378 //
379 #define LOGIC(p, f_op, q, c_op) {\
380 if ((lhs->mode.type == (p) && rhs->mode.type == (q)) ||\
381 (lhs->mode.type == (q) && rhs->mode.type == (p))) {\
382 if (EQUAL (op, f_op)) {\
383 _srecordf (lhs->str, "%s %s %s", lhs->str, c_op, rhs->str);\
384 lhs->mode = (MODE) {.type = LOGICAL, .len = 4, .dim = 0};\
385 return;\
386 }\
387 }}
388 //
389 if (lhs->mode.type == CHARACTER) {
390 oper_char (lhs, rhs, op);
391 } else if ((TYPE (lhs, COMPLEX, 64)) || (TYPE (rhs, COMPLEX, 64))) {
392 oper_complex_64 (lhs, rhs, op);
393 } else if ((TYPE (lhs, REAL, 32)) || (TYPE (rhs, REAL, 32))) {
394 oper_real_32 (lhs, rhs, op);
395 } else if (EQUAL (op, "**")) {
396 power (lhs, rhs, op);
397 } else {
398 MIXED (INTEGER, "+", INTEGER, INTEGER, "+");
399 MIXED (INTEGER, "+", REAL, REAL, "+");
400 MIXED (INTEGER, "+", COMPLEX, COMPLEX, "+");
401 MIXED (INTEGER, "-", INTEGER, INTEGER, "-");
402 MIXED (INTEGER, "-", REAL, REAL, "-");
403 MIXED (INTEGER, "-", COMPLEX, COMPLEX, "-");
404 MIXED (INTEGER, "*", INTEGER, INTEGER, "*");
405 MIXED (INTEGER, "*", REAL, REAL, "*");
406 MIXED (INTEGER, "*", COMPLEX, COMPLEX, "*");
407 MIXED (INTEGER, "/", INTEGER, INTEGER, "/");
408 MIXED (INTEGER, ".mod.", INTEGER, INTEGER, "%");
409 MIXED (INTEGER, "*%", INTEGER, INTEGER, "%");
410 MIXED (INTEGER, "/", REAL, REAL, "/");
411 MIXED (INTEGER, "/", COMPLEX, COMPLEX, "/");
412 MIXED (INTEGER, ".eq.", INTEGER, LOGICAL, "==");
413 MIXED (INTEGER, ".eq.", REAL, LOGICAL, "==");
414 MIXED (INTEGER, ".eq.", COMPLEX, LOGICAL, "==");
415 MIXED (INTEGER, ".ne.", INTEGER, LOGICAL, "!=");
416 MIXED (INTEGER, ".ne.", REAL, LOGICAL, "!=");
417 MIXED (INTEGER, ".ne.", COMPLEX, LOGICAL, "!=");
418 MIXED (INTEGER, ".le.", INTEGER, LOGICAL, "<=");
419 MIXED (INTEGER, ".le.", REAL, LOGICAL, "<=");
420 MIXED (INTEGER, ".ge.", INTEGER, LOGICAL, ">=");
421 MIXED (INTEGER, ".ge.", REAL, LOGICAL, ">=");
422 MIXED (INTEGER, ".lt.", INTEGER, LOGICAL, "<");
423 MIXED (INTEGER, ".lt.", REAL, LOGICAL, "<");
424 MIXED (INTEGER, ".gt.", INTEGER, LOGICAL, ">");
425 MIXED (INTEGER, ".gt.", REAL, LOGICAL, ">");
426 MIXED (INTEGER, "==", INTEGER, LOGICAL, "==");
427 MIXED (INTEGER, "==", REAL, LOGICAL, "==");
428 MIXED (INTEGER, "==", COMPLEX, LOGICAL, "==");
429 MIXED (INTEGER, "!=", INTEGER, LOGICAL, "!=");
430 MIXED (INTEGER, "!=", REAL, LOGICAL, "!=");
431 MIXED (INTEGER, "!=", COMPLEX, LOGICAL, "!=");
432 MIXED (INTEGER, "<=", INTEGER, LOGICAL, "<=");
433 MIXED (INTEGER, "<=", REAL, LOGICAL, "<=");
434 MIXED (INTEGER, ">=", INTEGER, LOGICAL, ">=");
435 MIXED (INTEGER, ">=", REAL, LOGICAL, ">=");
436 MIXED (INTEGER, "<", INTEGER, LOGICAL, "<");
437 MIXED (INTEGER, "<", REAL, LOGICAL, "<");
438 MIXED (INTEGER, ">", INTEGER, LOGICAL, ">");
439 MIXED (INTEGER, ">", REAL, LOGICAL, ">");
440 //
441 MIXED (REAL, "+", REAL, REAL, "+");
442 MIXED (REAL, "+", COMPLEX, COMPLEX, "+");
443 MIXED (REAL, "-", REAL, REAL, "-");
444 MIXED (REAL, "-", COMPLEX, COMPLEX, "-");
445 MIXED (REAL, "*", REAL, REAL, "*");
446 MIXED (REAL, "*", COMPLEX, COMPLEX, "*");
447 MIXED (REAL, "/", REAL, REAL, "/");
448 MIXED (REAL, "/", COMPLEX, COMPLEX, "/");
449 MIXED (REAL, ".eq.", REAL, LOGICAL, "==");
450 MIXED (REAL, ".eq.", COMPLEX, LOGICAL, "==");
451 MIXED (REAL, ".ne.", REAL, LOGICAL, "!=");
452 MIXED (REAL, ".ne.", COMPLEX, LOGICAL, "!=");
453 MIXED (REAL, ".le.", REAL, LOGICAL, "<=");
454 MIXED (REAL, ".ge.", REAL, LOGICAL, ">=");
455 MIXED (REAL, ".lt.", REAL, LOGICAL, "<");
456 MIXED (REAL, ".gt.", REAL, LOGICAL, ">");
457 MIXED (REAL, "==", REAL, LOGICAL, "==");
458 MIXED (REAL, "==", COMPLEX, LOGICAL, "==");
459 MIXED (REAL, "!=", REAL, LOGICAL, "!=");
460 MIXED (REAL, "!=", COMPLEX, LOGICAL, "!=");
461 MIXED (REAL, "<=", REAL, LOGICAL, "<=");
462 MIXED (REAL, ">=", REAL, LOGICAL, ">=");
463 MIXED (REAL, "<", REAL, LOGICAL, "<");
464 MIXED (REAL, ">", REAL, LOGICAL, ">");
465 //
466 MIXED (COMPLEX, "+", COMPLEX, COMPLEX, "+");
467 MIXED (COMPLEX, "-", COMPLEX, COMPLEX, "-");
468 MIXED (COMPLEX, "*", COMPLEX, COMPLEX, "*");
469 MIXED (COMPLEX, "/", COMPLEX, COMPLEX, "/");
470 MIXED (COMPLEX, ".eq.", COMPLEX, LOGICAL, "==");
471 MIXED (COMPLEX, ".ne.", COMPLEX, LOGICAL, "!=");
472 MIXED (COMPLEX, "==", COMPLEX, LOGICAL, "==");
473 MIXED (COMPLEX, "!=", COMPLEX, LOGICAL, "!=");
474 //
475 LOGIC (LOGICAL, "==", LOGICAL, "==");
476 LOGIC (LOGICAL, "!=", LOGICAL, "!=");
477 LOGIC (LOGICAL, ".eq.", LOGICAL, "==");
478 LOGIC (LOGICAL, ".neq.", LOGICAL, "!=");
479 LOGIC (LOGICAL, ".and.", LOGICAL, "&&");
480 LOGIC (LOGICAL, "&", LOGICAL, "&&");
481 LOGIC (LOGICAL, ".or.", LOGICAL, "||");
482 LOGIC (LOGICAL, "|", LOGICAL, "||");
483 LOGIC (LOGICAL, ".xor.", LOGICAL, "^");
484 LOGIC (LOGICAL, "^", LOGICAL, "^");
485 LOGIC (LOGICAL, ".eqv.", LOGICAL, "==");
486 LOGIC (LOGICAL, ".neqv.", LOGICAL, "^");
487 //
488 OP_ERROR (1311, "undefined operator");
489 }
490 #undef MIXED
491 #undef LOGIC
492 }
493
494 int_4 oper_prio (char *op, int_4 prio)
495 {
496 if (TOKEN (")")) {
497 return FALSE;
498 } else if (TOKEN ("=")) {
499 return FALSE;
500 }
501 // According VAX FORTRAN.
502 switch (prio) {
503 case 1: {
504 return TOKEN (".eqv.") || TOKEN (".neqv.") || TOKEN (".xor.") || TOKEN ("^");
505 }
506 case 2: {
507 return TOKEN (".or.") || TOKEN ("|");
508 }
509 case 3: {
510 return TOKEN (".and.") || TOKEN ("&");
511 }
512 case 4: {
513 return TOKEN (".not.") || TOKEN ("!");
514 }
515 case 5: {
516 return TOKEN (".eq.") || TOKEN (".ne.") ||
517 TOKEN (".lt.") || TOKEN (".le.") ||
518 TOKEN (".gt.") || TOKEN (".ge.") ||
519 TOKEN ("==") || TOKEN ("!=") ||
520 TOKEN ("<") || TOKEN ("<=") ||
521 TOKEN (">") || TOKEN (">=");
522 }
523 case 6: {
524 return TOKEN ("+") || TOKEN ("-") || TOKEN ("//");
525 }
526 case 7: {
527 return TOKEN ("*") || TOKEN ("/") || TOKEN (".mod.") || TOKEN ("*%");
528 }
529 case 8: {
530 return TOKEN ("**");
531 }
532 }
533 return FALSE;
534 }
535
536 void exprio (EXPR * reg, int_4 prio, logical_4 no_dim_var)
537 {
538 if (prio == MAX_PRIO) {
539 if (TOKEN (".not.") || TOKEN ("!")) {
540 _srecordf (reg->str, "TRUE");
541 reg->mode = (MODE) {.type = LOGICAL,.len = 4,.dim = 0};
542 reg->variant = EXPR_CONST;
543 UNSCAN;
544 } else {
545 factor (reg);
546 if (no_dim_var && reg->variant == EXPR_VAR) {
547 IDENT *idf = impl_decl (reg->str, NO_MODE);
548 if (idf != NO_IDENT && IS_ROW (idf->mode)) {
549 ERROR (1312, "dimensioned variable cannot be an operand", curlex);
550 }
551 }
552 }
553 } else {
554 int_4 rc;
555 EXPR lhs;
556 memset (&lhs, 0, sizeof (EXPR));
557 //
558 exprio (&lhs, prio + 1, no_dim_var);
559 rc = scan (EXPECT_NONE);
560 while (oper_prio (curlex, prio)) {
561 RECORD op;
562 EXPR rhs;
563 RECCLR (op);
564 memset (&rhs, 0, sizeof (EXPR));
565 strcpy (op, curlex);
566 rc = scan (EXPECT_NONE);
567 if (prio == MAX_PRIO - 1) {
568 exprio (&rhs, prio, no_dim_var);
569 } else {
570 exprio (&rhs, prio + 1, no_dim_var);
571 }
572 oper (&lhs, &rhs, op);
573 if (lhs.variant == EXPR_CONST && rhs.variant == EXPR_CONST) {
574 ;
575 } else {
576 lhs.variant = EXPR_OTHER;
577 }
578 rc = scan (EXPECT_NONE);
579 }
580 memcpy (reg, &lhs, sizeof (EXPR));
581 UNSCAN;
582 (void) rc;
583 }
584 }
585
586 #undef OP_ERROR
587
588 int_4 express (EXPR * reg, int_4 expect, int_4 len)
589 {
590 MODE expect_type = (MODE) {.type = expect, .len = len, .dim = 0 };
591 memset (reg, 0, sizeof (EXPR));
592 exprio (reg, 1, FALSE);
593 if (!valid_expr (reg)) {
594 return FALSE;
595 }
596 (void) fold_expr (reg, expect);
597 if (reg->variant == EXPR_CONST && reg->mode.type == INTEGER && expect == INTEGER) {
598 // INTEGER length denotations overlap.
599 factor_integer_number (reg, reg->str);
600 if (reg->mode.len <= len) {
601 reg->mode.len = len;
602 return TRUE;
603 } else {
604 MODE_ERROR (1313, qtype (&(reg->mode)), qtype (&expect_type));
605 return FALSE;
606 }
607 } else if (accept_mode (reg->mode.type, reg->mode.len, expect, len)) {
608 return TRUE;
609 } else {
610 MODE_ERROR (1314, qtype (&(reg->mode)), qtype (&expect_type));
611 return FALSE;
612 }
613 }
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|