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 __self, __attr obj) 35 { 36 return __INTEGER(obj) ? __builtins___boolean_True : __builtins___boolean_False; 37 } 38 39 __attr __fn_native_int_int_add(__attr __self, __attr self, __attr other) 40 { 41 /* self and other interpreted as int */ 42 int i = __TOINT(self); 43 int j = __TOINT(other); 44 45 /* Test for overflow. */ 46 if (((i > 0) && (j > 0) && (i > __MAXINT - j)) || 47 ((i < 0) && (j < 0) && (i < __MININT - j))) 48 49 __raise_overflow_error(); 50 51 /* Return the new integer. */ 52 return __new_int(i + j); 53 } 54 55 __attr __fn_native_int_int_sub(__attr __self, __attr self, __attr other) 56 { 57 /* self and other interpreted as int */ 58 int i = __TOINT(self); 59 int j = __TOINT(other); 60 61 /* Test for overflow. */ 62 if (((i < 0) && (j > 0) && (i < __MININT + j)) || 63 ((i > 0) && (j < 0) && (i > __MAXINT + j))) 64 65 __raise_overflow_error(); 66 67 /* Return the new integer. */ 68 return __new_int(i - j); 69 } 70 71 __attr __fn_native_int_int_mul(__attr __self, __attr self, __attr other) 72 { 73 /* self and other interpreted as int */ 74 int i = __TOINT(self); 75 int j = __TOINT(other); 76 77 /* Test for overflow. */ 78 if (((i > 0) && (j > 0) && (i > __MAXINT / j)) || 79 ((i < 0) && (j < 0) && (i > __MAXINT / j)) || 80 ((i < 0) && (j > 0) && (i < __MININT / j)) || 81 ((i > 0) && (j < 0) && (j < __MININT / i))) 82 83 __raise_overflow_error(); 84 85 /* Return the new integer. */ 86 return __new_int(i * j); 87 } 88 89 __attr __fn_native_int_int_div(__attr __self, __attr self, __attr other) 90 { 91 /* self and other interpreted as int */ 92 int i = __TOINT(self); 93 int j = __TOINT(other); 94 95 /* Test for division by zero or overflow. */ 96 if (j == 0) 97 __raise_zero_division_error(); 98 else if ((j == -1) && (i == __MININT)) 99 __raise_overflow_error(); 100 101 /* Return the new integer. */ 102 return __new_int(i / j); 103 } 104 105 __attr __fn_native_int_int_mod(__attr __self, __attr self, __attr other) 106 { 107 /* self and other interpreted as int */ 108 int i = __TOINT(self); 109 int j = __TOINT(other); 110 111 /* Test for division by zero or overflow. */ 112 if (j == 0) 113 __raise_zero_division_error(); 114 else if ((j == -1) && (i == __MININT)) 115 __raise_overflow_error(); 116 117 /* Return the new integer. */ 118 return __new_int(i % j); 119 } 120 121 __attr __fn_native_int_int_neg(__attr __self, __attr self) 122 { 123 /* self interpreted as int */ 124 int i = __TOINT(self); 125 126 /* Test for overflow. */ 127 if (i == __MININT) 128 __raise_overflow_error(); 129 130 /* Return the new integer. */ 131 return __new_int(-i); 132 } 133 134 __attr __fn_native_int_int_pow(__attr __self, __attr self, __attr other) 135 { 136 /* self and other interpreted as int */ 137 int i = __TOINT(self); 138 int j = __TOINT(other); 139 int k; 140 141 errno = 0; 142 k = (int) pow(i, j); 143 144 /* Test for overflow. */ 145 146 if (errno == ERANGE) 147 __raise_overflow_error(); 148 149 /* Return the new integer. */ 150 return __new_int(k); 151 } 152 153 __attr __fn_native_int_int_and(__attr __self, __attr self, __attr other) 154 { 155 /* self and other interpreted as int */ 156 int i = __TOINT(self); 157 int j = __TOINT(other); 158 159 /* Return the new integer. */ 160 /* NOTE: No overflow test applied. */ 161 return __new_int(i & j); 162 } 163 164 __attr __fn_native_int_int_not(__attr __self, __attr self) 165 { 166 /* self interpreted as int */ 167 int i = __TOINT(self); 168 169 /* Return the new integer. */ 170 return __new_int(~i); 171 } 172 173 __attr __fn_native_int_int_or(__attr __self, __attr self, __attr other) 174 { 175 /* self and other interpreted as int */ 176 int i = __TOINT(self); 177 int j = __TOINT(other); 178 179 /* Return the new integer. */ 180 /* NOTE: No overflow test applied. */ 181 return __new_int(i | j); 182 } 183 184 __attr __fn_native_int_int_xor(__attr __self, __attr self, __attr other) 185 { 186 /* self and other interpreted as int */ 187 int i = __TOINT(self); 188 int j = __TOINT(other); 189 190 /* Return the new integer. */ 191 /* NOTE: No overflow test applied. */ 192 return __new_int(i ^ j); 193 } 194 195 __attr __fn_native_int_int_lshift(__attr __self, __attr self, __attr other) 196 { 197 /* self and other interpreted as int */ 198 int i = __TOINT(self); 199 int j = __TOINT(other); 200 201 /* Return the new integer. */ 202 /* NOTE: No overflow test applied. */ 203 return __new_int(i << j); 204 } 205 206 __attr __fn_native_int_int_rshift(__attr __self, __attr self, __attr other) 207 { 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 __self, __attr self, __attr other) 218 { 219 /* self and other interpreted as int */ 220 int i = __TOINT(self); 221 int j = __TOINT(other); 222 223 /* Return a boolean result. */ 224 return i <= j ? __builtins___boolean_True : __builtins___boolean_False; 225 } 226 227 __attr __fn_native_int_int_lt(__attr __self, __attr self, __attr other) 228 { 229 /* self and other interpreted as int */ 230 int i = __TOINT(self); 231 int j = __TOINT(other); 232 233 /* Return a boolean result. */ 234 return i < j ? __builtins___boolean_True : __builtins___boolean_False; 235 } 236 237 __attr __fn_native_int_int_ge(__attr __self, __attr self, __attr other) 238 { 239 /* self and other interpreted as int */ 240 int i = __TOINT(self); 241 int j = __TOINT(other); 242 243 /* Return a boolean result. */ 244 return i >= j ? __builtins___boolean_True : __builtins___boolean_False; 245 } 246 247 __attr __fn_native_int_int_gt(__attr __self, __attr self, __attr other) 248 { 249 /* self and other interpreted as int */ 250 int i = __TOINT(self); 251 int j = __TOINT(other); 252 253 /* Return a boolean result. */ 254 return i > j ? __builtins___boolean_True : __builtins___boolean_False; 255 } 256 257 __attr __fn_native_int_int_eq(__attr __self, __attr self, __attr other) 258 { 259 /* self and other interpreted as int */ 260 int i = __TOINT(self); 261 int j = __TOINT(other); 262 263 /* Return a boolean result. */ 264 return i == j ? __builtins___boolean_True : __builtins___boolean_False; 265 } 266 267 __attr __fn_native_int_int_ne(__attr __self, __attr self, __attr other) 268 { 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_str(__attr __self, __attr self) 278 { 279 /* self interpreted as int */ 280 int i = __TOINT(self); 281 282 /* Employ a buffer big enough to fit the largest integer plus an extra 283 character, a minus sign, and the null terminator. */ 284 unsigned int n = (int) log10(__MAXINT) + 3; 285 char *s = (char *) __ALLOCATE(n, sizeof(char)); 286 287 snprintf(s, n, "%d", i); 288 289 /* Return a new string. */ 290 return __new_str(s, strlen(s)); 291 } 292 293 /* Module initialisation. */ 294 295 void __main_native_int() 296 { 297 }