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