Lichen

templates/ops.c

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