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-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 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 ();
46 return;
47 }
48 if (lhs.variant == EXPR_VAR) {
49 IDENT *idf = impl_decl (lhs.str, NULL);
50 if (idf != NULL && idf->mode.dim != 0) {
51 ERROR (103, "cannot assign to dimensioned variable", curlex);
52 skip_card ();
53 return;
54 }
55 }
56 rc = scan (NULL);
57 if (TOKEN ("=")) {
58 rc = scan (NULL);
59 exprio (&rhs, 1, TRUE);
60 (void) fold_expr (&rhs, rhs.mode.type);
61 rc = scan (NULL);
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 WARNING (105, "possible loss of precision", NULL);
69 }
70 }
71 if (lhs.mode.type == COMPLEX && rhs.mode.type == COMPLEX) {
72 if (lhs.mode.len != rhs.mode.len) {
73 WARNING (106, "possible loss of precision", NULL);
74 }
75 }
76 if (lhs.mode.type == COMPLEX && rhs.mode.type == REAL) {
77 if (lhs.mode.len != 2 * rhs.mode.len) {
78 WARNING (107, "possible loss of precision", NULL);
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 (lhs.mode.type == REAL && lhs.mode.len == 32) {
99 if (rhs.mode.type == REAL) {
100 // real*32 = real
101 if (rhs.variant == EXPR_CONST) {
102 _srecordf (rhs.str, "_dc_%d", code_real_32_const (pretty_float (rhs.str)));
103 _srecordf (reg->str, "%s = %s", lhs.str, rhs.str);
104 } else {
105 switch (rhs.mode.len) {
106 case 4: _srecordf (reg->str, "%s = flttox (%s)", lhs.str, rhs.str); break;
107 case 8: _srecordf (reg->str, "%s = dbltox (%s)", lhs.str, rhs.str); break;
108 case 16: _srecordf (reg->str, "%s = _quadtox (%s)", lhs.str, rhs.str); break;
109 }
110 }
111 } else if (rhs.mode.type == INTEGER) {
112 // real*32 = integer
113 switch (rhs.mode.len) {
114 case 2: _srecordf (reg->str, "%s = inttox (%s)", lhs.str, rhs.str); break;
115 case 4: _srecordf (reg->str, "%s = inttox (%s)", lhs.str, rhs.str); break;
116 case 8: _srecordf (reg->str, "%s = _quadtox (%s)", lhs.str, rhs.str); break;
117 }
118 } else {
119 ASSIGN_ERROR ("incompatible assignment")
120 }
121 } else if (lhs.mode.type == COMPLEX && lhs.mode.len == 64) {
122 if (rhs.mode.type == COMPLEX) {
123 // complex*64 = complex
124 switch (rhs.mode.len) {
125 case 8: _srecordf (reg->str, "%s = cxdbl (%s)", lhs.str, rhs.str); break;
126 case 16: _srecordf (reg->str, "%s = cxdbl (%s)", lhs.str, rhs.str); break;
127 case 32: _srecordf (reg->str, "%s = cxquad (%s)", lhs.str, rhs.str); break;
128 }
129 } else if (rhs.mode.type == REAL) {
130 // complex*64 = real
131 switch (rhs.mode.len) {
132 case 4: _srecordf (reg->str, "%s = cxdbl (CMPLX (%s, 0.0))", lhs.str, rhs.str); break;
133 case 8: _srecordf (reg->str, "%s = cxdbl (CMPLX (%s, 0.0))", lhs.str, rhs.str); break;
134 case 16: _srecordf (reg->str, "%s = cxquad (CMPLXQ (%s, 0.0q))", lhs.str, rhs.str); break;
135 case 32: _srecordf (reg->str, "%s = cxreal32 (%s)", lhs.str, rhs.str); break;
136 }
137 } else if (rhs.mode.type == INTEGER) {
138 // complex*64 = integer
139 switch (rhs.mode.len) {
140 case 2:
141 case 4: _srecordf (reg->str, "%s = cxdbl (CMPLX (%s, 0.0))", lhs.str, rhs.str); break;
142 case 8: _srecordf (reg->str, "%s = cxquad (CMPLXQ (%s, 0.0q))", lhs.str, rhs.str); break;
143 }
144 } else {
145 ASSIGN_ERROR ("incompatible assignment")
146 }
147 } else if (rhs.mode.type == REAL && rhs.mode.len == 32) {
148 if (lhs.mode.type == COMPLEX) {
149 // complex = real*32
150 switch (lhs.mode.len) {
151 case 8: _srecordf (reg->str, "%s = xtoflt (%s)", lhs.str, rhs.str); break;
152 case 16: _srecordf (reg->str, "%s = xtodbl (%s)", lhs.str, rhs.str); break;
153 case 32: _srecordf (reg->str, "%s = _xtoquad (%s)", lhs.str, rhs.str); break;
154 }
155 } else if (lhs.mode.type == REAL) {
156 // real = real*32
157 switch (lhs.mode.len) {
158 case 4: _srecordf (reg->str, "%s = xtoflt (%s)", lhs.str, rhs.str); break;
159 case 8: _srecordf (reg->str, "%s = xtodbl (%s)", lhs.str, rhs.str); break;
160 case 16: _srecordf (reg->str, "%s = _xtoquad (%s)", lhs.str, rhs.str); break;
161 }
162 } else if (lhs.mode.type == INTEGER) {
163 // integer = real*32
164 switch (lhs.mode.len) {
165 case 2: _srecordf (reg->str, "%s = (int_2) _xint8 (%s)", lhs.str, rhs.str); break;
166 case 4: _srecordf (reg->str, "%s = (int_4) _xint8 (%s)", lhs.str, rhs.str); break;
167 case 8: _srecordf (reg->str, "%s = _xint8 (%s)", lhs.str, rhs.str); break;
168 }
169 } else {
170 ASSIGN_ERROR ("incompatible assignment")
171 }
172 } else if (lhs.mode.type == INTEGER && lhs.mode.len == 4 && rhs.mode.type == CHARACTER) {
173 _srecordf (reg->str, "%s = _int4 (%s)", lhs.str, rhs.str);
174 } else {
175 _srecordf (reg->str, "%s = %s", lhs.str, rhs.str);
176 // ASSIGN_ERROR ("incompatible assignment")
177 }
178 skip_card_expr ();
179 (void) rc;
180 }
© 2002-2024 J.M. van der Veer (jmvdveer@xs4all.nl)
|