Lichen

templates/progops.c

284:c4617743ba3b
2016-11-30 Paul Boddie Replaced explicit declarations with an include directive.
     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 __fragment *__new_fragment(unsigned int n)     28 {    29     /* Allocate space for the list. */    30     __fragment *data = (__fragment *) __ALLOCATE(1, __FRAGMENT_SIZE(n));    31     32     /* The initial capacity is the same as the given size. */    33     data->size = 0;    34     data->capacity = n;    35     return data;    36 }    37     38 __mapping *__new_mapping(unsigned int n)     39 {    40     /* Allocate a number of buckets. */    41     __mapping *data = (__mapping *) __ALLOCATE(1, __MAPPING_SIZE(__MAPPING_BUCKETS));    42     unsigned int i;    43     44     /* Allocate fragments with an initial size of 2 * n / __MAPPING_BUCKETS,    45        assuming a mostly uniform distribution of values across the buckets. */    46     47     for (i = 0; i < __MAPPING_BUCKETS; i++)    48     {    49         data->keys[i] = __new_fragment(2 * n / __MAPPING_BUCKETS);    50         data->values[i] = __new_fragment(2 * n / __MAPPING_BUCKETS);    51     }    52     53     return data;    54 }    55     56 void __newdata_sequence(__attr args[], unsigned int number)    57 {    58     /* Calculate the size of the fragment. */    59     60     __fragment *data = __new_fragment(number);    61     __attr attr = {0, .seqvalue=data};    62     unsigned int i, j;    63     64     /* Copy the given number of values, starting from the second element. */    65     66     for (i = 1, j = 0; i <= number; i++, j++)    67         data->attrs[j] = args[i];    68     69     data->size = number;    70     71     /* Store a reference to the data in the object's __data__ attribute. */    72     73     __store_via_object(args[0].value, __pos___data__, attr);    74 }    75     76 void __newdata_mapping(__attr args[], unsigned int number)    77 {    78     __mapping *data = __new_mapping(number);    79     __attr attr = {0, .mapvalue=data};    80     __fragment *f;    81     __attr callargs[3];    82     unsigned int i;    83     84     /* Store a reference to the data in the object's __data__ attribute. */    85     86     __store_via_object(args[0].value, __pos___data__, attr);    87     88     /* Store the given number of values, starting from the second element. */    89     90     for (i = 1; i <= number; i++)    91     {    92         /* Obtain the tuple elements. */    93     94         f = __load_via_object(args[i].value, __pos___data__).seqvalue;    95         callargs[0] = args[0];    96         callargs[1] = f->attrs[0];    97         callargs[2] = f->attrs[1];    98     99         /* Call __setitem__ with the key and value. */   100    101         __fn___builtins___dict_dict___setitem__(callargs);   102     }   103 }   104    105 /* A helper for raising type errors within common operations. */   106    107 void __raise_type_error()   108 {   109     __attr args[1];   110     __attr exc = __TYPE_ERROR_INSTANTIATOR(args);   111     __Raise(exc);   112 }   113    114 /* A helper for raising memory errors within common operations. */   115    116 void __raise_memory_error()   117 {   118     __attr args[1];   119     __attr exc = __MEMORY_ERROR_INSTANTIATOR(args);   120     __Raise(exc);   121 }   122    123 /* Generic invocation operations. */   124    125 /* Invoke the given callable, supplying keyword argument details in the given   126    codes and arguments arrays, indicating the number of arguments described.   127    The number of positional arguments is specified, and such arguments then   128    follow as conventional function arguments. Typically, at least one argument   129    is specified, starting with any context argument.   130 */   131    132 __attr __invoke(__attr callable, int always_callable,   133                 unsigned int nkwargs, __param kwcodes[], __attr kwargs[],   134                 unsigned int nargs, __attr args[])   135 {   136     /* Obtain the __args__ special member, referencing the parameter table. */   137    138     __attr minparams = __check_and_load_via_object(callable.value, __pos___args__, __code___args__);   139    140     /* Refer to the table and minimum/maximum. */   141    142     const __ptable *ptable = minparams.ptable;   143     const unsigned int min = minparams.min, max = ptable->size;   144    145     /* Reserve enough space for the arguments. */   146    147     __attr allargs[max];   148    149     /* Traverse the arguments. */   150    151     unsigned int pos, kwpos;   152    153     /* Check the number of arguments. */   154    155     if ((min > (nargs + nkwargs)) || ((nargs + nkwargs) > max))   156         return __NULL;   157    158     /* Copy the arguments. */   159    160     for (pos = 0; pos < nargs; pos++)   161         allargs[pos] = args[pos];   162    163     /* Erase the remaining arguments. */   164    165     for (pos = nargs; pos < max; pos++)   166     {   167         allargs[pos].value = 0;   168     }   169    170     /* Fill keyword arguments. */   171    172     for (kwpos = 0; kwpos < nkwargs; kwpos++)   173     {   174         pos = __HASPARAM(ptable, kwcodes[kwpos].pos, kwcodes[kwpos].code);   175    176         /* Check the table entry against the supplied argument details.   177            Set the argument but only if it does not overwrite positional   178            arguments. */   179    180         if ((pos == -1) || (pos < nargs))   181             return __NULL;   182    183         /* Set the argument using the appropriate position. */   184    185         allargs[pos] = kwargs[kwpos];   186     }   187    188     /* Fill the defaults. */   189    190     for (pos = nargs; pos < max; pos++)   191     {   192         if (allargs[pos].value == 0)   193             allargs[pos] = __GETDEFAULT(callable.value, pos - min);   194     }   195    196     /* Call with the prepared arguments. */   197    198     return (always_callable ? __load_via_object(callable.value, __pos___fn__)   199                             : __check_and_load_via_object(callable.value, __pos___fn__, __code___fn__)   200                             ).fn(allargs);   201 }   202    203 /* Error routines. */   204    205 __attr __unbound_method(__attr args[])   206 {   207     __attr excargs[1];   208     __attr exc = __new___builtins___core_UnboundMethodInvocation(excargs);   209     __Raise(exc);   210     return __builtins___none_None; /* superfluous */   211 }   212    213 /* Generic operations depending on specific program details. */   214    215 void __SETDEFAULT(__ref obj, int pos, __attr value)   216 {   217     __store_via_object(obj, __FUNCTION_INSTANCE_SIZE + pos, value);   218 }   219    220 __attr __GETDEFAULT(__ref obj, int pos)   221 {   222     return __load_via_object(obj, __FUNCTION_INSTANCE_SIZE + pos);   223 }   224    225 int __BOOL(__attr attr)   226 {   227     __attr args[2] = {{0, 0}, attr};   228    229     /* Invoke the bool function with the object and test against True. */   230    231     return __fn___builtins___boolean_bool(args).value == __builtins___boolean_True.value;   232 }