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-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 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 != NULL && idf->mode.type == NOTYPE && idf->external == FALSE) {
33 ERROR (1401, "variable has no type", CID (idf));
34 }
35 _srecordf (loc->str, "%s", CID (idf));
36 loc->variant = EXPR_VAR;
37 loc->idf = idf;
38 loc->mode = idf->mode;
39 }
40
41 void variable (EXPR *loc, IDENT *idf, MODE *mode, RECORD name)
42 {
43 if (idf == NULL) {
44 idf = impl_decl (name, mode);
45 }
46 if (idf == NULL) {
47 BUG ("cannot store identifier");
48 }
49 if (idf->mode.type == NOTYPE && idf->external == FALSE) {
50 ERROR (1402, "variable has no type", CID (idf));
51 }
52 if (idf->arg || idf->alias != NULL) {
53 if (!is_array (idf->mode)) {
54 // bufcat (loc->str, "*", RECLN);
55 _srecordf (loc->str, "(*%s)", CID (idf), RECLN);
56 } else {
57 _srecordf (loc->str, "%s", CID (idf), RECLN);
58 }
59 // bufcat (loc->str, CID (idf), RECLN);
60 } else {
61 if (idf->common > 0) {
62 bufcat (loc->str, commons[idf->common], RECLN);
63 if (idf->common == EXTERN) {
64 bufcat (loc->str, "->", RECLN);
65 } else {
66 bufcat (loc->str, ".", RECLN);
67 }
68 bufcat (loc->str, CID (idf), RECLN);
69 } else if (idf->nest > 0) {
70 RECORD res;
71 _srecordf (res, "%s", edit_vn (CID (idf), idf->nest));
72 bufcat (loc->str, res, RECLN);
73 } else {
74 bufcat (loc->str, CID (idf), RECLN);
75 }
76 }
77 loc->variant = EXPR_VAR;
78 loc->idf = idf;
79 loc->mode = idf->mode;
80 }
81
82 static void integer_denotation (EXPR *loc)
83 {
84 // We let length depend on the denotation.
85 int_8 val = strtoll (curlex, NULL, 10);
86 loc->variant = EXPR_CONST;
87 if (val >= SHRT_MIN && val <= SHRT_MAX) {
88 _srecordf (loc->str, "%s", curlex);
89 loc->mode = (MODE) {.type = INTEGER, .len = 4, .dim = 0};
90 } else if (val >= INT_MIN && val <= INT_MAX) {
91 _srecordf (loc->str, "%s", curlex);
92 loc->mode = (MODE) {.type = INTEGER, .len = 4, .dim = 0};
93 } else if (val >= LLONG_MIN && val <= LLONG_MAX) {
94 _srecordf (loc->str, "%s", curlex);
95 loc->mode = (MODE) {.type = INTEGER, .len = 8, .dim = 0};
96 }
97 }
98
99 static void real_denotation (EXPR *loc)
100 {
101 char *expo;
102 RECORD edit;
103 RECCLR (edit);
104 strcpy (edit, curlex);
105 if ((expo = strchr (edit, 'e')) != NULL || (expo = strchr (edit, 'E')) != NULL) {
106 loc->mode = (MODE) {.type = REAL, .len = 4, .dim = 0};
107 _srecordf (loc->str, "%s", pretty_float (edit));
108 } else if ((expo = strchr (edit, 'd')) != NULL || (expo = strchr (edit, 'D')) != NULL) {
109 *expo = 'e';
110 loc->mode = (MODE) {.type = REAL, .len = 8, .dim = 0};
111 _srecordf (loc->str, "%s", pretty_float (edit));
112 } else if ((expo = strchr (edit, 'q')) != NULL || (expo = strchr (edit, 'Q')) != NULL) {
113 *expo = 'e';
114 loc->mode = (MODE) {.type = REAL, .len = 16, .dim = 0};
115 _srecordf (loc->str, "%sq", pretty_float (edit));
116 } else if ((expo = strchr (edit, 'x')) != NULL || (expo = strchr (edit, 'X')) != NULL) {
117 *expo = 'e';
118 loc->mode = (MODE) {.type = REAL, .len = 32, .dim = 0};
119 _srecordf (loc->str, "_dc_%d", code_real_32_const (pretty_float (edit)));
120 } else {
121 // No exponent.
122 loc->mode = (MODE) {.type = REAL, .len = 4, .dim = 0};
123 _srecordf (loc->str, "%s", pretty_float (edit));
124 }
125 loc->variant = EXPR_CONST;
126 }
127
128 static void complex_denotation (EXPR *loc, EXPR lhs)
129 {
130 (void) scan (NULL);
131 EXPR rhs;
132 memset (&rhs, 0, sizeof (rhs));
133 express (&rhs, NOTYPE, 0);
134 int_4 len = mix_len (&lhs, &rhs);
135 if (len == 32) {
136 _srecordf (loc->str, "CMPLXX (%s, %s)", lhs.str, rhs.str);
137 loc->mode = (MODE) {.type = COMPLEX, .len = 64, .dim = 0};
138 } else if (len == 16) {
139 _srecordf (loc->str, "CMPLXQ (%s, %s)", lhs.str, rhs.str);
140 loc->mode = (MODE) {.type = COMPLEX, .len = 32, .dim = 0};
141 } else if (len == 8) {
142 _srecordf (loc->str, "CMPLX (%s, %s)", lhs.str, rhs.str);
143 loc->mode = (MODE) {.type = COMPLEX, .len = 16, .dim = 0};
144 } else {
145 _srecordf (loc->str, "CMPLXF (%s, %s)", lhs.str, rhs.str);
146 loc->mode = (MODE) {.type = COMPLEX, .len = 8, .dim = 0};
147 }
148 if (lhs.variant == EXPR_CONST && rhs.variant == EXPR_CONST) {
149 loc->variant = EXPR_CONST;
150 }
151 (void) scan (NULL);
152 }
153
154 void factor (EXPR * reg)
155 {
156 int_4 rc;
157 MODE mode;
158 EXPR loc;
159 RECORD name;
160 bufcpy (name, curlex, RECLN);
161 memset (&loc, 0, sizeof (EXPR));
162 loc.variant = EXPR_OTHER;
163 if (curret == DECLAR) { // REAL (I)
164 intrinsic_call (name, &loc);
165 memcpy (reg, &loc, sizeof (EXPR));
166 return;
167 } else if (curret == WORD) {
168 IDENT *idf = find_local (name, &mode);
169 logical_4 ext_call = (idf != NULL && idf->external);
170 if (!ext_call && intrinsic_call (name, &loc)) {
171 memcpy (reg, &loc, sizeof (EXPR));
172 return;
173 }
174 if (idf != NULL && idf->intrinsic) {
175 if (!is_specific (name)) {
176 EXPECT (1403, "specific intrinsic subprogram name");
177 }
178 reg->idf = idf;
179 _srecordf (reg->str, "%s", edit_f (name));
180 reg->variant = EXPR_VAR;
181 return;
182 }
183 if (idf == NULL || ext_call) {
184 rc = scan (NULL);
185 if (TOKEN ("(")) {
186 function_call (&loc, name);
187 } else {
188 implicit_name (&loc, idf, &mode, name);
189 }
190 } else {
191 rc = scan (NULL);
192 if (TOKEN ("(")) {
193 idf = impl_decl (name, &mode);
194 if (idf->mode.type == CHARACTER) {
195 slice_char (&loc, idf);
196 if (idf->parm) {
197 loc.mode = idf->mode;
198 loc.variant = EXPR_CONST;
199 }
200 } else if (idf->mode.dim == 0) {
201 if (strcmp (name, modnam) == 0) {
202 recursion (&loc, modnam, idf);
203 } else if (idf->source == MACRO) {
204 macro_nest++;
205 macro (&loc, idf);
206 macro_nest--;
207 } else {
208 function_call (&loc, name);
209 }
210 } else {
211 // Array slice.
212 slice (&loc, idf);
213 }
214 } else {
215 UNSCAN;
216 if (idf->parm) {
217 bufcat (loc.str, idf->parm, RECLN);
218 loc.mode = idf->mode;
219 loc.variant = EXPR_CONST;
220 } else {
221 idf = impl_decl (name, &mode);
222 variable (&loc, idf, &mode, name);
223 }
224 }
225 }
226 memcpy (reg, &loc, sizeof (EXPR));
227 (void) rc;
228 return;
229 } else if (TOKEN ("+")) {
230 EXPR fac;
231 memset (&fac, 0, sizeof (EXPR));
232 rc = scan (NULL);
233 factor (&fac);
234 if (fac.mode.type != INTEGER && fac.mode.type != REAL && fac.mode.type != COMPLEX) {
235 EXPECT (1404, "arithmetical expression");
236 }
237 _srecordf (loc.str, "%s", fac.str);
238 loc.mode = fac.mode;
239 if (fac.variant == EXPR_CONST) {
240 loc.variant = EXPR_CONST;
241 } else {
242 loc.variant = EXPR_OTHER;
243 }
244 } else if (TOKEN ("-")) {
245 EXPR fac;
246 memset (&fac, 0, sizeof (EXPR));
247 rc = scan (NULL);
248 factor (&fac);
249 if (fac.mode.type != INTEGER && fac.mode.type != REAL && fac.mode.type != COMPLEX) {
250 EXPECT (1405, "arithmetical expression");
251 }
252 if (fac.mode.type == COMPLEX && fac.mode.len == 64) {
253 _srecordf (loc.str, "cxneg (%s)", fac.str);
254 } else if (fac.mode.type == REAL && fac.mode.len == 32) {
255 _srecordf (loc.str, "xneg (%s)", fac.str);
256 } else {
257 _srecordf (loc.str, "-%s", fac.str);
258 }
259 loc.mode = fac.mode;
260 if (fac.variant == EXPR_CONST) {
261 loc.variant = EXPR_CONST;
262 } else {
263 loc.variant = EXPR_OTHER;
264 }
265 } else if (TOKEN (".true.") || TOKEN (".t.")) {
266 _srecordf (loc.str, "TRUE");
267 loc.mode = (MODE) {
268 .type = LOGICAL, .len = 4, .dim = 0};
269 loc.variant = EXPR_CONST;
270 } else if (TOKEN (".false.") || TOKEN (".f.")) {
271 _srecordf (loc.str, "FALSE");
272 loc.mode = (MODE) {
273 .type = LOGICAL, .len = 4, .dim = 0};
274 loc.variant = EXPR_CONST;
275 } else if (curret == INT_NUMBER) {
276 integer_denotation (&loc);
277 } else if (curret == FLT_NUMBER) {
278 real_denotation (&loc);
279 } else if (curret == TEXT) {
280 RECORD idf;
281 _srecordf (idf, "_dc_%d", code_uniq_str (curlex));
282 _srecordf (loc.str, "%s", idf);
283 int len = strlen (curlex) - 2;
284 if (len < 1) {
285 len = 1;
286 }
287 loc.mode = (MODE) {.type = CHARACTER, .len = len, .dim = 0};
288 norm_mode (&loc.mode);
289 loc.variant = EXPR_CONST;
290 } else if (TOKEN ("(")) {
291 EXPR lhs;
292 memset (&lhs, 0, sizeof (lhs));
293 rc = scan (NULL);
294 express (&lhs, NOTYPE, 0);
295 rc = scan (NULL);
296 if (TOKEN (",")) {
297 complex_denotation (&loc, lhs);
298 } else {
299 if (lhs.variant == EXPR_CONST) {
300 loc.variant = EXPR_CONST;
301 _srecordf (loc.str, "%s", lhs.str);
302 } else {
303 loc.variant = EXPR_OTHER;
304 _srecordf (loc.str, "(%s)", lhs.str);
305 }
306 loc.mode = lhs.mode;
307 }
308 CHECKPOINT (1406, ")");
309 } else {
310 ERROR (1407, "expected operand", NULL);
311 loc.mode.type = ETYPE;
312 }
313 memcpy (reg, &loc, sizeof (EXPR));
314 (void) rc;
315 }
© 2002-2024 J.M. van der Veer (jmvdveer@xs4all.nl)
|