Lichen

templates/ops.c

338:61776a5a0e16
2016-12-07 Paul Boddie Associate constant name information with references so that structure members such as function instance default members can be generated statically, thus eliminating unnecessary structure initialisation in the translated code. Improved the determination of dynamic functions in the importer to consider only non-constant defaults.
     1 /* Common operations. */     2      3 #include <stdlib.h>     4 #include "ops.h"     5 #include "progops.h" /* for raising errors */     6 #include "progconsts.h"     7 #include "progtypes.h"     8      9 /* Direct access and manipulation of static objects. */    10     11 __attr __load_static(__ref parent, __ref obj)    12 {    13     __attr out = {.context=parent, .value=obj};    14     return out;    15 }    16     17 /* Direct retrieval operations, returning and setting attributes. */    18     19 __attr __load_via_object(__ref obj, int pos)    20 {    21     return obj->attrs[pos];    22 }    23     24 __attr __load_via_class(__ref obj, int pos)    25 {    26     return __load_via_object(__get_class(obj), pos);    27 }    28     29 __attr __get_class_and_load(__ref obj, int pos)    30 {    31     if (__is_instance(obj))    32         return __load_via_class(obj, pos);    33     else    34         return __load_via_object(obj, pos);    35 }    36     37 /* Direct storage operations. */    38     39 int __store_via_object(__ref obj, int pos, __attr value)    40 {    41     obj->attrs[pos] = value;    42     return 1;    43 }    44     45 int __get_class_and_store(__ref obj, int pos, __attr value)    46 {    47     /* Forbid class-relative assignments. */    48     49     __raise_type_error();    50     return 0;    51 }    52     53 /* Introspection. */    54     55 int __is_instance(__ref obj)    56 {    57     return obj->pos == __INSTANCEPOS;    58 }    59     60 int __is_type_instance(__ref obj)    61 {    62     return __HASATTR(__get_class(obj), __TYPE_CLASS_POS, __TYPE_CLASS_CODE);    63 }    64     65 __ref __get_class(__ref obj)    66 {    67     return __load_via_object(obj, __pos___class__).value;    68 }    69     70 __attr __get_class_attr(__ref obj)    71 {    72     return __load_via_object(obj, __pos___class__);    73 }    74     75 /* Attribute testing operations. */    76     77 __ref __test_specific_instance(__ref obj, __ref type)    78 {    79     return __get_class(obj) == type ? obj : 0;    80 }    81     82 __ref __test_specific_object(__ref obj, __ref type)    83 {    84     return __test_specific_type(obj, type) || __test_specific_instance(obj, type) ? obj : 0;    85 }    86     87 __ref __test_specific_type(__ref obj, __ref type)    88 {    89     return obj == type ? obj : 0;    90 }    91     92 __ref __test_common_instance(__ref obj, int pos, int code)    93 {    94     return __HASATTR(__get_class(obj), pos, code) ? obj : 0;    95 }    96     97 __ref __test_common_object(__ref obj, int pos, int code)    98 {    99     return __test_common_type(obj, pos, code) || __test_common_instance(obj, pos, code) ? obj : 0;   100 }   101    102 __ref __test_common_type(__ref obj, int pos, int code)   103 {   104     return __HASATTR(obj, pos, code) ? obj : 0;   105 }   106    107 /* Attribute testing and retrieval operations. */   108    109 static __attr __check_and_load_via_object_null(__ref obj, int pos, int code)   110 {   111     if (__HASATTR(obj, pos, code))   112         return __load_via_object(obj, pos);   113     else   114         return __NULL;   115 }   116    117 __attr __check_and_load_via_class(__ref obj, int pos, int code)   118 {   119     return __check_and_load_via_object(__get_class(obj), pos, code);   120 }   121    122 __attr __check_and_load_via_object(__ref obj, int pos, int code)   123 {   124     if (__HASATTR(obj, pos, code))   125         return __load_via_object(obj, pos);   126    127     __raise_type_error();   128     return __NULL;   129 }   130    131 __attr __check_and_load_via_any(__ref obj, int pos, int code)   132 {   133     __attr out = __check_and_load_via_object_null(obj, pos, code);   134     if (out.value == 0)   135         out = __check_and_load_via_class(obj, pos, code);   136     return out;   137 }   138    139 /* Attribute testing and storage operations. */   140    141 int __check_and_store_via_class(__ref obj, int pos, int code, __attr value)   142 {   143     /* Forbid class-relative assignments. */   144    145     __raise_type_error();   146     return 0;   147 }   148    149 int __check_and_store_via_object(__ref obj, int pos, int code, __attr value)   150 {   151     if (__HASATTR(obj, pos, code))   152     {   153         __store_via_object(obj, pos, value);   154         return 1;   155     }   156    157     /* No suitable attribute. */   158    159     __raise_type_error();   160     return 0;   161 }   162    163 int __check_and_store_via_any(__ref obj, int pos, int code, __attr value)   164 {   165     if (__check_and_store_via_object(obj, pos, code, value))   166         return 1;   167    168     /* Forbid class-relative assignments. */   169    170     __raise_type_error();   171     return 0;   172 }   173    174 /* Context-related operations. */   175    176 __attr __test_context(__ref context, __attr attr)   177 {   178     /* Preserve any existing null or instance context. */   179    180     if ((attr.context == 0) || __is_instance(attr.context))   181         return attr;   182    183     /* Test any instance context against the context employed by the   184        attribute. */   185    186     if (__is_instance(context))   187         if (__test_common_instance(context, __TYPEPOS(attr.context), __TYPECODE(attr.context)))   188             return __replace_context(context, attr);   189         else   190             __raise_type_error();   191    192     /* Test for access to a type class attribute using a type instance. */   193    194     if (__test_specific_type(attr.context, &__TYPE_CLASS_TYPE) && __is_type_instance(context))   195         return __replace_context(context, attr);   196    197     /* Otherwise, preserve the attribute as retrieved. */   198    199     return attr;   200 }   201    202 __attr __replace_context(__ref context, __attr attr)   203 {   204     __attr out;   205    206     /* Set the context. */   207    208     out.context = context;   209    210     /* Reference a callable version of the attribute by obtaining the bound   211        method reference from the __fn__ special attribute. */   212    213     out.value = __load_via_object(attr.value, __ATTRPOS(__fn__)).b;   214     return out;   215 }   216    217 __attr __update_context(__ref context, __attr attr)   218 {   219     __attr out = {context, .fn=attr.fn};   220     return out;   221 }   222    223 /* Basic structure tests. */   224    225 int __WITHIN(__ref obj, int pos)   226 {   227     return pos < obj->table->size;   228 }   229    230 int __HASATTR(__ref obj, int pos, int code)   231 {   232     return __WITHIN(obj, pos) && (obj->table->attrs[pos] == code);   233 }   234    235 /* Parameter position operations. */   236    237 int __HASPARAM(const __ptable *ptable, int ppos, int pcode)   238 {   239     __param param;   240    241     if (ppos < ptable->size)   242     {   243         param = ptable->params[ppos];   244         if (param.code == pcode)   245             return param.pos;   246     }   247    248     return -1;   249 }   250    251 /* Conversions. */   252    253 __attr __CONTEXT_AS_VALUE(__attr attr)   254 {   255     __attr out;   256     out.context = attr.context;   257     out.value = attr.context;   258     return out;   259 }   260    261 /* Type testing. */   262    263 __ref __ISFUNC(__ref obj)   264 {   265     return __test_specific_instance(obj, &__FUNCTION_TYPE);   266 }   267    268 int __ISNULL(__attr value)   269 {   270     /* (value.context == __NULL.context) is superfluous */   271     return (value.value == 0); /* __NULL.value */   272 }   273    274 /* Attribute codes and positions for type objects. */   275    276 unsigned int __TYPECODE(__ref obj)   277 {   278     return obj->table->attrs[obj->pos];   279 }   280    281 unsigned int __TYPEPOS(__ref obj)   282 {   283     return obj->pos;   284 }   285    286 /* Memory allocation. */   287    288 void *__ALLOCATE(size_t nmemb, size_t size)   289 {   290     void *ptr = calloc(nmemb, size);   291     if (ptr == NULL)   292         __raise_memory_error();   293     return ptr;   294 }   295    296 void *__REALLOCATE(void *ptr, size_t size)   297 {   298     void *nptr = realloc(ptr, size);   299     if (nptr == NULL)   300         __raise_memory_error();   301     return nptr;   302 }   303    304 /* Copying of structures. */   305    306 __ref __COPY(__ref obj, int size)   307 {   308     __ref copy = (__ref) __ALLOCATE(1, size);   309     memcpy(copy, obj, size);   310     return copy;   311 }