Lichen

templates/ops.c

289:9f7b491d750c
2016-12-01 Paul Boddie Tidied up the string class.
     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 }