1 /* Operations depending on program specifics. 2 3 Copyright (C) 2015, 2016 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 28 /* Generic instantiation operations, defining common members. */ 29 30 __attr __new(const __table * table, __ref cls, size_t size) 31 { 32 __ref obj = (__ref) __ALLOCATE(1, size); 33 __attr self = {obj, obj}; 34 __attr tmp = {0, cls}; 35 obj->table = table; 36 __store_via_object(obj, __pos___class__, tmp); 37 return self; 38 } 39 40 /* Generic internal data allocation. */ 41 42 __fragment *__new_fragment(unsigned int n) 43 { 44 /* Allocate space for the list. */ 45 46 __fragment *data = (__fragment *) __ALLOCATE(1, __FRAGMENT_SIZE(n)); 47 48 /* The initial capacity is the same as the given size. */ 49 50 data->size = 0; 51 data->capacity = n; 52 return data; 53 } 54 55 void __newdata_sequence(__attr args[], unsigned int number) 56 { 57 /* Calculate the size of the fragment. */ 58 59 __fragment *data = __new_fragment(number); 60 __attr attr = {0, .seqvalue=data}; 61 unsigned int i, j; 62 63 /* Copy the given number of values, starting from the second element. */ 64 65 for (i = 1, j = 0; i <= number; i++, j++) 66 data->attrs[j] = args[i]; 67 68 data->size = number; 69 70 /* Store a reference to the data in the object's __data__ attribute. */ 71 72 __store_via_object(args[0].value, __pos___data__, attr); 73 } 74 75 #ifdef __HAVE___builtins___dict_dict 76 void __newdata_mapping(__attr args[], unsigned int number) 77 { 78 __attr dict = args[0]; 79 __attr callargs[2]; 80 81 /* Create a temporary list using the arguments. */ 82 83 __newliteral___builtins___list_list(args, number); 84 85 /* Call __init__ with the dict object and list argument. */ 86 87 callargs[0] = dict; 88 callargs[1] = args[0]; 89 90 __fn___builtins___dict_dict___init__(callargs); 91 args[0] = dict; 92 } 93 #endif /* __HAVE___builtins___dict_dict */ 94 95 /* Helpers for raising errors within common operations. */ 96 97 void __raise_eof_error() 98 { 99 #ifdef __HAVE___builtins___exception_io_EOFError 100 __attr args[1]; 101 __attr exc = __new___builtins___exception_io_EOFError(args); 102 __Raise(exc); 103 #endif /* __HAVE___builtins___exception_io_EOFError */ 104 } 105 106 void __raise_incomplete_sequence_error(__attr value, __attr arg) 107 { 108 #ifdef __HAVE_posix_iconv_IncompleteSequenceError 109 __attr args[3] = {{0, 0}, value, arg}; 110 __attr exc = __new_posix_iconv_IncompleteSequenceError(args); 111 __Raise(exc); 112 #endif /* __HAVE_posix_iconv_IncompleteSequenceError */ 113 } 114 115 void __raise_invalid_sequence_error(__attr value, __attr arg) 116 { 117 #ifdef __HAVE_posix_iconv_InvalidSequenceError 118 __attr args[3] = {{0, 0}, value, arg}; 119 __attr exc = __new_posix_iconv_InvalidSequenceError(args); 120 __Raise(exc); 121 #endif /* __HAVE_posix_iconv_InvalidSequenceError */ 122 } 123 124 void __raise_io_error(__attr value) 125 { 126 #ifdef __HAVE___builtins___exception_io_IOError 127 __attr args[2] = {{0, 0}, value}; 128 __attr exc = __new___builtins___exception_io_IOError(args); 129 __Raise(exc); 130 #endif /* __HAVE___builtins___exception_io_IOError */ 131 } 132 133 void __raise_memory_error() 134 { 135 __attr args[1]; 136 __attr exc = __new___builtins___core_MemoryError(args); 137 __Raise(exc); 138 } 139 140 void __raise_os_error(__attr value, __attr arg) 141 { 142 #ifdef __HAVE___builtins___exception_system_OSError 143 __attr args[3] = {{0, 0}, value, arg}; 144 __attr exc = __new___builtins___exception_system_OSError(args); 145 __Raise(exc); 146 #endif /* __HAVE___builtins___exception_system_OSError */ 147 } 148 149 void __raise_overflow_error() 150 { 151 __attr args[1]; 152 __attr exc = __new___builtins___core_OverflowError(args); 153 __Raise(exc); 154 } 155 156 void __raise_type_error() 157 { 158 __attr args[1]; 159 __attr exc = __new___builtins___core_TypeError(args); 160 __Raise(exc); 161 } 162 163 void __raise_zero_division_error() 164 { 165 __attr args[1]; 166 __attr exc = __new___builtins___core_ZeroDivisionError(args); 167 __Raise(exc); 168 } 169 170 /* Helper for raising exception instances. */ 171 172 __attr __ensure_instance(__attr arg) 173 { 174 /* Reserve space for the instance. */ 175 176 __attr args[1]; 177 178 /* Return instances as provided. */ 179 180 if (__is_instance(arg.value)) 181 return arg; 182 183 /* Invoke non-instances to produce instances. */ 184 185 else 186 return __invoke(arg, 0, 0, 0, 0, 1, args); 187 } 188 189 /* Generic invocation operations. */ 190 191 /* Invoke the given callable, supplying keyword argument details in the given 192 codes and arguments arrays, indicating the number of arguments described. 193 The number of positional arguments is specified, and such arguments then 194 follow as conventional function arguments. Typically, at least one argument 195 is specified, starting with any context argument. 196 */ 197 198 __attr __invoke(__attr callable, int always_callable, 199 unsigned int nkwargs, __param kwcodes[], __attr kwargs[], 200 unsigned int nargs, __attr args[]) 201 { 202 /* Obtain the __args__ special member, referencing the parameter table. */ 203 204 __attr minparams = __check_and_load_via_object(callable.value, __pos___args__, __code___args__); 205 206 /* Refer to the table and minimum/maximum. */ 207 208 const __ptable *ptable = minparams.ptable; 209 const unsigned int min = minparams.min, max = ptable->size; 210 211 /* Reserve enough space for the arguments. */ 212 213 __attr allargs[max]; 214 215 /* Traverse the arguments. */ 216 217 unsigned int pos, kwpos; 218 219 /* Check the number of arguments. */ 220 221 if ((min > (nargs + nkwargs)) || ((nargs + nkwargs) > max)) 222 return __NULL; 223 224 /* Copy the arguments. */ 225 226 for (pos = 0; pos < nargs; pos++) 227 allargs[pos] = args[pos]; 228 229 /* Erase the remaining arguments. */ 230 231 for (pos = nargs; pos < max; pos++) 232 { 233 allargs[pos].value = 0; 234 } 235 236 /* Fill keyword arguments. */ 237 238 for (kwpos = 0; kwpos < nkwargs; kwpos++) 239 { 240 pos = __HASPARAM(ptable, kwcodes[kwpos].pos, kwcodes[kwpos].code); 241 242 /* Check the table entry against the supplied argument details. 243 Set the argument but only if it does not overwrite positional 244 arguments. */ 245 246 if ((pos == -1) || (pos < nargs)) 247 return __NULL; 248 249 /* Set the argument using the appropriate position. */ 250 251 allargs[pos] = kwargs[kwpos]; 252 } 253 254 /* Fill the defaults. */ 255 256 for (pos = nargs; pos < max; pos++) 257 { 258 if (allargs[pos].value == 0) 259 allargs[pos] = __GETDEFAULT(callable.value, pos - min); 260 } 261 262 /* Call with the prepared arguments. */ 263 264 return (always_callable ? __load_via_object(callable.value, __pos___fn__) 265 : __check_and_load_via_object(callable.value, __pos___fn__, __code___fn__) 266 ).fn(allargs); 267 } 268 269 /* Error routines. */ 270 271 __attr __unbound_method(__attr args[]) 272 { 273 __attr excargs[1]; 274 __attr exc = __new___builtins___core_UnboundMethodInvocation(excargs); 275 __Raise(exc); 276 return __builtins___none_None; /* superfluous */ 277 } 278 279 /* Generic operations depending on specific program details. */ 280 281 void __SETDEFAULT(__ref obj, int pos, __attr value) 282 { 283 __store_via_object(obj, __FUNCTION_INSTANCE_SIZE + pos, value); 284 } 285 286 __attr __GETDEFAULT(__ref obj, int pos) 287 { 288 return __load_via_object(obj, __FUNCTION_INSTANCE_SIZE + pos); 289 } 290 291 int __BOOL(__attr attr) 292 { 293 __attr args[2] = {{0, 0}, attr}; 294 295 /* Invoke the bool function with the object and test against True. */ 296 297 return __fn___builtins___boolean_bool(args).value == __builtins___boolean_True.value; 298 }