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 int __test_specific_instance(__ref obj, __ref type) 66 { 67 return __get_class(obj) == type; 68 } 69 70 int __test_common_instance(__ref obj, int pos, int code) 71 { 72 return __HASATTR(__get_class(obj), pos, code); 73 } 74 75 /* Attribute testing and retrieval operations. */ 76 77 __attr __check_and_load_via_class(__ref obj, int pos, int code) 78 { 79 return __check_and_load_via_object(__get_class(obj), pos, code); 80 } 81 82 __attr __check_and_load_via_object(__ref obj, int pos, int code) 83 { 84 return __HASATTR(obj, pos, code) ? __load_via_object(obj, pos) : __NULL; 85 } 86 87 __attr __check_and_load_via_any(__ref obj, int pos, int code) 88 { 89 __attr out = __check_and_load_via_object(obj, pos, code); 90 if (out.value == 0) 91 out = __check_and_load_via_class(obj, pos, code); 92 return out; 93 } 94 95 /* Attribute testing and storage operations. */ 96 97 int __check_and_store_via_object(__ref obj, int pos, int code, __attr value) 98 { 99 if (__HASATTR(obj, pos, code)) 100 { 101 __store_via_object(obj, pos, value); 102 return 1; 103 } 104 return 0; 105 } 106 107 int __check_and_store_via_any(__ref obj, int pos, int code, __attr value) 108 { 109 if (__check_and_store_via_object(obj, pos, code, value)) 110 return 1; 111 return __check_and_store_via_object(__get_class(obj), pos, code, value); 112 } 113 114 /* Context-related operations. */ 115 116 __attr __test_context(__ref context, __attr attr) 117 { 118 if (__is_instance(attr.context)) 119 return attr; 120 if (__test_common_instance(context, __TYPEPOS(attr.context), __TYPECODE(attr.context))) 121 return __replace_context(context, attr); 122 123 /* NOTE: An error may be more appropriate. */ 124 125 return __NULL; 126 } 127 128 __attr __replace_context(__ref context, __attr attr) 129 { 130 __attr out; 131 132 /* Set the context. */ 133 134 out.context = context; 135 136 /* Reference a callable version of the attribute by obtaining the bound 137 method reference from the __fn__ special attribute. */ 138 139 out.value = __load_via_object(attr.value, __ATTRPOS(__fn__)).b; 140 return out; 141 } 142 143 __attr __update_context(__ref context, __attr attr) 144 { 145 __attr out = {context, .fn=attr.fn}; 146 return out; 147 } 148 149 /* Basic structure tests. */ 150 151 int __WITHIN(__ref obj, int pos) 152 { 153 return pos < obj->table->size; 154 } 155 156 int __HASATTR(__ref obj, int pos, int code) 157 { 158 return __WITHIN(obj, pos) && (obj->table->attrs[pos] == code); 159 } 160 161 /* Parameter position operations. */ 162 163 int __HASPARAM(const __ptable *ptable, int ppos, int pcode) 164 { 165 __param param; 166 167 if (ppos < ptable->size) 168 { 169 param = ptable->params[ppos]; 170 if (param.code == pcode) 171 return param.pos; 172 } 173 174 return -1; 175 } 176 177 /* Conversions. */ 178 179 __attr __CONTEXT_AS_VALUE(__attr attr) 180 { 181 __attr out; 182 out.context = attr.context; 183 out.value = attr.context; 184 return out; 185 } 186 187 /* Type testing. */ 188 189 int __ISFUNC(__ref obj) 190 { 191 return __test_specific_instance(obj, &__FUNCTION_TYPE); 192 } 193 194 int __ISNULL(__attr value) 195 { 196 /* (value.context == __NULL.context) is superfluous */ 197 return (value.value == 0); /* __NULL.value */ 198 } 199 200 /* Attribute codes and positions for type objects. */ 201 202 unsigned int __TYPECODE(__ref obj) 203 { 204 return obj->table->attrs[obj->pos]; 205 } 206 207 unsigned int __TYPEPOS(__ref obj) 208 { 209 return obj->pos; 210 }