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