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