1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/templates/native/int.c Fri Dec 09 16:22:37 2016 +0100
1.3 @@ -0,0 +1,278 @@
1.4 +/* Native functions for integer operations.
1.5 +
1.6 +Copyright (C) 2016 Paul Boddie <paul@boddie.org.uk>
1.7 +
1.8 +This program is free software; you can redistribute it and/or modify it under
1.9 +the terms of the GNU General Public License as published by the Free Software
1.10 +Foundation; either version 3 of the License, or (at your option) any later
1.11 +version.
1.12 +
1.13 +This program is distributed in the hope that it will be useful, but WITHOUT
1.14 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.15 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.16 +details.
1.17 +
1.18 +You should have received a copy of the GNU General Public License along with
1.19 +this program. If not, see <http://www.gnu.org/licenses/>.
1.20 +*/
1.21 +
1.22 +#include <limits.h> /* INT_MAX, INT_MIN */
1.23 +#include <math.h> /* ceil, log10, pow */
1.24 +#include <stdio.h> /* fdopen, snprintf */
1.25 +#include <errno.h> /* errno */
1.26 +#include "native/common.h"
1.27 +#include "types.h"
1.28 +#include "exceptions.h"
1.29 +#include "ops.h"
1.30 +#include "progconsts.h"
1.31 +#include "progops.h"
1.32 +#include "progtypes.h"
1.33 +#include "main.h"
1.34 +
1.35 +/* Integer operations. */
1.36 +
1.37 +__attr __fn_native_int_int_add(__attr __args[])
1.38 +{
1.39 + __attr * const _data = &__args[1];
1.40 + __attr * const other = &__args[2];
1.41 + /* _data and other interpreted as int */
1.42 + int i = _data->intvalue;
1.43 + int j = other->intvalue;
1.44 +
1.45 + /* Test for overflow. */
1.46 + if (((i > 0) && (j > 0) && (i > INT_MAX - j)) ||
1.47 + ((i < 0) && (j < 0) && (i < INT_MIN - j)))
1.48 +
1.49 + __raise_overflow_error();
1.50 +
1.51 + /* Return the new integer. */
1.52 + return __new_int(i + j);
1.53 +}
1.54 +
1.55 +__attr __fn_native_int_int_sub(__attr __args[])
1.56 +{
1.57 + __attr * const _data = &__args[1];
1.58 + __attr * const other = &__args[2];
1.59 + /* _data and other interpreted as int */
1.60 + int i = _data->intvalue;
1.61 + int j = other->intvalue;
1.62 +
1.63 + /* Test for overflow. */
1.64 + if (((i < 0) && (j > 0) && (i < INT_MIN + j)) ||
1.65 + ((i > 0) && (j < 0) && (i > INT_MAX + j)))
1.66 +
1.67 + __raise_overflow_error();
1.68 +
1.69 + /* Return the new integer. */
1.70 + return __new_int(i - j);
1.71 +}
1.72 +
1.73 +__attr __fn_native_int_int_mul(__attr __args[])
1.74 +{
1.75 + __attr * const _data = &__args[1];
1.76 + __attr * const other = &__args[2];
1.77 + /* _data and other interpreted as int */
1.78 + int i = _data->intvalue;
1.79 + int j = other->intvalue;
1.80 +
1.81 + /* Test for overflow. */
1.82 + if (((i > 0) && (j > 0) && (i > INT_MAX / j)) ||
1.83 + ((i < 0) && (j < 0) && (i > INT_MAX / j)) ||
1.84 + ((i < 0) && (j > 0) && (i < INT_MIN / j)) ||
1.85 + ((i > 0) && (j < 0) && (j < INT_MIN / i)))
1.86 +
1.87 + __raise_overflow_error();
1.88 +
1.89 + /* Return the new integer. */
1.90 + return __new_int(i * j);
1.91 +}
1.92 +
1.93 +__attr __fn_native_int_int_div(__attr __args[])
1.94 +{
1.95 + __attr * const _data = &__args[1];
1.96 + __attr * const other = &__args[2];
1.97 + /* _data and other interpreted as int */
1.98 + int i = _data->intvalue;
1.99 + int j = other->intvalue;
1.100 +
1.101 + /* Test for division by zero or overflow. */
1.102 + if (j == 0)
1.103 + __raise_zero_division_error();
1.104 + else if ((j == -1) && (i == INT_MIN))
1.105 + __raise_overflow_error();
1.106 +
1.107 + /* Return the new integer. */
1.108 + return __new_int(i / j);
1.109 +}
1.110 +
1.111 +__attr __fn_native_int_int_mod(__attr __args[])
1.112 +{
1.113 + __attr * const _data = &__args[1];
1.114 + __attr * const other = &__args[2];
1.115 + /* _data and other interpreted as int */
1.116 + int i = _data->intvalue;
1.117 + int j = other->intvalue;
1.118 +
1.119 + /* Test for division by zero or overflow. */
1.120 + if (j == 0)
1.121 + __raise_zero_division_error();
1.122 + else if ((j == -1) && (i == INT_MIN))
1.123 + __raise_overflow_error();
1.124 +
1.125 + /* Return the new integer. */
1.126 + return __new_int(i % j);
1.127 +}
1.128 +
1.129 +__attr __fn_native_int_int_neg(__attr __args[])
1.130 +{
1.131 + __attr * const _data = &__args[1];
1.132 + /* _data interpreted as int */
1.133 + int i = _data->intvalue;
1.134 +
1.135 + /* Test for overflow. */
1.136 + if (i == INT_MIN)
1.137 + __raise_overflow_error();
1.138 +
1.139 + /* Return the new integer. */
1.140 + return __new_int(-i);
1.141 +}
1.142 +
1.143 +__attr __fn_native_int_int_pow(__attr __args[])
1.144 +{
1.145 + __attr * const _data = &__args[1];
1.146 + __attr * const other = &__args[2];
1.147 + /* _data and other interpreted as int */
1.148 + int i = _data->intvalue;
1.149 + int j = other->intvalue;
1.150 + int k;
1.151 +
1.152 + errno = 0;
1.153 + k = (int) pow(i, j);
1.154 +
1.155 + /* Test for overflow. */
1.156 +
1.157 + if (errno == ERANGE)
1.158 + __raise_overflow_error();
1.159 +
1.160 + /* Return the new integer. */
1.161 + return __new_int(k);
1.162 +}
1.163 +
1.164 +__attr __fn_native_int_int_and(__attr __args[])
1.165 +{
1.166 + __attr * const _data = &__args[1];
1.167 + __attr * const other = &__args[2];
1.168 + /* _data and other interpreted as int */
1.169 + int i = _data->intvalue;
1.170 + int j = other->intvalue;
1.171 +
1.172 + /* Return the new integer. */
1.173 + /* NOTE: No overflow test applied. */
1.174 + return __new_int(i & j);
1.175 +}
1.176 +
1.177 +__attr __fn_native_int_int_not(__attr __args[])
1.178 +{
1.179 + __attr * const _data = &__args[1];
1.180 + /* _data interpreted as int */
1.181 + int i = _data->intvalue;
1.182 +
1.183 + /* Return the new integer. */
1.184 + return __new_int(~i);
1.185 +}
1.186 +
1.187 +__attr __fn_native_int_int_or(__attr __args[])
1.188 +{
1.189 + __attr * const _data = &__args[1];
1.190 + __attr * const other = &__args[2];
1.191 + /* _data and other interpreted as int */
1.192 + int i = _data->intvalue;
1.193 + int j = other->intvalue;
1.194 +
1.195 + /* Return the new integer. */
1.196 + /* NOTE: No overflow test applied. */
1.197 + return __new_int(i | j);
1.198 +}
1.199 +
1.200 +__attr __fn_native_int_int_xor(__attr __args[])
1.201 +{
1.202 + __attr * const _data = &__args[1];
1.203 + __attr * const other = &__args[2];
1.204 + /* _data and other interpreted as int */
1.205 + int i = _data->intvalue;
1.206 + int j = other->intvalue;
1.207 +
1.208 + /* Return the new integer. */
1.209 + /* NOTE: No overflow test applied. */
1.210 + return __new_int(i ^ j);
1.211 +}
1.212 +
1.213 +__attr __fn_native_int_int_lt(__attr __args[])
1.214 +{
1.215 + __attr * const _data = &__args[1];
1.216 + __attr * const other = &__args[2];
1.217 + /* _data and other interpreted as int */
1.218 + int i = _data->intvalue;
1.219 + int j = other->intvalue;
1.220 +
1.221 + /* Return a boolean result. */
1.222 + return i < j ? __builtins___boolean_True : __builtins___boolean_False;
1.223 +}
1.224 +
1.225 +__attr __fn_native_int_int_gt(__attr __args[])
1.226 +{
1.227 + __attr * const _data = &__args[1];
1.228 + __attr * const other = &__args[2];
1.229 + /* _data and other interpreted as int */
1.230 + int i = _data->intvalue;
1.231 + int j = other->intvalue;
1.232 +
1.233 + /* Return a boolean result. */
1.234 + return i > j ? __builtins___boolean_True : __builtins___boolean_False;
1.235 +}
1.236 +
1.237 +__attr __fn_native_int_int_eq(__attr __args[])
1.238 +{
1.239 + __attr * const _data = &__args[1];
1.240 + __attr * const other = &__args[2];
1.241 + /* _data and other interpreted as int */
1.242 + int i = _data->intvalue;
1.243 + int j = other->intvalue;
1.244 +
1.245 + /* Return a boolean result. */
1.246 + return i == j ? __builtins___boolean_True : __builtins___boolean_False;
1.247 +}
1.248 +
1.249 +__attr __fn_native_int_int_ne(__attr __args[])
1.250 +{
1.251 + __attr * const _data = &__args[1];
1.252 + __attr * const other = &__args[2];
1.253 + /* _data and other interpreted as int */
1.254 + int i = _data->intvalue;
1.255 + int j = other->intvalue;
1.256 +
1.257 + /* Return a boolean result. */
1.258 + return i != j ? __builtins___boolean_True : __builtins___boolean_False;
1.259 +}
1.260 +
1.261 +__attr __fn_native_int_int_str(__attr __args[])
1.262 +{
1.263 + __attr * const _data = &__args[1];
1.264 + /* _data interpreted as int */
1.265 + int i = _data->intvalue;
1.266 + /* Employ a buffer big enough to fit the largest integer plus an extra
1.267 + character, a minus sign, and the null terminator. */
1.268 + unsigned int n = (int) log10(INT_MAX) + 3;
1.269 + char *s = (char *) __ALLOCATE(n, sizeof(char));
1.270 +
1.271 + snprintf(s, n, "%d", i);
1.272 +
1.273 + /* Return a new string. */
1.274 + return __new_str(s);
1.275 +}
1.276 +
1.277 +/* Module initialisation. */
1.278 +
1.279 +void __main_native_int()
1.280 +{
1.281 +}