Lichen

templates/native.c

307:fc291b59f67b
2016-12-03 Paul Boddie Implemented the inversion operator for integers.
     1 #include <stdlib.h> /* abs, exit */     2 #include <unistd.h> /* read, write */     3 #include <limits.h> /* INT_MAX, INT_MIN */     4 #include <math.h>   /* ceil, log10, pow */     5 #include <string.h> /* strcmp, strncpy, strlen */     6 #include <stdio.h>  /* snprintf */     7 #include <errno.h>  /* errno */     8 #include "types.h"     9 #include "exceptions.h"    10 #include "ops.h"    11 #include "progconsts.h"    12 #include "progops.h"    13 #include "progtypes.h"    14 #include "main.h"    15     16 /* Utility functions. */    17     18 static __attr __new_int(int i)    19 {    20     /* Create a new integer and mutate the __data__ attribute. */    21     __attr attr = __new(&__InstanceTable___builtins___int_int, &__builtins___int_int, sizeof(__obj___builtins___int_int));    22     attr.value->attrs[__pos___data__].intvalue = i;    23     return attr;    24 }    25     26 static __attr __new_str(char *s)    27 {    28     /* Create a new string and mutate the __data__ attribute. */    29     __attr attr = __new(&__InstanceTable___builtins___str_string, &__builtins___str_string, sizeof(__obj___builtins___str_string));    30     attr.value->attrs[__pos___data__].strvalue = s;    31     return attr;    32 }    33     34 static __attr __new_list(__fragment *f)    35 {    36     /* Create a new list and mutate the __data__ attribute. */    37     __attr attr = __new(&__InstanceTable___builtins___list_list, &__builtins___list_list, sizeof(__obj___builtins___list_list));    38     attr.value->attrs[__pos___data__].seqvalue = f;    39     return attr;    40 }    41     42 static __fragment *__fragment_append(__fragment *data, __attr * const value)    43 {    44     __fragment *newdata = data;    45     unsigned int size = data->size, capacity = data->capacity;    46     unsigned int n;    47     48     /* Re-allocate the fragment if the capacity has been reached. */    49     if (size >= capacity)    50     {    51         /* NOTE: Consider various restrictions on capacity increases. */    52         n = capacity ? capacity * 2 : 1;    53         newdata = (__fragment *) __REALLOCATE(data, __FRAGMENT_SIZE(n));    54         newdata->capacity = n;    55     }    56     57     /* Insert the new element and increment the list size. */    58     newdata->attrs[size] = *value;    59     newdata->size = size + 1;    60     61     return newdata;    62 }    63     64 /* Native functions. */    65     66 __attr __fn_native__exit(__attr __args[])    67 {    68     __attr * const status = &__args[1];    69     70     exit(__load_via_object(status->value, __pos___data__).intvalue);    71     return __builtins___none_None;    72 }    73     74 __attr __fn_native__get_argv(__attr __args[])    75 {    76     __attr * const status = &__args[1];    77     78     /* NOTE: To be written. */    79     return __builtins___none_None;    80 }    81     82 __attr __fn_native__get_path(__attr __args[])    83 {    84     __attr * const status = &__args[1];    85     86     /* NOTE: To be written. */    87     return __builtins___none_None;    88 }    89     90 __attr __fn_native__is(__attr __args[])    91 {    92     __attr * const x = &__args[1];    93     __attr * const y = &__args[2];    94     95     return x->value == y->value ? __builtins___boolean_True : __builtins___boolean_False;    96 }    97     98 __attr __fn_native__is_not(__attr __args[])    99 {   100     __attr * const x = &__args[1];   101     __attr * const y = &__args[2];   102    103     return x->value != y->value ? __builtins___boolean_True : __builtins___boolean_False;   104 }   105    106 __attr __fn_native__int_add(__attr __args[])   107 {   108     __attr * const _data = &__args[1];   109     __attr * const other = &__args[2];   110     /* _data and other interpreted as int */   111     int i = _data->intvalue;   112     int j = other->intvalue;   113    114     /* Test for overflow. */   115     if (((i > 0) && (j > 0) && (i > INT_MAX - j)) ||   116         ((i < 0) && (j < 0) && (i < INT_MIN - j)))   117    118         __raise_overflow_error();   119    120     /* Return the new integer. */   121     return __new_int(i + j);   122 }   123    124 __attr __fn_native__int_sub(__attr __args[])   125 {   126     __attr * const _data = &__args[1];   127     __attr * const other = &__args[2];   128     /* _data and other interpreted as int */   129     int i = _data->intvalue;   130     int j = other->intvalue;   131    132     /* Test for overflow. */   133     if (((i < 0) && (j > 0) && (i < INT_MIN + j)) ||   134         ((i > 0) && (j < 0) && (i > INT_MAX + j)))   135    136         __raise_overflow_error();   137    138     /* Return the new integer. */   139     return __new_int(i - j);   140 }   141    142 __attr __fn_native__int_mul(__attr __args[])   143 {   144     __attr * const _data = &__args[1];   145     __attr * const other = &__args[2];   146     /* _data and other interpreted as int */   147     int i = _data->intvalue;   148     int j = other->intvalue;   149    150     /* Test for overflow. */   151     if (((i > 0) && (j > 0) && (i > INT_MAX / j)) ||   152         ((i < 0) && (j < 0) && (i > INT_MAX / j)) ||   153         ((i < 0) && (j > 0) && (i < INT_MIN / j)) ||   154         ((i > 0) && (j < 0) && (j < INT_MIN / i)))   155    156         __raise_overflow_error();   157    158     /* Return the new integer. */   159     return __new_int(i * j);   160 }   161    162 __attr __fn_native__int_div(__attr __args[])   163 {   164     __attr * const _data = &__args[1];   165     __attr * const other = &__args[2];   166     /* _data and other interpreted as int */   167     int i = _data->intvalue;   168     int j = other->intvalue;   169    170     /* Test for division by zero or overflow. */   171     if (j == 0)   172         __raise_zero_division_error();   173     else if ((j == -1) && (i == INT_MIN))   174         __raise_overflow_error();   175    176     /* Return the new integer. */   177     return __new_int(i / j);   178 }   179    180 __attr __fn_native__int_mod(__attr __args[])   181 {   182     __attr * const _data = &__args[1];   183     __attr * const other = &__args[2];   184     /* _data and other interpreted as int */   185     int i = _data->intvalue;   186     int j = other->intvalue;   187    188     /* Test for division by zero or overflow. */   189     if (j == 0)   190         __raise_zero_division_error();   191     else if ((j == -1) && (i == INT_MIN))   192         __raise_overflow_error();   193    194     /* Return the new integer. */   195     return __new_int(i % j);   196 }   197    198 __attr __fn_native__int_neg(__attr __args[])   199 {   200     __attr * const _data = &__args[1];   201     /* _data interpreted as int */   202     int i = _data->intvalue;   203    204     /* Test for overflow. */   205     if (i == INT_MIN)   206         __raise_overflow_error();   207    208     /* Return the new integer. */   209     return __new_int(-i);   210 }   211    212 __attr __fn_native__int_pow(__attr __args[])   213 {   214     __attr * const _data = &__args[1];   215     __attr * const other = &__args[2];   216     /* _data and other interpreted as int */   217     int i = _data->intvalue;   218     int j = other->intvalue;   219     int k;   220    221     errno = 0;   222     k = (int) pow(i, j);   223    224     /* Test for overflow. */   225    226     if (errno == ERANGE)   227         __raise_overflow_error();   228    229     /* Return the new integer. */   230     return __new_int(k);   231 }   232    233 __attr __fn_native__int_and(__attr __args[])   234 {   235     __attr * const _data = &__args[1];   236     __attr * const other = &__args[2];   237     /* _data and other interpreted as int */   238     int i = _data->intvalue;   239     int j = other->intvalue;   240    241     /* Return the new integer. */   242     /* NOTE: No overflow test applied. */   243     return __new_int(i & j);   244 }   245    246 __attr __fn_native__int_not(__attr __args[])   247 {   248     __attr * const _data = &__args[1];   249     /* _data interpreted as int */   250     int i = _data->intvalue;   251    252     /* Return the new integer. */   253     return __new_int(~i);   254 }   255    256 __attr __fn_native__int_or(__attr __args[])   257 {   258     __attr * const _data = &__args[1];   259     __attr * const other = &__args[2];   260     /* _data and other interpreted as int */   261     int i = _data->intvalue;   262     int j = other->intvalue;   263    264     /* Return the new integer. */   265     /* NOTE: No overflow test applied. */   266     return __new_int(i | j);   267 }   268    269 __attr __fn_native__int_xor(__attr __args[])   270 {   271     __attr * const _data = &__args[1];   272     __attr * const other = &__args[2];   273     /* _data and other interpreted as int */   274     int i = _data->intvalue;   275     int j = other->intvalue;   276    277     /* Return the new integer. */   278     /* NOTE: No overflow test applied. */   279     return __new_int(i ^ j);   280 }   281    282 __attr __fn_native__int_lt(__attr __args[])   283 {   284     __attr * const _data = &__args[1];   285     __attr * const other = &__args[2];   286     /* _data and other interpreted as int */   287     int i = _data->intvalue;   288     int j = other->intvalue;   289    290     /* Return a boolean result. */   291     return i < j ? __builtins___boolean_True : __builtins___boolean_False;   292 }   293    294 __attr __fn_native__int_gt(__attr __args[])   295 {   296     __attr * const _data = &__args[1];   297     __attr * const other = &__args[2];   298     /* _data and other interpreted as int */   299     int i = _data->intvalue;   300     int j = other->intvalue;   301    302     /* Return a boolean result. */   303     return i > j ? __builtins___boolean_True : __builtins___boolean_False;   304 }   305    306 __attr __fn_native__int_eq(__attr __args[])   307 {   308     __attr * const _data = &__args[1];   309     __attr * const other = &__args[2];   310     /* _data and other interpreted as int */   311     int i = _data->intvalue;   312     int j = other->intvalue;   313    314     /* Return a boolean result. */   315     return i == j ? __builtins___boolean_True : __builtins___boolean_False;   316 }   317    318 __attr __fn_native__int_ne(__attr __args[])   319 {   320     __attr * const _data = &__args[1];   321     __attr * const other = &__args[2];   322     /* _data and other interpreted as int */   323     int i = _data->intvalue;   324     int j = other->intvalue;   325    326     /* Return a boolean result. */   327     return i != j ? __builtins___boolean_True : __builtins___boolean_False;   328 }   329    330 __attr __fn_native__int_str(__attr __args[])   331 {   332     __attr * const _data = &__args[1];   333     /* _data interpreted as int */   334     int i = _data->intvalue;   335     int n = i != 0 ? (int) ceil(log10(abs(i)+1)) + 1 : 2;   336     char *s = (char *) __ALLOCATE(n, sizeof(char));   337    338     if (i < 0) n++;   339     snprintf(s, n, "%d", i);   340    341     /* Return a new string. */   342     return __new_str(s);   343 }   344    345 __attr __fn_native__str_add(__attr __args[])   346 {   347     __attr * const _data = &__args[1];   348     __attr * const other = &__args[2];   349     /* _data, other interpreted as string */   350     char *s = _data->strvalue;   351     char *o = other->strvalue;   352     int n = strlen(s) + strlen(o) + 1;   353     char *r = (char *) __ALLOCATE(n, sizeof(char));   354    355     strncpy(r, s, n);   356     strncpy(r + strlen(s), o, n - strlen(s)); /* should null terminate */   357    358     /* Return a new string. */   359     return __new_str(r);   360 }   361    362 __attr __fn_native__str_lt(__attr __args[])   363 {   364     __attr * const _data = &__args[1];   365     __attr * const other = &__args[2];   366     /* _data, other interpreted as string */   367     char *s = _data->strvalue;   368     char *o = other->strvalue;   369    370     /* NOTE: Using simple byte-level string operations. */   371     return strcmp(s, o) < 0 ? __builtins___boolean_True : __builtins___boolean_False;   372 }   373    374 __attr __fn_native__str_gt(__attr __args[])   375 {   376     __attr * const _data = &__args[1];   377     __attr * const other = &__args[2];   378     /* _data, other interpreted as string */   379     char *s = _data->strvalue;   380     char *o = other->strvalue;   381    382     /* NOTE: Using simple byte-level string operations. */   383     return strcmp(s, o) > 0 ? __builtins___boolean_True : __builtins___boolean_False;   384 }   385    386 __attr __fn_native__str_eq(__attr __args[])   387 {   388     __attr * const _data = &__args[1];   389     __attr * const other = &__args[2];   390     /* _data, other interpreted as string */   391     char *s = _data->strvalue;   392     char *o = other->strvalue;   393    394     /* NOTE: Using simple byte-level string operations. */   395     return strcmp(s, o) == 0 ? __builtins___boolean_True : __builtins___boolean_False;   396 }   397    398 __attr __fn_native__str_len(__attr __args[])   399 {   400     __attr * const _data = &__args[1];   401     /* _data interpreted as string */   402     char *s = _data->strvalue;   403    404     /* Return the new integer. */   405     return __new_int(strlen(s));   406 }   407    408 __attr __fn_native__str_nonempty(__attr __args[])   409 {   410     __attr * const _data = &__args[1];   411     /* _data interpreted as string */   412     char *s = _data->strvalue;   413    414     return strlen(s) ? __builtins___boolean_True : __builtins___boolean_False;   415 }   416    417 __attr __fn_native__str_ord(__attr __args[])   418 {   419     __attr * const _data = &__args[1];   420     /* _data interpreted as string */   421     char *s = _data->strvalue;   422    423     return __new_int((unsigned int) s[0]);   424 }   425    426 __attr __fn_native__str_substr(__attr __args[])   427 {   428     __attr * const _data = &__args[1];   429     __attr * const start = &__args[2];   430     __attr * const size = &__args[3];   431     /* _data interpreted as string */   432     char *s = _data->strvalue, *sub;   433     /* start.__data__ interpreted as int */   434     int i = __load_via_object(start->value, __pos___data__).intvalue;   435     /* size.__data__ interpreted as int */   436     int l = __load_via_object(size->value, __pos___data__).intvalue;   437    438     /* Reserve space for a new string. */   439     sub = (char *) __ALLOCATE(l + 1, sizeof(char));   440     strncpy(sub, s + i, l); /* does not null terminate but final byte should be zero */   441     return __new_str(sub);   442 }   443    444 __attr __fn_native__list_init(__attr __args[])   445 {   446     __attr * const size = &__args[1];   447     /* size.__data__ interpreted as int */   448     unsigned int n = __load_via_object(size->value, __pos___data__).intvalue;   449     __attr attr = {0, .seqvalue=__new_fragment(n)};   450    451     /* Return the __data__ attribute. */   452     return attr;   453 }   454    455 __attr __fn_native__list_setsize(__attr __args[])   456 {   457     __attr * const _data = &__args[1];   458     __attr * const size = &__args[2];   459     /* _data interpreted as list */   460     __fragment *data = _data->seqvalue;   461     /* size.__data__ interpreted as int */   462     unsigned int n = __load_via_object(size->value, __pos___data__).intvalue;   463    464     data->size = n;   465     return __builtins___none_None;   466 }   467    468 __attr __fn_native__list_append(__attr __args[])   469 {   470     __attr * const self = &__args[1];   471     __attr * const value = &__args[2];   472     /* self.__data__ interpreted as list */   473     __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue;   474     __fragment *newdata = __fragment_append(data, value);   475    476     /* Replace the __data__ attribute if appropriate. */   477     if (newdata != data)   478         __store_via_object(self->value, __pos___data__, ((__attr) {0, .seqvalue=newdata}));   479     return __builtins___none_None;   480 }   481    482 __attr __fn_native__list_concat(__attr __args[])   483 {   484     __attr * const self = &__args[1];   485     __attr * const other = &__args[2];   486     /* self.__data__, other interpreted as list */   487     __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue;   488     __fragment *other_data = other->seqvalue;   489     __fragment *newdata = data;   490     unsigned int size = data->size, capacity = data->capacity;   491     unsigned int other_size = other_data->size;   492     unsigned int i, j, n;   493    494     /* Re-allocate the fragment if the capacity has been reached. */   495     if (size + other_size >= capacity)   496     {   497         n = size + other_size;   498         newdata = (__fragment *) __REALLOCATE(data, __FRAGMENT_SIZE(n));   499         newdata->capacity = n;   500     }   501    502     /* Copy the elements from the other list and increment the list size. */   503     for (i = size, j = 0; j < other_size; i++, j++)   504         newdata->attrs[i] = other_data->attrs[j];   505     newdata->size = n;   506    507     /* Replace the __data__ attribute if appropriate. */   508     if (newdata != data)   509         __store_via_object(self->value, __pos___data__, ((__attr) {0, .seqvalue=newdata}));   510     return __builtins___none_None;   511 }   512    513 __attr __fn_native__list_len(__attr __args[])   514 {   515     __attr * const _data = &__args[1];   516     /* _data interpreted as fragment */   517     unsigned int size = _data->seqvalue->size;   518    519     /* Return the new integer. */   520     return __new_int(size);   521 }   522    523 __attr __fn_native__list_nonempty(__attr __args[])   524 {   525     __attr * const _data = &__args[1];   526    527     return _data->seqvalue->size ? __builtins___boolean_True : __builtins___boolean_False;   528 }   529    530 __attr __fn_native__list_element(__attr __args[])   531 {   532     __attr * const _data = &__args[1];   533     __attr * const index = &__args[2];   534     /* _data interpreted as fragment */   535     __attr *elements = _data->seqvalue->attrs;   536     /* index.__data__ interpreted as int */   537     int i = __load_via_object(index->value, __pos___data__).intvalue;   538    539     return elements[i];   540 }   541    542 __attr __fn_native__list_setelement(__attr __args[])   543 {   544     __attr * const _data = &__args[1];   545     __attr * const index = &__args[2];   546     __attr * const value = &__args[3];   547     /* _data interpreted as fragment */   548     __attr *elements = _data->seqvalue->attrs;   549     /* index.__data__ interpreted as int */   550     int i = __load_via_object(index->value, __pos___data__).intvalue;   551    552     /* Set the element. */   553     elements[i] = *value;   554     return __builtins___none_None;   555 }   556    557 __attr __fn_native__buffer_str(__attr __args[])   558 {   559     __attr * const _data = &__args[1];   560     /* _data interpreted as buffer */   561     __fragment *data = _data->seqvalue;   562     unsigned int size = 0, i, j, n;   563     char *s, *o;   564    565     /* Calculate the size of the string. */   566     for (i = 0; i < data->size; i++)   567         size += strlen(__load_via_object(data->attrs[i].value, __pos___data__).strvalue);   568    569     /* Reserve space for a new string. */   570     s = (char *) __ALLOCATE(size + 1, sizeof(char));   571    572     /* Build a single string from the buffer contents. */   573     for (i = 0, j = 0; i < data->size; i++)   574     {   575         o = __load_via_object(data->attrs[i].value, __pos___data__).strvalue;   576         n = strlen(o);   577         strncpy(s + j, o, n); /* does not null terminate but final byte should be zero */   578         j += n;   579     }   580    581     /* Return a new string. */   582     return __new_str(s);   583 }   584    585 __attr __fn_native__get_using(__attr __args[])   586 {   587     __attr * const callable = &__args[1];   588     __attr * const instance = &__args[2];   589    590     return __replace_context(instance->value, *callable);   591 }   592    593 __attr __fn_native__object_getattr(__attr __args[])   594 {   595     __attr * const obj = &__args[1];   596     __attr * const name = &__args[2];   597     __attr * const _default = &__args[3];   598    599     /* NOTE: To be written. */   600     return __builtins___none_None;   601 }   602    603 static int __issubclass(__ref obj, __attr cls)   604 {   605     return (__HASATTR(obj, __TYPEPOS(cls.value), __TYPECODE(cls.value)));   606 }   607    608 __attr __fn_native__isinstance(__attr __args[])   609 {   610     __attr * const obj = &__args[1];   611     __attr * const cls = &__args[2];   612    613     /* cls must be a class. */   614     if (__is_instance(obj->value) && __issubclass(__get_class(obj->value), *cls))   615         return __builtins___boolean_True;   616     else   617         return __builtins___boolean_False;   618 }   619    620 __attr __fn_native__issubclass(__attr __args[])   621 {   622     __attr * const obj = &__args[1];   623     __attr * const cls = &__args[2];   624    625     /* obj and cls must be classes. */   626     if (__issubclass(obj->value, *cls))   627         return __builtins___boolean_True;   628     else   629         return __builtins___boolean_False;   630 }   631    632 __attr __fn_native__read(__attr __args[])   633 {   634     __attr * const fd = &__args[1];   635     __attr * const n = &__args[2];   636    637     /* NOTE: To be written. */   638     return __builtins___none_None;   639 }   640    641 __attr __fn_native__write(__attr __args[])   642 {   643     __attr * const fd = &__args[1];   644     __attr * const str = &__args[2];   645     /* fd.__data__ interpreted as int */   646     int i = __load_via_object(fd->value, __pos___data__).intvalue;   647     /* str.__data__ interpreted as string */   648     char *s = __load_via_object(str->value, __pos___data__).strvalue;   649    650     write(i, s, sizeof(char) * strlen(s));   651     return __builtins___none_None;   652 }   653    654 /* Module initialisation. */   655    656 void __main_native()   657 {   658 }