Lichen

templates/ops.c

275:6a85c86bb1f1
2016-11-29 Paul Boddie Changed lplc to always return 1 upon failure, eliminating unnecessary options. Changed the test runner to continue after expected test failures.
     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 int __is_type_instance(__ref obj)    63 {    64     return __HASATTR(__get_class(obj), __TYPE_CLASS_POS, __TYPE_CLASS_CODE);    65 }    66     67 __ref __get_class(__ref obj)    68 {    69     return __load_via_object(obj, __pos___class__).value;    70 }    71     72 __attr __get_class_attr(__ref obj)    73 {    74     return __load_via_object(obj, __pos___class__);    75 }    76     77 /* Attribute testing operations. */    78     79 __ref __test_specific_instance(__ref obj, __ref type)    80 {    81     return __get_class(obj) == type ? obj : 0;    82 }    83     84 __ref __test_specific_object(__ref obj, __ref type)    85 {    86     return __test_specific_type(obj, type) || __test_specific_instance(obj, type) ? obj : 0;    87 }    88     89 __ref __test_specific_type(__ref obj, __ref type)    90 {    91     return obj == type ? obj : 0;    92 }    93     94 __ref __test_common_instance(__ref obj, int pos, int code)    95 {    96     return __HASATTR(__get_class(obj), pos, code) ? obj : 0;    97 }    98     99 __ref __test_common_object(__ref obj, int pos, int code)   100 {   101     return __test_common_type(obj, pos, code) || __test_common_instance(obj, pos, code) ? obj : 0;   102 }   103    104 __ref __test_common_type(__ref obj, int pos, int code)   105 {   106     return __HASATTR(obj, pos, code) ? obj : 0;   107 }   108    109 /* Attribute testing and retrieval operations. */   110    111 static __attr __check_and_load_via_object_null(__ref obj, int pos, int code)   112 {   113     if (__HASATTR(obj, pos, code))   114         return __load_via_object(obj, pos);   115     else   116         return __NULL;   117 }   118    119 __attr __check_and_load_via_class(__ref obj, int pos, int code)   120 {   121     return __check_and_load_via_object(__get_class(obj), pos, code);   122 }   123    124 __attr __check_and_load_via_object(__ref obj, int pos, int code)   125 {   126     if (__HASATTR(obj, pos, code))   127         return __load_via_object(obj, pos);   128    129     __raise_type_error();   130     return __NULL;   131 }   132    133 __attr __check_and_load_via_any(__ref obj, int pos, int code)   134 {   135     __attr out = __check_and_load_via_object_null(obj, pos, code);   136     if (out.value == 0)   137         out = __check_and_load_via_class(obj, pos, code);   138     return out;   139 }   140    141 /* Attribute testing and storage operations. */   142    143 int __check_and_store_via_class(__ref obj, int pos, int code, __attr value)   144 {   145     /* Forbid class-relative assignments. */   146    147     __raise_type_error();   148     return 0;   149 }   150    151 int __check_and_store_via_object(__ref obj, int pos, int code, __attr value)   152 {   153     if (__HASATTR(obj, pos, code))   154     {   155         __store_via_object(obj, pos, value);   156         return 1;   157     }   158    159     /* No suitable attribute. */   160    161     __raise_type_error();   162     return 0;   163 }   164    165 int __check_and_store_via_any(__ref obj, int pos, int code, __attr value)   166 {   167     if (__check_and_store_via_object(obj, pos, code, value))   168         return 1;   169    170     /* Forbid class-relative assignments. */   171    172     __raise_type_error();   173     return 0;   174 }   175    176 /* Context-related operations. */   177    178 __attr __test_context(__ref context, __attr attr)   179 {   180     /* Preserve any existing null or instance context. */   181    182     if ((attr.context == 0) || __is_instance(attr.context))   183         return attr;   184    185     /* Test any instance context against the context employed by the   186        attribute. */   187    188     if (__is_instance(context))   189         if (__test_common_instance(context, __TYPEPOS(attr.context), __TYPECODE(attr.context)))   190             return __replace_context(context, attr);   191         else   192             __raise_type_error();   193    194     /* Test for access to a type class attribute using a type instance. */   195    196     if (__test_specific_type(attr.context, &__TYPE_CLASS_TYPE) && __is_type_instance(context))   197         return __replace_context(context, attr);   198    199     /* Otherwise, preserve the attribute as retrieved. */   200    201     return attr;   202 }   203    204 __attr __replace_context(__ref context, __attr attr)   205 {   206     __attr out;   207    208     /* Set the context. */   209    210     out.context = context;   211    212     /* Reference a callable version of the attribute by obtaining the bound   213        method reference from the __fn__ special attribute. */   214    215     out.value = __load_via_object(attr.value, __ATTRPOS(__fn__)).b;   216     return out;   217 }   218    219 __attr __update_context(__ref context, __attr attr)   220 {   221     __attr out = {context, .fn=attr.fn};   222     return out;   223 }   224    225 /* Basic structure tests. */   226    227 int __WITHIN(__ref obj, int pos)   228 {   229     return pos < obj->table->size;   230 }   231    232 int __HASATTR(__ref obj, int pos, int code)   233 {   234     return __WITHIN(obj, pos) && (obj->table->attrs[pos] == code);   235 }   236    237 /* Parameter position operations. */   238    239 int __HASPARAM(const __ptable *ptable, int ppos, int pcode)   240 {   241     __param param;   242    243     if (ppos < ptable->size)   244     {   245         param = ptable->params[ppos];   246         if (param.code == pcode)   247             return param.pos;   248     }   249    250     return -1;   251 }   252    253 /* Conversions. */   254    255 __attr __CONTEXT_AS_VALUE(__attr attr)   256 {   257     __attr out;   258     out.context = attr.context;   259     out.value = attr.context;   260     return out;   261 }   262    263 /* Type testing. */   264    265 __ref __ISFUNC(__ref obj)   266 {   267     return __test_specific_instance(obj, &__FUNCTION_TYPE);   268 }   269    270 int __ISNULL(__attr value)   271 {   272     /* (value.context == __NULL.context) is superfluous */   273     return (value.value == 0); /* __NULL.value */   274 }   275    276 /* Attribute codes and positions for type objects. */   277    278 unsigned int __TYPECODE(__ref obj)   279 {   280     return obj->table->attrs[obj->pos];   281 }   282    283 unsigned int __TYPEPOS(__ref obj)   284 {   285     return obj->pos;   286 }   287    288 /* Memory allocation. */   289    290 void *__ALLOCATE(size_t nmemb, size_t size)   291 {   292     void *ptr = calloc(nmemb, size);   293     if (ptr == NULL)   294         __raise_memory_error();   295     return ptr;   296 }   297    298 void *__REALLOCATE(void *ptr, size_t size)   299 {   300     void *nptr = realloc(ptr, size);   301     if (nptr == NULL)   302         __raise_memory_error();   303     return nptr;   304 }   305    306 /* Copying of structures. */   307    308 __ref __COPY(__ref obj, int size)   309 {   310     __ref copy = (__ref) __ALLOCATE(1, size);   311     memcpy(copy, obj, size);   312     return copy;   313 }