Lichen

templates/native.c

229:f3ea117e51db
2016-11-24 Paul Boddie Make sure that variable references are assigned to names appropriately.
     1 #include <stdlib.h> /* calloc, exit, realloc */     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 inline __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 inline __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 /* Native functions. */    33     34 __attr __fn_native__exit(__attr __args[])    35 {    36     __attr * const status = &__args[1];    37     38     exit(__load_via_object(status->value, __pos___data__).intvalue);    39     return __builtins___none_None;    40 }    41     42 __attr __fn_native__get_argv(__attr __args[])    43 {    44     __attr * const status = &__args[1];    45     46     /* NOTE: To be written. */    47     return __builtins___none_None;    48 }    49     50 __attr __fn_native__get_path(__attr __args[])    51 {    52     __attr * const status = &__args[1];    53     54     /* NOTE: To be written. */    55     return __builtins___none_None;    56 }    57     58 __attr __fn_native__is(__attr __args[])    59 {    60     __attr * const x = &__args[1];    61     __attr * const y = &__args[2];    62     63     return x->value == y->value ? __builtins___boolean_True : __builtins___boolean_False;    64 }    65     66 __attr __fn_native__is_not(__attr __args[])    67 {    68     __attr * const x = &__args[1];    69     __attr * const y = &__args[2];    70     71     return x->value != y->value ? __builtins___boolean_True : __builtins___boolean_False;    72 }    73     74 __attr __fn_native__int_add(__attr __args[])    75 {    76     __attr * const self = &__args[1];    77     __attr * const other = &__args[2];    78     /* self.__data__ and other.__data__ interpreted as int */    79     int i = __load_via_object(self->value, __pos___data__).intvalue;    80     int j = __load_via_object(other->value, __pos___data__).intvalue;    81     82     /* Return the new integer. */    83     /* NOTE: No overflow test applied. */    84     return __new_int(i + j);    85 }    86     87 __attr __fn_native__int_sub(__attr __args[])    88 {    89     __attr * const self = &__args[1];    90     __attr * const other = &__args[2];    91     /* self.__data__ and other.__data__ interpreted as int */    92     int i = __load_via_object(self->value, __pos___data__).intvalue;    93     int j = __load_via_object(other->value, __pos___data__).intvalue;    94     95     /* Return the new integer. */    96     /* NOTE: No overflow test applied. */    97     return __new_int(i - j);    98 }    99    100 __attr __fn_native__int_mul(__attr __args[])   101 {   102     __attr * const self = &__args[1];   103     __attr * const other = &__args[2];   104     /* self.__data__ and other.__data__ interpreted as int */   105     int i = __load_via_object(self->value, __pos___data__).intvalue;   106     int j = __load_via_object(other->value, __pos___data__).intvalue;   107    108     /* Return the new integer. */   109     /* NOTE: No overflow test applied. */   110     return __new_int(i * j);   111 }   112    113 __attr __fn_native__int_div(__attr __args[])   114 {   115     __attr * const self = &__args[1];   116     __attr * const other = &__args[2];   117     /* self.__data__ and other.__data__ interpreted as int */   118     int i = __load_via_object(self->value, __pos___data__).intvalue;   119     int j = __load_via_object(other->value, __pos___data__).intvalue;   120    121     /* Return the new integer. */   122     /* NOTE: No overflow test applied. */   123     return __new_int(i / j);   124 }   125    126 __attr __fn_native__int_mod(__attr __args[])   127 {   128     __attr * const self = &__args[1];   129     __attr * const other = &__args[2];   130     /* self.__data__ and other.__data__ interpreted as int */   131     int i = __load_via_object(self->value, __pos___data__).intvalue;   132     int j = __load_via_object(other->value, __pos___data__).intvalue;   133    134     /* Return the new integer. */   135     /* NOTE: No overflow test applied. */   136     return __new_int(i % j);   137 }   138    139 __attr __fn_native__int_neg(__attr __args[])   140 {   141     __attr * const self = &__args[1];   142     /* self.__data__ interpreted as int */   143     int i = __load_via_object(self->value, __pos___data__).intvalue;   144    145     /* Return the new integer. */   146     return __new_int(-i);   147 }   148    149 __attr __fn_native__int_pow(__attr __args[])   150 {   151     __attr * const self = &__args[1];   152     __attr * const other = &__args[2];   153     /* self.__data__ and other.__data__ interpreted as int */   154     int i = __load_via_object(self->value, __pos___data__).intvalue;   155     int j = __load_via_object(other->value, __pos___data__).intvalue;   156    157     /* Return the new integer. */   158     /* NOTE: No overflow test applied. */   159     return __new_int((int) pow(i, j));   160 }   161    162 __attr __fn_native__int_and(__attr __args[])   163 {   164     __attr * const self = &__args[1];   165     __attr * const other = &__args[2];   166     /* self.__data__ and other.__data__ interpreted as int */   167     int i = __load_via_object(self->value, __pos___data__).intvalue;   168     int j = __load_via_object(other->value, __pos___data__).intvalue;   169    170     /* Return the new integer. */   171     /* NOTE: No overflow test applied. */   172     return __new_int(i & j);   173 }   174    175 __attr __fn_native__int_or(__attr __args[])   176 {   177     __attr * const self = &__args[1];   178     __attr * const other = &__args[2];   179     /* self.__data__ and other.__data__ interpreted as int */   180     int i = __load_via_object(self->value, __pos___data__).intvalue;   181     int j = __load_via_object(other->value, __pos___data__).intvalue;   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_xor(__attr __args[])   189 {   190     __attr * const self = &__args[1];   191     __attr * const other = &__args[2];   192     /* self.__data__ and other.__data__ interpreted as int */   193     int i = __load_via_object(self->value, __pos___data__).intvalue;   194     int j = __load_via_object(other->value, __pos___data__).intvalue;   195    196     /* Return the new integer. */   197     /* NOTE: No overflow test applied. */   198     return __new_int(i ^ j);   199 }   200    201 __attr __fn_native__int_lt(__attr __args[])   202 {   203     __attr * const self = &__args[1];   204     __attr * const other = &__args[2];   205     /* self.__data__ and other.__data__ interpreted as int */   206     int i = __load_via_object(self->value, __pos___data__).intvalue;   207     int j = __load_via_object(other->value, __pos___data__).intvalue;   208    209     /* Return a boolean result. */   210     return i < j ? __builtins___boolean_True : __builtins___boolean_False;   211 }   212    213 __attr __fn_native__int_gt(__attr __args[])   214 {   215     __attr * const self = &__args[1];   216     __attr * const other = &__args[2];   217     /* self.__data__ and other.__data__ interpreted as int */   218     int i = __load_via_object(self->value, __pos___data__).intvalue;   219     int j = __load_via_object(other->value, __pos___data__).intvalue;   220    221     /* Return a boolean result. */   222     return i > j ? __builtins___boolean_True : __builtins___boolean_False;   223 }   224    225 __attr __fn_native__int_eq(__attr __args[])   226 {   227     __attr * const self = &__args[1];   228     __attr * const other = &__args[2];   229     /* self.__data__ and other.__data__ interpreted as int */   230     int i = __load_via_object(self->value, __pos___data__).intvalue;   231     int j = __load_via_object(other->value, __pos___data__).intvalue;   232    233     /* Return a boolean result. */   234     return i == j ? __builtins___boolean_True : __builtins___boolean_False;   235 }   236    237 __attr __fn_native__int_ne(__attr __args[])   238 {   239     __attr * const self = &__args[1];   240     __attr * const other = &__args[2];   241     /* self.__data__ and other.__data__ interpreted as int */   242     int i = __load_via_object(self->value, __pos___data__).intvalue;   243     int j = __load_via_object(other->value, __pos___data__).intvalue;   244    245     /* Return a boolean result. */   246     return i != j ? __builtins___boolean_True : __builtins___boolean_False;   247 }   248    249 __attr __fn_native__int_str(__attr __args[])   250 {   251     __attr * const self = &__args[1];   252     /* self.__data__ interpreted as int */   253     int i = __load_via_object(self->value, __pos___data__).intvalue;   254     int n = i != 0 ? (int) ceil(log10(i+1)) + 1 : 2;   255     char *s = calloc(n, sizeof(char));   256    257     if (i < 0) n++;   258     snprintf(s, n, "%d", i);   259    260     /* Return a new string. */   261     return __new_str(s);   262 }   263    264 __attr __fn_native__str_add(__attr __args[])   265 {   266     __attr * const self = &__args[1];   267     __attr * const other = &__args[2];   268     /* self.__data__, other.__data__ interpreted as string */   269     char *s = __load_via_object(self->value, __pos___data__).strvalue;   270     char *o = __load_via_object(other->value, __pos___data__).strvalue;   271     int n = strlen(s) + strlen(o) + 1;   272     char *r = calloc(n, sizeof(char));   273    274     strncpy(r, s, n);   275     strncpy(r + strlen(s), o, n - strlen(s));   276    277     /* Return a new string. */   278     return __new_str(r);   279 }   280    281 __attr __fn_native__str_lt(__attr __args[])   282 {   283     __attr * const self = &__args[1];   284     __attr * const other = &__args[2];   285     /* self.__data__, other.__data__ interpreted as string */   286     char *s = __load_via_object(self->value, __pos___data__).strvalue;   287     char *o = __load_via_object(other->value, __pos___data__).strvalue;   288    289     /* NOTE: Using simple byte-level string operations. */   290     return strcmp(s, o) < 0 ? __builtins___boolean_True : __builtins___boolean_False;   291 }   292    293 __attr __fn_native__str_gt(__attr __args[])   294 {   295     __attr * const self = &__args[1];   296     __attr * const other = &__args[2];   297     /* self.__data__, other.__data__ interpreted as string */   298     char *s = __load_via_object(self->value, __pos___data__).strvalue;   299     char *o = __load_via_object(other->value, __pos___data__).strvalue;   300    301     /* NOTE: Using simple byte-level string operations. */   302     return strcmp(s, o) > 0 ? __builtins___boolean_True : __builtins___boolean_False;   303 }   304    305 __attr __fn_native__str_eq(__attr __args[])   306 {   307     __attr * const self = &__args[1];   308     __attr * const other = &__args[2];   309     /* self.__data__, other.__data__ interpreted as string */   310     char *s = __load_via_object(self->value, __pos___data__).strvalue;   311     char *o = __load_via_object(other->value, __pos___data__).strvalue;   312    313     /* NOTE: Using simple byte-level string operations. */   314     return strcmp(s, o) == 0 ? __builtins___boolean_True : __builtins___boolean_False;   315 }   316    317 __attr __fn_native__str_len(__attr __args[])   318 {   319     __attr * const self = &__args[1];   320     /* self.__data__ interpreted as string */   321     char *s = __load_via_object(self->value, __pos___data__).strvalue;   322    323     /* Return the new integer. */   324     return __new_int(strlen(s));   325 }   326    327 __attr __fn_native__str_nonempty(__attr __args[])   328 {   329     __attr * const self = &__args[1];   330     /* self.__data__ interpreted as string */   331     char *s = __load_via_object(self->value, __pos___data__).strvalue;   332    333     return strlen(s) ? __builtins___boolean_True : __builtins___boolean_False;   334 }   335    336 __attr __fn_native__list_init(__attr __args[])   337 {   338     __attr * const size = &__args[1];   339     /* size.__data__ interpreted as int */   340     unsigned int n = __load_via_object(size->value, __pos___data__).intvalue;   341    342     /* Allocate space for the list. */   343     __fragment *data = calloc(1, __FRAGMENT_SIZE(n));   344     __attr attr = {0, .data=data};   345    346     /* The initial capacity is the same as the given size. */   347     data->size = 0;   348     data->capacity = n;   349     return attr;   350 }   351    352 __attr __fn_native__list_setsize(__attr __args[])   353 {   354     __attr * const self = &__args[1];   355     __attr * const size = &__args[2];   356     /* self.__data__ interpreted as list */   357     __fragment *data = __load_via_object(self->value, __pos___data__).data;   358     /* size.__data__ interpreted as int */   359     unsigned int n = __load_via_object(size->value, __pos___data__).intvalue;   360    361     data->size = n;   362     return __builtins___none_None;   363 }   364    365 __attr __fn_native__list_append(__attr __args[])   366 {   367     __attr * const self = &__args[1];   368     __attr * const value = &__args[2];   369     /* self.__data__ interpreted as list */   370     __fragment *data = __load_via_object(self->value, __pos___data__).data;   371     __fragment *newdata = data;   372     unsigned int size = data->size, capacity = data->capacity;   373     unsigned int n;   374    375     /* Re-allocate the fragment if the capacity has been reached. */   376     if (size >= capacity)   377     {   378         /* NOTE: Consider various restrictions on capacity increases. */   379         n = capacity ? capacity * 2 : 1;   380         newdata = realloc(data, __FRAGMENT_SIZE(n));   381         newdata->capacity = n;   382     }   383    384     /* Insert the new element and increment the list size. */   385     newdata->attrs[size] = *value;   386     newdata->size = size + 1;   387    388     /* Replace the __data__ attribute if appropriate. */   389     if (newdata != data)   390         __store_via_object(self->value, __pos___data__, ((__attr) {0, .data=newdata}));   391     return __builtins___none_None;   392 }   393    394 __attr __fn_native__list_concat(__attr __args[])   395 {   396     __attr * const self = &__args[1];   397     __attr * const other = &__args[2];   398     /* self.__data__, other.__data__ interpreted as list */   399     __fragment *data = __load_via_object(self->value, __pos___data__).data;   400     __fragment *other_data = __load_via_object(other->value, __pos___data__).data;   401     __fragment *newdata = data;   402     unsigned int size = data->size, capacity = data->capacity;   403     unsigned int other_size = other_data->size;   404     unsigned int i, j, n;   405    406     /* Re-allocate the fragment if the capacity has been reached. */   407     if (size + other_size >= capacity)   408     {   409         n = size + other_size;   410         newdata = realloc(data, __FRAGMENT_SIZE(n));   411         newdata->capacity = n;   412     }   413    414     /* Copy the elements from the other list and increment the list size. */   415     for (i = size, j = 0; j < other_size; i++, j++)   416         newdata->attrs[i] = other_data->attrs[j];   417     newdata->size = n;   418    419     /* Replace the __data__ attribute if appropriate. */   420     if (newdata != data)   421         __store_via_object(self->value, __pos___data__, ((__attr) {0, .data=newdata}));   422     return __builtins___none_None;   423 }   424    425 __attr __fn_native__list_len(__attr __args[])   426 {   427     __attr * const self = &__args[1];   428     /* self.__data__ interpreted as fragment */   429     unsigned int size = __load_via_object(self->value, __pos___data__).data->size;   430    431     /* Return the new integer. */   432     return __new_int(size);   433 }   434    435 __attr __fn_native__list_nonempty(__attr __args[])   436 {   437     __attr * const self = &__args[1];   438    439     return __load_via_object(self->value, __pos___data__).data->size ? __builtins___boolean_True : __builtins___boolean_False;   440 }   441    442 __attr __fn_native__list_element(__attr __args[])   443 {   444     __attr * const self = &__args[1];   445     __attr * const index = &__args[2];   446     /* self.__data__ interpreted as fragment */   447     __attr *elements = __load_via_object(self->value, __pos___data__).data->attrs;   448     /* index.__data__ interpreted as int */   449     int i = __load_via_object(index->value, __pos___data__).intvalue;   450    451     return elements[i];   452 }   453    454 __attr __fn_native__list_setelement(__attr __args[])   455 {   456     __attr * const self = &__args[1];   457     __attr * const index = &__args[2];   458     __attr * const value = &__args[3];   459     /* self.__data__ interpreted as fragment */   460     __attr *elements = __load_via_object(self->value, __pos___data__).data->attrs;   461     /* index.__data__ interpreted as int */   462     int i = __load_via_object(index->value, __pos___data__).intvalue;   463    464     /* Set the element. */   465     elements[i] = *value;   466     return __builtins___none_None;   467 }   468    469 __attr __fn_native__buffer_str(__attr __args[])   470 {   471     __attr * const self = &__args[1];   472     /* self.__data__ interpreted as buffer */   473     __fragment *data = __load_via_object(self->value, __pos___data__).data;   474     unsigned int size = 0, i, j, n;   475     char *s, *o;   476    477     /* Calculate the size of the string. */   478     for (i = 0; i < data->size; i++)   479         size += strlen(data->attrs[i].strvalue);   480    481     /* Reserve space for a new string. */   482     s = calloc(size + 1, sizeof(char));   483    484     /* Build a single string from the buffer contents. */   485     for (i = 0, j = 0; i < data->size; i++)   486     {   487         o = __load_via_object(data->attrs[i].value, __pos___data__).strvalue;   488         n = strlen(o);   489         strncpy(s + j, o, n);   490         j += n;   491     }   492    493     /* Return a new string. */   494     return __new_str(s);   495 }   496    497 __attr __fn_native__object_getattr(__attr __args[])   498 {   499     __attr * const obj = &__args[1];   500     __attr * const name = &__args[2];   501     __attr * const _default = &__args[3];   502    503     /* NOTE: To be written. */   504     return __builtins___none_None;   505 }   506    507 __attr __fn_native__isinstance(__attr __args[])   508 {   509     __attr * const obj = &__args[1];   510     __attr * const cls = &__args[2];   511    512     if (__is_instance(obj->value) && __HASATTR(__get_class(obj->value), __TYPEPOS(cls->value), __TYPECODE(cls->value)))   513         return __builtins___boolean_True;   514     else   515         return __builtins___boolean_False;   516 }   517    518 __attr __fn_native__read(__attr __args[])   519 {   520     __attr * const fd = &__args[1];   521     __attr * const n = &__args[2];   522    523     /* NOTE: To be written. */   524     return __builtins___none_None;   525 }   526    527 __attr __fn_native__write(__attr __args[])   528 {   529     __attr * const fd = &__args[1];   530     __attr * const str = &__args[2];   531     /* fd.__data__ interpreted as int */   532     int i = __load_via_object(fd->value, __pos___data__).intvalue;   533     /* str.__data__ interpreted as string */   534     char *s = __load_via_object(str->value, __pos___data__).strvalue;   535    536     write(i, s, sizeof(char) * strlen(s));   537     return __builtins___none_None;   538 }   539    540 /* Module initialisation. */   541    542 void __main_native()   543 {   544 }