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