Lichen

templates/native.c

213:0ebba845f9b0
2016-11-23 Paul Boddie Fixed anonymous accesses, preventing accidental lookup of None. Fixed the attribute access plan output, encoding anonymous accessors.
     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_append(__attr __args[])   353 {   354     __attr * const self = &__args[1];   355     __attr * const value = &__args[2];   356     /* self.__data__ interpreted as list */   357     __fragment *data = __load_via_object(self->value, __pos___data__).data;   358     unsigned int size = data->size, capacity = data->capacity;   359     unsigned int n;   360    361     /* Re-allocate the fragment if the capacity has been reached. */   362     if (size >= capacity)   363     {   364         /* NOTE: Consider various restrictions on capacity increases. */   365         n = capacity ? capacity * 2 : 1;   366         data = realloc(data, __FRAGMENT_SIZE(n));   367         data->capacity = n;   368     }   369    370     /* Insert the new element and increment the list size. */   371     data->attrs[size] = *value;   372     data->size = size + 1;   373     return __builtins___none_None;   374 }   375    376 __attr __fn_native__list_concat(__attr __args[])   377 {   378     __attr * const self = &__args[1];   379     __attr * const __other = &__args[2];   380     /* self.__data__, __other.__data__ interpreted as list */   381     __fragment *data = __load_via_object(self->value, __pos___data__).data;   382     __fragment *other_data = __load_via_object(__other->value, __pos___data__).data;   383     unsigned int size = data->size, capacity = data->capacity;   384     unsigned int other_size = other_data->size;   385     unsigned int i, j, n;   386    387     /* Re-allocate the fragment if the capacity has been reached. */   388     if (size + other_size >= capacity)   389     {   390         n = size + other_size;   391         data = realloc(data, __FRAGMENT_SIZE(n));   392         data->capacity = n;   393     }   394    395     /* Copy the elements from the other list and increment the list size. */   396     for (i = size, j = 0; j < other_size; i++, j++)   397         data->attrs[i] = other_data->attrs[j];   398     data->size = n;   399     return __builtins___none_None;   400 }   401    402 __attr __fn_native__list_len(__attr __args[])   403 {   404     __attr * const self = &__args[1];   405     /* self.__data__ interpreted as fragment */   406     unsigned int size = __load_via_object(self->value, __pos___data__).data->size;   407    408     /* Return the new integer. */   409     return __new_int(size);   410 }   411    412 __attr __fn_native__list_nonempty(__attr __args[])   413 {   414     __attr * const self = &__args[1];   415    416     return __load_via_object(self->value, __pos___data__).data->size ? __builtins___boolean_True : __builtins___boolean_False;   417 }   418    419 __attr __fn_native__list_element(__attr __args[])   420 {   421     __attr * const self = &__args[1];   422     __attr * const index = &__args[2];   423     /* self.__data__ interpreted as fragment */   424     __attr *elements = __load_via_object(self->value, __pos___data__).data->attrs;   425     /* index.__data__ interpreted as int */   426     int i = __load_via_object(index->value, __pos___data__).intvalue;   427    428     return elements[i];   429 }   430    431 __attr __fn_native__list_to_tuple(__attr __args[])   432 {   433     __attr * const l = &__args[1];   434    435     /* NOTE: To be written. */   436     return __builtins___none_None;   437 }   438    439 __attr __fn_native__buffer_str(__attr __args[])   440 {   441     __attr * const self = &__args[1];   442     /* self.__data__ interpreted as buffer */   443     __fragment *data = __load_via_object(self->value, __pos___data__).data;   444     unsigned int size = 0, i, j, n;   445     char *s, *o;   446    447     /* Calculate the size of the string. */   448     for (i = 0; i < data->size; i++)   449         size += strlen(data->attrs[i].strvalue);   450    451     /* Reserve space for a new string. */   452     s = calloc(size + 1, sizeof(char));   453    454     /* Build a single string from the buffer contents. */   455     for (i = 0, j = 0; i < data->size; i++)   456     {   457         o = __load_via_object(data->attrs[i].value, __pos___data__).strvalue;   458         n = strlen(o);   459         strncpy(s + j, o, n);   460         j += n;   461     }   462    463     /* Return a new string. */   464     return __new_str(s);   465 }   466    467 __attr __fn_native__tuple_init(__attr __args[])   468 {   469     __attr * const size = &__args[1];   470     /* size.__data__ interpreted as fragment */   471     __fragment *data = calloc(__load_via_object(size->value, __pos___data__).intvalue, sizeof(__attr));   472     __attr attr = {0, .data=data};   473    474     return attr;   475 }   476    477 __attr __fn_native__tuple_len(__attr __args[])   478 {   479     __attr * const self = &__args[1];   480     /* self.__data__ interpreted as fragment */   481     unsigned int size = __load_via_object(self->value, __pos___data__).data->size;   482    483     /* Return the new integer. */   484     return __new_int(size);   485 }   486    487 __attr __fn_native__tuple_element(__attr __args[])   488 {   489     __attr * const self = &__args[1];   490     __attr * const index = &__args[2];   491     /* self.__data__ interpreted as fragment */   492     __attr *elements = __load_via_object(self->value, __pos___data__).data->attrs;   493     /* index.__data__ interpreted as int */   494     int i = __load_via_object(index->value, __pos___data__).intvalue;   495    496     return elements[i];   497 }   498    499 __attr __fn_native__isinstance(__attr __args[])   500 {   501     __attr * const obj = &__args[1];   502     __attr * const cls = &__args[2];   503    504     if (__is_instance(obj->value) && __HASATTR(__get_class(obj->value), __TYPEPOS(cls->value), __TYPECODE(cls->value)))   505         return __builtins___boolean_True;   506     else   507         return __builtins___boolean_False;   508 }   509    510 __attr __fn_native__read(__attr __args[])   511 {   512     __attr * const fd = &__args[1];   513     __attr * const n = &__args[2];   514    515     /* NOTE: To be written. */   516     return __builtins___none_None;   517 }   518    519 __attr __fn_native__write(__attr __args[])   520 {   521     __attr * const fd = &__args[1];   522     __attr * const str = &__args[2];   523     /* fd.__data__ interpreted as int */   524     int i = __load_via_object(fd->value, __pos___data__).intvalue;   525     /* str.__data__ interpreted as string */   526     char *s = __load_via_object(str->value, __pos___data__).strvalue;   527    528     write(i, s, sizeof(char) * strlen(s));   529     return __builtins___none_None;   530 }   531    532 /* Module initialisation. */   533    534 void __main_native()   535 {   536 }