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