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 /* Introspection. */ 45 46 int __is_instance(__ref obj) 47 { 48 return obj->pos == __INSTANCEPOS; 49 } 50 51 __ref __get_class(__ref obj) 52 { 53 return __load_via_object(obj, __pos___class__).value; 54 } 55 56 __attr __get_class_attr(__ref obj) 57 { 58 return __load_via_object(obj, __pos___class__); 59 } 60 61 /* Attribute testing operations. */ 62 63 __ref __test_specific_instance(__ref obj, __ref type) 64 { 65 return __get_class(obj) == type ? obj : 0; 66 } 67 68 __ref __test_specific_object(__ref obj, __ref type) 69 { 70 return __test_specific_type(obj, type) || __test_specific_instance(obj, type) ? obj : 0; 71 } 72 73 __ref __test_specific_type(__ref obj, __ref type) 74 { 75 return obj == type ? obj : 0; 76 } 77 78 __ref __test_common_instance(__ref obj, int pos, int code) 79 { 80 return __HASATTR(__get_class(obj), pos, code) ? obj : 0; 81 } 82 83 __ref __test_common_object(__ref obj, int pos, int code) 84 { 85 return __test_common_type(obj, pos, code) || __test_common_instance(obj, pos, code) ? obj : 0; 86 } 87 88 __ref __test_common_type(__ref obj, int pos, int code) 89 { 90 return __HASATTR(obj, pos, code) ? obj : 0; 91 } 92 93 /* Attribute testing and retrieval operations. */ 94 95 static __attr __check_and_load_via_object_null(__ref obj, int pos, int code) 96 { 97 if (__HASATTR(obj, pos, code)) 98 return __load_via_object(obj, pos); 99 else 100 return __NULL; 101 } 102 103 __attr __check_and_load_via_class(__ref obj, int pos, int code) 104 { 105 return __check_and_load_via_object(__get_class(obj), pos, code); 106 } 107 108 __attr __check_and_load_via_object(__ref obj, int pos, int code) 109 { 110 if (__HASATTR(obj, pos, code)) 111 return __load_via_object(obj, pos); 112 113 __raise_type_error(); 114 return __NULL; 115 } 116 117 __attr __check_and_load_via_any(__ref obj, int pos, int code) 118 { 119 __attr out = __check_and_load_via_object_null(obj, pos, code); 120 if (out.value == 0) 121 out = __check_and_load_via_class(obj, pos, code); 122 return out; 123 } 124 125 /* Attribute testing and storage operations. */ 126 127 int __check_and_store_via_object(__ref obj, int pos, int code, __attr value) 128 { 129 if (__HASATTR(obj, pos, code)) 130 { 131 __store_via_object(obj, pos, value); 132 return 1; 133 } 134 return 0; 135 } 136 137 int __check_and_store_via_any(__ref obj, int pos, int code, __attr value) 138 { 139 if (__check_and_store_via_object(obj, pos, code, value)) 140 return 1; 141 return __check_and_store_via_object(__get_class(obj), pos, code, value); 142 } 143 144 /* Context-related operations. */ 145 146 __attr __test_context(__ref context, __attr attr) 147 { 148 /* Preserve any existing instance context. */ 149 150 if (__is_instance(attr.context)) 151 return attr; 152 153 /* Test any instance context against the context employed by the 154 attribute. */ 155 156 if (__is_instance(context)) 157 if (__test_common_instance(context, __TYPEPOS(attr.context), __TYPECODE(attr.context))) 158 return __replace_context(context, attr); 159 else 160 __raise_type_error(); 161 162 /* Otherwise, preserve the attribute as retrieved. */ 163 164 return attr; 165 } 166 167 __attr __replace_context(__ref context, __attr attr) 168 { 169 __attr out; 170 171 /* Set the context. */ 172 173 out.context = context; 174 175 /* Reference a callable version of the attribute by obtaining the bound 176 method reference from the __fn__ special attribute. */ 177 178 out.value = __load_via_object(attr.value, __ATTRPOS(__fn__)).b; 179 return out; 180 } 181 182 __attr __update_context(__ref context, __attr attr) 183 { 184 __attr out = {context, .fn=attr.fn}; 185 return out; 186 } 187 188 /* Basic structure tests. */ 189 190 int __WITHIN(__ref obj, int pos) 191 { 192 return pos < obj->table->size; 193 } 194 195 int __HASATTR(__ref obj, int pos, int code) 196 { 197 return __WITHIN(obj, pos) && (obj->table->attrs[pos] == code); 198 } 199 200 /* Parameter position operations. */ 201 202 int __HASPARAM(const __ptable *ptable, int ppos, int pcode) 203 { 204 __param param; 205 206 if (ppos < ptable->size) 207 { 208 param = ptable->params[ppos]; 209 if (param.code == pcode) 210 return param.pos; 211 } 212 213 return -1; 214 } 215 216 /* Conversions. */ 217 218 __attr __CONTEXT_AS_VALUE(__attr attr) 219 { 220 __attr out; 221 out.context = attr.context; 222 out.value = attr.context; 223 return out; 224 } 225 226 /* Type testing. */ 227 228 __ref __ISFUNC(__ref obj) 229 { 230 return __test_specific_instance(obj, &__FUNCTION_TYPE); 231 } 232 233 int __ISNULL(__attr value) 234 { 235 /* (value.context == __NULL.context) is superfluous */ 236 return (value.value == 0); /* __NULL.value */ 237 } 238 239 /* Attribute codes and positions for type objects. */ 240 241 unsigned int __TYPECODE(__ref obj) 242 { 243 return obj->table->attrs[obj->pos]; 244 } 245 246 unsigned int __TYPEPOS(__ref obj) 247 { 248 return obj->pos; 249 } 250 251 /* Copying of structures. */ 252 253 __ref __COPY(__ref obj, int size) 254 { 255 __ref copy = calloc(1, size); 256 memcpy(copy, obj, size); 257 return copy; 258 }