1 /* Native functions for list operations. 2 3 Copyright (C) 2016 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, __pos___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, __pos___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, __pos___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, __pos___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, __pos___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; 79 80 /* Re-allocate the fragment if the capacity has been reached. */ 81 if (size + other_size >= capacity) 82 { 83 n = size + other_size; 84 newdata = (__fragment *) __REALLOCATE(data, __FRAGMENT_SIZE(n)); 85 newdata->capacity = n; 86 } 87 88 /* Copy the elements from the other list and increment the list size. */ 89 for (i = size, j = 0; j < other_size; i++, j++) 90 newdata->attrs[i] = other_data->attrs[j]; 91 newdata->size = n; 92 93 /* Replace the __data__ attribute if appropriate. */ 94 if (newdata != data) 95 __store_via_object(self->value, __pos___data__, ((__attr) {.seqvalue=newdata})); 96 return __builtins___none_None; 97 } 98 99 __attr __fn_native_list_list_len(__attr __args[]) 100 { 101 __attr * const _data = &__args[1]; 102 /* _data interpreted as fragment */ 103 unsigned int size = _data->seqvalue->size; 104 105 /* Return the new integer. */ 106 return __new_int(size); 107 } 108 109 __attr __fn_native_list_list_nonempty(__attr __args[]) 110 { 111 __attr * const _data = &__args[1]; 112 113 return _data->seqvalue->size ? __builtins___boolean_True : __builtins___boolean_False; 114 } 115 116 __attr __fn_native_list_list_element(__attr __args[]) 117 { 118 __attr * const _data = &__args[1]; 119 __attr * const index = &__args[2]; 120 /* _data interpreted as fragment */ 121 __attr *elements = _data->seqvalue->attrs; 122 /* index.__data__ interpreted as int */ 123 int i = __load_via_object(index->value, __pos___data__).intvalue; 124 125 return elements[i]; 126 } 127 128 __attr __fn_native_list_list_setelement(__attr __args[]) 129 { 130 __attr * const _data = &__args[1]; 131 __attr * const index = &__args[2]; 132 __attr * const value = &__args[3]; 133 /* _data interpreted as fragment */ 134 __attr *elements = _data->seqvalue->attrs; 135 /* index.__data__ interpreted as int */ 136 int i = __load_via_object(index->value, __pos___data__).intvalue; 137 138 /* Set the element. */ 139 elements[i] = *value; 140 return __builtins___none_None; 141 } 142 143 /* Module initialisation. */ 144 145 void __main_native_list() 146 { 147 }