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