expression.c
1 //! @file expression.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 NEW_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 logical_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 NEW_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 (1401, "mixed mode expression");
137 } else {
138 char *routine = (use_strcasecmp ? "strcasecmp" : "strcmp");
139 if (EQUAL (op, "+") || EQUAL (op, "//")) {
140 int len;
141 if (lhs->mode.len == 0 || rhs->mode.len == 0) {
142 len = MAX_STRLEN;
143 } else {
144 len = lhs->mode.len + rhs->mode.len;
145 }
146 MODE m = {.type = CHARACTER, .len = (len > MAX_STRLEN ? MAX_STRLEN : len)};
147 norm_mode (&m);
148 NEW_RECORD (tmp);
149 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
150 add_local (tmp, CHARACTER, m.len, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
151 _srecordf (lhs->str, "concat (%s, %s, %s)", tmp, lhs->str, rhs->str);
152 lhs->mode = (MODE) {.type = CHARACTER, .len = m.len, .dim = 0};
153 } else if (EQUAL (op, ".eq.") || EQUAL (op, "==")) {
154 _srecordf (lhs->str, "(%s (%s, %s) == 0)", routine, lhs->str, rhs->str);
155 lhs->mode = (MODE) {.type = LOGICAL, .len = 4, .dim = 0};
156 } else if (EQUAL (op, ".ne.") || EQUAL (op, "!=")) {
157 _srecordf (lhs->str, "(%s (%s, %s) != 0)", routine, lhs->str, rhs->str);
158 lhs->mode = (MODE) {.type = LOGICAL, .len = 4, .dim = 0};
159 } else if (EQUAL (op, ".le.") || EQUAL (op, ".lle.") || EQUAL (op, "<=")) {
160 _srecordf (lhs->str, "(%s (%s, %s) <= 0)", routine, lhs->str, rhs->str);
161 lhs->mode = (MODE) {.type = LOGICAL, .len = 4, .dim = 0};
162 } else if (EQUAL (op, ".ge.") || EQUAL (op, ".lge.") || EQUAL (op, ">=")) {
163 _srecordf (lhs->str, "(%s (%s, %s) >= 0)", routine, lhs->str, rhs->str);
164 lhs->mode = (MODE) {.type = LOGICAL, .len = 4, .dim = 0};
165 } else if (EQUAL (op, ".lt.") || EQUAL (op, ".llt.") || EQUAL (op, "<")) {
166 _srecordf (lhs->str, "(%s (%s, %s) < 0)", routine, lhs->str, rhs->str);
167 lhs->mode = (MODE) {.type = LOGICAL, .len = 4, .dim = 0};
168 } else if (EQUAL (op, ".gt.") || EQUAL (op, ".lgt.") || EQUAL (op, ">")) {
169 _srecordf (lhs->str, "(%s (%s, %s) > 0)", routine, lhs->str, rhs->str);
170 lhs->mode = (MODE) {.type = LOGICAL, .len = 4, .dim = 0};
171 } else {
172 OP_ERROR (1402, "undefined operator");
173 }
174 }
175 }
176
177 static void oper_real_32 (EXPR * lhs, EXPR * rhs, char *op)
178 {
179 if (TYPE (lhs, REAL, 32)) {
180 if (TYPE (rhs, REAL, 32)) {
181 /* Ok */;
182 } else if (rhs->mode.type == REAL || rhs->mode.type == INTEGER) {
183 NEW_RECORD (tmp);
184 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
185 add_local (tmp, REAL, 32, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
186 _srecordf (rhs->str, "_quadtop (&%s, %s)", tmp, rhs->str);
187 rhs->mode = (MODE) {.type = REAL, .len = 32, .dim = 0};
188 }
189 } else if (TYPE (rhs, REAL, 32)) {
190 if (TYPE (lhs, REAL, 32)) {
191 /* Ok */;
192 } else if (lhs->mode.type == REAL || lhs->mode.type == INTEGER) {
193 NEW_RECORD (tmp);
194 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
195 add_local (tmp, REAL, 32, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
196 _srecordf (lhs->str, "_quadtop (&%s, %s)", tmp, lhs->str);
197 lhs->mode = (MODE) {.type = REAL, .len = 32, .dim = 0};
198 }
199 }
200 if (lhs->mode.type != rhs->mode.type) {
201 OP_ERROR (1403, "undefined operator");
202 } else if (lhs->mode.len != rhs->mode.len) {
203 OP_ERROR (1404, "undefined operator");
204 } else if (EQUAL (op, "+")) {
205 _srecordf (lhs->str, "xsum (%s, %s)", lhs->str, rhs->str);
206 } else if (EQUAL (op, "-")) {
207 _srecordf (lhs->str, "xsub (%s, %s)", lhs->str, rhs->str);
208 } else if (EQUAL (op, "*")) {
209 _srecordf (lhs->str, "xmul (%s, %s)", lhs->str, rhs->str);
210 } else if (EQUAL (op, "/")) {
211 _srecordf (lhs->str, "xdiv (%s, %s)", lhs->str, rhs->str);
212 } else if (EQUAL (op, ".eq.") || EQUAL (op, "==")) {
213 _srecordf (lhs->str, "xeq (%s, %s)", lhs->str, rhs->str);
214 lhs->mode = (MODE) {.type = LOGICAL,.len = 4,.dim = 0};
215 } else if (EQUAL (op, ".ne.") || EQUAL (op, "!=")) {
216 _srecordf (lhs->str, "xneq (%s, %s)", lhs->str, rhs->str);
217 lhs->mode = (MODE) {.type = LOGICAL,.len = 4,.dim = 0};
218 } else if (EQUAL (op, ".le.") || EQUAL (op, "<=")) {
219 _srecordf (lhs->str, "xle (%s, %s)", lhs->str, rhs->str);
220 lhs->mode = (MODE) {.type = LOGICAL,.len = 4,.dim = 0};
221 } else if (EQUAL (op, ".lt.") || EQUAL (op, "<")) {
222 _srecordf (lhs->str, "xlt (%s, %s)", lhs->str, rhs->str);
223 lhs->mode = (MODE) {.type = LOGICAL,.len = 4,.dim = 0};
224 } else if (EQUAL (op, ".ge.") || EQUAL (op, ">=")) {
225 _srecordf (lhs->str, "xge (%s, %s)", lhs->str, rhs->str);
226 lhs->mode = (MODE) {.type = LOGICAL,.len = 4,.dim = 0};
227 } else if (EQUAL (op, ".gt.") || EQUAL (op, ">")) {
228 _srecordf (lhs->str, "xgt (%s, %s)", lhs->str, rhs->str);
229 lhs->mode = (MODE) {.type = LOGICAL,.len = 4,.dim = 0};
230 } else {
231 OP_ERROR (1405, "undefined operator");
232 }
233 }
234
235 static void oper_complex_64 (EXPR * lhs, EXPR * rhs, char *op)
236 {
237 if (TYPE (lhs, COMPLEX, 64)) {
238 if (TYPE (rhs, COMPLEX, 64)) {
239 /* Ok */;
240 } else if (TYPE (rhs, REAL, 32)) {
241 NEW_RECORD (tmp);
242 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
243 add_local (tmp, COMPLEX, 64, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
244 _srecordf (rhs->str, "_coctotop (&%s, %s)", tmp, rhs->str);
245 rhs->mode = (MODE) {.type = COMPLEX, .len = 64, .dim = 0};
246 } else if (rhs->mode.type == INTEGER || rhs->mode.type == REAL) {
247 NEW_RECORD (tmp);
248 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
249 add_local (tmp, COMPLEX, 64, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
250 _srecordf (rhs->str, "_cquadtop (&%s, %s)", tmp, rhs->str);
251 rhs->mode = (MODE) {.type = COMPLEX, .len = 64, .dim = 0};
252 }
253 } else if (TYPE (rhs, COMPLEX, 64)) {
254 if (TYPE (lhs, REAL, 32)) {
255 NEW_RECORD (tmp);
256 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
257 add_local (tmp, COMPLEX, 64, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
258 _srecordf (lhs->str, "_coctotop (&%s, %s)", tmp, lhs->str);
259 lhs->mode = (MODE) {.type = COMPLEX, .len = 64, .dim = 0};
260 } else if (lhs->mode.type == INTEGER || lhs->mode.type == REAL) {
261 NEW_RECORD (tmp);
262 _srecordf (tmp, "%s", edit_tmp (nloctmps++));
263 add_local (tmp, COMPLEX, 64, UNIQ, NOPATCH, NOARG, LOCAL, TEMP);
264 _srecordf (lhs->str, "_cquadtop (&%s, %s)", tmp, lhs->str);
265 lhs->mode = (MODE) {.type = COMPLEX, .len = 64, .dim = 0};
266 }
267 }
268 if (lhs->mode.type != rhs->mode.type) {
269 OP_ERROR (1406, "undefined operator");
270 } else if (lhs->mode.len != rhs->mode.len) {
271 OP_ERROR (1407, "undefined operator");
272 } else if (EQUAL (op, "+")) {
273 _srecordf (lhs->str, "cxsum (%s, %s)", lhs->str, rhs->str);
274 } else if (EQUAL (op, "-")) {
275 _srecordf (lhs->str, "cxsub (%s, %s)", lhs->str, rhs->str);
276 } else if (EQUAL (op, "*")) {
277 _srecordf (lhs->str, "cxmul (%s, %s)", lhs->str, rhs->str);
278 } else if (EQUAL (op, "/")) {
279 _srecordf (lhs->str, "cxdiv (%s, %s)", lhs->str, rhs->str);
280 } else if (EQUAL (op, ".eq.")) {
281 _srecordf (lhs->str, "cxeq (%s, %s)", lhs->str, rhs->str);
282 } else if (EQUAL (op, ".ne.")) {
283 _srecordf (lhs->str, "cxneq (%s, %s)", lhs->str, rhs->str);
284 } else {
285 OP_ERROR (1408, "undefined operator");
286 }
287 }
288
289 int_4 mix_len (EXPR * lhs, EXPR * rhs)
290 {
291 return _max (lhs->mode.len, rhs->mode.len);
292 }
293
294 void power (EXPR * lhs, EXPR * rhs, char *op)
295 {
296 NEW_RECORD (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 (1409, "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 RECCPY (lhs->str, str);
320 return;
321 } else {
322 NEW_RECORD (proc);
323 if (lhs->mode.type == INTEGER) {
324 if (lhs->mode.len == 4) {
325 RECCPY (proc, "_up_int_4");
326 } else if (lhs->mode.len == 8) {
327 RECCPY (proc, "_up_int_8");
328 }
329 } else if (lhs->mode.type == REAL) {
330 if (lhs->mode.len == 4) {
331 RECCPY (proc, "_up_real_4");
332 } else if (lhs->mode.len == 8) {
333 RECCPY (proc, "_up_real_8");
334 } else if (lhs->mode.len == 16) {
335 RECCPY (proc, "_up_real_16");
336 }
337 } else if (lhs->mode.type == COMPLEX) {
338 if (lhs->mode.len == 8) {
339 RECCPY (proc, "_up_complex_8");
340 } else if (lhs->mode.len == 16) {
341 RECCPY (proc, "_up_complex");
342 } else if (lhs->mode.len == 32) {
343 RECCPY (proc, "_up_complex_32");
344 }
345 } else {
346 OP_ERROR (1410, "not an arithmetic operand");
347 }
348 _srecordf (lhs->str, "%s (%s, %s)", proc, lhs->str, rhs->str);
349 return;
350 }
351 }
352 }
353
354 void oper (EXPR * lhs, EXPR * rhs, char *op)
355 {
356 //
357 if (lhs->mode.type == ETYPE || rhs->mode.type == ETYPE) {
358 lhs->mode.type = ETYPE;
359 return;
360 }
361 //
362 if (EQUAL (op, ".not.") || EQUAL (op, "!")) {
363 _srecordf (lhs->str, "! (%s)", rhs->str);\
364 lhs->mode = (MODE) {.type = LOGICAL, .len = 4, .dim = 0};\
365 return;
366 }
367 //
368 #define MIXED(p, f_op, q, r, c_op) {\
369 if ((lhs->mode.type == (p) && rhs->mode.type == (q)) ||\
370 (lhs->mode.type == (q) && rhs->mode.type == (p))) {\
371 if (EQUAL (op, f_op)) {\
372 _srecordf (lhs->str, "%s %s %s", lhs->str, c_op, rhs->str);\
373 lhs->mode = (MODE) {.type = r, .len = mix_len (lhs, rhs), .dim = 0};\
374 return;\
375 }\
376 }}
377 //
378 #define LOGIC(p, f_op, q, c_op) {\
379 if ((lhs->mode.type == (p) && rhs->mode.type == (q)) ||\
380 (lhs->mode.type == (q) && rhs->mode.type == (p))) {\
381 if (EQUAL (op, f_op)) {\
382 _srecordf (lhs->str, "%s %s %s", lhs->str, c_op, rhs->str);\
383 lhs->mode = (MODE) {.type = LOGICAL, .len = 4, .dim = 0};\
384 return;\
385 }\
386 }}
387 //
388 if (lhs->mode.type == CHARACTER) {
389 oper_char (lhs, rhs, op);
390 } else if ((TYPE (lhs, COMPLEX, 64)) || (TYPE (rhs, COMPLEX, 64))) {
391 oper_complex_64 (lhs, rhs, op);
392 } else if ((TYPE (lhs, REAL, 32)) || (TYPE (rhs, REAL, 32))) {
393 oper_real_32 (lhs, rhs, op);
394 } else if (EQUAL (op, "**")) {
395 power (lhs, rhs, op);
396 } else {
397 MIXED (INTEGER, "+", INTEGER, INTEGER, "+");
398 MIXED (INTEGER, "+", REAL, REAL, "+");
399 MIXED (INTEGER, "+", COMPLEX, COMPLEX, "+");
400 MIXED (INTEGER, "-", INTEGER, INTEGER, "-");
401 MIXED (INTEGER, "-", REAL, REAL, "-");
402 MIXED (INTEGER, "-", COMPLEX, COMPLEX, "-");
403 MIXED (INTEGER, "*", INTEGER, INTEGER, "*");
404 MIXED (INTEGER, "*", REAL, REAL, "*");
405 MIXED (INTEGER, "*", COMPLEX, COMPLEX, "*");
406 MIXED (INTEGER, "/", INTEGER, INTEGER, "/");
407 MIXED (INTEGER, ".mod.", INTEGER, INTEGER, "%");
408 MIXED (INTEGER, "*%", INTEGER, INTEGER, "%");
409 MIXED (INTEGER, "/", REAL, REAL, "/");
410 MIXED (INTEGER, "/", COMPLEX, COMPLEX, "/");
411 MIXED (INTEGER, ".eq.", INTEGER, LOGICAL, "==");
412 MIXED (INTEGER, ".eq.", REAL, LOGICAL, "==");
413 MIXED (INTEGER, ".eq.", COMPLEX, LOGICAL, "==");
414 MIXED (INTEGER, ".ne.", INTEGER, LOGICAL, "!=");
415 MIXED (INTEGER, ".ne.", REAL, LOGICAL, "!=");
416 MIXED (INTEGER, ".ne.", COMPLEX, LOGICAL, "!=");
417 MIXED (INTEGER, ".le.", INTEGER, LOGICAL, "<=");
418 MIXED (INTEGER, ".le.", REAL, LOGICAL, "<=");
419 MIXED (INTEGER, ".ge.", INTEGER, LOGICAL, ">=");
420 MIXED (INTEGER, ".ge.", REAL, LOGICAL, ">=");
421 MIXED (INTEGER, ".lt.", INTEGER, LOGICAL, "<");
422 MIXED (INTEGER, ".lt.", REAL, LOGICAL, "<");
423 MIXED (INTEGER, ".gt.", INTEGER, LOGICAL, ">");
424 MIXED (INTEGER, ".gt.", REAL, LOGICAL, ">");
425 MIXED (INTEGER, "==", INTEGER, LOGICAL, "==");
426 MIXED (INTEGER, "==", REAL, LOGICAL, "==");
427 MIXED (INTEGER, "==", COMPLEX, LOGICAL, "==");
428 MIXED (INTEGER, "!=", INTEGER, LOGICAL, "!=");
429 MIXED (INTEGER, "!=", REAL, LOGICAL, "!=");
430 MIXED (INTEGER, "!=", COMPLEX, LOGICAL, "!=");
431 MIXED (INTEGER, "<=", INTEGER, LOGICAL, "<=");
432 MIXED (INTEGER, "<=", REAL, LOGICAL, "<=");
433 MIXED (INTEGER, ">=", INTEGER, LOGICAL, ">=");
434 MIXED (INTEGER, ">=", REAL, LOGICAL, ">=");
435 MIXED (INTEGER, "<", INTEGER, LOGICAL, "<");
436 MIXED (INTEGER, "<", REAL, LOGICAL, "<");
437 MIXED (INTEGER, ">", INTEGER, LOGICAL, ">");
438 MIXED (INTEGER, ">", REAL, LOGICAL, ">");
439 //
440 MIXED (REAL, "+", REAL, REAL, "+");
441 MIXED (REAL, "+", COMPLEX, COMPLEX, "+");
442 MIXED (REAL, "-", REAL, REAL, "-");
443 MIXED (REAL, "-", COMPLEX, COMPLEX, "-");
444 MIXED (REAL, "*", REAL, REAL, "*");
445 MIXED (REAL, "*", COMPLEX, COMPLEX, "*");
446 MIXED (REAL, "/", REAL, REAL, "/");
447 MIXED (REAL, "/", COMPLEX, COMPLEX, "/");
448 MIXED (REAL, ".eq.", REAL, LOGICAL, "==");
449 MIXED (REAL, ".eq.", COMPLEX, LOGICAL, "==");
450 MIXED (REAL, ".ne.", REAL, LOGICAL, "!=");
451 MIXED (REAL, ".ne.", COMPLEX, LOGICAL, "!=");
452 MIXED (REAL, ".le.", REAL, LOGICAL, "<=");
453 MIXED (REAL, ".ge.", REAL, LOGICAL, ">=");
454 MIXED (REAL, ".lt.", REAL, LOGICAL, "<");
455 MIXED (REAL, ".gt.", REAL, LOGICAL, ">");
456 MIXED (REAL, "==", REAL, LOGICAL, "==");
457 MIXED (REAL, "==", COMPLEX, LOGICAL, "==");
458 MIXED (REAL, "!=", REAL, LOGICAL, "!=");
459 MIXED (REAL, "!=", COMPLEX, LOGICAL, "!=");
460 MIXED (REAL, "<=", REAL, LOGICAL, "<=");
461 MIXED (REAL, ">=", REAL, LOGICAL, ">=");
462 MIXED (REAL, "<", REAL, LOGICAL, "<");
463 MIXED (REAL, ">", REAL, LOGICAL, ">");
464 //
465 MIXED (COMPLEX, "+", COMPLEX, COMPLEX, "+");
466 MIXED (COMPLEX, "-", COMPLEX, COMPLEX, "-");
467 MIXED (COMPLEX, "*", COMPLEX, COMPLEX, "*");
468 MIXED (COMPLEX, "/", COMPLEX, COMPLEX, "/");
469 MIXED (COMPLEX, ".eq.", COMPLEX, LOGICAL, "==");
470 MIXED (COMPLEX, ".ne.", COMPLEX, LOGICAL, "!=");
471 MIXED (COMPLEX, "==", COMPLEX, LOGICAL, "==");
472 MIXED (COMPLEX, "!=", COMPLEX, LOGICAL, "!=");
473 //
474 LOGIC (LOGICAL, "==", LOGICAL, "==");
475 LOGIC (LOGICAL, "!=", LOGICAL, "!=");
476 LOGIC (LOGICAL, ".eq.", LOGICAL, "==");
477 LOGIC (LOGICAL, ".neq.", LOGICAL, "!=");
478 LOGIC (LOGICAL, ".and.", LOGICAL, "&&");
479 LOGIC (LOGICAL, "&", LOGICAL, "&&");
480 LOGIC (LOGICAL, ".or.", LOGICAL, "||");
481 LOGIC (LOGICAL, "|", LOGICAL, "||");
482 LOGIC (LOGICAL, ".xor.", LOGICAL, "^");
483 LOGIC (LOGICAL, "^", LOGICAL, "^");
484 LOGIC (LOGICAL, ".eqv.", LOGICAL, "==");
485 LOGIC (LOGICAL, ".neqv.", LOGICAL, "^");
486 //
487 OP_ERROR (1411, "undefined operator");
488 }
489 #undef MIXED
490 #undef LOGIC
491 }
492
493 int_4 oper_prio (char *op, int_4 prio)
494 {
495 if (TOKEN (")")) {
496 return FALSE;
497 } else if (TOKEN ("=")) {
498 return FALSE;
499 }
500 // According VAX FORTRAN.
501 switch (prio) {
502 case 1: {
503 return TOKEN (".eqv.") || TOKEN (".neqv.") || TOKEN (".xor.") || TOKEN ("^");
504 }
505 case 2: {
506 return TOKEN (".or.") || TOKEN ("|");
507 }
508 case 3: {
509 return TOKEN (".and.") || TOKEN ("&");
510 }
511 case 4: {
512 return TOKEN (".not.") || TOKEN ("!");
513 }
514 case 5: {
515 return TOKEN (".eq.") || TOKEN (".ne.") ||
516 TOKEN (".lt.") || TOKEN (".le.") ||
517 TOKEN (".gt.") || TOKEN (".ge.") ||
518 TOKEN ("==") || TOKEN ("!=") ||
519 TOKEN ("<") || TOKEN ("<=") ||
520 TOKEN (">") || TOKEN (">=");
521 }
522 case 6: {
523 return TOKEN ("+") || TOKEN ("-") || TOKEN ("//");
524 }
525 case 7: {
526 return TOKEN ("*") || TOKEN ("/") || TOKEN (".mod.") || TOKEN ("*%");
527 }
528 case 8: {
529 return TOKEN ("**");
530 }
531 }
532 return FALSE;
533 }
534
535 void exprio (EXPR * reg, int_4 prio, logical_4 no_dim_var)
536 {
537 if (prio == MAX_PRIO) {
538 if (TOKEN (".not.") || TOKEN ("!")) {
539 _srecordf (reg->str, "TRUE");
540 reg->mode = (MODE) {.type = LOGICAL,.len = 4,.dim = 0};
541 reg->variant = EXPR_CONST;
542 UNSCAN;
543 } else {
544 factor (reg);
545 if (no_dim_var && reg->variant == EXPR_VAR) {
546 IDENT *idf = impl_decl (reg->str, NO_MODE);
547 if (idf != NO_IDENT && IS_ROW (idf->mode)) {
548 ERROR (1412, "dimensioned variable cannot be an operand", curlex);
549 }
550 }
551 }
552 } else {
553 int_4 rc;
554 EXPR lhs;
555 memset (&lhs, 0, sizeof (EXPR));
556 //
557 exprio (&lhs, prio + 1, no_dim_var);
558 rc = scan (EXPECT_NONE);
559 while (oper_prio (curlex, prio)) {
560 EXPR rhs;
561 NEW_RECORD (op);
562 memset (&rhs, 0, sizeof (EXPR));
563 RECCPY (op, curlex);
564 rc = scan (EXPECT_NONE);
565 if (prio == MAX_PRIO - 1) {
566 exprio (&rhs, prio, no_dim_var);
567 } else {
568 exprio (&rhs, prio + 1, no_dim_var);
569 }
570 oper (&lhs, &rhs, op);
571 if (lhs.variant == EXPR_CONST && rhs.variant == EXPR_CONST) {
572 ;
573 } else {
574 lhs.variant = EXPR_OTHER;
575 }
576 rc = scan (EXPECT_NONE);
577 }
578 memcpy (reg, &lhs, sizeof (EXPR));
579 UNSCAN;
580 (void) rc;
581 }
582 }
583
584 #undef OP_ERROR
585
586 logical_4 express (EXPR * reg, int_4 expect, int_4 len)
587 {
588 MODE expect_type = (MODE) {.type = expect, .len = len, .dim = 0 };
589 memset (reg, 0, sizeof (EXPR));
590 exprio (reg, 1, FALSE);
591 if (!valid_expr (reg)) {
592 return FALSE;
593 }
594 (void) fold_expr (reg, expect);
595 if (reg->variant == EXPR_CONST && reg->mode.type == INTEGER && expect == INTEGER) {
596 // INTEGER length denotations overlap.
597 factor_integer_number (reg, reg->str);
598 if (reg->mode.len <= len) {
599 reg->mode.len = len;
600 return TRUE;
601 } else {
602 MODE_ERROR (1413, qtype (&(reg->mode)), qtype (&expect_type));
603 return FALSE;
604 }
605 } else if (accept_mode (reg->mode.type, reg->mode.len, expect, len)) {
606 return TRUE;
607 } else {
608 MODE_ERROR (1414, qtype (&(reg->mode)), qtype (&expect_type));
609 return FALSE;
610 }
611 }
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|