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 if ((k > 0) && (k > __MAXINT)) 149 __raise_overflow_error(); 150 if ((k < 0) && (k < __MININT)) 151 __raise_overflow_error(); 152 153 /* Return the new integer. */ 154 return __new_int(k); 155 } 156 157 __attr __fn_native_int_int_and(__attr __self, __attr self, __attr other) 158 { 159 /* self and other interpreted as int */ 160 int i = __TOINT(self); 161 int j = __TOINT(other); 162 163 /* Return the new integer. */ 164 /* NOTE: No overflow test applied. */ 165 return __new_int(i & j); 166 } 167 168 __attr __fn_native_int_int_not(__attr __self, __attr self) 169 { 170 /* self interpreted as int */ 171 int i = __TOINT(self); 172 173 /* Return the new integer. */ 174 return __new_int(~i); 175 } 176 177 __attr __fn_native_int_int_or(__attr __self, __attr self, __attr other) 178 { 179 /* self and other interpreted as int */ 180 int i = __TOINT(self); 181 int j = __TOINT(other); 182 183 /* Return the new integer. */ 184 /* NOTE: No overflow test applied. */ 185 return __new_int(i | j); 186 } 187 188 __attr __fn_native_int_int_xor(__attr __self, __attr self, __attr other) 189 { 190 /* self and other interpreted as int */ 191 int i = __TOINT(self); 192 int j = __TOINT(other); 193 194 /* Return the new integer. */ 195 /* NOTE: No overflow test applied. */ 196 return __new_int(i ^ j); 197 } 198 199 __attr __fn_native_int_int_lshift(__attr __self, __attr self, __attr other) 200 { 201 /* self and other interpreted as int */ 202 int i = __TOINT(self); 203 int j = __TOINT(other); 204 205 /* Return the new integer. */ 206 /* NOTE: No overflow test applied. */ 207 return __new_int(i << j); 208 } 209 210 __attr __fn_native_int_int_rshift(__attr __self, __attr self, __attr other) 211 { 212 /* self and other interpreted as int */ 213 int i = __TOINT(self); 214 int j = __TOINT(other); 215 216 /* Return the new integer. */ 217 /* NOTE: No overflow test applied. */ 218 return __new_int(i >> j); 219 } 220 221 __attr __fn_native_int_int_le(__attr __self, __attr self, __attr other) 222 { 223 /* self and other interpreted as int */ 224 int i = __TOINT(self); 225 int j = __TOINT(other); 226 227 /* Return a boolean result. */ 228 return i <= j ? __builtins___boolean_True : __builtins___boolean_False; 229 } 230 231 __attr __fn_native_int_int_lt(__attr __self, __attr self, __attr other) 232 { 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 __self, __attr self, __attr other) 242 { 243 /* self and other interpreted as int */ 244 int i = __TOINT(self); 245 int j = __TOINT(other); 246 247 /* Return a boolean result. */ 248 return i >= j ? __builtins___boolean_True : __builtins___boolean_False; 249 } 250 251 __attr __fn_native_int_int_gt(__attr __self, __attr self, __attr other) 252 { 253 /* self and other interpreted as int */ 254 int i = __TOINT(self); 255 int j = __TOINT(other); 256 257 /* Return a boolean result. */ 258 return i > j ? __builtins___boolean_True : __builtins___boolean_False; 259 } 260 261 __attr __fn_native_int_int_eq(__attr __self, __attr self, __attr other) 262 { 263 /* self and other interpreted as int */ 264 int i = __TOINT(self); 265 int j = __TOINT(other); 266 267 /* Return a boolean result. */ 268 return i == j ? __builtins___boolean_True : __builtins___boolean_False; 269 } 270 271 __attr __fn_native_int_int_ne(__attr __self, __attr self, __attr other) 272 { 273 /* self and other interpreted as int */ 274 int i = __TOINT(self); 275 int j = __TOINT(other); 276 277 /* Return a boolean result. */ 278 return i != j ? __builtins___boolean_True : __builtins___boolean_False; 279 } 280 281 __attr __fn_native_int_int_str(__attr __self, __attr self) 282 { 283 /* self interpreted as int */ 284 int i = __TOINT(self); 285 286 /* Employ a buffer big enough to fit the largest integer plus an extra 287 character, a minus sign, and the null terminator. */ 288 unsigned int n = (int) log10(__MAXINT) + 3; 289 char *s = (char *) __ALLOCATE(n, sizeof(char)); 290 291 snprintf(s, n, "%d", i); 292 293 /* Return a new string. */ 294 return __new_str(s, strlen(s)); 295 } 296 297 /* Module initialisation. */ 298 299 void __main_native_int() 300 { 301 }