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