|
|
1 //! @file genie-rows.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 //! Interpreter routines for ROW values. 25 26 // An A68G row is a reference to a descriptor in the heap: 27 // 28 // A68G_REF row -> A68G_ARRAY ----+ ARRAY: Description of row, ref to elements. 29 // A68G_TUPLE 1 | TUPLE: Bounds, one for every dimension. 30 // ... | 31 // A68G_TUPLE dim | 32 // ... | 33 // ... | 34 // Element 1 <---+ Sequential row elements in the heap. 35 // ... 36 // Element n 37 38 #include "a68g.h" 39 #include "a68g-genie.h" 40 #include "a68g-prelude.h" 41 42 // Operators for ROW values. 43 44 //! @brief OP ELEMS = (ROWS) INT 45 46 void genie_monad_elems (NODE_T * p) 47 { 48 A68G_REF row; 49 POP_REF (p, &row); 50 DECREMENT_STACK_POINTER (p, A68G_UNION_SIZE); // Pop UNION. 51 CHECK_REF (p, row, M_ROWS); 52 A68G_ARRAY *arr; A68G_TUPLE *tup; 53 GET_DESCRIPTOR (arr, tup, &row); 54 PUSH_VALUE (p, get_row_size (tup, DIM (arr)), A68G_INT); 55 } 56 57 //! @brief OP LWB = (ROWS) INT 58 59 void genie_monad_lwb (NODE_T * p) 60 { 61 A68G_REF row; 62 POP_REF (p, &row); 63 DECREMENT_STACK_POINTER (p, A68G_UNION_SIZE); // Pop UNION. 64 CHECK_REF (p, row, M_ROWS); 65 A68G_ARRAY *arr; A68G_TUPLE *tup; 66 GET_DESCRIPTOR (arr, tup, &row); 67 PUSH_VALUE (p, LWB (tup), A68G_INT); 68 } 69 70 //! @brief OP UPB = (ROWS) INT 71 72 void genie_monad_upb (NODE_T * p) 73 { 74 A68G_REF row; 75 POP_REF (p, &row); 76 DECREMENT_STACK_POINTER (p, A68G_UNION_SIZE); // Pop UNION. 77 CHECK_REF (p, row, M_ROWS); 78 A68G_ARRAY *arr; A68G_TUPLE *tup; 79 GET_DESCRIPTOR (arr, tup, &row); 80 PUSH_VALUE (p, UPB (tup), A68G_INT); 81 } 82 83 //! @brief OP ELEMS = (INT, ROWS) INT 84 85 void genie_dyad_elems (NODE_T * p) 86 { 87 A68G_REF row; 88 POP_REF (p, &row); 89 DECREMENT_STACK_POINTER (p, A68G_UNION_SIZE); // Pop UNION. 90 CHECK_REF (p, row, M_ROWS); 91 A68G_INT k; 92 POP_OBJECT (p, &k, A68G_INT); 93 A68G_ARRAY *arr; A68G_TUPLE *tup; 94 GET_DESCRIPTOR (arr, tup, &row); 95 if (VALUE (&k) < 1 || VALUE (&k) > DIM (arr)) { 96 diagnostic (A68G_RUNTIME_ERROR, p, ERROR_INVALID_DIMENSION, (int) VALUE (&k)); 97 exit_genie (p, A68G_RUNTIME_ERROR); 98 } 99 A68G_TUPLE *u = &(tup[VALUE (&k) - 1]); 100 PUSH_VALUE (p, ROW_SIZE (u), A68G_INT); 101 } 102 103 //! @brief OP LWB = (INT, ROWS) INT 104 105 void genie_dyad_lwb (NODE_T * p) 106 { 107 A68G_REF row; 108 POP_REF (p, &row); 109 DECREMENT_STACK_POINTER (p, A68G_UNION_SIZE); // Pop UNION. 110 CHECK_REF (p, row, M_ROWS); 111 A68G_INT k; 112 POP_OBJECT (p, &k, A68G_INT); 113 A68G_ARRAY *arr; A68G_TUPLE *tup; 114 GET_DESCRIPTOR (arr, tup, &row); 115 if (VALUE (&k) < 1 || VALUE (&k) > DIM (arr)) { 116 diagnostic (A68G_RUNTIME_ERROR, p, ERROR_INVALID_DIMENSION, (int) VALUE (&k)); 117 exit_genie (p, A68G_RUNTIME_ERROR); 118 } 119 PUSH_VALUE (p, LWB (&(tup[VALUE (&k) - 1])), A68G_INT); 120 } 121 122 //! @brief OP UPB = (INT, ROWS) INT 123 124 void genie_dyad_upb (NODE_T * p) 125 { 126 A68G_REF row; 127 POP_REF (p, &row); 128 DECREMENT_STACK_POINTER (p, A68G_UNION_SIZE); // Pop UNION. 129 CHECK_REF (p, row, M_ROWS); 130 A68G_INT k; 131 POP_OBJECT (p, &k, A68G_INT); 132 A68G_ARRAY *arr; A68G_TUPLE *tup; 133 GET_DESCRIPTOR (arr, tup, &row); 134 if (VALUE (&k) < 1 || VALUE (&k) > DIM (arr)) { 135 diagnostic (A68G_RUNTIME_ERROR, p, ERROR_INVALID_DIMENSION, (int) VALUE (&k)); 136 exit_genie (p, A68G_RUNTIME_ERROR); 137 } 138 PUSH_VALUE (p, UPB (&(tup[VALUE (&k) - 1])), A68G_INT); 139 }
© 2001-2026 J.M. van der Veer
jmvdveer@algol68genie.nl