Lichen

templates/native.c

300:503985ccf893
2016-12-02 Paul Boddie Added a simple hash function for strings; expanded string and dictionary tests.
     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 self = &__args[1];   107     __attr * const other = &__args[2];   108     /* self.__data__ and other.__data__ interpreted as int */   109     int i = __load_via_object(self->value, __pos___data__).intvalue;   110     int j = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   120     __attr * const other = &__args[2];   121     /* self.__data__ and other.__data__ interpreted as int */   122     int i = __load_via_object(self->value, __pos___data__).intvalue;   123     int j = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   133     __attr * const other = &__args[2];   134     /* self.__data__ and other.__data__ interpreted as int */   135     int i = __load_via_object(self->value, __pos___data__).intvalue;   136     int j = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   146     __attr * const other = &__args[2];   147     /* self.__data__ and other.__data__ interpreted as int */   148     int i = __load_via_object(self->value, __pos___data__).intvalue;   149     int j = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   159     __attr * const other = &__args[2];   160     /* self.__data__ and other.__data__ interpreted as int */   161     int i = __load_via_object(self->value, __pos___data__).intvalue;   162     int j = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   172     /* self.__data__ interpreted as int */   173     int i = __load_via_object(self->value, __pos___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 self = &__args[1];   182     __attr * const other = &__args[2];   183     /* self.__data__ and other.__data__ interpreted as int */   184     int i = __load_via_object(self->value, __pos___data__).intvalue;   185     int j = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   195     __attr * const other = &__args[2];   196     /* self.__data__ and other.__data__ interpreted as int */   197     int i = __load_via_object(self->value, __pos___data__).intvalue;   198     int j = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   208     __attr * const other = &__args[2];   209     /* self.__data__ and other.__data__ interpreted as int */   210     int i = __load_via_object(self->value, __pos___data__).intvalue;   211     int j = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   221     __attr * const other = &__args[2];   222     /* self.__data__ and other.__data__ interpreted as int */   223     int i = __load_via_object(self->value, __pos___data__).intvalue;   224     int j = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   234     __attr * const other = &__args[2];   235     /* self.__data__ and other.__data__ interpreted as int */   236     int i = __load_via_object(self->value, __pos___data__).intvalue;   237     int j = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   246     __attr * const other = &__args[2];   247     /* self.__data__ and other.__data__ interpreted as int */   248     int i = __load_via_object(self->value, __pos___data__).intvalue;   249     int j = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   258     __attr * const 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 }   266    267 __attr __fn_native__int_ne(__attr __args[])   268 {   269     __attr * const self = &__args[1];   270     __attr * const other = &__args[2];   271     /* self.__data__ and other.__data__ interpreted as int */   272     int i = __load_via_object(self->value, __pos___data__).intvalue;   273     int j = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   282     /* self.__data__ interpreted as int */   283     int i = __load_via_object(self->value, __pos___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 self = &__args[1];   297     __attr * const other = &__args[2];   298     /* self.__data__, other.__data__ interpreted as string */   299     char *s = __load_via_object(self->value, __pos___data__).strvalue;   300     char *o = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   314     __attr * const other = &__args[2];   315     /* self.__data__, other.__data__ interpreted as string */   316     char *s = __load_via_object(self->value, __pos___data__).strvalue;   317     char *o = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   326     __attr * const other = &__args[2];   327     /* self.__data__, other.__data__ interpreted as string */   328     char *s = __load_via_object(self->value, __pos___data__).strvalue;   329     char *o = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   338     __attr * const other = &__args[2];   339     /* self.__data__, other.__data__ interpreted as string */   340     char *s = __load_via_object(self->value, __pos___data__).strvalue;   341     char *o = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   350     /* self.__data__ interpreted as string */   351     char *s = __load_via_object(self->value, __pos___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 self = &__args[1];   360     /* self.__data__ interpreted as string */   361     char *s = __load_via_object(self->value, __pos___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 self = &__args[1];   369     /* self.__data__ interpreted as string */   370     char *s = __load_via_object(self->value, __pos___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 self = &__args[1];   378     __attr * const start = &__args[2];   379     __attr * const size = &__args[3];   380     /* self.__data__ interpreted as string */   381     char *s = __load_via_object(self->value, __pos___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 self = &__args[1];   407     __attr * const size = &__args[2];   408     /* self.__data__ interpreted as list */   409     __fragment *data = __load_via_object(self->value, __pos___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.__data__ interpreted as list */   436     __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue;   437     __fragment *other_data = __load_via_object(other->value, __pos___data__).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 self = &__args[1];   465     /* self.__data__ interpreted as fragment */   466     unsigned int size = __load_via_object(self->value, __pos___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 self = &__args[1];   475    476     return __load_via_object(self->value, __pos___data__).seqvalue->size ? __builtins___boolean_True : __builtins___boolean_False;   477 }   478    479 __attr __fn_native__list_element(__attr __args[])   480 {   481     __attr * const self = &__args[1];   482     __attr * const index = &__args[2];   483     /* self.__data__ interpreted as fragment */   484     __attr *elements = __load_via_object(self->value, __pos___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 self = &__args[1];   494     __attr * const index = &__args[2];   495     __attr * const value = &__args[3];   496     /* self.__data__ interpreted as fragment */   497     __attr *elements = __load_via_object(self->value, __pos___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__dict_init(__attr __args[])   507 {   508     __attr * const size = &__args[1];   509     /* size.__data__ interpreted as int */   510     unsigned int n = __load_via_object(size->value, __pos___data__).intvalue;   511     __mapping *data = __new_mapping(n);   512     __attr attr = {0, .mapvalue=data};   513    514     /* Return the __data__ attribute. */   515     return attr;   516 }   517    518 __attr __fn_native__dict_bucketsize(__attr __args[])   519 {   520     __attr * const self = &__args[1];   521     __attr * const index = &__args[2];   522     /* self.__data__ interpreted as dict */   523     __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue;   524     /* index.__data__ interpreted as int */   525     int k = __load_via_object(index->value, __pos___data__).intvalue % __MAPPING_BUCKETS;   526    527     /* Return size of bucket k. */   528     return __new_int(data->keys[k]->size);   529 }   530    531 __attr __fn_native__dict_keys(__attr __args[])   532 {   533     __attr * const self = &__args[1];   534     /* self.__data__ interpreted as dict */   535     __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue;   536     unsigned int k, i, j, size = 0;   537     __fragment *f;   538    539     /* Count the number of keys. */   540     for (k = 0; k < __MAPPING_BUCKETS; k++)   541         size += data->keys[k]->size;   542    543     /* Create a fragment for the keys. */   544     f =  __new_fragment(size);   545    546     /* Populate the fragment with the keys. */   547     for (j = 0, k = 0; k < __MAPPING_BUCKETS; k++)   548         for (i = 0; i < data->keys[k]->size; i++, j++)   549             f->attrs[j] = data->keys[k]->attrs[i];   550     f->size = size;   551    552     /* Return a list. */   553     return __new_list(f);   554 }   555    556 __attr __fn_native__dict_values(__attr __args[])   557 {   558     __attr * const self = &__args[1];   559     /* self.__data__ interpreted as dict */   560     __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue;   561     unsigned int k, i, j, size = 0;   562     __fragment *f;   563    564     /* Count the number of values. */   565     for (k = 0; k < __MAPPING_BUCKETS; k++)   566         size += data->values[k]->size;   567    568     /* Create a fragment for the values. */   569     f =  __new_fragment(size);   570    571     /* Populate the fragment with the values. */   572     for (j = 0, k = 0; k < __MAPPING_BUCKETS; k++)   573         for (i = 0; i < data->values[k]->size; i++, j++)   574             f->attrs[j] = data->values[k]->attrs[i];   575     f->size = size;   576    577     /* Return a list. */   578     return __new_list(f);   579 }   580    581 __attr __fn_native__dict_key(__attr __args[])   582 {   583     __attr * const self = &__args[1];   584     __attr * const index = &__args[2];   585     __attr * const element = &__args[3];   586     /* self.__data__ interpreted as dict */   587     __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue;   588     /* index.__data__ interpreted as int */   589     int k = __load_via_object(index->value, __pos___data__).intvalue % __MAPPING_BUCKETS;   590     /* element.__data__ interpreted as int */   591     int i = __load_via_object(element->value, __pos___data__).intvalue;   592    593     /* Return key from bucket k, element i. */   594     return data->keys[k]->attrs[i];   595 }   596    597 __attr __fn_native__dict_value(__attr __args[])   598 {   599     __attr * const self = &__args[1];   600     __attr * const index = &__args[2];   601     __attr * const element = &__args[3];   602     /* self.__data__ interpreted as dict */   603     __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue;   604     /* index.__data__ interpreted as int */   605     int k = __load_via_object(index->value, __pos___data__).intvalue % __MAPPING_BUCKETS;   606     /* element.__data__ interpreted as int */   607     int i = __load_via_object(element->value, __pos___data__).intvalue;   608    609     /* Return value from bucket k, element i. */   610     return data->values[k]->attrs[i];   611 }   612    613 __attr __fn_native__dict_additem(__attr __args[])   614 {   615     __attr * const self = &__args[1];   616     __attr * const index = &__args[2];   617     __attr * const key = &__args[3];   618     __attr * const value = &__args[4];   619     /* self.__data__ interpreted as dict */   620     __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue;   621     /* index.__data__ interpreted as int */   622     int k = __load_via_object(index->value, __pos___data__).intvalue % __MAPPING_BUCKETS;   623     __fragment *keys = data->keys[k], *newkeys;   624     __fragment *values = data->values[k], *newvalues;   625    626     /* Append the item. */   627     newkeys = __fragment_append(keys, key);   628     newvalues = __fragment_append(values, value);   629    630     /* Replace the fragments if appropriate. */   631     if (newkeys != keys)   632         data->keys[k] = newkeys;   633     if (newvalues != values)   634         data->values[k] = newvalues;   635     return __builtins___none_None;   636 }   637    638 __attr __fn_native__dict_setitem(__attr __args[])   639 {   640     __attr * const self = &__args[1];   641     __attr * const index = &__args[2];   642     __attr * const element = &__args[3];   643     __attr * const key = &__args[4];   644     __attr * const value = &__args[5];   645     /* self.__data__ interpreted as dict */   646     __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue;   647     /* index.__data__ interpreted as int */   648     int k = __load_via_object(index->value, __pos___data__).intvalue % __MAPPING_BUCKETS;   649     /* element.__data__ interpreted as int */   650     int i = __load_via_object(element->value, __pos___data__).intvalue;   651    652     /* Replace the item. */   653     data->keys[k]->attrs[i] = *key;   654     data->values[k]->attrs[i] = *value;   655    656     return __builtins___none_None;   657 }   658    659 __attr __fn_native__buffer_str(__attr __args[])   660 {   661     __attr * const self = &__args[1];   662     /* self.__data__ interpreted as buffer */   663     __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue;   664     unsigned int size = 0, i, j, n;   665     char *s, *o;   666    667     /* Calculate the size of the string. */   668     for (i = 0; i < data->size; i++)   669         size += strlen(__load_via_object(data->attrs[i].value, __pos___data__).strvalue);   670    671     /* Reserve space for a new string. */   672     s = (char *) __ALLOCATE(size + 1, sizeof(char));   673    674     /* Build a single string from the buffer contents. */   675     for (i = 0, j = 0; i < data->size; i++)   676     {   677         o = __load_via_object(data->attrs[i].value, __pos___data__).strvalue;   678         n = strlen(o);   679         strncpy(s + j, o, n); /* does not null terminate but final byte should be zero */   680         j += n;   681     }   682    683     /* Return a new string. */   684     return __new_str(s);   685 }   686    687 __attr __fn_native__get_using(__attr __args[])   688 {   689     __attr * const callable = &__args[1];   690     __attr * const instance = &__args[2];   691    692     return __replace_context(instance->value, *callable);   693 }   694    695 __attr __fn_native__object_getattr(__attr __args[])   696 {   697     __attr * const obj = &__args[1];   698     __attr * const name = &__args[2];   699     __attr * const _default = &__args[3];   700    701     /* NOTE: To be written. */   702     return __builtins___none_None;   703 }   704    705 static int __issubclass(__ref obj, __attr cls)   706 {   707     return (__HASATTR(obj, __TYPEPOS(cls.value), __TYPECODE(cls.value)));   708 }   709    710 __attr __fn_native__isinstance(__attr __args[])   711 {   712     __attr * const obj = &__args[1];   713     __attr * const cls = &__args[2];   714    715     /* cls must be a class. */   716     if (__is_instance(obj->value) && __issubclass(__get_class(obj->value), *cls))   717         return __builtins___boolean_True;   718     else   719         return __builtins___boolean_False;   720 }   721    722 __attr __fn_native__issubclass(__attr __args[])   723 {   724     __attr * const obj = &__args[1];   725     __attr * const cls = &__args[2];   726    727     /* obj and cls must be classes. */   728     if (__issubclass(obj->value, *cls))   729         return __builtins___boolean_True;   730     else   731         return __builtins___boolean_False;   732 }   733    734 __attr __fn_native__read(__attr __args[])   735 {   736     __attr * const fd = &__args[1];   737     __attr * const n = &__args[2];   738    739     /* NOTE: To be written. */   740     return __builtins___none_None;   741 }   742    743 __attr __fn_native__write(__attr __args[])   744 {   745     __attr * const fd = &__args[1];   746     __attr * const str = &__args[2];   747     /* fd.__data__ interpreted as int */   748     int i = __load_via_object(fd->value, __pos___data__).intvalue;   749     /* str.__data__ interpreted as string */   750     char *s = __load_via_object(str->value, __pos___data__).strvalue;   751    752     write(i, s, sizeof(char) * strlen(s));   753     return __builtins___none_None;   754 }   755    756 /* Module initialisation. */   757    758 void __main_native()   759 {   760 }