|
|
1 //! @file plugin-basic.c 2 //! @author J. Marcel van der Veer 3 4 //! @section Copyright 5 //! 6 //! This file is part of Algol68G - an Algol 68 compiler-interpreter. 7 //! Copyright 2001-2026 J. Marcel van der Veer [algol68g@algol68genie.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 //! Plugin compiler routines. 25 26 #include "a68g.h" 27 #include "a68g-optimiser.h" 28 #include "a68g-plugin.h" 29 30 // Whether stuff is sufficiently "basic" to be compiled. 31 32 //! @brief Whether primitive mode, with simple C equivalent. 33 34 BOOL_T primitive_mode (const MOID_T * m) 35 { 36 if (m == M_INT) { 37 return A68G_TRUE; 38 } else if (m == M_REAL) { 39 return A68G_TRUE; 40 } else if (m == M_BOOL) { 41 return A68G_TRUE; 42 } else if (m == M_CHAR) { 43 return A68G_TRUE; 44 } else if (m == M_BITS) { 45 return A68G_TRUE; 46 } else { 47 return A68G_FALSE; 48 } 49 } 50 51 //! @brief Whether basic mode, for which units are compiled. 52 53 BOOL_T basic_mode (MOID_T * m) 54 { 55 if (primitive_mode (m)) { 56 return A68G_TRUE; 57 } else if (IS (m, REF_SYMBOL)) { 58 if (IS (SUB (m), REF_SYMBOL) || IS (SUB (m), PROC_SYMBOL)) { 59 return A68G_FALSE; 60 } else { 61 return basic_mode (SUB (m)); 62 } 63 } else if (IS (m, ROW_SYMBOL)) { 64 return A68G_FALSE; 65 // Not (fully) implemented yet. 66 // TODO: code to convert stacked units into an array. 67 // if (primitive_mode (SUB (m))) { 68 // return A68G_TRUE; 69 // } else if (IS (SUB (m), STRUCT_SYMBOL)) { 70 // return basic_mode (SUB (m)); 71 // } else { 72 // return A68G_FALSE; 73 // } 74 } else if (IS (m, STRUCT_SYMBOL)) { 75 for (PACK_T *p = PACK (m); p != NO_PACK; FORWARD (p)) { 76 if (!primitive_mode (MOID (p))) { 77 return A68G_FALSE; 78 } 79 } 80 return A68G_TRUE; 81 } else { 82 return A68G_FALSE; 83 } 84 } 85 86 //! @brief Whether basic mode, which is not a row. 87 88 BOOL_T basic_mode_non_row (MOID_T * m) 89 { 90 if (primitive_mode (m)) { 91 return A68G_TRUE; 92 } else if (IS (m, REF_SYMBOL)) { 93 if (IS (SUB (m), REF_SYMBOL) || IS (SUB (m), PROC_SYMBOL)) { 94 return A68G_FALSE; 95 } else { 96 return basic_mode_non_row (SUB (m)); 97 } 98 } else if (IS (m, STRUCT_SYMBOL)) { 99 for (PACK_T *p = PACK (m); p != NO_PACK; FORWARD (p)) { 100 if (!primitive_mode (MOID (p))) { 101 return A68G_FALSE; 102 } 103 } 104 return A68G_TRUE; 105 } else { 106 return A68G_FALSE; 107 } 108 } 109 110 //! @brief Whether basic collateral clause. 111 112 BOOL_T basic_collateral (NODE_T * p) 113 { 114 if (p == NO_NODE) { 115 return A68G_TRUE; 116 } else if (IS (p, UNIT)) { 117 return (BOOL_T) (basic_mode (MOID (p)) && basic_unit (SUB (p)) && basic_collateral (NEXT (p))); 118 } else { 119 return (BOOL_T) (basic_collateral (SUB (p)) && basic_collateral (NEXT (p))); 120 } 121 } 122 123 //! @brief Whether basic serial clause. 124 125 void count_basic_units (NODE_T * p, int *total, int *good) 126 { 127 for (; p != NO_NODE; FORWARD (p)) { 128 if (IS (p, UNIT)) { 129 (*total)++; 130 if (basic_unit (p)) { 131 (*good)++; 132 } 133 } else if (IS (p, DECLARATION_LIST)) { 134 (*total)++; 135 } else { 136 count_basic_units (SUB (p), total, good); 137 } 138 } 139 } 140 141 //! @brief Whether basic serial clause. 142 143 BOOL_T basic_serial (NODE_T * p, int want) 144 { 145 int total = 0, good = 0; 146 count_basic_units (p, &total, &good); 147 if (want > 0) { 148 return total == want && total == good; 149 } else { 150 return total == good; 151 } 152 } 153 154 //! @brief Whether basic indexer. 155 156 BOOL_T basic_indexer (NODE_T * p) 157 { 158 if (p == NO_NODE) { 159 return A68G_TRUE; 160 } else if (IS (p, TRIMMER)) { 161 return A68G_FALSE; 162 } else if (IS (p, UNIT)) { 163 return basic_unit (p); 164 } else { 165 return (BOOL_T) (basic_indexer (SUB (p)) && basic_indexer (NEXT (p))); 166 } 167 } 168 169 //! @brief Whether basic slice. 170 171 BOOL_T basic_slice (NODE_T * p) 172 { 173 if (IS (p, SLICE)) { 174 NODE_T *prim = SUB (p); 175 NODE_T *idf = stems_from (prim, IDENTIFIER); 176 if (idf != NO_NODE) { 177 NODE_T *indx = NEXT (prim); 178 return basic_indexer (indx); 179 } 180 } 181 return A68G_FALSE; 182 } 183 184 //! @brief Whether basic argument. 185 186 BOOL_T basic_argument (NODE_T * p) 187 { 188 if (p == NO_NODE) { 189 return A68G_TRUE; 190 } else if (IS (p, UNIT)) { 191 return (BOOL_T) (basic_mode (MOID (p)) && basic_unit (p) && basic_argument (NEXT (p))); 192 } else { 193 return (BOOL_T) (basic_argument (SUB (p)) && basic_argument (NEXT (p))); 194 } 195 } 196 197 //! @brief Whether basic call. 198 199 BOOL_T basic_call (NODE_T * p) 200 { 201 if (IS (p, CALL)) { 202 NODE_T *prim = SUB (p); 203 NODE_T *idf = stems_from (prim, IDENTIFIER); 204 if (idf == NO_NODE) { 205 return A68G_FALSE; 206 } else if (SUB_MOID (idf) == MOID (p)) { // Prevent partial parametrisation 207 for (int k = 0; PROCEDURE (&functions[k]) != NO_GPROC; k++) { 208 if (PROCEDURE (TAX (idf)) == PROCEDURE (&functions[k])) { 209 NODE_T *args = NEXT (prim); 210 return basic_argument (args); 211 } 212 } 213 } 214 } 215 return A68G_FALSE; 216 } 217 218 //! @brief Whether basic monadic formula. 219 220 BOOL_T basic_monadic_formula (NODE_T * p) 221 { 222 if (IS (p, MONADIC_FORMULA)) { 223 NODE_T *op = SUB (p); 224 for (int k = 0; PROCEDURE (&monadics[k]) != NO_GPROC; k++) { 225 if (PROCEDURE (TAX (op)) == PROCEDURE (&monadics[k])) { 226 NODE_T *rhs = NEXT (op); 227 return basic_unit (rhs); 228 } 229 } 230 } 231 return A68G_FALSE; 232 } 233 234 //! @brief Whether basic dyadic formula. 235 236 BOOL_T basic_formula (NODE_T * p) 237 { 238 if (IS (p, FORMULA)) { 239 NODE_T *lhs = SUB (p); 240 NODE_T *op = NEXT (lhs); 241 if (op == NO_NODE) { 242 return basic_monadic_formula (lhs); 243 } else { 244 for (int k = 0; PROCEDURE (&dyadics[k]) != NO_GPROC; k++) { 245 if (PROCEDURE (TAX (op)) == PROCEDURE (&dyadics[k])) { 246 NODE_T *rhs = NEXT (op); 247 return (BOOL_T) (basic_unit (lhs) && basic_unit (rhs)); 248 } 249 } 250 } 251 } 252 return A68G_FALSE; 253 } 254 255 //! @brief Whether basic conditional clause. 256 257 BOOL_T basic_conditional (NODE_T * p) 258 { 259 if (!(IS (p, IF_PART) || IS (p, OPEN_PART))) { 260 return A68G_FALSE; 261 } 262 if (!basic_serial (NEXT_SUB (p), 1)) { 263 return A68G_FALSE; 264 } 265 FORWARD (p); 266 if (!(IS (p, THEN_PART) || IS (p, CHOICE))) { 267 return A68G_FALSE; 268 } 269 if (!basic_serial (NEXT_SUB (p), 1)) { 270 return A68G_FALSE; 271 } 272 FORWARD (p); 273 if (IS (p, ELSE_PART) || IS (p, CHOICE)) { 274 return basic_serial (NEXT_SUB (p), 1); 275 } else if (IS (p, FI_SYMBOL)) { 276 return A68G_TRUE; 277 } else { 278 return A68G_FALSE; 279 } 280 } 281 282 //! @brief Whether basic unit. 283 284 BOOL_T basic_unit (NODE_T * p) 285 { 286 if (p == NO_NODE) { 287 return A68G_FALSE; 288 } else if (IS (p, UNIT)) { 289 return basic_unit (SUB (p)); 290 } else if (IS (p, TERTIARY)) { 291 return basic_unit (SUB (p)); 292 } else if (IS (p, SECONDARY)) { 293 return basic_unit (SUB (p)); 294 } else if (IS (p, PRIMARY)) { 295 return basic_unit (SUB (p)); 296 } else if (IS (p, ENCLOSED_CLAUSE)) { 297 return basic_unit (SUB (p)); 298 } 299 if (A68G_OPT (OPTION_CODE_LEVEL) >= 3) { 300 if (IS (p, CLOSED_CLAUSE)) { 301 return basic_serial (NEXT_SUB (p), 1); 302 } else if (IS (p, COLLATERAL_CLAUSE)) { 303 return basic_mode (MOID (p)) && basic_collateral (NEXT_SUB (p)); 304 } else if (IS (p, CONDITIONAL_CLAUSE)) { 305 return basic_mode (MOID (p)) && basic_conditional (SUB (p)); 306 } 307 } 308 if (A68G_OPT (OPTION_CODE_LEVEL) >= 2) { 309 if (IS (p, VOIDING) && IS (SUB (p), ASSIGNATION) && stems_from (SUB_SUB (p), IDENTIFIER) != NO_NODE) { 310 NODE_T *dst = SUB_SUB (p); 311 NODE_T *src = NEXT_NEXT (dst); 312 return (BOOL_T) basic_unit (src) && basic_mode_non_row (MOID (src)); 313 } else if (IS (p, VOIDING) && IS (SUB (p), ASSIGNATION) && stems_from (SUB_SUB (p), SLICE) != NO_NODE) { 314 NODE_T *dst = SUB_SUB (p); 315 NODE_T *src = NEXT_NEXT (dst); 316 NODE_T *slice = stems_from (dst, SLICE); 317 return (BOOL_T) (IS (MOID (slice), REF_SYMBOL) && basic_slice (slice) && basic_unit (src) && basic_mode_non_row (MOID (src))); 318 } else if (IS (p, VOIDING) && IS (SUB (p), ASSIGNATION) && stems_from (SUB_SUB (p), SELECTION) != NO_NODE) { 319 NODE_T *dst = SUB_SUB (p); 320 NODE_T *src = NEXT_NEXT (dst); 321 return (BOOL_T) (stems_from (NEXT_SUB (stems_from (dst, SELECTION)), IDENTIFIER) != NO_NODE && basic_unit (src) && basic_mode_non_row (MOID (dst))); 322 } else if (IS (p, VOIDING)) { 323 return basic_unit (SUB (p)); 324 } else if (IS (p, DEREFERENCING) && stems_from (SUB (p), SLICE)) { 325 NODE_T *slice = stems_from (SUB (p), SLICE); 326 return (BOOL_T) (basic_mode (MOID (p)) && IS (MOID (SUB (slice)), REF_SYMBOL) && basic_slice (slice)); 327 } else if (IS (p, DEREFERENCING) && stems_from (SUB (p), SELECTION)) { 328 return (BOOL_T) (primitive_mode (MOID (p)) && BASIC (SUB (p), SELECTION)); 329 } else if (IS (p, WIDENING)) { 330 if (WIDEN_TO (p, INT, REAL)) { 331 return basic_unit (SUB (p)); 332 } else if (WIDEN_TO (p, REAL, COMPLEX)) { 333 return basic_unit (SUB (p)); 334 } else { 335 return A68G_FALSE; 336 } 337 } else if (IS (p, CAST)) { 338 return (BOOL_T) (folder_mode (MOID (SUB (p))) && basic_unit (NEXT_SUB (p))); 339 } else if (IS (p, SLICE)) { 340 return (BOOL_T) (basic_mode (MOID (p)) && basic_slice (p)); 341 } else if (IS (p, SELECTION)) { 342 NODE_T *sec = stems_from (NEXT_SUB (p), IDENTIFIER); 343 if (sec == NO_NODE) { 344 return A68G_FALSE; 345 } else { 346 return basic_mode_non_row (MOID (sec)); 347 } 348 } else if (IS (p, IDENTITY_RELATION)) { 349 #define GOOD(p) (stems_from (p, IDENTIFIER) != NO_NODE && IS (MOID (stems_from ((p), IDENTIFIER)), REF_SYMBOL)) 350 NODE_T *lhs = SUB (p); 351 NODE_T *rhs = NEXT_NEXT (lhs); 352 if (GOOD (lhs) && GOOD (rhs)) { 353 return A68G_TRUE; 354 } else if (GOOD (lhs) && stems_from (rhs, NIHIL) != NO_NODE) { 355 return A68G_TRUE; 356 } else { 357 return A68G_FALSE; 358 } 359 #undef GOOD 360 } 361 } 362 if (A68G_OPT (OPTION_CODE_LEVEL) >= 1) { 363 if (IS (p, IDENTIFIER)) { 364 if (A68G_STANDENV_PROC (TAX (p))) { 365 for (int k = 0; PROCEDURE (&constants[k]) != NO_GPROC; k++) { 366 if (PROCEDURE (TAX (p)) == PROCEDURE (&constants[k])) { 367 return A68G_TRUE; 368 } 369 } 370 return A68G_FALSE; 371 } else { 372 return basic_mode (MOID (p)); 373 } 374 } else if (IS (p, DEREFERENCING) && stems_from (SUB (p), IDENTIFIER)) { 375 return (BOOL_T) (basic_mode (MOID (p)) && BASIC (SUB (p), IDENTIFIER)); 376 } else if (IS (p, DENOTATION)) { 377 return primitive_mode (MOID (p)); 378 } else if (IS (p, MONADIC_FORMULA)) { 379 return (BOOL_T) (basic_mode (MOID (p)) && basic_monadic_formula (p)); 380 } else if (IS (p, FORMULA)) { 381 return (BOOL_T) (basic_mode (MOID (p)) && basic_formula (p)); 382 } else if (IS (p, CALL)) { 383 return (BOOL_T) (basic_mode (MOID (p)) && basic_call (p)); 384 } 385 } 386 return A68G_FALSE; 387 } 388
© 2001-2026 J.M. van der Veer
jmvdveer@algol68genie.nl