factor.c
1 //! @file factor.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 expression factors.
25
26 #include <vif.h>
27
28 static void implicit_name (EXPR *loc, IDENT *idf, MODE *mode, RECORD name)
29 {
30 UNSCAN;
31 idf = impl_decl (name, mode);
32 if (idf != NO_IDENT && idf->mode.type == NOTYPE && idf->external == FALSE) {
33 ERROR (1701, "variable has no type", C_NAME (idf));
34 }
35 _srecordf (loc->str, "%s", C_NAME (idf));
36 loc->variant = EXPR_VAR;
37 loc->idf = idf;
38 loc->mode = idf->mode;
39 }
40
41 void factor_variable (EXPR *loc, IDENT *idf, MODE *mode, RECORD name)
42 {
43 if (idf == NO_IDENT) {
44 idf = impl_decl (name, mode);
45 }
46 if (idf == NO_IDENT) {
47 BUG ("cannot store identifier");
48 }
49 if (idf->mode.type == NOTYPE && idf->external == FALSE) {
50 ERROR (1702, "variable has no type", FTN_NAME (idf));
51 }
52 if (idf->arg || idf->alias != NO_IDENT) {
53 if (IS_ROW (idf->mode) || idf->mode.type == CHARACTER) {
54 _srecordf (loc->str, "%s", C_NAME (idf), RECLN);
55 } else {
56 _srecordf (loc->str, "(*%s)", C_NAME (idf), RECLN);
57 }
58 } else {
59 if (NOT_LOCAL (idf)) {
60 (void) idf_full_c_name (loc->str, idf);
61 } else if (idf->nest > 0) {
62 NEW_RECORD (res);
63 _srecordf (res, "%s", edit_vn (C_NAME (idf), idf->nest));
64 bufcat (loc->str, res, RECLN);
65 } else {
66 bufcat (loc->str, C_NAME (idf), RECLN);
67 }
68 }
69 loc->variant = EXPR_VAR;
70 loc->idf = idf;
71 loc->mode = idf->mode;
72 }
73
74 void factor_integer_number (EXPR *loc, char *str)
75 {
76 // We let length depend on the denotation.
77 int_8 val = strtoll (str, NO_REF_TEXT, 10);
78 loc->variant = EXPR_CONST;
79 if (val >= SHRT_MIN && val <= SHRT_MAX) {
80 _srecordf (loc->str, "%s", str);
81 loc->mode = (MODE) {.type = INTEGER, .len = 2, .dim = 0};
82 } else if (val >= INT_MIN && val <= INT_MAX) {
83 _srecordf (loc->str, "%s", str);
84 loc->mode = (MODE) {.type = INTEGER, .len = 4, .dim = 0};
85 } else if (val >= LLONG_MIN && val <= LLONG_MAX) {
86 _srecordf (loc->str, "%s", str);
87 loc->mode = (MODE) {.type = INTEGER, .len = 8, .dim = 0};
88 } else {
89 FATAL (1703, INTERNAL_CONSISTENCY, NO_TEXT);
90 }
91 }
92
93 static void factor_real_number (EXPR *loc)
94 {
95 char *expo;
96 NEW_RECORD (edit);
97 RECCPY (edit, curlex);
98 if ((expo = strchr (edit, 'e')) != NO_TEXT || (expo = strchr (edit, 'E')) != NO_TEXT) {
99 loc->mode = (MODE) {.type = REAL, .len = 4, .dim = 0};
100 _srecordf (loc->str, "%s", pretty_float (edit));
101 } else if ((expo = strchr (edit, 'd')) != NO_TEXT || (expo = strchr (edit, 'D')) != NO_TEXT) {
102 *expo = 'e';
103 loc->mode = (MODE) {.type = REAL, .len = 8, .dim = 0};
104 _srecordf (loc->str, "%s", pretty_float (edit));
105 } else if ((expo = strchr (edit, 'q')) != NO_TEXT || (expo = strchr (edit, 'Q')) != NO_TEXT) {
106 *expo = 'e';
107 loc->mode = (MODE) {.type = REAL, .len = 16, .dim = 0};
108 _srecordf (loc->str, "%sq", pretty_float (edit));
109 } else if ((expo = strchr (edit, 'x')) != NO_TEXT || (expo = strchr (edit, 'X')) != NO_TEXT) {
110 *expo = 'e';
111 loc->mode = (MODE) {.type = REAL, .len = 32, .dim = 0};
112 _srecordf (loc->str, "_dc_%d", code_real_32_const (pretty_float (edit)));
113 } else {
114 // No exponent.
115 loc->mode = (MODE) {.type = REAL, .len = 4, .dim = 0};
116 _srecordf (loc->str, "%s", pretty_float (edit));
117 }
118 loc->variant = EXPR_CONST;
119 }
120
121 static void factor_complex_number (EXPR *loc, EXPR lhs)
122 {
123 (void) scan (EXPECT_NONE);
124 EXPR rhs;
125 memset (&rhs, 0, sizeof (rhs));
126 express (&rhs, NOTYPE, 0);
127 int_4 len = mix_len (&lhs, &rhs);
128 if (len == 32) {
129 _srecordf (loc->str, "CMPLXX (%s, %s)", lhs.str, rhs.str);
130 loc->mode = (MODE) {.type = COMPLEX, .len = 64, .dim = 0};
131 } else if (len == 16) {
132 _srecordf (loc->str, "CMPLXQ (%s, %s)", lhs.str, rhs.str);
133 loc->mode = (MODE) {.type = COMPLEX, .len = 32, .dim = 0};
134 } else if (len == 8) {
135 _srecordf (loc->str, "CMPLX (%s, %s)", lhs.str, rhs.str);
136 loc->mode = (MODE) {.type = COMPLEX, .len = 16, .dim = 0};
137 } else {
138 _srecordf (loc->str, "CMPLXF (%s, %s)", lhs.str, rhs.str);
139 loc->mode = (MODE) {.type = COMPLEX, .len = 8, .dim = 0};
140 }
141 if (lhs.variant == EXPR_CONST && rhs.variant == EXPR_CONST) {
142 loc->variant = EXPR_CONST;
143 }
144 (void) scan (EXPECT_NONE);
145 }
146
147 void factor (EXPR * reg)
148 {
149 int_4 rc;
150 MODE mode;
151 EXPR loc;
152 NEW_RECORD (name);
153 bufcpy (name, curlex, RECLN);
154 memset (&loc, 0, sizeof (EXPR));
155 loc.variant = EXPR_OTHER;
156 if (curret == WORD || curret == DECLAR) {
157 IDENT *idf = find_local (name, &mode);
158 logical_4 pack = lookahead ("(");
159 if (curret == DECLAR && pack) {
160 // Some intrinsics share name with a declarer, like REAL (I).
161 intrinsic_call (name, &loc);
162 memcpy (reg, &loc, sizeof (EXPR));
163 return;
164 }
165 if (idf != NO_IDENT && idf->intrinsic && !pack) {
166 // Intrinsic function as parameter must be 'specific'.
167 // Otherwise ambiguity results -> implementation dependent result.
168 // implicit dcos
169 // call zeroin (dcos, ...)
170 if (!is_specific (name)) {
171 EXPECT (1704, "generic intrinsic subprogram name");
172 }
173 reg->idf = idf;
174 _srecordf (reg->str, "%s", edit_i (name));
175 reg->variant = EXPR_VAR;
176 return;
177 }
178 if (idf != NO_IDENT && idf->intrinsic && pack) {
179 // intrinsic dcos
180 // ... dcos (x)
181 rc = scan (EXPECT_NONE);
182 if (TOKEN ("(")) {
183 factor_function_call (&loc, name);
184 }
185 memcpy (reg, &loc, sizeof (EXPR));
186 (void) rc;
187 return;
188 }
189 if (! (idf != NO_IDENT && idf->external)) {
190 // Not a call to a declared external name.
191 logical_4 int_call = FALSE;
192 if (idf != NO_IDENT && idf->intrinsic && pack) {
193 int_call = intrinsic_call (name, &loc);
194 } else if (idf == NO_IDENT) {
195 int_call = intrinsic_call (name, &loc);
196 }
197 if (int_call) {
198 memcpy (reg, &loc, sizeof (EXPR));
199 return;
200 }
201 }
202 if (idf != NO_IDENT && idf->mode.dim == 0 && !idf->intrinsic && !idf->external && pack) {
203 // Name is declared but not as intrinsic or external.
204 // In VIF this gives a check on function return type.
205 // real*8 cos
206 // y = cos (1.0d0)
207 INTRINS *fun;
208 if (is_intrins (name, &fun)) {
209 if (intrinsic_call (name, &loc)) {
210 if (!accept_mode (loc.mode.type, loc.mode.len, idf->mode.type, idf->mode.len)) {
211 MODE_ERROR (1705, qtype (&(loc.mode)), qtype (&(idf->mode)));
212 }
213 memcpy (reg, &loc, sizeof (EXPR));
214 return;
215 }
216 }
217 }
218 if (idf == NO_IDENT || idf->external) {
219 // Undefined locally can mean function call.
220 // In VIF, 'external' always means you supply the routine.
221 // external cos
222 // call zeroin (cos, ...)
223 rc = scan (EXPECT_NONE);
224 if (TOKEN ("(")) {
225 factor_function_call (&loc, name);
226 } else {
227 implicit_name (&loc, idf, &mode, name);
228 }
229 memcpy (reg, &loc, sizeof (EXPR));
230 (void) rc;
231 return;
232 }
233 //
234 if (pack) {
235 rc = scan (EXPECT_NONE);
236 idf = impl_decl (name, &mode);
237 if (idf->mode.type == CHARACTER) {
238 factor_slice_char (&loc, idf);
239 if (idf->parm) {
240 loc.mode = idf->mode;
241 loc.variant = EXPR_CONST;
242 }
243 } else if (IS_SCALAR (idf->mode)) {
244 if (strcmp (name, modnam) == 0) {
245 recursion (&loc, modnam, idf);
246 } else if (idf->source == MACRO) {
247 macro (&loc, idf);
248 } else {
249 factor_function_call (&loc, name);
250 }
251 } else {
252 // Row slice.
253 factor_slice (&loc, idf);
254 }
255 } else {
256 if (idf->parm) {
257 bufcat (loc.str, idf->parm, RECLN);
258 loc.mode = idf->mode;
259 loc.variant = EXPR_CONST;
260 } else {
261 idf = impl_decl (name, &mode);
262 factor_variable (&loc, idf, &mode, name);
263 }
264 }
265 memcpy (reg, &loc, sizeof (EXPR));
266 return;
267 } else if (TOKEN ("+")) {
268 // + factor.
269 EXPR fac;
270 memset (&fac, 0, sizeof (EXPR));
271 rc = scan (EXPECT_NONE);
272 factor (&fac);
273 if (fac.mode.type != INTEGER && fac.mode.type != REAL && fac.mode.type != COMPLEX) {
274 EXPECT (1706, "arithmetical expression");
275 }
276 _srecordf (loc.str, "%s", fac.str);
277 loc.mode = fac.mode;
278 if (fac.variant == EXPR_CONST) {
279 loc.variant = EXPR_CONST;
280 } else {
281 loc.variant = EXPR_OTHER;
282 }
283 } else if (TOKEN ("-")) {
284 // - factor.
285 EXPR fac;
286 memset (&fac, 0, sizeof (EXPR));
287 rc = scan (EXPECT_NONE);
288 factor (&fac);
289 if (fac.mode.type != INTEGER && fac.mode.type != REAL && fac.mode.type != COMPLEX) {
290 EXPECT (1707, "arithmetical expression");
291 }
292 if (fac.mode.type == COMPLEX && fac.mode.len == 64) {
293 _srecordf (loc.str, "cxneg (%s)", fac.str);
294 } else if (fac.mode.type == REAL && fac.mode.len == 32) {
295 _srecordf (loc.str, "xneg (%s)", fac.str);
296 } else {
297 _srecordf (loc.str, "-%s", fac.str);
298 }
299 loc.mode = fac.mode;
300 if (fac.variant == EXPR_CONST) {
301 loc.variant = EXPR_CONST;
302 } else {
303 loc.variant = EXPR_OTHER;
304 }
305 } else if (TOKEN (".true.") || TOKEN (".t.")) {
306 // LOGICAL constant TRUE.
307 _srecordf (loc.str, "TRUE");
308 loc.mode = (MODE) {
309 .type = LOGICAL, .len = 4, .dim = 0};
310 loc.variant = EXPR_CONST;
311 } else if (TOKEN (".false.") || TOKEN (".f.")) {
312 // LOGICAL constant FALSE.
313 _srecordf (loc.str, "FALSE");
314 loc.mode = (MODE) {
315 .type = LOGICAL, .len = 4, .dim = 0};
316 loc.variant = EXPR_CONST;
317 } else if (curret == INT_NUMBER) {
318 // INTEGER constant.
319 factor_integer_number (&loc, curlex);
320 MAXIMISE (loc.mode.len, 4);
321 } else if (curret == FLT_NUMBER) {
322 // REAL constnat.
323 factor_real_number (&loc);
324 } else if (curret == TEXT) {
325 // TEXT constant.
326 NEW_RECORD (idf);
327 _srecordf (idf, "_dc_%d", code_uniq_str (curlex));
328 _srecordf (loc.str, "%s", idf);
329 int len = strlen (curlex) - 2;
330 if (len < 1) {
331 len = 1;
332 }
333 loc.mode = (MODE) {.type = CHARACTER, .len = len, .dim = 0};
334 norm_mode (&loc.mode);
335 loc.variant = EXPR_CONST;
336 } else if (TOKEN ("(")) {
337 EXPR lhs;
338 memset (&lhs, 0, sizeof (lhs));
339 rc = scan (EXPECT_NONE);
340 express (&lhs, NOTYPE, 0);
341 rc = scan (EXPECT_NONE);
342 if (TOKEN (",")) {
343 // COMPLEX number.
344 factor_complex_number (&loc, lhs);
345 } else {
346 // Parenthesized expression.
347 if (lhs.variant == EXPR_CONST) {
348 loc.variant = EXPR_CONST;
349 _srecordf (loc.str, "%s", lhs.str);
350 } else {
351 loc.variant = EXPR_OTHER;
352 _srecordf (loc.str, "(%s)", lhs.str);
353 }
354 loc.mode = lhs.mode;
355 }
356 CHECKPOINT (1708, ")");
357 } else {
358 ERROR (1709, "expected operand", NO_TEXT);
359 loc.mode.type = ETYPE;
360 }
361 memcpy (reg, &loc, sizeof (EXPR));
362 (void) rc;
363 }
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|