Lichen

templates/progops.c

275:6a85c86bb1f1
2016-11-29 Paul Boddie Changed lplc to always return 1 upon failure, eliminating unnecessary options. Changed the test runner to continue after expected test failures.
     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) __ALLOCATE(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 *) __ALLOCATE(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 /* A helper for raising type errors within common operations. */    46     47 void __raise_type_error()    48 {    49     __attr args[1];    50     __attr exc = __TYPE_ERROR_INSTANTIATOR(args);    51     __Raise(exc);    52 }    53     54 /* A helper for raising memory errors within common operations. */    55     56 void __raise_memory_error()    57 {    58     __attr args[1];    59     __attr exc = __MEMORY_ERROR_INSTANTIATOR(args);    60     __Raise(exc);    61 }    62     63 /* Generic invocation operations. */    64     65 /* Invoke the given callable, supplying keyword argument details in the given    66    codes and arguments arrays, indicating the number of arguments described.    67    The number of positional arguments is specified, and such arguments then    68    follow as conventional function arguments. Typically, at least one argument    69    is specified, starting with any context argument.    70 */    71     72 __attr __invoke(__attr callable, int always_callable,    73                 unsigned int nkwargs, __param kwcodes[], __attr kwargs[],    74                 unsigned int nargs, __attr args[])    75 {    76     /* Obtain the __args__ special member, referencing the parameter table. */    77     78     __attr minparams = __check_and_load_via_object(callable.value, __pos___args__, __code___args__);    79     80     /* Refer to the table and minimum/maximum. */    81     82     const __ptable *ptable = minparams.ptable;    83     const unsigned int min = minparams.min, max = ptable->size;    84     85     /* Reserve enough space for the arguments. */    86     87     __attr allargs[max];    88     89     /* Traverse the arguments. */    90     91     unsigned int pos, kwpos;    92     93     /* Check the number of arguments. */    94     95     if ((min > (nargs + nkwargs)) || ((nargs + nkwargs) > max))    96         return __NULL;    97     98     /* Copy the arguments. */    99    100     for (pos = 0; pos < nargs; pos++)   101         allargs[pos] = args[pos];   102    103     /* Erase the remaining arguments. */   104    105     for (pos = nargs; pos < max; pos++)   106     {   107         allargs[pos].value = 0;   108     }   109    110     /* Fill keyword arguments. */   111    112     for (kwpos = 0; kwpos < nkwargs; kwpos++)   113     {   114         pos = __HASPARAM(ptable, kwcodes[kwpos].pos, kwcodes[kwpos].code);   115    116         /* Check the table entry against the supplied argument details.   117            Set the argument but only if it does not overwrite positional   118            arguments. */   119    120         if ((pos == -1) || (pos < nargs))   121             return __NULL;   122    123         /* Set the argument using the appropriate position. */   124    125         allargs[pos] = kwargs[kwpos];   126     }   127    128     /* Fill the defaults. */   129    130     for (pos = nargs; pos < max; pos++)   131     {   132         if (allargs[pos].value == 0)   133             allargs[pos] = __GETDEFAULT(callable.value, pos - min);   134     }   135    136     /* Call with the prepared arguments. */   137    138     return (always_callable ? __load_via_object(callable.value, __pos___fn__)   139                             : __check_and_load_via_object(callable.value, __pos___fn__, __code___fn__)   140                             ).fn(allargs);   141 }   142    143 /* Error routines. */   144    145 __attr __unbound_method(__attr args[])   146 {   147     __attr excargs[1];   148     __attr exc = __new___builtins___core_UnboundMethodInvocation(excargs);   149     __Raise(exc);   150     return __builtins___none_None; /* superfluous */   151 }   152    153 /* Generic operations depending on specific program details. */   154    155 void __SETDEFAULT(__ref obj, int pos, __attr value)   156 {   157     __store_via_object(obj, __FUNCTION_INSTANCE_SIZE + pos, value);   158 }   159    160 __attr __GETDEFAULT(__ref obj, int pos)   161 {   162     return __load_via_object(obj, __FUNCTION_INSTANCE_SIZE + pos);   163 }   164    165 int __BOOL(__attr attr)   166 {   167     __attr args[2] = {{0, 0}, attr};   168    169     /* Invoke the bool function with the object and test against True. */   170    171     return __fn___builtins___boolean_bool(args).value == __builtins___boolean_True.value;   172 }