assign.c
1 //! @file assign.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 assignment statements.
25
26 #include <vif.h>
27
28 void assign (EXPR * reg)
29 {
30 #define ASSIGN_ERROR(s) {\
31 RECORD str;\
32 _srecordf (str, "%s = %s", qtype (&(lhs.mode)), qtype (&(rhs.mode)));\
33 ERROR (101, (s), str);\
34 return;\
35 }
36 int_4 rc;
37 EXPR lhs, rhs;
38 memset (&lhs, 0, sizeof (lhs));
39 memset (&rhs, 0, sizeof (rhs));
40 lhs_factor = TRUE;
41 factor (&lhs);
42 lhs_factor = FALSE;
43 if (lhs.variant != EXPR_VAR && lhs.variant != EXPR_SLICE && lhs.variant != EXPR_SUBSTR) {
44 ERROR (102, "invalid lhs in assignment", lhs.str);
45 skip_card (FALSE);
46 return;
47 }
48 if (lhs.variant == EXPR_VAR) {
49 IDENT *idf = impl_decl (lhs.str, NO_MODE);
50 if (idf != NO_IDENT && IS_ROW (idf->mode)) {
51 ERROR (103, "cannot assign to dimensioned variable", curlex);
52 skip_card (FALSE);
53 return;
54 }
55 }
56 rc = scan (EXPECT_NONE);
57 if (TOKEN ("=")) {
58 rc = scan (EXPECT_NONE);
59 exprio (&rhs, 1, TRUE);
60 (void) fold_expr (&rhs, rhs.mode.type);
61 rc = scan (EXPECT_NONE);
62 } else {
63 EXPECT (104, "=");
64 }
65 // Warn for precision loss.
66 if (lhs.mode.type == REAL && rhs.mode.type == REAL) {
67 if (lhs.mode.len < rhs.mode.len) {
68 PRECISION_LOSS (105, qtype (&(rhs.mode)), qtype (&(lhs.mode)));
69 }
70 }
71 if (lhs.mode.type == COMPLEX && rhs.mode.type == COMPLEX) {
72 if (lhs.mode.len < rhs.mode.len) {
73 PRECISION_LOSS (106, qtype (&(rhs.mode)), qtype (&(lhs.mode)));
74 }
75 }
76 if (lhs.mode.type == COMPLEX && rhs.mode.type == REAL) {
77 if (lhs.mode.len < 2 * rhs.mode.len) {
78 PRECISION_LOSS (107, qtype (&(rhs.mode)), qtype (&(lhs.mode)));
79 }
80 }
81 // Assign.
82 if (strcmp (lhs.str, rhs.str) == 0) {
83 // Peephole.
84 _srecordf (reg->str, "/* %s = %s */", lhs.str, rhs.str);
85 } else if (lhs.mode.type == CHARACTER && rhs.mode.type == CHARACTER) {
86 // character*n = character*m; m <= n
87 if (lhs.variant == EXPR_SUBSTR) {
88 _srecordf (reg->str, "bufrep (%s, %s)", lhs.str, rhs.str);
89 } else if (lhs.mode.len == 0) {
90 // _srecordf (reg->str, "bufcpy (%s, %s, MAX_STRLEN)", lhs.str, rhs.str);
91 _srecordf (reg->str, "strcpy (%s, %s)", lhs.str, rhs.str);
92 } else {
93 _srecordf (reg->str, "bufcpy (%s, %s, %d)", lhs.str, rhs.str, lhs.mode.len);
94 }
95 } else if (lhs.mode.type == rhs.mode.type && lhs.mode.len == rhs.mode.len) {
96 // same type, length assignment
97 _srecordf (reg->str, "%s = %s", lhs.str, rhs.str);
98 } else if (rhs.variant == EXPR_CONST && rhs.mode.type == INTEGER && lhs.mode.type == INTEGER) {
99 // INTEGER length denotations overlap.
100 factor_integer_number (&rhs, rhs.str);
101 if (rhs.mode.len > lhs.mode.len) {
102 MODE_ERROR (108, qtype (&(rhs.mode)), qtype (&(lhs.mode)));
103 }
104
105 /*
106 int_8 val = strtoll (rhs.str, NO_REF_TEXT, 10);
107 int_4 lenval;
108 if (val >= SHRT_MIN && val <= SHRT_MAX) {
109 lenval = 2;
110 } else if (val >= INT_MIN && val <= INT_MAX) {
111 lenval = 4;
112 } else if (val >= LLONG_MIN && val <= LLONG_MAX) {
113 lenval = 8;
114 }
115 if (lenval > lhs.mode.len) {
116 MODE_ERROR (108, qtype (&(rhs.mode)), qtype (&(lhs.mode)));
117 }
118 */
119 _srecordf (reg->str, "%s = %s", lhs.str, rhs.str);
120 } else if (lhs.mode.type == REAL && lhs.mode.len == 32) {
121 if (rhs.mode.type == REAL) {
122 // real*32 = real
123 if (rhs.variant == EXPR_CONST) {
124 _srecordf (rhs.str, "_dc_%d", code_real_32_const (pretty_float (rhs.str)));
125 _srecordf (reg->str, "%s = %s", lhs.str, rhs.str);
126 } else {
127 switch (rhs.mode.len) {
128 case 4: _srecordf (reg->str, "%s = flttox (%s)", lhs.str, rhs.str); break;
129 case 8: _srecordf (reg->str, "%s = dbltox (%s)", lhs.str, rhs.str); break;
130 case 16: _srecordf (reg->str, "%s = _quadtox (%s)", lhs.str, rhs.str); break;
131 }
132 }
133 } else if (rhs.mode.type == INTEGER) {
134 // real*32 = integer
135 switch (rhs.mode.len) {
136 case 2: _srecordf (reg->str, "%s = inttox (%s)", lhs.str, rhs.str); break;
137 case 4: _srecordf (reg->str, "%s = inttox (%s)", lhs.str, rhs.str); break;
138 case 8: _srecordf (reg->str, "%s = _quadtox (%s)", lhs.str, rhs.str); break;
139 }
140 } else {
141 ASSIGN_ERROR ("incompatible assignment")
142 }
143 } else if (lhs.mode.type == COMPLEX && lhs.mode.len == 64) {
144 if (rhs.mode.type == COMPLEX) {
145 // complex*64 = complex
146 switch (rhs.mode.len) {
147 case 8: _srecordf (reg->str, "%s = cxdbl (%s)", lhs.str, rhs.str); break;
148 case 16: _srecordf (reg->str, "%s = cxdbl (%s)", lhs.str, rhs.str); break;
149 case 32: _srecordf (reg->str, "%s = cxquad (%s)", lhs.str, rhs.str); break;
150 }
151 } else if (rhs.mode.type == REAL) {
152 // complex*64 = real
153 switch (rhs.mode.len) {
154 case 4: _srecordf (reg->str, "%s = cxdbl (CMPLX (%s, 0.0))", lhs.str, rhs.str); break;
155 case 8: _srecordf (reg->str, "%s = cxdbl (CMPLX (%s, 0.0))", lhs.str, rhs.str); break;
156 case 16: _srecordf (reg->str, "%s = cxquad (CMPLXQ (%s, 0.0q))", lhs.str, rhs.str); break;
157 case 32: _srecordf (reg->str, "%s = cxreal32 (%s)", lhs.str, rhs.str); break;
158 }
159 } else if (rhs.mode.type == INTEGER) {
160 // complex*64 = integer
161 switch (rhs.mode.len) {
162 case 2:
163 case 4: _srecordf (reg->str, "%s = cxdbl (CMPLX (%s, 0.0))", lhs.str, rhs.str); break;
164 case 8: _srecordf (reg->str, "%s = cxquad (CMPLXQ (%s, 0.0q))", lhs.str, rhs.str); break;
165 }
166 } else {
167 ASSIGN_ERROR ("incompatible assignment")
168 }
169 } else if (rhs.mode.type == REAL && rhs.mode.len == 32) {
170 if (lhs.mode.type == COMPLEX) {
171 // complex = real*32
172 switch (lhs.mode.len) {
173 case 8: _srecordf (reg->str, "%s = xtoflt (%s)", lhs.str, rhs.str); break;
174 case 16: _srecordf (reg->str, "%s = xtodbl (%s)", lhs.str, rhs.str); break;
175 case 32: _srecordf (reg->str, "%s = _xtoquad (%s)", lhs.str, rhs.str); break;
176 }
177 } else if (lhs.mode.type == REAL) {
178 // real = real*32
179 switch (lhs.mode.len) {
180 case 4: _srecordf (reg->str, "%s = xtoflt (%s)", lhs.str, rhs.str); break;
181 case 8: _srecordf (reg->str, "%s = xtodbl (%s)", lhs.str, rhs.str); break;
182 case 16: _srecordf (reg->str, "%s = _xtoquad (%s)", lhs.str, rhs.str); break;
183 }
184 } else if (lhs.mode.type == INTEGER) {
185 // integer = real*32
186 switch (lhs.mode.len) {
187 case 2: _srecordf (reg->str, "%s = (int_2) _xint8 (%s)", lhs.str, rhs.str); break;
188 case 4: _srecordf (reg->str, "%s = (int_4) _xint8 (%s)", lhs.str, rhs.str); break;
189 case 8: _srecordf (reg->str, "%s = _xint8 (%s)", lhs.str, rhs.str); break;
190 }
191 } else {
192 ASSIGN_ERROR ("incompatible assignment")
193 }
194 } else if (lhs.mode.type == INTEGER && lhs.mode.len == 4 && rhs.mode.type == CHARACTER) {
195 _srecordf (reg->str, "%s = _str_to_int4 (%s)", lhs.str, rhs.str);
196 } else if (lhs.mode.type == REAL && lhs.mode.len == 8 && rhs.mode.type == CHARACTER) {
197 _srecordf (reg->str, "%s = _str_to_real8 (%s)", lhs.str, rhs.str);
198 } else {
199 _srecordf (reg->str, "%s = %s", lhs.str, rhs.str);
200 // ASSIGN_ERROR ("incompatible assignment")
201 }
202 skip_card (TRUE);
203 (void) rc;
204 }
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|