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