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 #ifdef __HAVE___builtins___dict_dict 77 78 void __newdata_mapping(__attr args[], unsigned int number) 79 { 80 __mapping *data = __new_mapping(number); 81 __attr attr = {0, .mapvalue=data}; 82 __fragment *f; 83 __attr callargs[3]; 84 unsigned int i; 85 86 /* Store a reference to the data in the object's __data__ attribute. */ 87 88 __store_via_object(args[0].value, __pos___data__, attr); 89 90 /* Store the given number of values, starting from the second element. */ 91 92 for (i = 1; i <= number; i++) 93 { 94 /* Obtain the tuple elements. */ 95 96 f = __load_via_object(args[i].value, __pos___data__).seqvalue; 97 callargs[0] = args[0]; 98 callargs[1] = f->attrs[0]; 99 callargs[2] = f->attrs[1]; 100 101 /* Call __setitem__ with the key and value. */ 102 103 __fn___builtins___dict_dict___setitem__(callargs); 104 } 105 } 106 107 #endif /* __HAVE___builtins___dict_dict */ 108 109 /* A helper for raising type errors within common operations. */ 110 111 void __raise_type_error() 112 { 113 __attr args[1]; 114 __attr exc = __TYPE_ERROR_INSTANTIATOR(args); 115 __Raise(exc); 116 } 117 118 /* A helper for raising memory errors within common operations. */ 119 120 void __raise_memory_error() 121 { 122 __attr args[1]; 123 __attr exc = __MEMORY_ERROR_INSTANTIATOR(args); 124 __Raise(exc); 125 } 126 127 /* Generic invocation operations. */ 128 129 /* Invoke the given callable, supplying keyword argument details in the given 130 codes and arguments arrays, indicating the number of arguments described. 131 The number of positional arguments is specified, and such arguments then 132 follow as conventional function arguments. Typically, at least one argument 133 is specified, starting with any context argument. 134 */ 135 136 __attr __invoke(__attr callable, int always_callable, 137 unsigned int nkwargs, __param kwcodes[], __attr kwargs[], 138 unsigned int nargs, __attr args[]) 139 { 140 /* Obtain the __args__ special member, referencing the parameter table. */ 141 142 __attr minparams = __check_and_load_via_object(callable.value, __pos___args__, __code___args__); 143 144 /* Refer to the table and minimum/maximum. */ 145 146 const __ptable *ptable = minparams.ptable; 147 const unsigned int min = minparams.min, max = ptable->size; 148 149 /* Reserve enough space for the arguments. */ 150 151 __attr allargs[max]; 152 153 /* Traverse the arguments. */ 154 155 unsigned int pos, kwpos; 156 157 /* Check the number of arguments. */ 158 159 if ((min > (nargs + nkwargs)) || ((nargs + nkwargs) > max)) 160 return __NULL; 161 162 /* Copy the arguments. */ 163 164 for (pos = 0; pos < nargs; pos++) 165 allargs[pos] = args[pos]; 166 167 /* Erase the remaining arguments. */ 168 169 for (pos = nargs; pos < max; pos++) 170 { 171 allargs[pos].value = 0; 172 } 173 174 /* Fill keyword arguments. */ 175 176 for (kwpos = 0; kwpos < nkwargs; kwpos++) 177 { 178 pos = __HASPARAM(ptable, kwcodes[kwpos].pos, kwcodes[kwpos].code); 179 180 /* Check the table entry against the supplied argument details. 181 Set the argument but only if it does not overwrite positional 182 arguments. */ 183 184 if ((pos == -1) || (pos < nargs)) 185 return __NULL; 186 187 /* Set the argument using the appropriate position. */ 188 189 allargs[pos] = kwargs[kwpos]; 190 } 191 192 /* Fill the defaults. */ 193 194 for (pos = nargs; pos < max; pos++) 195 { 196 if (allargs[pos].value == 0) 197 allargs[pos] = __GETDEFAULT(callable.value, pos - min); 198 } 199 200 /* Call with the prepared arguments. */ 201 202 return (always_callable ? __load_via_object(callable.value, __pos___fn__) 203 : __check_and_load_via_object(callable.value, __pos___fn__, __code___fn__) 204 ).fn(allargs); 205 } 206 207 /* Error routines. */ 208 209 __attr __unbound_method(__attr args[]) 210 { 211 __attr excargs[1]; 212 __attr exc = __new___builtins___core_UnboundMethodInvocation(excargs); 213 __Raise(exc); 214 return __builtins___none_None; /* superfluous */ 215 } 216 217 /* Generic operations depending on specific program details. */ 218 219 void __SETDEFAULT(__ref obj, int pos, __attr value) 220 { 221 __store_via_object(obj, __FUNCTION_INSTANCE_SIZE + pos, value); 222 } 223 224 __attr __GETDEFAULT(__ref obj, int pos) 225 { 226 return __load_via_object(obj, __FUNCTION_INSTANCE_SIZE + pos); 227 } 228 229 int __BOOL(__attr attr) 230 { 231 __attr args[2] = {{0, 0}, attr}; 232 233 /* Invoke the bool function with the object and test against True. */ 234 235 return __fn___builtins___boolean_bool(args).value == __builtins___boolean_True.value; 236 }