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