1.1 --- a/templates/native.c Tue Nov 29 23:13:18 2016 +0100
1.2 +++ b/templates/native.c Wed Nov 30 16:18:17 2016 +0100
1.3 @@ -29,6 +29,36 @@
1.4 return attr;
1.5 }
1.6
1.7 +static __attr __new_list(__fragment *f)
1.8 +{
1.9 + /* Create a new list and mutate the __data__ attribute. */
1.10 + __attr attr = __new(&__InstanceTable___builtins___list_list, &__builtins___list_list, sizeof(__obj___builtins___list_list));
1.11 + attr.value->attrs[__pos___data__].seqvalue = f;
1.12 + return attr;
1.13 +}
1.14 +
1.15 +static __fragment *__fragment_append(__fragment *data, __attr * const value)
1.16 +{
1.17 + __fragment *newdata = data;
1.18 + unsigned int size = data->size, capacity = data->capacity;
1.19 + unsigned int n;
1.20 +
1.21 + /* Re-allocate the fragment if the capacity has been reached. */
1.22 + if (size >= capacity)
1.23 + {
1.24 + /* NOTE: Consider various restrictions on capacity increases. */
1.25 + n = capacity ? capacity * 2 : 1;
1.26 + newdata = (__fragment *) __REALLOCATE(data, __FRAGMENT_SIZE(n));
1.27 + newdata->capacity = n;
1.28 + }
1.29 +
1.30 + /* Insert the new element and increment the list size. */
1.31 + newdata->attrs[size] = *value;
1.32 + newdata->size = size + 1;
1.33 +
1.34 + return newdata;
1.35 +}
1.36 +
1.37 /* Native functions. */
1.38
1.39 __attr __fn_native__exit(__attr __args[])
1.40 @@ -338,14 +368,9 @@
1.41 __attr * const size = &__args[1];
1.42 /* size.__data__ interpreted as int */
1.43 unsigned int n = __load_via_object(size->value, __pos___data__).intvalue;
1.44 + __attr attr = {0, .seqvalue=__new_fragment(n)};
1.45
1.46 - /* Allocate space for the list. */
1.47 - __fragment *data = (__fragment *) __ALLOCATE(1, __FRAGMENT_SIZE(n));
1.48 - __attr attr = {0, .seqvalue=data};
1.49 -
1.50 - /* The initial capacity is the same as the given size. */
1.51 - data->size = 0;
1.52 - data->capacity = n;
1.53 + /* Return the __data__ attribute. */
1.54 return attr;
1.55 }
1.56
1.57 @@ -368,22 +393,7 @@
1.58 __attr * const value = &__args[2];
1.59 /* self.__data__ interpreted as list */
1.60 __fragment *data = __load_via_object(self->value, __pos___data__).seqvalue;
1.61 - __fragment *newdata = data;
1.62 - unsigned int size = data->size, capacity = data->capacity;
1.63 - unsigned int n;
1.64 -
1.65 - /* Re-allocate the fragment if the capacity has been reached. */
1.66 - if (size >= capacity)
1.67 - {
1.68 - /* NOTE: Consider various restrictions on capacity increases. */
1.69 - n = capacity ? capacity * 2 : 1;
1.70 - newdata = (__fragment *) __REALLOCATE(data, __FRAGMENT_SIZE(n));
1.71 - newdata->capacity = n;
1.72 - }
1.73 -
1.74 - /* Insert the new element and increment the list size. */
1.75 - newdata->attrs[size] = *value;
1.76 - newdata->size = size + 1;
1.77 + __fragment *newdata = __fragment_append(data, value);
1.78
1.79 /* Replace the __data__ attribute if appropriate. */
1.80 if (newdata != data)
1.81 @@ -466,6 +476,159 @@
1.82 return __builtins___none_None;
1.83 }
1.84
1.85 +__attr __fn_native__dict_init(__attr __args[])
1.86 +{
1.87 + __attr * const size = &__args[1];
1.88 + /* size.__data__ interpreted as int */
1.89 + unsigned int n = __load_via_object(size->value, __pos___data__).intvalue;
1.90 + __mapping *data = __new_mapping(n);
1.91 + __attr attr = {0, .mapvalue=data};
1.92 +
1.93 + /* Return the __data__ attribute. */
1.94 + return attr;
1.95 +}
1.96 +
1.97 +__attr __fn_native__dict_bucketsize(__attr __args[])
1.98 +{
1.99 + __attr * const self = &__args[1];
1.100 + __attr * const index = &__args[2];
1.101 + /* self.__data__ interpreted as dict */
1.102 + __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue;
1.103 + /* index.__data__ interpreted as int */
1.104 + int k = __load_via_object(index->value, __pos___data__).intvalue % __MAPPING_BUCKETS;
1.105 +
1.106 + /* Return size of bucket k. */
1.107 + return __new_int(data->keys[k]->size);
1.108 +}
1.109 +
1.110 +__attr __fn_native__dict_keys(__attr __args[])
1.111 +{
1.112 + __attr * const self = &__args[1];
1.113 + /* self.__data__ interpreted as dict */
1.114 + __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue;
1.115 + unsigned int k, i, j, size = 0;
1.116 + __fragment *f;
1.117 +
1.118 + /* Count the number of keys. */
1.119 + for (k = 0; k < __MAPPING_BUCKETS; k++)
1.120 + size += data->keys[k]->size;
1.121 +
1.122 + /* Create a fragment for the keys. */
1.123 + f = __new_fragment(size);
1.124 +
1.125 + /* Populate the fragment with the keys. */
1.126 + for (j = 0, k = 0; k < __MAPPING_BUCKETS; k++)
1.127 + for (i = 0; i < data->keys[k]->size; i++, j++)
1.128 + f->attrs[j] = data->keys[k]->attrs[i];
1.129 + f->size = size;
1.130 +
1.131 + /* Return a list. */
1.132 + return __new_list(f);
1.133 +}
1.134 +
1.135 +__attr __fn_native__dict_values(__attr __args[])
1.136 +{
1.137 + __attr * const self = &__args[1];
1.138 + /* self.__data__ interpreted as dict */
1.139 + __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue;
1.140 + unsigned int k, i, j, size = 0;
1.141 + __fragment *f;
1.142 +
1.143 + /* Count the number of values. */
1.144 + for (k = 0; k < __MAPPING_BUCKETS; k++)
1.145 + size += data->values[k]->size;
1.146 +
1.147 + /* Create a fragment for the values. */
1.148 + f = __new_fragment(size);
1.149 +
1.150 + /* Populate the fragment with the values. */
1.151 + for (j = 0, k = 0; k < __MAPPING_BUCKETS; k++)
1.152 + for (i = 0; i < data->values[k]->size; i++, j++)
1.153 + f->attrs[j] = data->values[k]->attrs[i];
1.154 + f->size = size;
1.155 +
1.156 + /* Return a list. */
1.157 + return __new_list(f);
1.158 +}
1.159 +
1.160 +__attr __fn_native__dict_key(__attr __args[])
1.161 +{
1.162 + __attr * const self = &__args[1];
1.163 + __attr * const index = &__args[2];
1.164 + __attr * const element = &__args[3];
1.165 + /* self.__data__ interpreted as dict */
1.166 + __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue;
1.167 + /* index.__data__ interpreted as int */
1.168 + int k = __load_via_object(index->value, __pos___data__).intvalue % __MAPPING_BUCKETS;
1.169 + /* element.__data__ interpreted as int */
1.170 + int i = __load_via_object(element->value, __pos___data__).intvalue;
1.171 +
1.172 + /* Return key from bucket k, element i. */
1.173 + return data->keys[k]->attrs[i];
1.174 +}
1.175 +
1.176 +__attr __fn_native__dict_value(__attr __args[])
1.177 +{
1.178 + __attr * const self = &__args[1];
1.179 + __attr * const index = &__args[2];
1.180 + __attr * const element = &__args[3];
1.181 + /* self.__data__ interpreted as dict */
1.182 + __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue;
1.183 + /* index.__data__ interpreted as int */
1.184 + int k = __load_via_object(index->value, __pos___data__).intvalue % __MAPPING_BUCKETS;
1.185 + /* element.__data__ interpreted as int */
1.186 + int i = __load_via_object(element->value, __pos___data__).intvalue;
1.187 +
1.188 + /* Return value from bucket k, element i. */
1.189 + return data->values[k]->attrs[i];
1.190 +}
1.191 +
1.192 +__attr __fn_native__dict_additem(__attr __args[])
1.193 +{
1.194 + __attr * const self = &__args[1];
1.195 + __attr * const index = &__args[2];
1.196 + __attr * const key = &__args[3];
1.197 + __attr * const value = &__args[4];
1.198 + /* self.__data__ interpreted as dict */
1.199 + __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue;
1.200 + /* index.__data__ interpreted as int */
1.201 + int k = __load_via_object(index->value, __pos___data__).intvalue % __MAPPING_BUCKETS;
1.202 + __fragment *keys = data->keys[k], *newkeys;
1.203 + __fragment *values = data->values[k], *newvalues;
1.204 +
1.205 + /* Append the item. */
1.206 + newkeys = __fragment_append(keys, key);
1.207 + newvalues = __fragment_append(values, value);
1.208 +
1.209 + /* Replace the fragments if appropriate. */
1.210 + if (newkeys != keys)
1.211 + data->keys[k] = newkeys;
1.212 + if (newvalues != values)
1.213 + data->values[k] = newvalues;
1.214 + return __builtins___none_None;
1.215 +}
1.216 +
1.217 +__attr __fn_native__dict_setitem(__attr __args[])
1.218 +{
1.219 + __attr * const self = &__args[1];
1.220 + __attr * const index = &__args[2];
1.221 + __attr * const element = &__args[3];
1.222 + __attr * const key = &__args[4];
1.223 + __attr * const value = &__args[5];
1.224 + /* self.__data__ interpreted as dict */
1.225 + __mapping *data = __load_via_object(self->value, __pos___data__).mapvalue;
1.226 + /* index.__data__ interpreted as int */
1.227 + int k = __load_via_object(index->value, __pos___data__).intvalue % __MAPPING_BUCKETS;
1.228 + /* element.__data__ interpreted as int */
1.229 + int i = __load_via_object(element->value, __pos___data__).intvalue;
1.230 +
1.231 + /* Replace the item. */
1.232 + data->keys[k]->attrs[i] = *key;
1.233 + data->values[k]->attrs[i] = *value;
1.234 +
1.235 + return __builtins___none_None;
1.236 +}
1.237 +
1.238 __attr __fn_native__buffer_str(__attr __args[])
1.239 {
1.240 __attr * const self = &__args[1];