1 /* Operations depending on program specifics. 2 3 Copyright (C) 2015, 2016, 2017 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(__attr self, __attr args[], unsigned int number, __fragment *data) 66 { 67 __attr attr = {.seqvalue=data}; 68 unsigned int i; 69 70 /* Copy the given number of values. */ 71 72 for (i = 0; i < number; i++) 73 data->attrs[i] = args[i]; 74 75 data->size = number; 76 77 /* Store a reference to the data in the object's __data__ attribute. */ 78 79 __store_via_object(__VALUE(self), __data__, attr); 80 } 81 82 __attr __newdata_list(__attr args[], unsigned int number) 83 { 84 __attr self = __NEWINSTANCE(__builtins___list_list); 85 __fragment *data = __new_fragment(number); 86 __newdata_sequence(self, args, number, data); 87 return self; 88 } 89 90 __attr __newdata_tuple(__attr args[], unsigned int number) 91 { 92 /* Allocate the tuple and fragment together. */ 93 94 __attr self = __new(&__INSTANCETABLE(__builtins___tuple_tuple), 95 &__builtins___tuple_tuple, 96 __INSTANCESIZE(__builtins___tuple_tuple) + __FRAGMENT_SIZE(number), 0); 97 98 /* Initialise the fragment. */ 99 100 __newdata_sequence(self, args, number, (__fragment *) ((void *) __VALUE(self) + __INSTANCESIZE(__builtins___tuple_tuple))); 101 return self; 102 } 103 104 #ifdef __HAVE___builtins___dict_dict 105 __attr __newdata_dict(__attr args[], unsigned int number) 106 { 107 __attr self = __NEWINSTANCE(__builtins___dict_dict); 108 109 /* Create a temporary list using the arguments. */ 110 111 __attr tmp = __newliteral___builtins___list_list(args, number); 112 113 /* Call __init__ with the dict object and list argument. */ 114 115 __fn___builtins___dict_dict___init__(self, tmp); 116 return self; 117 } 118 #endif /* __HAVE___builtins___dict_dict */ 119 120 /* Helpers for raising errors within common operations. */ 121 122 void __raise_eof_error() 123 { 124 #ifdef __HAVE___builtins___exception_io_EOFError 125 __Raise(__new___builtins___exception_io_EOFError(__NULL)); 126 #endif /* __HAVE___builtins___exception_io_EOFError */ 127 } 128 129 void __raise_io_error(__attr value) 130 { 131 #ifdef __HAVE___builtins___exception_io_IOError 132 __Raise(__new___builtins___exception_io_IOError(__NULL, value)); 133 #endif /* __HAVE___builtins___exception_io_IOError */ 134 } 135 136 void __raise_memory_error() 137 { 138 __Raise(__new___builtins___core_MemoryError(__NULL)); 139 } 140 141 void __raise_os_error(__attr value, __attr arg) 142 { 143 #ifdef __HAVE___builtins___exception_system_OSError 144 __Raise(__new___builtins___exception_system_OSError(__NULL, value, arg)); 145 #endif /* __HAVE___builtins___exception_system_OSError */ 146 } 147 148 void __raise_overflow_error() 149 { 150 __Raise(__new___builtins___core_OverflowError(__NULL)); 151 } 152 153 void __raise_type_error() 154 { 155 __Raise(__new___builtins___core_TypeError(__NULL)); 156 } 157 158 void __raise_zero_division_error() 159 { 160 __Raise(__new___builtins___core_ZeroDivisionError(__NULL)); 161 } 162 163 /* Helper for raising exception instances. */ 164 165 __attr __ensure_instance(__attr arg) 166 { 167 /* Reserve space for the instance. */ 168 169 __attr args[1] = {__NULL}; 170 171 /* Return instances as provided. */ 172 173 if (__is_instance(__VALUE(arg))) 174 return arg; 175 176 /* Invoke non-instances to produce instances. */ 177 178 else 179 return __invoke(arg, 0, 0, 0, 0, 1, args); 180 } 181 182 /* Generic invocation operations. */ 183 184 /* Invoke the given callable, supplying keyword argument details in the given 185 codes and arguments arrays, indicating the number of arguments described. 186 The number of positional arguments is specified, and such arguments then 187 follow as conventional function arguments. Typically, at least one argument 188 is specified, starting with any context argument. 189 */ 190 191 __attr __invoke(__attr callable, int always_callable, 192 unsigned int nkwargs, __param kwcodes[], __attr kwargs[], 193 unsigned int nargs, __attr args[]) 194 { 195 /* Unwrap any wrapped function. */ 196 197 __attr target = __unwrap_callable(callable); 198 199 /* Obtain the __args__ special member, referencing the parameter table. */ 200 /* Refer to the table and minimum/maximum. */ 201 202 const __ptable *ptable = __check_and_load_via_object(__VALUE(target), __args__).ptable; 203 const unsigned int min = ptable->min, max = ptable->max; 204 205 /* Reserve enough space for the arguments. */ 206 207 __attr *allargs = args, moreargs[max]; 208 209 /* Traverse the arguments. */ 210 211 unsigned int pos, kwpos; 212 213 /* Check the number of arguments. */ 214 215 if ((nargs == max) && (nkwargs == 0)) 216 { 217 /* pass */ 218 } 219 220 /* NOTE: Should use a more specific exception. */ 221 222 else if ((min > (nargs + nkwargs)) || ((nargs + nkwargs) > max)) 223 { 224 __raise_type_error(); 225 } 226 227 /* Copy the arguments. */ 228 229 else if (nargs < max) 230 { 231 allargs = moreargs; 232 233 for (pos = 0; pos < nargs; pos++) 234 allargs[pos] = args[pos]; 235 236 /* Erase the remaining arguments. */ 237 238 for (pos = nargs; pos < max; pos++) 239 __SETNULL(allargs[pos]); 240 241 /* Fill keyword arguments. */ 242 243 for (kwpos = 0; kwpos < nkwargs; kwpos++) 244 { 245 pos = __HASPARAM(ptable, kwcodes[kwpos].pos, kwcodes[kwpos].code); 246 247 /* Check the table entry against the supplied argument details. 248 Set the argument but only if it does not overwrite positional 249 arguments. */ 250 /* NOTE: Should use a more specific exception. */ 251 252 if ((pos == -1) || (pos < nargs)) 253 __raise_type_error(); 254 255 /* Set the argument using the appropriate position. */ 256 257 allargs[pos] = kwargs[kwpos]; 258 } 259 260 /* Fill the defaults. */ 261 262 for (pos = nargs; pos < max; pos++) 263 { 264 if (__ISNULL(allargs[pos])) 265 allargs[pos] = __GETDEFAULT(__VALUE(target), pos - min); 266 } 267 } 268 269 /* Call with the prepared arguments via a special adaptor function that 270 converts the array to an argument list. */ 271 272 return __call_with_args( 273 always_callable ? 274 __get_function_unwrapped(allargs[0], target) : 275 __check_and_get_function_unwrapped(allargs[0], target), 276 allargs, max); 277 } 278 279 /* Error routines. */ 280 281 __attr __unbound_method(__attr __self) 282 { 283 __Raise(__new___builtins___core_UnboundMethodInvocation(__NULL)); 284 return __builtins___none_None; /* superfluous */ 285 } 286 287 /* Generic operations depending on specific program details. */ 288 289 void __SETDEFAULT(__ref obj, int pos, __attr value) 290 { 291 __store_via_object__(obj, __FUNCTION_INSTANCE_SIZE + pos, value); 292 } 293 294 __attr __GETDEFAULT(__ref obj, int pos) 295 { 296 return __load_via_object__(obj, __FUNCTION_INSTANCE_SIZE + pos); 297 } 298 299 int __BOOL(__attr attr) 300 { 301 /* Invoke the bool function with the object and test against True. */ 302 303 return __VALUE(attr) == &__predefined___builtins___boolean_True ? 1 : 304 __VALUE(attr) == &__predefined___builtins___boolean_False ? 0 : 305 __VALUE(__fn___builtins___boolean_bool(__NULL, attr)) == &__predefined___builtins___boolean_True; 306 }