1 /* Operations depending on program specifics. 2 */ 3 4 #include <stdlib.h> 5 #include "types.h" 6 #include "ops.h" 7 #include "progconsts.h" 8 #include "progops.h" 9 #include "progtypes.h" 10 #include "main.h" 11 #include "exceptions.h" 12 13 /* Generic instantiation operations, defining common members. */ 14 15 __attr __new(const __table * table, __ref cls, size_t size) 16 { 17 __ref obj = (__ref) __ALLOCATE(1, size); 18 __attr self = {obj, obj}; 19 __attr tmp = {0, cls}; 20 obj->table = table; 21 __store_via_object(obj, __pos___class__, tmp); 22 return self; 23 } 24 25 /* Generic internal data allocation. */ 26 27 __fragment *__new_fragment(unsigned int n) 28 { 29 /* Allocate space for the list. */ 30 __fragment *data = (__fragment *) __ALLOCATE(1, __FRAGMENT_SIZE(n)); 31 32 /* The initial capacity is the same as the given size. */ 33 data->size = 0; 34 data->capacity = n; 35 return data; 36 } 37 38 __mapping *__new_mapping(unsigned int n) 39 { 40 /* Allocate a number of buckets. */ 41 __mapping *data = (__mapping *) __ALLOCATE(1, __MAPPING_SIZE(__MAPPING_BUCKETS)); 42 unsigned int i; 43 44 /* Allocate fragments with an initial size of 2 * n / __MAPPING_BUCKETS, 45 assuming a mostly uniform distribution of values across the buckets. */ 46 47 for (i = 0; i < __MAPPING_BUCKETS; i++) 48 { 49 data->keys[i] = __new_fragment(2 * n / __MAPPING_BUCKETS); 50 data->values[i] = __new_fragment(2 * n / __MAPPING_BUCKETS); 51 } 52 53 return data; 54 } 55 56 void __newdata_sequence(__attr args[], unsigned int number) 57 { 58 /* Calculate the size of the fragment. */ 59 60 __fragment *data = __new_fragment(number); 61 __attr attr = {0, .seqvalue=data}; 62 unsigned int i, j; 63 64 /* Copy the given number of values, starting from the second element. */ 65 66 for (i = 1, j = 0; i <= number; i++, j++) 67 data->attrs[j] = args[i]; 68 69 data->size = number; 70 71 /* Store a reference to the data in the object's __data__ attribute. */ 72 73 __store_via_object(args[0].value, __pos___data__, attr); 74 } 75 76 void __newdata_mapping(__attr args[], unsigned int number) 77 { 78 __mapping *data = __new_mapping(number); 79 __attr attr = {0, .mapvalue=data}; 80 __fragment *f; 81 __attr callargs[3]; 82 unsigned int i; 83 84 /* Store a reference to the data in the object's __data__ attribute. */ 85 86 __store_via_object(args[0].value, __pos___data__, attr); 87 88 /* Store the given number of values, starting from the second element. */ 89 90 for (i = 1; i <= number; i++) 91 { 92 /* Obtain the tuple elements. */ 93 94 f = __load_via_object(args[i].value, __pos___data__).seqvalue; 95 callargs[0] = args[0]; 96 callargs[1] = f->attrs[0]; 97 callargs[2] = f->attrs[1]; 98 99 /* Call __setitem__ with the key and value. */ 100 101 __fn___builtins___dict_dict___setitem__(callargs); 102 } 103 } 104 105 /* A helper for raising type errors within common operations. */ 106 107 void __raise_type_error() 108 { 109 __attr args[1]; 110 __attr exc = __TYPE_ERROR_INSTANTIATOR(args); 111 __Raise(exc); 112 } 113 114 /* A helper for raising memory errors within common operations. */ 115 116 void __raise_memory_error() 117 { 118 __attr args[1]; 119 __attr exc = __MEMORY_ERROR_INSTANTIATOR(args); 120 __Raise(exc); 121 } 122 123 /* Generic invocation operations. */ 124 125 /* Invoke the given callable, supplying keyword argument details in the given 126 codes and arguments arrays, indicating the number of arguments described. 127 The number of positional arguments is specified, and such arguments then 128 follow as conventional function arguments. Typically, at least one argument 129 is specified, starting with any context argument. 130 */ 131 132 __attr __invoke(__attr callable, int always_callable, 133 unsigned int nkwargs, __param kwcodes[], __attr kwargs[], 134 unsigned int nargs, __attr args[]) 135 { 136 /* Obtain the __args__ special member, referencing the parameter table. */ 137 138 __attr minparams = __check_and_load_via_object(callable.value, __pos___args__, __code___args__); 139 140 /* Refer to the table and minimum/maximum. */ 141 142 const __ptable *ptable = minparams.ptable; 143 const unsigned int min = minparams.min, max = ptable->size; 144 145 /* Reserve enough space for the arguments. */ 146 147 __attr allargs[max]; 148 149 /* Traverse the arguments. */ 150 151 unsigned int pos, kwpos; 152 153 /* Check the number of arguments. */ 154 155 if ((min > (nargs + nkwargs)) || ((nargs + nkwargs) > max)) 156 return __NULL; 157 158 /* Copy the arguments. */ 159 160 for (pos = 0; pos < nargs; pos++) 161 allargs[pos] = args[pos]; 162 163 /* Erase the remaining arguments. */ 164 165 for (pos = nargs; pos < max; pos++) 166 { 167 allargs[pos].value = 0; 168 } 169 170 /* Fill keyword arguments. */ 171 172 for (kwpos = 0; kwpos < nkwargs; kwpos++) 173 { 174 pos = __HASPARAM(ptable, kwcodes[kwpos].pos, kwcodes[kwpos].code); 175 176 /* Check the table entry against the supplied argument details. 177 Set the argument but only if it does not overwrite positional 178 arguments. */ 179 180 if ((pos == -1) || (pos < nargs)) 181 return __NULL; 182 183 /* Set the argument using the appropriate position. */ 184 185 allargs[pos] = kwargs[kwpos]; 186 } 187 188 /* Fill the defaults. */ 189 190 for (pos = nargs; pos < max; pos++) 191 { 192 if (allargs[pos].value == 0) 193 allargs[pos] = __GETDEFAULT(callable.value, pos - min); 194 } 195 196 /* Call with the prepared arguments. */ 197 198 return (always_callable ? __load_via_object(callable.value, __pos___fn__) 199 : __check_and_load_via_object(callable.value, __pos___fn__, __code___fn__) 200 ).fn(allargs); 201 } 202 203 /* Error routines. */ 204 205 __attr __unbound_method(__attr args[]) 206 { 207 __attr excargs[1]; 208 __attr exc = __new___builtins___core_UnboundMethodInvocation(excargs); 209 __Raise(exc); 210 return __builtins___none_None; /* superfluous */ 211 } 212 213 /* Generic operations depending on specific program details. */ 214 215 void __SETDEFAULT(__ref obj, int pos, __attr value) 216 { 217 __store_via_object(obj, __FUNCTION_INSTANCE_SIZE + pos, value); 218 } 219 220 __attr __GETDEFAULT(__ref obj, int pos) 221 { 222 return __load_via_object(obj, __FUNCTION_INSTANCE_SIZE + pos); 223 } 224 225 int __BOOL(__attr attr) 226 { 227 __attr args[2] = {{0, 0}, attr}; 228 229 /* Invoke the bool function with the object and test against True. */ 230 231 return __fn___builtins___boolean_bool(args).value == __builtins___boolean_True.value; 232 }