Lichen

templates/native.c

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