Lichen

templates/native.c

303:c07a749f5bd0
2016-12-02 Paul Boddie Use __data__ attributes with native functions apart from when __data__ needs replacing (such as in the list append and concatenation functions).
     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__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_items(__attr __args[])   519 {   520     __attr * const _data = &__args[1];   521     /* _data interpreted as dict */   522     __mapping *data = _data->mapvalue;   523    524     return __new_int(data->size);   525 }   526    527 __attr __fn_native__dict_buckets(__attr __args[])   528 {   529     __attr * const _data = &__args[1];   530     /* _data interpreted as dict */   531     __mapping *data = _data->mapvalue;   532    533     return __new_int(data->capacity);   534 }   535    536 __attr __fn_native__dict_bucketsize(__attr __args[])   537 {   538     __attr * const _data = &__args[1];   539     __attr * const index = &__args[2];   540     /* _data interpreted as dict */   541     __mapping *data = _data->mapvalue;   542     /* index.__data__ interpreted as int */   543     int k = __load_via_object(index->value, __pos___data__).intvalue % data->capacity;   544    545     /* Return size of bucket k. */   546     return __new_int(data->keys[k]->size);   547 }   548    549 __attr __fn_native__dict_keys(__attr __args[])   550 {   551     __attr * const _data = &__args[1];   552     /* _data interpreted as dict */   553     __mapping *data = _data->mapvalue;   554     unsigned int k, i, j, size = 0;   555     __fragment *f;   556    557     /* Count the number of keys. */   558     for (k = 0; k < data->capacity; k++)   559         size += data->keys[k]->size;   560    561     /* Create a fragment for the keys. */   562     f =  __new_fragment(size);   563    564     /* Populate the fragment with the keys. */   565     for (j = 0, k = 0; k < data->capacity; k++)   566         for (i = 0; i < data->keys[k]->size; i++, j++)   567             f->attrs[j] = data->keys[k]->attrs[i];   568     f->size = size;   569    570     /* Return a list. */   571     return __new_list(f);   572 }   573    574 __attr __fn_native__dict_values(__attr __args[])   575 {   576     __attr * const _data = &__args[1];   577     /* _data interpreted as dict */   578     __mapping *data = _data->mapvalue;   579     unsigned int k, i, j, size = 0;   580     __fragment *f;   581    582     /* Count the number of values. */   583     for (k = 0; k < data->capacity; k++)   584         size += data->values[k]->size;   585    586     /* Create a fragment for the values. */   587     f =  __new_fragment(size);   588    589     /* Populate the fragment with the values. */   590     for (j = 0, k = 0; k < data->capacity; k++)   591         for (i = 0; i < data->values[k]->size; i++, j++)   592             f->attrs[j] = data->values[k]->attrs[i];   593     f->size = size;   594    595     /* Return a list. */   596     return __new_list(f);   597 }   598    599 __attr __fn_native__dict_key(__attr __args[])   600 {   601     __attr * const _data = &__args[1];   602     __attr * const index = &__args[2];   603     __attr * const element = &__args[3];   604     /* _data interpreted as dict */   605     __mapping *data = _data->mapvalue;   606     /* index.__data__ interpreted as int */   607     int k = __load_via_object(index->value, __pos___data__).intvalue % data->capacity;   608     /* element.__data__ interpreted as int */   609     int i = __load_via_object(element->value, __pos___data__).intvalue;   610    611     /* Return key from bucket k, element i. */   612     return data->keys[k]->attrs[i];   613 }   614    615 __attr __fn_native__dict_value(__attr __args[])   616 {   617     __attr * const _data = &__args[1];   618     __attr * const index = &__args[2];   619     __attr * const element = &__args[3];   620     /* _data interpreted as dict */   621     __mapping *data = _data->mapvalue;   622     /* index.__data__ interpreted as int */   623     int k = __load_via_object(index->value, __pos___data__).intvalue % data->capacity;   624     /* element.__data__ interpreted as int */   625     int i = __load_via_object(element->value, __pos___data__).intvalue;   626    627     /* Return value from bucket k, element i. */   628     return data->values[k]->attrs[i];   629 }   630    631 __attr __fn_native__dict_additem(__attr __args[])   632 {   633     __attr * const _data = &__args[1];   634     __attr * const index = &__args[2];   635     __attr * const key = &__args[3];   636     __attr * const value = &__args[4];   637     /* _data interpreted as dict */   638     __mapping *data = _data->mapvalue;   639     /* index.__data__ interpreted as int */   640     int k = __load_via_object(index->value, __pos___data__).intvalue % data->capacity;   641     unsigned int size = data->size;   642     __fragment *keys = data->keys[k], *newkeys;   643     __fragment *values = data->values[k], *newvalues;   644    645     /* Append the item. */   646     newkeys = __fragment_append(keys, key);   647     newvalues = __fragment_append(values, value);   648    649     /* Replace the fragments if appropriate. */   650     if (newkeys != keys)   651         data->keys[k] = newkeys;   652     if (newvalues != values)   653         data->values[k] = newvalues;   654    655     data->size = size + 1;   656     return __builtins___none_None;   657 }   658    659 __attr __fn_native__dict_setitem(__attr __args[])   660 {   661     __attr * const _data = &__args[1];   662     __attr * const index = &__args[2];   663     __attr * const element = &__args[3];   664     __attr * const key = &__args[4];   665     __attr * const value = &__args[5];   666     /* _data interpreted as dict */   667     __mapping *data = _data->mapvalue;   668     /* index.__data__ interpreted as int */   669     int k = __load_via_object(index->value, __pos___data__).intvalue % data->capacity;   670     /* element.__data__ interpreted as int */   671     int i = __load_via_object(element->value, __pos___data__).intvalue;   672    673     /* Replace the item. */   674     data->keys[k]->attrs[i] = *key;   675     data->values[k]->attrs[i] = *value;   676    677     return __builtins___none_None;   678 }   679    680 __attr __fn_native__buffer_str(__attr __args[])   681 {   682     __attr * const _data = &__args[1];   683     /* _data interpreted as buffer */   684     __fragment *data = _data->seqvalue;   685     unsigned int size = 0, i, j, n;   686     char *s, *o;   687    688     /* Calculate the size of the string. */   689     for (i = 0; i < data->size; i++)   690         size += strlen(__load_via_object(data->attrs[i].value, __pos___data__).strvalue);   691    692     /* Reserve space for a new string. */   693     s = (char *) __ALLOCATE(size + 1, sizeof(char));   694    695     /* Build a single string from the buffer contents. */   696     for (i = 0, j = 0; i < data->size; i++)   697     {   698         o = __load_via_object(data->attrs[i].value, __pos___data__).strvalue;   699         n = strlen(o);   700         strncpy(s + j, o, n); /* does not null terminate but final byte should be zero */   701         j += n;   702     }   703    704     /* Return a new string. */   705     return __new_str(s);   706 }   707    708 __attr __fn_native__get_using(__attr __args[])   709 {   710     __attr * const callable = &__args[1];   711     __attr * const instance = &__args[2];   712    713     return __replace_context(instance->value, *callable);   714 }   715    716 __attr __fn_native__object_getattr(__attr __args[])   717 {   718     __attr * const obj = &__args[1];   719     __attr * const name = &__args[2];   720     __attr * const _default = &__args[3];   721    722     /* NOTE: To be written. */   723     return __builtins___none_None;   724 }   725    726 static int __issubclass(__ref obj, __attr cls)   727 {   728     return (__HASATTR(obj, __TYPEPOS(cls.value), __TYPECODE(cls.value)));   729 }   730    731 __attr __fn_native__isinstance(__attr __args[])   732 {   733     __attr * const obj = &__args[1];   734     __attr * const cls = &__args[2];   735    736     /* cls must be a class. */   737     if (__is_instance(obj->value) && __issubclass(__get_class(obj->value), *cls))   738         return __builtins___boolean_True;   739     else   740         return __builtins___boolean_False;   741 }   742    743 __attr __fn_native__issubclass(__attr __args[])   744 {   745     __attr * const obj = &__args[1];   746     __attr * const cls = &__args[2];   747    748     /* obj and cls must be classes. */   749     if (__issubclass(obj->value, *cls))   750         return __builtins___boolean_True;   751     else   752         return __builtins___boolean_False;   753 }   754    755 __attr __fn_native__read(__attr __args[])   756 {   757     __attr * const fd = &__args[1];   758     __attr * const n = &__args[2];   759    760     /* NOTE: To be written. */   761     return __builtins___none_None;   762 }   763    764 __attr __fn_native__write(__attr __args[])   765 {   766     __attr * const fd = &__args[1];   767     __attr * const str = &__args[2];   768     /* fd.__data__ interpreted as int */   769     int i = __load_via_object(fd->value, __pos___data__).intvalue;   770     /* str.__data__ interpreted as string */   771     char *s = __load_via_object(str->value, __pos___data__).strvalue;   772    773     write(i, s, sizeof(char) * strlen(s));   774     return __builtins___none_None;   775 }   776    777 /* Module initialisation. */   778    779 void __main_native()   780 {   781 }