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 #ifdef __HAVE___builtins___exception_io_EOFError 98 void __raise_eof_error() 99 { 100 __attr args[1]; 101 __attr exc = __new___builtins___exception_io_EOFError(args); 102 __Raise(exc); 103 } 104 #endif /* __HAVE___builtins___exception_io_EOFError */ 105 106 #ifdef __HAVE___builtins___exception_io_IOError 107 void __raise_io_error(__attr value) 108 { 109 __attr args[2] = {{0, 0}, value}; 110 __attr exc = __new___builtins___exception_io_IOError(args); 111 __Raise(exc); 112 } 113 #endif /* __HAVE___builtins___exception_io_IOError */ 114 115 void __raise_memory_error() 116 { 117 __attr args[1]; 118 __attr exc = __new___builtins___core_MemoryError(args); 119 __Raise(exc); 120 } 121 122 void __raise_overflow_error() 123 { 124 __attr args[1]; 125 __attr exc = __new___builtins___core_OverflowError(args); 126 __Raise(exc); 127 } 128 129 void __raise_type_error() 130 { 131 __attr args[1]; 132 __attr exc = __new___builtins___core_TypeError(args); 133 __Raise(exc); 134 } 135 136 void __raise_zero_division_error() 137 { 138 __attr args[1]; 139 __attr exc = __new___builtins___core_ZeroDivisionError(args); 140 __Raise(exc); 141 } 142 143 /* Helper for raising exception instances. */ 144 145 __attr __ensure_instance(__attr arg) 146 { 147 /* Reserve space for the instance. */ 148 149 __attr args[1]; 150 151 /* Return instances as provided. */ 152 153 if (__is_instance(arg.value)) 154 return arg; 155 156 /* Invoke non-instances to produce instances. */ 157 158 else 159 return __invoke(arg, 0, 0, 0, 0, 1, args); 160 } 161 162 /* Generic invocation operations. */ 163 164 /* Invoke the given callable, supplying keyword argument details in the given 165 codes and arguments arrays, indicating the number of arguments described. 166 The number of positional arguments is specified, and such arguments then 167 follow as conventional function arguments. Typically, at least one argument 168 is specified, starting with any context argument. 169 */ 170 171 __attr __invoke(__attr callable, int always_callable, 172 unsigned int nkwargs, __param kwcodes[], __attr kwargs[], 173 unsigned int nargs, __attr args[]) 174 { 175 /* Obtain the __args__ special member, referencing the parameter table. */ 176 177 __attr minparams = __check_and_load_via_object(callable.value, __pos___args__, __code___args__); 178 179 /* Refer to the table and minimum/maximum. */ 180 181 const __ptable *ptable = minparams.ptable; 182 const unsigned int min = minparams.min, max = ptable->size; 183 184 /* Reserve enough space for the arguments. */ 185 186 __attr allargs[max]; 187 188 /* Traverse the arguments. */ 189 190 unsigned int pos, kwpos; 191 192 /* Check the number of arguments. */ 193 194 if ((min > (nargs + nkwargs)) || ((nargs + nkwargs) > max)) 195 return __NULL; 196 197 /* Copy the arguments. */ 198 199 for (pos = 0; pos < nargs; pos++) 200 allargs[pos] = args[pos]; 201 202 /* Erase the remaining arguments. */ 203 204 for (pos = nargs; pos < max; pos++) 205 { 206 allargs[pos].value = 0; 207 } 208 209 /* Fill keyword arguments. */ 210 211 for (kwpos = 0; kwpos < nkwargs; kwpos++) 212 { 213 pos = __HASPARAM(ptable, kwcodes[kwpos].pos, kwcodes[kwpos].code); 214 215 /* Check the table entry against the supplied argument details. 216 Set the argument but only if it does not overwrite positional 217 arguments. */ 218 219 if ((pos == -1) || (pos < nargs)) 220 return __NULL; 221 222 /* Set the argument using the appropriate position. */ 223 224 allargs[pos] = kwargs[kwpos]; 225 } 226 227 /* Fill the defaults. */ 228 229 for (pos = nargs; pos < max; pos++) 230 { 231 if (allargs[pos].value == 0) 232 allargs[pos] = __GETDEFAULT(callable.value, pos - min); 233 } 234 235 /* Call with the prepared arguments. */ 236 237 return (always_callable ? __load_via_object(callable.value, __pos___fn__) 238 : __check_and_load_via_object(callable.value, __pos___fn__, __code___fn__) 239 ).fn(allargs); 240 } 241 242 /* Error routines. */ 243 244 __attr __unbound_method(__attr args[]) 245 { 246 __attr excargs[1]; 247 __attr exc = __new___builtins___core_UnboundMethodInvocation(excargs); 248 __Raise(exc); 249 return __builtins___none_None; /* superfluous */ 250 } 251 252 /* Generic operations depending on specific program details. */ 253 254 void __SETDEFAULT(__ref obj, int pos, __attr value) 255 { 256 __store_via_object(obj, __FUNCTION_INSTANCE_SIZE + pos, value); 257 } 258 259 __attr __GETDEFAULT(__ref obj, int pos) 260 { 261 return __load_via_object(obj, __FUNCTION_INSTANCE_SIZE + pos); 262 } 263 264 int __BOOL(__attr attr) 265 { 266 __attr args[2] = {{0, 0}, attr}; 267 268 /* Invoke the bool function with the object and test against True. */ 269 270 return __fn___builtins___boolean_bool(args).value == __builtins___boolean_True.value; 271 }