Lichen

templates/native/int.c

932:c07b0dd14f85
10 months ago Paul Boddie Moved integer instantiation support to library functions.
     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 }