Lichen

templates/native.c

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