Lichen

templates/progops.c

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