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 (1401, "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 (1402, "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 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 (1401, INTERNAL_CONSISTENCY, NO_TEXT);
90 }
91 }
92
93 static void factor_real_number (EXPR *loc)
94 {
95 char *expo;
96 RECORD edit;
97 RECCLR (edit);
98 strcpy (edit, curlex);
99 if ((expo = strchr (edit, 'e')) != NO_TEXT || (expo = strchr (edit, 'E')) != NO_TEXT) {
100 loc->mode = (MODE) {.type = REAL, .len = 4, .dim = 0};
101 _srecordf (loc->str, "%s", pretty_float (edit));
102 } else if ((expo = strchr (edit, 'd')) != NO_TEXT || (expo = strchr (edit, 'D')) != NO_TEXT) {
103 *expo = 'e';
104 loc->mode = (MODE) {.type = REAL, .len = 8, .dim = 0};
105 _srecordf (loc->str, "%s", pretty_float (edit));
106 } else if ((expo = strchr (edit, 'q')) != NO_TEXT || (expo = strchr (edit, 'Q')) != NO_TEXT) {
107 *expo = 'e';
108 loc->mode = (MODE) {.type = REAL, .len = 16, .dim = 0};
109 _srecordf (loc->str, "%sq", pretty_float (edit));
110 } else if ((expo = strchr (edit, 'x')) != NO_TEXT || (expo = strchr (edit, 'X')) != NO_TEXT) {
111 *expo = 'e';
112 loc->mode = (MODE) {.type = REAL, .len = 32, .dim = 0};
113 _srecordf (loc->str, "_dc_%d", code_real_32_const (pretty_float (edit)));
114 } else {
115 // No exponent.
116 loc->mode = (MODE) {.type = REAL, .len = 4, .dim = 0};
117 _srecordf (loc->str, "%s", pretty_float (edit));
118 }
119 loc->variant = EXPR_CONST;
120 }
121
122 static void factor_complex_number (EXPR *loc, EXPR lhs)
123 {
124 (void) scan (EXPECT_NONE);
125 EXPR rhs;
126 memset (&rhs, 0, sizeof (rhs));
127 express (&rhs, NOTYPE, 0);
128 int_4 len = mix_len (&lhs, &rhs);
129 if (len == 32) {
130 _srecordf (loc->str, "CMPLXX (%s, %s)", lhs.str, rhs.str);
131 loc->mode = (MODE) {.type = COMPLEX, .len = 64, .dim = 0};
132 } else if (len == 16) {
133 _srecordf (loc->str, "CMPLXQ (%s, %s)", lhs.str, rhs.str);
134 loc->mode = (MODE) {.type = COMPLEX, .len = 32, .dim = 0};
135 } else if (len == 8) {
136 _srecordf (loc->str, "CMPLX (%s, %s)", lhs.str, rhs.str);
137 loc->mode = (MODE) {.type = COMPLEX, .len = 16, .dim = 0};
138 } else {
139 _srecordf (loc->str, "CMPLXF (%s, %s)", lhs.str, rhs.str);
140 loc->mode = (MODE) {.type = COMPLEX, .len = 8, .dim = 0};
141 }
142 if (lhs.variant == EXPR_CONST && rhs.variant == EXPR_CONST) {
143 loc->variant = EXPR_CONST;
144 }
145 (void) scan (EXPECT_NONE);
146 }
147
148 void factor (EXPR * reg)
149 {
150 int_4 rc;
151 MODE mode;
152 EXPR loc;
153 RECORD name;
154 bufcpy (name, curlex, RECLN);
155 memset (&loc, 0, sizeof (EXPR));
156 loc.variant = EXPR_OTHER;
157 if (curret == DECLAR) {
158 // Some intrinsics share name with a declarer, like REAL (I).
159 intrinsic_call (name, &loc);
160 memcpy (reg, &loc, sizeof (EXPR));
161 return;
162 } else if (curret == WORD) {
163 IDENT *idf = find_local (name, &mode);
164 logical_4 ext_call = (idf != NO_IDENT && idf->external);
165 if (!ext_call && intrinsic_call (name, &loc)) {
166 // Intrinsic call like SQRT (...).
167 memcpy (reg, &loc, sizeof (EXPR));
168 return;
169 }
170 if (idf != NO_IDENT && idf->intrinsic) {
171 // When passed as an argument, an intrinsic function must be
172 // 'specific' for the mode it accepts, so DSIN and not generic SIN.
173 if (!is_specific (name)) {
174 EXPECT (1403, "specific intrinsic subprogram name");
175 }
176 reg->idf = idf;
177 _srecordf (reg->str, "%s", edit_f (name));
178 reg->variant = EXPR_VAR;
179 return;
180 }
181 if (idf == NO_IDENT || ext_call) {
182 // Undefined locally can mean function call.
183 rc = scan (EXPECT_NONE);
184 if (TOKEN ("(")) {
185 factor_function_call (&loc, name);
186 } else {
187 implicit_name (&loc, idf, &mode, name);
188 }
189 memcpy (reg, &loc, sizeof (EXPR));
190 (void) rc;
191 return;
192 } else {
193 rc = scan (EXPECT_NONE);
194 if (TOKEN ("(")) {
195 idf = impl_decl (name, &mode);
196 if (idf->mode.type == CHARACTER) {
197 factor_slice_char (&loc, idf);
198 if (idf->parm) {
199 loc.mode = idf->mode;
200 loc.variant = EXPR_CONST;
201 }
202 } else if (IS_SCALAR (idf->mode)) {
203 if (strcmp (name, modnam) == 0) {
204 recursion (&loc, modnam, idf);
205 } else if (idf->source == MACRO) {
206 macro_nest++;
207 macro (&loc, idf);
208 macro_nest--;
209 } else {
210 factor_function_call (&loc, name);
211 }
212 } else {
213 // Row slice.
214 factor_slice (&loc, idf);
215 }
216 } else {
217 UNSCAN;
218 if (idf->parm) {
219 bufcat (loc.str, idf->parm, RECLN);
220 loc.mode = idf->mode;
221 loc.variant = EXPR_CONST;
222 } else {
223 idf = impl_decl (name, &mode);
224 factor_variable (&loc, idf, &mode, name);
225 }
226 }
227 }
228 memcpy (reg, &loc, sizeof (EXPR));
229 return;
230 } else if (TOKEN ("+")) {
231 // + factor.
232 EXPR fac;
233 memset (&fac, 0, sizeof (EXPR));
234 rc = scan (EXPECT_NONE);
235 factor (&fac);
236 if (fac.mode.type != INTEGER && fac.mode.type != REAL && fac.mode.type != COMPLEX) {
237 EXPECT (1404, "arithmetical expression");
238 }
239 _srecordf (loc.str, "%s", fac.str);
240 loc.mode = fac.mode;
241 if (fac.variant == EXPR_CONST) {
242 loc.variant = EXPR_CONST;
243 } else {
244 loc.variant = EXPR_OTHER;
245 }
246 } else if (TOKEN ("-")) {
247 // - factor.
248 EXPR fac;
249 memset (&fac, 0, sizeof (EXPR));
250 rc = scan (EXPECT_NONE);
251 factor (&fac);
252 if (fac.mode.type != INTEGER && fac.mode.type != REAL && fac.mode.type != COMPLEX) {
253 EXPECT (1405, "arithmetical expression");
254 }
255 if (fac.mode.type == COMPLEX && fac.mode.len == 64) {
256 _srecordf (loc.str, "cxneg (%s)", fac.str);
257 } else if (fac.mode.type == REAL && fac.mode.len == 32) {
258 _srecordf (loc.str, "xneg (%s)", fac.str);
259 } else {
260 _srecordf (loc.str, "-%s", fac.str);
261 }
262 loc.mode = fac.mode;
263 if (fac.variant == EXPR_CONST) {
264 loc.variant = EXPR_CONST;
265 } else {
266 loc.variant = EXPR_OTHER;
267 }
268 } else if (TOKEN (".true.") || TOKEN (".t.")) {
269 // LOGICAL constant TRUE.
270 _srecordf (loc.str, "TRUE");
271 loc.mode = (MODE) {
272 .type = LOGICAL, .len = 4, .dim = 0};
273 loc.variant = EXPR_CONST;
274 } else if (TOKEN (".false.") || TOKEN (".f.")) {
275 // LOGICAL constant FALSE.
276 _srecordf (loc.str, "FALSE");
277 loc.mode = (MODE) {
278 .type = LOGICAL, .len = 4, .dim = 0};
279 loc.variant = EXPR_CONST;
280 } else if (curret == INT_NUMBER) {
281 // INTEGER constant.
282 factor_integer_number (&loc, curlex);
283 MAXIMISE (loc.mode.len, 4);
284 } else if (curret == FLT_NUMBER) {
285 // REAL constnat.
286 factor_real_number (&loc);
287 } else if (curret == TEXT) {
288 // TEXT constant.
289 RECORD idf;
290 _srecordf (idf, "_dc_%d", code_uniq_str (curlex));
291 _srecordf (loc.str, "%s", idf);
292 int len = strlen (curlex) - 2;
293 if (len < 1) {
294 len = 1;
295 }
296 loc.mode = (MODE) {.type = CHARACTER, .len = len, .dim = 0};
297 norm_mode (&loc.mode);
298 loc.variant = EXPR_CONST;
299 } else if (TOKEN ("(")) {
300 EXPR lhs;
301 memset (&lhs, 0, sizeof (lhs));
302 rc = scan (EXPECT_NONE);
303 express (&lhs, NOTYPE, 0);
304 rc = scan (EXPECT_NONE);
305 if (TOKEN (",")) {
306 // COMPLEX number.
307 factor_complex_number (&loc, lhs);
308 } else {
309 // Parenthesized expression.
310 if (lhs.variant == EXPR_CONST) {
311 loc.variant = EXPR_CONST;
312 _srecordf (loc.str, "%s", lhs.str);
313 } else {
314 loc.variant = EXPR_OTHER;
315 _srecordf (loc.str, "(%s)", lhs.str);
316 }
317 loc.mode = lhs.mode;
318 }
319 CHECKPOINT (1406, ")");
320 } else {
321 ERROR (1407, "expected operand", NO_TEXT);
322 loc.mode.type = ETYPE;
323 }
324 memcpy (reg, &loc, sizeof (EXPR));
325 (void) rc;
326 }
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|