Lichen

templates/native/int.c

570:4e9856fce8e3
2017-02-11 Paul Boddie Tidied up table output and made use of convenience macros. attr-strvalue-without-size
     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, strlen */    22 #include <errno.h>  /* errno */    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 __args[])    35 {    36     __attr * const _data = &__args[1];    37     __attr * const other = &__args[2];    38     /* _data and other interpreted as int */    39     int i = _data->intvalue;    40     int j = other->intvalue;    41     42     /* Test for overflow. */    43     if (((i > 0) && (j > 0) && (i > INT_MAX - j)) ||    44         ((i < 0) && (j < 0) && (i < INT_MIN - j)))    45     46         __raise_overflow_error();    47     48     /* Return the new integer. */    49     return __new_int(i + j);    50 }    51     52 __attr __fn_native_int_int_sub(__attr __args[])    53 {    54     __attr * const _data = &__args[1];    55     __attr * const other = &__args[2];    56     /* _data and other interpreted as int */    57     int i = _data->intvalue;    58     int j = other->intvalue;    59     60     /* Test for overflow. */    61     if (((i < 0) && (j > 0) && (i < INT_MIN + j)) ||    62         ((i > 0) && (j < 0) && (i > INT_MAX + j)))    63     64         __raise_overflow_error();    65     66     /* Return the new integer. */    67     return __new_int(i - j);    68 }    69     70 __attr __fn_native_int_int_mul(__attr __args[])    71 {    72     __attr * const _data = &__args[1];    73     __attr * const other = &__args[2];    74     /* _data and other interpreted as int */    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 __args[])    91 {    92     __attr * const _data = &__args[1];    93     __attr * const other = &__args[2];    94     /* _data and other interpreted as int */    95     int i = _data->intvalue;    96     int j = other->intvalue;    97     98     /* Test for division by zero or overflow. */    99     if (j == 0)   100         __raise_zero_division_error();   101     else if ((j == -1) && (i == INT_MIN))   102         __raise_overflow_error();   103    104     /* Return the new integer. */   105     return __new_int(i / j);   106 }   107    108 __attr __fn_native_int_int_mod(__attr __args[])   109 {   110     __attr * const _data = &__args[1];   111     __attr * const other = &__args[2];   112     /* _data and other interpreted as int */   113     int i = _data->intvalue;   114     int j = other->intvalue;   115    116     /* Test for division by zero or overflow. */   117     if (j == 0)   118         __raise_zero_division_error();   119     else if ((j == -1) && (i == INT_MIN))   120         __raise_overflow_error();   121    122     /* Return the new integer. */   123     return __new_int(i % j);   124 }   125    126 __attr __fn_native_int_int_neg(__attr __args[])   127 {   128     __attr * const _data = &__args[1];   129     /* _data interpreted as int */   130     int i = _data->intvalue;   131    132     /* Test for overflow. */   133     if (i == INT_MIN)   134         __raise_overflow_error();   135    136     /* Return the new integer. */   137     return __new_int(-i);   138 }   139    140 __attr __fn_native_int_int_pow(__attr __args[])   141 {   142     __attr * const _data = &__args[1];   143     __attr * const other = &__args[2];   144     /* _data and other interpreted as int */   145     int i = _data->intvalue;   146     int j = other->intvalue;   147     int k;   148    149     errno = 0;   150     k = (int) pow(i, j);   151    152     /* Test for overflow. */   153    154     if (errno == ERANGE)   155         __raise_overflow_error();   156    157     /* Return the new integer. */   158     return __new_int(k);   159 }   160    161 __attr __fn_native_int_int_and(__attr __args[])   162 {   163     __attr * const _data = &__args[1];   164     __attr * const other = &__args[2];   165     /* _data and other interpreted as int */   166     int i = _data->intvalue;   167     int j = other->intvalue;   168    169     /* Return the new integer. */   170     /* NOTE: No overflow test applied. */   171     return __new_int(i & j);   172 }   173    174 __attr __fn_native_int_int_not(__attr __args[])   175 {   176     __attr * const _data = &__args[1];   177     /* _data interpreted as int */   178     int i = _data->intvalue;   179    180     /* Return the new integer. */   181     return __new_int(~i);   182 }   183    184 __attr __fn_native_int_int_or(__attr __args[])   185 {   186     __attr * const _data = &__args[1];   187     __attr * const other = &__args[2];   188     /* _data and other interpreted as int */   189     int i = _data->intvalue;   190     int j = other->intvalue;   191    192     /* Return the new integer. */   193     /* NOTE: No overflow test applied. */   194     return __new_int(i | j);   195 }   196    197 __attr __fn_native_int_int_xor(__attr __args[])   198 {   199     __attr * const _data = &__args[1];   200     __attr * const other = &__args[2];   201     /* _data and other interpreted as int */   202     int i = _data->intvalue;   203     int j = other->intvalue;   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_lt(__attr __args[])   211 {   212     __attr * const _data = &__args[1];   213     __attr * const other = &__args[2];   214     /* _data and other interpreted as int */   215     int i = _data->intvalue;   216     int j = other->intvalue;   217    218     /* Return a boolean result. */   219     return i < j ? __builtins___boolean_True : __builtins___boolean_False;   220 }   221    222 __attr __fn_native_int_int_gt(__attr __args[])   223 {   224     __attr * const _data = &__args[1];   225     __attr * const other = &__args[2];   226     /* _data and other interpreted as int */   227     int i = _data->intvalue;   228     int j = other->intvalue;   229    230     /* Return a boolean result. */   231     return i > j ? __builtins___boolean_True : __builtins___boolean_False;   232 }   233    234 __attr __fn_native_int_int_eq(__attr __args[])   235 {   236     __attr * const _data = &__args[1];   237     __attr * const other = &__args[2];   238     /* _data and other interpreted as int */   239     int i = _data->intvalue;   240     int j = other->intvalue;   241    242     /* Return a boolean result. */   243     return i == j ? __builtins___boolean_True : __builtins___boolean_False;   244 }   245    246 __attr __fn_native_int_int_ne(__attr __args[])   247 {   248     __attr * const _data = &__args[1];   249     __attr * const other = &__args[2];   250     /* _data and other interpreted as int */   251     int i = _data->intvalue;   252     int j = other->intvalue;   253    254     /* Return a boolean result. */   255     return i != j ? __builtins___boolean_True : __builtins___boolean_False;   256 }   257    258 __attr __fn_native_int_int_str(__attr __args[])   259 {   260     __attr * const _data = &__args[1];   261     /* _data interpreted as int */   262     int i = _data->intvalue;   263     /* Employ a buffer big enough to fit the largest integer plus an extra   264        character, a minus sign, and the null terminator. */   265     unsigned int n = (int) log10(INT_MAX) + 3;   266     char *s = (char *) __ALLOCATE(n, sizeof(char));   267    268     snprintf(s, n, "%d", i);   269    270     /* Return a new string. */   271     return __new_str(s);   272 }   273    274 /* Module initialisation. */   275    276 void __main_native_int()   277 {   278 }