Lichen

templates/progops.c

210:263f32338b37
2016-11-22 Paul Boddie Prevent lambdas with defaults being referenced as static function objects.
     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) calloc(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 __attr __newdata(__attr args[], unsigned int number)    28 {    29     /* Calculate the size of the fragment. */    30     31     __fragment *data = (__fragment *) calloc(1, __FRAGMENT_SIZE(number));    32     __attr attr = {0, .data=data};    33     unsigned int i, j;    34     35     /* Copy the given number of values, starting from the second element. */    36     37     for (i = 1, j = 0; i <= number; i++, j++)    38         data->attrs[j] = args[i];    39     40     data->size = number;    41     data->capacity = number;    42     return attr;    43 }    44     45 /* Generic invocation operations. */    46     47 /* Invoke the given callable, supplying keyword argument details in the given    48    codes and arguments arrays, indicating the number of arguments described.    49    The number of positional arguments is specified, and such arguments then    50    follow as conventional function arguments. Typically, at least one argument    51    is specified, starting with any context argument.    52 */    53     54 __attr __invoke(__attr callable, int always_callable,    55                 unsigned int nkwargs, __param kwcodes[], __attr kwargs[],    56                 unsigned int nargs, __attr args[])    57 {    58     /* Obtain the __args__ special member, referencing the parameter table. */    59     60     __attr minparams = __load_via_object(callable.value, __pos___args__);    61     62     /* Refer to the table and minimum/maximum. */    63     64     const __ptable *ptable = minparams.ptable;    65     const unsigned int min = minparams.min, max = ptable->size;    66     67     /* Reserve enough space for the arguments. */    68     69     __attr allargs[max];    70     71     /* Traverse the arguments. */    72     73     unsigned int pos, kwpos;    74     75     /* Check the number of arguments. */    76     77     if ((min > (nargs + nkwargs)) || ((nargs + nkwargs) > max))    78         return __NULL;    79     80     /* Copy the arguments. */    81     82     for (pos = 0; pos < nargs; pos++)    83         allargs[pos] = args[pos];    84     85     /* Erase the remaining arguments. */    86     87     for (pos = nargs; pos < max; pos++)    88     {    89         allargs[pos].value = 0;    90     }    91     92     /* Fill keyword arguments. */    93     94     for (kwpos = 0; kwpos < nkwargs; kwpos++)    95     {    96         pos = __HASPARAM(ptable, kwcodes[kwpos].pos, kwcodes[kwpos].code);    97     98         /* Check the table entry against the supplied argument details.    99            Set the argument but only if it does not overwrite positional   100            arguments. */   101    102         if ((pos == -1) || (pos < nargs))   103             return __NULL;   104    105         /* Set the argument using the appropriate position. */   106    107         allargs[pos] = kwargs[kwpos];   108     }   109    110     /* Fill the defaults. */   111    112     for (pos = nargs; pos < max; pos++)   113     {   114         if (allargs[pos].value == 0)   115             allargs[pos] = __GETDEFAULT(callable.value, pos - nargs);   116     }   117    118     /* Call with the prepared arguments. */   119    120     return (always_callable ? __load_via_object(callable.value, __pos___fn__)   121                             : __check_and_load_via_object(callable.value, __pos___fn__, __code___fn__)   122                             ).fn(allargs);   123 }   124    125 /* Error routines. */   126    127 __attr __unbound_method(__attr args[])   128 {   129     __attr excargs[1];   130     __attr exc = __new___builtins___core_UnboundMethodInvocation(excargs);   131     __Raise(exc);   132     return __builtins___none_None; /* superfluous */   133 }   134    135 /* Generic operations depending on specific program details. */   136    137 void __SETDEFAULT(__ref obj, int pos, __attr value)   138 {   139     __store_via_object(obj, __FUNCTION_INSTANCE_SIZE + pos, value);   140 }   141    142 __attr __GETDEFAULT(__ref obj, int pos)   143 {   144     return __load_via_object(obj, __FUNCTION_INSTANCE_SIZE + pos);   145 }   146    147 int __BOOL(__attr attr)   148 {   149     __attr args[2] = {{0, 0}, attr};   150    151     /* Invoke the bool function with the object and test against True. */   152    153     return __fn___builtins___boolean_bool(args).value == __builtins___boolean_True.value;   154 }