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