1 /* Native functions for list operations. 2 3 Copyright (C) 2016, 2017 Paul Boddie <paul@boddie.org.uk> 4 5 This program is free software; you can redistribute it and/or modify it under 6 the terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3 of the License, or (at your option) any later 8 version. 9 10 This program is distributed in the hope that it will be useful, but WITHOUT 11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 13 details. 14 15 You should have received a copy of the GNU General Public License along with 16 this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include "native/common.h" 20 #include "types.h" 21 #include "exceptions.h" 22 #include "ops.h" 23 #include "progconsts.h" 24 #include "progops.h" 25 #include "progtypes.h" 26 #include "main.h" 27 28 /* List operations. */ 29 30 __attr __fn_native_list_list_init(__attr __args[]) 31 { 32 __attr * const size = &__args[1]; 33 /* size.__data__ interpreted as int */ 34 unsigned int n = __load_via_object(size->value, __data__).intvalue; 35 __attr attr = {.seqvalue=__new_fragment(n)}; 36 37 /* Return the __data__ attribute. */ 38 return attr; 39 } 40 41 __attr __fn_native_list_list_setsize(__attr __args[]) 42 { 43 __attr * const _data = &__args[1]; 44 __attr * const size = &__args[2]; 45 /* _data interpreted as list */ 46 __fragment *data = _data->seqvalue; 47 /* size.__data__ interpreted as int */ 48 unsigned int n = __load_via_object(size->value, __data__).intvalue; 49 50 data->size = n; 51 return __builtins___none_None; 52 } 53 54 __attr __fn_native_list_list_append(__attr __args[]) 55 { 56 __attr * const self = &__args[1]; 57 __attr * const value = &__args[2]; 58 /* self.__data__ interpreted as list */ 59 __fragment *data = __load_via_object(self->value, __data__).seqvalue; 60 __fragment *newdata = __fragment_append(data, value); 61 62 /* Replace the __data__ attribute if appropriate. */ 63 if (newdata != data) 64 __store_via_object(self->value, __data__, ((__attr) {.seqvalue=newdata})); 65 return __builtins___none_None; 66 } 67 68 __attr __fn_native_list_list_concat(__attr __args[]) 69 { 70 __attr * const self = &__args[1]; 71 __attr * const other = &__args[2]; 72 /* self.__data__, other interpreted as list */ 73 __fragment *data = __load_via_object(self->value, __data__).seqvalue; 74 __fragment *other_data = other->seqvalue; 75 __fragment *newdata = data; 76 unsigned int size = data->size, capacity = data->capacity; 77 unsigned int other_size = other_data->size; 78 unsigned int i, j, n = size + other_size; 79 80 /* Re-allocate the fragment if the capacity has been reached. */ 81 if (n >= capacity) 82 { 83 newdata = (__fragment *) __REALLOCATE(data, __FRAGMENT_SIZE(n)); 84 newdata->capacity = n; 85 } 86 87 /* Copy the elements from the other list and increment the list size. */ 88 for (i = size, j = 0; j < other_size; i++, j++) 89 newdata->attrs[i] = other_data->attrs[j]; 90 newdata->size = n; 91 92 /* Replace the __data__ attribute if appropriate. */ 93 if (newdata != data) 94 __store_via_object(self->value, __data__, ((__attr) {.seqvalue=newdata})); 95 return __builtins___none_None; 96 } 97 98 __attr __fn_native_list_list_len(__attr __args[]) 99 { 100 __attr * const _data = &__args[1]; 101 /* _data interpreted as fragment */ 102 unsigned int size = _data->seqvalue->size; 103 104 /* Return the new integer. */ 105 return __new_int(size); 106 } 107 108 __attr __fn_native_list_list_nonempty(__attr __args[]) 109 { 110 __attr * const _data = &__args[1]; 111 112 return _data->seqvalue->size ? __builtins___boolean_True : __builtins___boolean_False; 113 } 114 115 __attr __fn_native_list_list_element(__attr __args[]) 116 { 117 __attr * const _data = &__args[1]; 118 __attr * const index = &__args[2]; 119 /* _data interpreted as fragment */ 120 __attr *elements = _data->seqvalue->attrs; 121 /* index.__data__ interpreted as int */ 122 int i = __load_via_object(index->value, __data__).intvalue; 123 124 return elements[i]; 125 } 126 127 __attr __fn_native_list_list_setelement(__attr __args[]) 128 { 129 __attr * const _data = &__args[1]; 130 __attr * const index = &__args[2]; 131 __attr * const value = &__args[3]; 132 /* _data interpreted as fragment */ 133 __attr *elements = _data->seqvalue->attrs; 134 /* index.__data__ interpreted as int */ 135 int i = __load_via_object(index->value, __data__).intvalue; 136 137 /* Set the element. */ 138 elements[i] = *value; 139 return __builtins___none_None; 140 } 141 142 /* Module initialisation. */ 143 144 void __main_native_list() 145 { 146 }