Lichen

templates/native/int.c

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