Lichen

templates/native/int.c

934:2989aab1b4f7
10 months ago Paul Boddie Renamed the utf8string class to unicode, eliminating the unicode function. This means that the simple case of merely returning an object if it is already a Unicode object no longer occurs when using the unicode callable, but such behaviour might be better supported with more general customised instantiation functionality.
     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 }