Lichen

templates/ops.c

131:197ae84b7b28
2016-10-25 Paul Boddie Introduced an encoder function for special type attributes.
     1 /* Common operations. */     2      3 #include "ops.h"     4 #include "progconsts.h"     5 #include "progtypes.h"     6      7 __attr null = {0, 0};     8      9 /* Direct access to functions. */    10     11 __attr __load_function(__func fn)    12 {    13     __attr out = {0, .fn=fn};    14     return out;    15 }    16     17 /* Direct access and manipulation of static objects. */    18     19 __attr __load_static(__ref obj)    20 {    21     __attr out = {0, .value=obj};    22     return out;    23 }    24     25 /* Direct retrieval operations, returning and setting attributes. */    26     27 __attr __load_via_object(__ref obj, int pos)    28 {    29     return obj->attrs[pos];    30 }    31     32 __attr __load_via_class(__ref obj, int pos)    33 {    34     return __load_via_object(__get_class(obj), pos);    35 }    36     37 __attr __get_class_and_load(__ref obj, int pos)    38 {    39     if (!__is_instance(obj))    40         return __load_via_object(obj, pos);    41     else    42         return __load_via_class(obj, pos);    43 }    44     45 /* Direct storage operations. */    46     47 int __store_via_object(__ref obj, int pos, __attr value)    48 {    49     obj->attrs[pos] = value;    50     return 1;    51 }    52     53 /* Introspection. */    54     55 int __is_instance(__ref obj)    56 {    57     return obj->pos == __INSTANCEPOS;    58 }    59     60 __ref __get_class(__ref obj)    61 {    62     return __load_via_object(obj, __pos___class__).value;    63 }    64     65 /* Attribute testing operations. */    66     67 int __test_specific_instance(__ref obj, __ref type)    68 {    69     return __get_class(obj) == type;    70 }    71     72 int __test_common_instance(__ref obj, int pos, int code)    73 {    74     return __HASATTR(__get_class(obj), pos, code);    75 }    76     77 /* Attribute testing and retrieval operations. */    78     79 __attr __check_and_load_via_class(__ref obj, int pos, int code)    80 {    81     return __check_and_load_via_object(__get_class(obj), pos, code);    82 }    83     84 __attr __check_and_load_via_object(__ref obj, int pos, int code)    85 {    86     return __HASATTR(obj, pos, code) ? __load_via_object(obj, pos) : null;    87 }    88     89 __attr __check_and_load_via_any(__ref obj, int pos, int code)    90 {    91     __attr out = __check_and_load_via_object(obj, pos, code);    92     if (out.value == 0)    93         out = __check_and_load_via_class(obj, pos, code);    94     return out;    95 }    96     97 /* Attribute testing and storage operations. */    98     99 int __check_and_store_via_object(__ref obj, int pos, int code, __attr value)   100 {   101     if (__HASATTR(obj, pos, code))   102     {   103         __store_via_object(obj, pos, value);   104         return 1;   105     }   106     return 0;   107 }   108    109 int __check_and_store_via_any(__ref obj, int pos, int code, __attr value)   110 {   111     if (__check_and_store_via_object(obj, pos, code, value))   112         return 1;   113     return __check_and_store_via_object(__get_class(obj), pos, code, value);   114 }   115    116 /* Context-related operations. */   117    118 __attr __test_context(__ref context, __attr attr)   119 {   120     if (__is_instance(attr.context))   121         return attr;   122     if (__test_common_instance(context, __TYPEPOS(attr.context), __TYPECODE(attr.context)))   123         return __replace_context(context, attr);   124    125     /* NOTE: An error may be more appropriate. */   126    127     return null;   128 }   129    130 __attr __replace_context(__ref context, __attr attr)   131 {   132     __attr out;   133    134     /* Set the context. */   135    136     out.context = context;   137    138     /* Reference a callable version of the attribute by obtaining the bound   139        method reference from the __fn__ special attribute. */   140    141     out.value = __load_via_object(attr.value, __ATTRPOS(__fn__)).b;   142     return out;   143 }   144    145 __attr __update_context(__ref context, __attr attr)   146 {   147     __attr out = {context, .fn=attr.fn};   148     return out;   149 }   150    151 /* Basic structure tests. */   152    153 int __WITHIN(__ref obj, int pos)   154 {   155     return pos < obj->table->size;   156 }   157    158 int __HASATTR(__ref obj, int pos, int code)   159 {   160     return __WITHIN(obj, pos) && (obj->table->attrs[pos] == code);   161 }   162    163 /* Parameter position operations. */   164    165 int __HASPARAM(const __ptable *ptable, int ppos, int pcode)   166 {   167     __param param;   168    169     if (ppos < ptable->size)   170     {   171         param = ptable->params[ppos];   172         if (param.code == pcode)   173             return param.pos;   174     }   175    176     return -1;   177 }   178    179 /* Conversions. */   180    181 __attr __CONTEXT_AS_VALUE(__attr attr)   182 {   183     __attr out;   184     out.context = attr.context;   185     out.value = attr.context;   186     return out;   187 }   188    189 /* Type testing. */   190    191 int __ISFUNC(__ref obj)   192 {   193     return __test_specific_instance(obj, &__FUNCTION_TYPE);   194 }   195    196 int __ISNULL(__attr value)   197 {   198     /* (value.context == null.context) is superfluous */   199     return (value.value == null.value);   200 }   201    202 /* Attribute codes and positions for type objects. */   203    204 unsigned int __TYPECODE(__ref obj)   205 {   206     return obj->table->attrs[obj->pos];   207 }   208    209 unsigned int __TYPEPOS(__ref obj)   210 {   211     return obj->pos;   212 }