1 /* Operations depending on program specifics. 2 3 Copyright (C) 2015, 2016, 2017, 2018, 2019 Paul Boddie <paul@boddie.org.uk> 4 5 This program is free software; you can redistribute it and/or modify it under 6 the terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3 of the License, or (at your option) any later 8 version. 9 10 This program is distributed in the hope that it will be useful, but WITHOUT 11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 details. 14 15 You should have received a copy of the GNU General Public License along with 16 this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <stdlib.h> 20 #include "types.h" 21 #include "ops.h" 22 #include "progconsts.h" 23 #include "progops.h" 24 #include "progtypes.h" 25 #include "main.h" 26 #include "exceptions.h" 27 #include "calls.h" 28 29 /* Generic instantiation operations, defining common members. */ 30 31 void __init(__ref obj, const __table * table, __ref cls) 32 { 33 obj->table = table; 34 obj->pos = __INSTANCEPOS; 35 __store_via_object(obj, __class__, __ATTRVALUE(cls)); 36 } 37 38 __attr __new(const __table * table, __ref cls, size_t size, int immutable) 39 { 40 __ref obj = (__ref) (immutable ? __ALLOCATEIM : __ALLOCATE)(1, size); 41 __init(obj, table, cls); 42 return __ATTRVALUE(obj); 43 } 44 45 __attr __new_wrapper(__attr context, __attr attr) 46 { 47 return __new___builtins___core_wrapper(__NULL, context, attr); 48 } 49 50 /* Generic internal data allocation. */ 51 52 __fragment *__new_fragment(unsigned int n) 53 { 54 /* Allocate space for the list. */ 55 56 __fragment *data = (__fragment *) __ALLOCATE(1, __FRAGMENT_SIZE(n)); 57 58 /* The initial capacity is the same as the given size. */ 59 60 data->size = 0; 61 data->capacity = n; 62 return data; 63 } 64 65 void __newdata_sequence(unsigned int number, __fragment *data, __attr args[]) 66 { 67 unsigned int i; 68 69 /* Copy the given number of values. */ 70 71 for (i = 0; i < number; i++) 72 data->attrs[i] = args[i]; 73 74 data->size = number; 75 } 76 77 __attr __newdata_list(unsigned int number, __attr args[]) 78 { 79 __attr self = __NEWINSTANCE(__builtins___list_list); 80 __fragment *data = __new_fragment(number); 81 82 /* Store a reference to the data in the object's __data__ attribute. */ 83 84 __store_via_object(__VALUE(self), __data__, (__attr) {.seqvalue=data}); 85 __newdata_sequence(number, data, args); 86 return self; 87 } 88 89 __attr __newdata_tuple(unsigned int number, __attr args[]) 90 { 91 /* Allocate the tuple and fragment together. */ 92 93 __attr self = __new(&__INSTANCETABLE(__builtins___tuple_tuple), 94 &__builtins___tuple_tuple, 95 __INSTANCESIZE(__builtins___tuple_tuple) + __FRAGMENT_SIZE(number), 0); 96 __fragment *data = (__fragment *) ((void *) __VALUE(self) + __INSTANCESIZE(__builtins___tuple_tuple)); 97 98 /* Store a reference to the data in the object's __data__ attribute. */ 99 100 __store_via_object(__VALUE(self), __data__, (__attr) {.seqvalue=data}); 101 __newdata_sequence(number, data, args); 102 return self; 103 } 104 105 #ifdef __HAVE___builtins___dict_dict 106 __attr __newdata_dict(unsigned int number, __attr args[]) 107 { 108 __attr self = __NEWINSTANCE(__builtins___dict_dict); 109 110 /* Create a temporary list using the arguments. */ 111 112 __attr tmp = __newdata_list(number, args); 113 114 /* Call __init__ with the dict object and list argument. */ 115 116 __fn___builtins___dict_dict___init__(self, tmp); 117 return self; 118 } 119 #endif /* __HAVE___builtins___dict_dict */ 120 121 /* Helpers for raising errors within common operations. */ 122 123 void __raise_eof_error() 124 { 125 #ifdef __HAVE___builtins___exception_io_EOFError 126 __Raise(__new___builtins___exception_io_EOFError(__NULL)); 127 #endif /* __HAVE___builtins___exception_io_EOFError */ 128 } 129 130 void __raise_floating_point_error() 131 { 132 __Raise(__new___builtins___core_FloatingPointError(__NULL)); 133 } 134 135 void __raise_io_error(__attr value) 136 { 137 #ifdef __HAVE___builtins___exception_io_IOError 138 __Raise(__new___builtins___exception_io_IOError(__NULL, value)); 139 #endif /* __HAVE___builtins___exception_io_IOError */ 140 } 141 142 void __raise_memory_error() 143 { 144 __Raise(__new___builtins___core_MemoryError(__NULL)); 145 } 146 147 void __raise_os_error(__attr value, __attr arg) 148 { 149 #ifdef __HAVE___builtins___exception_system_OSError 150 __Raise(__new___builtins___exception_system_OSError(__NULL, value, arg)); 151 #endif /* __HAVE___builtins___exception_system_OSError */ 152 } 153 154 void __raise_overflow_error() 155 { 156 __Raise(__new___builtins___core_OverflowError(__NULL)); 157 } 158 159 void __raise_unbound_method_error() 160 { 161 __Raise(__new___builtins___core_UnboundMethodInvocation(__NULL)); 162 } 163 164 void __raise_type_error() 165 { 166 __Raise(__new___builtins___core_TypeError(__NULL)); 167 } 168 169 void __raise_underflow_error() 170 { 171 __Raise(__new___builtins___core_UnderflowError(__NULL)); 172 } 173 174 void __raise_zero_division_error() 175 { 176 __Raise(__new___builtins___core_ZeroDivisionError(__NULL)); 177 } 178 179 /* Helper for raising exception instances. */ 180 181 __attr __ensure_instance(__attr arg) 182 { 183 /* Reserve space for the instance. */ 184 185 __attr args[1] = {__NULL}; 186 187 /* Return instances as provided. */ 188 189 if (__is_instance(__VALUE(arg))) 190 return arg; 191 192 /* Invoke non-instances to produce instances. */ 193 194 else 195 return __invoke(arg, 0, 0, 0, 0, 1, args); 196 } 197 198 /* Generic invocation operations. */ 199 200 /* Invoke the given callable, supplying keyword argument details in the given 201 codes and arguments arrays, indicating the number of arguments described. 202 The number of positional arguments is specified, and such arguments then 203 follow as conventional function arguments. Typically, at least one argument 204 is specified, starting with any context argument. 205 */ 206 207 __attr __invoke(__attr callable, int always_callable, 208 unsigned int nkwargs, __param kwcodes[], __attr kwargs[], 209 unsigned int nargs, __attr args[]) 210 { 211 /* Unwrap any wrapped function. */ 212 213 __attr target = __unwrap_callable(callable); 214 215 /* Obtain the __args__ special member, referencing the parameter table. */ 216 /* Refer to the table and minimum/maximum. */ 217 218 const __ptable *ptable = __check_and_load_via_object(__VALUE(target), __args__).ptable; 219 const unsigned int min = ptable->min, max = ptable->max; 220 221 /* Reserve enough space for the arguments. */ 222 223 __attr *allargs = args, moreargs[max]; 224 225 /* Traverse the arguments. */ 226 227 unsigned int pos, kwpos; 228 229 /* Check the number of arguments. */ 230 231 if ((nargs == max) && (nkwargs == 0)) 232 { 233 /* pass */ 234 } 235 236 /* NOTE: Should use a more specific exception. */ 237 238 else if ((min > (nargs + nkwargs)) || ((nargs + nkwargs) > max)) 239 { 240 __raise_type_error(); 241 } 242 243 /* Copy the arguments. */ 244 245 else if (nargs < max) 246 { 247 allargs = moreargs; 248 249 for (pos = 0; pos < nargs; pos++) 250 allargs[pos] = args[pos]; 251 252 /* Erase the remaining arguments. */ 253 254 for (pos = nargs; pos < max; pos++) 255 __SETNULL(allargs[pos]); 256 257 /* Fill keyword arguments. */ 258 259 for (kwpos = 0; kwpos < nkwargs; kwpos++) 260 { 261 pos = __HASPARAM(ptable, kwcodes[kwpos].pos, kwcodes[kwpos].code); 262 263 /* Check the table entry against the supplied argument details. 264 Set the argument but only if it does not overwrite positional 265 arguments. */ 266 /* NOTE: Should use a more specific exception. */ 267 268 if ((pos == -1) || (pos < nargs)) 269 __raise_type_error(); 270 271 /* Set the argument using the appropriate position. */ 272 273 allargs[pos] = kwargs[kwpos]; 274 } 275 276 /* Fill the defaults. */ 277 278 for (pos = nargs; pos < max; pos++) 279 { 280 if (__ISNULL(allargs[pos])) 281 allargs[pos] = __GETDEFAULT(__VALUE(target), pos - min); 282 } 283 } 284 285 /* Call with the prepared arguments via a special adaptor function that 286 converts the array to an argument list. */ 287 288 return __call_with_args( 289 always_callable ? 290 __get_function_unwrapped(allargs[0], target) : 291 __check_and_get_function_unwrapped(allargs[0], target), 292 allargs, max); 293 } 294 295 /* Error routines. */ 296 297 __attr __unbound_method(__attr __self) 298 { 299 __Raise(__new___builtins___core_UnboundMethodInvocation(__NULL)); 300 return __builtins___none_None; /* superfluous */ 301 } 302 303 /* Generic operations depending on specific program details. */ 304 305 void __SETDEFAULT(__ref obj, int pos, __attr value) 306 { 307 __store_via_object__(obj, __FUNCTION_INSTANCE_SIZE + pos, value); 308 } 309 310 __attr __GETDEFAULT(__ref obj, int pos) 311 { 312 return __load_via_object__(obj, __FUNCTION_INSTANCE_SIZE + pos); 313 } 314 315 int __BOOL(__attr attr) 316 { 317 /* Invoke the bool function with the object and test against True. */ 318 319 __ref value = __VALUE(attr); 320 321 return value == (__ref) &__predefined___builtins___boolean_True ? 1 : 322 value == (__ref) &__predefined___builtins___boolean_False ? 0 : 323 __VALUE(__fn___builtins___boolean_bool(__NULL, attr)) == (__ref) &__predefined___builtins___boolean_True; 324 }