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-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 //! 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 if (lhs->mode.type == INTEGER) {
324 if (lhs->mode.len == 4) {
325 strcpy (proc, "_up_int_4");
326 } else if (lhs->mode.len == 8) {
327 strcpy (proc, "_up_int_8");
328 }
329 } else if (lhs->mode.type == REAL) {
330 if (lhs->mode.len == 4) {
331 strcpy (proc, "_up_real_4");
332 } else if (lhs->mode.len == 8) {
333 strcpy (proc, "_up_real_8");
334 } else if (lhs->mode.len == 16) {
335 strcpy (proc, "_up_real_16");
336 }
337 } else if (lhs->mode.type == COMPLEX) {
338 if (lhs->mode.len == 8) {
339 strcpy (proc, "_up_complex_8");
340 } else if (lhs->mode.len == 16) {
341 strcpy (proc, "_up_complex");
342 } else if (lhs->mode.len == 32) {
343 strcpy (proc, "_up_complex_32");
344 }
345 } else {
346 OP_ERROR (1310, "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 (1311, "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, NULL);
547 if (idf != NULL && idf->mode.dim != 0) {
548 ERROR (1312, "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 (NULL);
559 while (oper_prio (curlex, prio)) {
560 RECORD op;
561 EXPR rhs;
562 RECCLR (op);
563 memset (&rhs, 0, sizeof (EXPR));
564 strcpy (op, curlex);
565 rc = scan (NULL);
566 if (prio == MAX_PRIO - 1) {
567 exprio (&rhs, prio, no_dim_var);
568 } else {
569 exprio (&rhs, prio + 1, no_dim_var);
570 }
571 oper (&lhs, &rhs, op);
572 if (lhs.variant == EXPR_CONST && rhs.variant == EXPR_CONST) {
573 ;
574 } else {
575 lhs.variant = EXPR_OTHER;
576 }
577 rc = scan (NULL);
578 }
579 memcpy (reg, &lhs, sizeof (EXPR));
580 UNSCAN;
581 (void) rc;
582 }
583 }
584
585 #undef OP_ERROR
586
587 int_4 express (EXPR * reg, int_4 expect, int_4 len)
588 {
589 MODE mode = (MODE) {.type = expect,.len = len,.dim = 0 };
590 memset (reg, 0, sizeof (EXPR));
591 exprio (reg, 1, FALSE);
592 if (!valid_expr (reg)) {
593 return FALSE;
594 }
595 (void) fold_expr (reg, expect);
596 if (accept_mode (reg->mode.type, reg->mode.len, expect, len)) {
597 return TRUE;
598 } else {
599 MODE_ERROR (1313, qtype (&(reg->mode)), qtype (&mode));
600 return FALSE;
601 }
602 }
603
© 2002-2024 J.M. van der Veer (jmvdveer@xs4all.nl)
|