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