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 void __newdata_mapping(__attr args[], unsigned int number) 62 { 63 __attr dict = args[0]; 64 __attr callargs[2]; 65 66 /* Create a temporary list using the arguments. */ 67 68 __newliteral___builtins___list_list(args, number); 69 70 /* Call __init__ with the dict object and list argument. */ 71 72 callargs[0] = dict; 73 callargs[1] = args[0]; 74 75 __fn___builtins___dict_dict___init__(callargs); 76 args[0] = dict; 77 } 78 #endif /* __HAVE___builtins___dict_dict */ 79 80 /* Helpers for raising errors within common operations. */ 81 82 #ifdef __HAVE___builtins___exception_io_IOError 83 void __raise_io_error(__attr value) 84 { 85 __attr args[2] = {{0, 0}, value}; 86 __attr exc = __new___builtins___exception_io_IOError(args); 87 __Raise(exc); 88 } 89 #endif /* __HAVE___builtins___exception_io_IOError */ 90 91 void __raise_memory_error() 92 { 93 __attr args[1]; 94 __attr exc = __new___builtins___core_MemoryError(args); 95 __Raise(exc); 96 } 97 98 void __raise_overflow_error() 99 { 100 __attr args[1]; 101 __attr exc = __new___builtins___core_OverflowError(args); 102 __Raise(exc); 103 } 104 105 void __raise_type_error() 106 { 107 __attr args[1]; 108 __attr exc = __new___builtins___core_TypeError(args); 109 __Raise(exc); 110 } 111 112 void __raise_zero_division_error() 113 { 114 __attr args[1]; 115 __attr exc = __new___builtins___core_ZeroDivisionError(args); 116 __Raise(exc); 117 } 118 119 /* Helper for raising exception instances. */ 120 121 __attr __ensure_instance(__attr arg) 122 { 123 /* Reserve space for the instance. */ 124 125 __attr args[1]; 126 127 /* Return instances as provided. */ 128 129 if (__is_instance(arg.value)) 130 return arg; 131 132 /* Invoke non-instances to produce instances. */ 133 134 else 135 return __invoke(arg, 0, 0, 0, 0, 1, args); 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 }