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