1 /* Native functions for integer operations. 2 3 Copyright (C) 2016, 2017 Paul Boddie <paul@boddie.org.uk> 4 5 This program is free software; you can redistribute it and/or modify it under 6 the terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3 of the License, or (at your option) any later 8 version. 9 10 This program is distributed in the hope that it will be useful, but WITHOUT 11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 details. 14 15 You should have received a copy of the GNU General Public License along with 16 this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <math.h> /* ceil, log10, pow */ 20 #include <stdio.h> /* fdopen, snprintf */ 21 #include <errno.h> /* errno */ 22 #include <string.h> /* strlen */ 23 #include "native/common.h" 24 #include "types.h" 25 #include "exceptions.h" 26 #include "ops.h" 27 #include "progconsts.h" 28 #include "progops.h" 29 #include "progtypes.h" 30 #include "main.h" 31 32 /* Integer operations. */ 33 34 __attr __fn_native_int_is_int(__attr __args[]) 35 { 36 __attr * const obj = &__args[1]; 37 38 return __INTEGER(*obj) ? __builtins___boolean_True : __builtins___boolean_False; 39 } 40 41 __attr __fn_native_int_int_add(__attr __args[]) 42 { 43 __attr * const self = &__args[1]; 44 __attr * const other = &__args[2]; 45 /* self and other interpreted as int */ 46 int i = __TOINT(*self); 47 int j = __TOINT(*other); 48 49 /* Test for overflow. */ 50 if (((i > 0) && (j > 0) && (i > __MAXINT - j)) || 51 ((i < 0) && (j < 0) && (i < __MININT - j))) 52 53 __raise_overflow_error(); 54 55 /* Return the new integer. */ 56 return __new_int(i + j); 57 } 58 59 __attr __fn_native_int_int_sub(__attr __args[]) 60 { 61 __attr * const self = &__args[1]; 62 __attr * const other = &__args[2]; 63 /* self and other interpreted as int */ 64 int i = __TOINT(*self); 65 int j = __TOINT(*other); 66 67 /* Test for overflow. */ 68 if (((i < 0) && (j > 0) && (i < __MININT + j)) || 69 ((i > 0) && (j < 0) && (i > __MAXINT + j))) 70 71 __raise_overflow_error(); 72 73 /* Return the new integer. */ 74 return __new_int(i - j); 75 } 76 77 __attr __fn_native_int_int_mul(__attr __args[]) 78 { 79 __attr * const self = &__args[1]; 80 __attr * const other = &__args[2]; 81 /* self and other interpreted as int */ 82 int i = __TOINT(*self); 83 int j = __TOINT(*other); 84 85 /* Test for overflow. */ 86 if (((i > 0) && (j > 0) && (i > __MAXINT / j)) || 87 ((i < 0) && (j < 0) && (i > __MAXINT / j)) || 88 ((i < 0) && (j > 0) && (i < __MININT / j)) || 89 ((i > 0) && (j < 0) && (j < __MININT / i))) 90 91 __raise_overflow_error(); 92 93 /* Return the new integer. */ 94 return __new_int(i * j); 95 } 96 97 __attr __fn_native_int_int_div(__attr __args[]) 98 { 99 __attr * const self = &__args[1]; 100 __attr * const other = &__args[2]; 101 /* self and other interpreted as int */ 102 int i = __TOINT(*self); 103 int j = __TOINT(*other); 104 105 /* Test for division by zero or overflow. */ 106 if (j == 0) 107 __raise_zero_division_error(); 108 else if ((j == -1) && (i == __MININT)) 109 __raise_overflow_error(); 110 111 /* Return the new integer. */ 112 return __new_int(i / j); 113 } 114 115 __attr __fn_native_int_int_mod(__attr __args[]) 116 { 117 __attr * const self = &__args[1]; 118 __attr * const other = &__args[2]; 119 /* self and other interpreted as int */ 120 int i = __TOINT(*self); 121 int j = __TOINT(*other); 122 123 /* Test for division by zero or overflow. */ 124 if (j == 0) 125 __raise_zero_division_error(); 126 else if ((j == -1) && (i == __MININT)) 127 __raise_overflow_error(); 128 129 /* Return the new integer. */ 130 return __new_int(i % j); 131 } 132 133 __attr __fn_native_int_int_neg(__attr __args[]) 134 { 135 __attr * const self = &__args[1]; 136 /* self interpreted as int */ 137 int i = __TOINT(*self); 138 139 /* Test for overflow. */ 140 if (i == __MININT) 141 __raise_overflow_error(); 142 143 /* Return the new integer. */ 144 return __new_int(-i); 145 } 146 147 __attr __fn_native_int_int_pow(__attr __args[]) 148 { 149 __attr * const self = &__args[1]; 150 __attr * const other = &__args[2]; 151 /* self and other interpreted as int */ 152 int i = __TOINT(*self); 153 int j = __TOINT(*other); 154 int k; 155 156 errno = 0; 157 k = (int) pow(i, j); 158 159 /* Test for overflow. */ 160 161 if (errno == ERANGE) 162 __raise_overflow_error(); 163 164 /* Return the new integer. */ 165 return __new_int(k); 166 } 167 168 __attr __fn_native_int_int_and(__attr __args[]) 169 { 170 __attr * const self = &__args[1]; 171 __attr * const other = &__args[2]; 172 /* self and other interpreted as int */ 173 int i = __TOINT(*self); 174 int j = __TOINT(*other); 175 176 /* Return the new integer. */ 177 /* NOTE: No overflow test applied. */ 178 return __new_int(i & j); 179 } 180 181 __attr __fn_native_int_int_not(__attr __args[]) 182 { 183 __attr * const self = &__args[1]; 184 /* self interpreted as int */ 185 int i = __TOINT(*self); 186 187 /* Return the new integer. */ 188 return __new_int(~i); 189 } 190 191 __attr __fn_native_int_int_or(__attr __args[]) 192 { 193 __attr * const self = &__args[1]; 194 __attr * const other = &__args[2]; 195 /* self and other interpreted as int */ 196 int i = __TOINT(*self); 197 int j = __TOINT(*other); 198 199 /* Return the new integer. */ 200 /* NOTE: No overflow test applied. */ 201 return __new_int(i | j); 202 } 203 204 __attr __fn_native_int_int_xor(__attr __args[]) 205 { 206 __attr * const self = &__args[1]; 207 __attr * const other = &__args[2]; 208 /* self and other interpreted as int */ 209 int i = __TOINT(*self); 210 int j = __TOINT(*other); 211 212 /* Return the new integer. */ 213 /* NOTE: No overflow test applied. */ 214 return __new_int(i ^ j); 215 } 216 217 __attr __fn_native_int_int_le(__attr __args[]) 218 { 219 __attr * const self = &__args[1]; 220 __attr * const other = &__args[2]; 221 /* self and other interpreted as int */ 222 int i = __TOINT(*self); 223 int j = __TOINT(*other); 224 225 /* Return a boolean result. */ 226 return i <= j ? __builtins___boolean_True : __builtins___boolean_False; 227 } 228 229 __attr __fn_native_int_int_lt(__attr __args[]) 230 { 231 __attr * const self = &__args[1]; 232 __attr * const other = &__args[2]; 233 /* self and other interpreted as int */ 234 int i = __TOINT(*self); 235 int j = __TOINT(*other); 236 237 /* Return a boolean result. */ 238 return i < j ? __builtins___boolean_True : __builtins___boolean_False; 239 } 240 241 __attr __fn_native_int_int_ge(__attr __args[]) 242 { 243 __attr * const self = &__args[1]; 244 __attr * const other = &__args[2]; 245 /* self and other interpreted as int */ 246 int i = __TOINT(*self); 247 int j = __TOINT(*other); 248 249 /* Return a boolean result. */ 250 return i >= j ? __builtins___boolean_True : __builtins___boolean_False; 251 } 252 253 __attr __fn_native_int_int_gt(__attr __args[]) 254 { 255 __attr * const self = &__args[1]; 256 __attr * const other = &__args[2]; 257 /* self and other interpreted as int */ 258 int i = __TOINT(*self); 259 int j = __TOINT(*other); 260 261 /* Return a boolean result. */ 262 return i > j ? __builtins___boolean_True : __builtins___boolean_False; 263 } 264 265 __attr __fn_native_int_int_eq(__attr __args[]) 266 { 267 __attr * const self = &__args[1]; 268 __attr * const other = &__args[2]; 269 /* self and other interpreted as int */ 270 int i = __TOINT(*self); 271 int j = __TOINT(*other); 272 273 /* Return a boolean result. */ 274 return i == j ? __builtins___boolean_True : __builtins___boolean_False; 275 } 276 277 __attr __fn_native_int_int_ne(__attr __args[]) 278 { 279 __attr * const self = &__args[1]; 280 __attr * const other = &__args[2]; 281 /* self and other interpreted as int */ 282 int i = __TOINT(*self); 283 int j = __TOINT(*other); 284 285 /* Return a boolean result. */ 286 return i != j ? __builtins___boolean_True : __builtins___boolean_False; 287 } 288 289 __attr __fn_native_int_int_str(__attr __args[]) 290 { 291 __attr * const self = &__args[1]; 292 /* self interpreted as int */ 293 int i = __TOINT(*self); 294 /* Employ a buffer big enough to fit the largest integer plus an extra 295 character, a minus sign, and the null terminator. */ 296 unsigned int n = (int) log10(__MAXINT) + 3; 297 char *s = (char *) __ALLOCATE(n, sizeof(char)); 298 299 snprintf(s, n, "%d", i); 300 301 /* Return a new string. */ 302 return __new_str(s, strlen(s)); 303 } 304 305 /* Module initialisation. */ 306 307 void __main_native_int() 308 { 309 }