1.1 --- a/lib/__builtins__/buffer.py Mon Nov 21 22:56:52 2016 +0100
1.2 +++ b/lib/__builtins__/buffer.py Tue Nov 22 01:28:58 2016 +0100
1.3 @@ -3,7 +3,7 @@
1.4 """
1.5 Buffer object.
1.6
1.7 -Copyright (C) 2015 Paul Boddie <paul@boddie.org.uk>
1.8 +Copyright (C) 2015, 2016 Paul Boddie <paul@boddie.org.uk>
1.9
1.10 This program is free software; you can redistribute it and/or modify it under
1.11 the terms of the GNU General Public License as published by the Free Software
1.12 @@ -19,9 +19,39 @@
1.13 this program. If not, see <http://www.gnu.org/licenses/>.
1.14 """
1.15
1.16 +from native import _list_init, _list_append, _list_concat, _buffer_str
1.17 +
1.18 class buffer(object):
1.19 - def __init__(self, size): pass
1.20 - def append(self, s): pass
1.21 - def __str__(self): pass
1.22 +
1.23 + "A buffer, used to build strings."
1.24 +
1.25 + def __init__(self, args=None, size=None):
1.26 +
1.27 + "Initialise a buffer from the given 'args' or the given 'size'."
1.28 +
1.29 + self.__data__ = _list_init(len(args) or size or 0)
1.30 +
1.31 + # Append all arguments in string form to the buffer.
1.32 +
1.33 + if args:
1.34 + for arg in args:
1.35 + _list_append(self, str(arg))
1.36 +
1.37 + def append(self, s):
1.38 +
1.39 + "Append 's' to the buffer."
1.40 +
1.41 + if isinstance(s, buffer):
1.42 + _list_concat(self, s)
1.43 + elif isinstance(s, string):
1.44 + _list_append(self, s)
1.45 + else:
1.46 + raise TypeError(s)
1.47 +
1.48 + def __str__(self):
1.49 +
1.50 + "Return a string representation."
1.51 +
1.52 + return _buffer_str(self)
1.53
1.54 # vim: tabstop=4 expandtab shiftwidth=4
2.1 --- a/lib/__builtins__/list.py Mon Nov 21 22:56:52 2016 +0100
2.2 +++ b/lib/__builtins__/list.py Tue Nov 22 01:28:58 2016 +0100
2.3 @@ -31,9 +31,10 @@
2.4
2.5 "Initialise the list."
2.6
2.7 - # Reserve space for a fragment reference.
2.8 + # Reserve an attribute for a fragment reference along with some space
2.9 + # for elements.
2.10
2.11 - self.__data__ = native._list_init(len(args)) # reserve space for elements
2.12 + self.__data__ = native._list_init(len(args))
2.13
2.14 if args is not None:
2.15 self.extend(args)
2.16 @@ -56,7 +57,13 @@
2.17
2.18 def __setslice__(self, start, end, slice): pass
2.19 def __delslice__(self, start, end): pass
2.20 - def append(self, value): pass
2.21 +
2.22 + def append(self, value):
2.23 +
2.24 + "Append 'value' to the list."
2.25 +
2.26 + native._list_append(self, value)
2.27 +
2.28 def insert(self, i, value): pass
2.29
2.30 def extend(self, iterable):
2.31 @@ -77,15 +84,38 @@
2.32 return native._list_len(self)
2.33
2.34 def __add__(self, other): pass
2.35 - def __iadd__(self, other): pass
2.36 +
2.37 + def __iadd__(self, other):
2.38 +
2.39 + "Concatenate 'other' to the list."
2.40 +
2.41 + if isinstance(other, list):
2.42 + native._list_concat(self, other)
2.43 + else:
2.44 + self.extend(other)
2.45 + return self
2.46
2.47 def __str__(self):
2.48
2.49 "Return a string representation of the list."
2.50
2.51 - # NOTE: To be implemented, maybe using a buffer.
2.52 + b = buffer()
2.53 + i = 0
2.54 + l = self.__len__()
2.55 + first = True
2.56 +
2.57 + # NOTE: Should really show quoted forms of the items.
2.58
2.59 - return "[...]"
2.60 + b.append("[")
2.61 + while i < l:
2.62 + if first:
2.63 + first = False
2.64 + else:
2.65 + b.append(", ")
2.66 + b.append(self.__get_single_item__(i))
2.67 + b.append("]")
2.68 +
2.69 + return str(b)
2.70
2.71 def __bool__(self):
2.72
3.1 --- a/lib/native.py Mon Nov 21 22:56:52 2016 +0100
3.2 +++ b/lib/native.py Tue Nov 22 01:28:58 2016 +0100
3.3 @@ -52,10 +52,14 @@
3.4 def _str_nonempty(self): pass
3.5
3.6 def _list_init(size): pass
3.7 +def _list_append(self, value): pass
3.8 +def _list_concat(self, other): pass
3.9 def _list_len(self): pass
3.10 def _list_nonempty(self): pass
3.11 def _list_element(self, index): pass
3.12
3.13 +def _buffer_str(self): pass
3.14 +
3.15 def _list_to_tuple(l): pass
3.16
3.17 def _tuple_init(args, size): pass
4.1 --- a/templates/native.c Mon Nov 21 22:56:52 2016 +0100
4.2 +++ b/templates/native.c Tue Nov 22 01:28:58 2016 +0100
4.3 @@ -1,4 +1,4 @@
4.4 -#include <stdlib.h> /* calloc, exit */
4.5 +#include <stdlib.h> /* calloc, exit, realloc */
4.6 #include <unistd.h> /* read, write */
4.7 #include <math.h> /* ceil, log10, pow */
4.8 #include <string.h> /* strcmp, strlen */
4.9 @@ -370,13 +370,73 @@
4.10
4.11 __attr __fn_native__list_init(__attr __args[])
4.12 {
4.13 - #define size (__args[1])
4.14 - /* size.__data__ interpreted as fragment */
4.15 - __fragment *data = calloc(__load_via_object(size.value, __pos___data__).intvalue, sizeof(__attr));
4.16 + #define __size (__args[1])
4.17 + /* __size.__data__ interpreted as int */
4.18 + unsigned int n = __load_via_object(__size.value, __pos___data__).intvalue;
4.19 +
4.20 + /* Allocate space for the list. */
4.21 + __fragment *data = calloc(1, __FRAGMENT_SIZE(n));
4.22 __attr attr = {0, .data=data};
4.23
4.24 + /* The initial capacity is the same as the given size. */
4.25 + data->size = 0;
4.26 + data->capacity = n;
4.27 return attr;
4.28 - #undef size
4.29 + #undef __size
4.30 +}
4.31 +
4.32 +__attr __fn_native__list_append(__attr __args[])
4.33 +{
4.34 + #define self (__args[1])
4.35 + #define __value (__args[2])
4.36 + /* self.__data__ interpreted as list */
4.37 + __fragment *data = __load_via_object(self.value, __pos___data__).data;
4.38 + unsigned int size = data->size, capacity = data->capacity;
4.39 + unsigned int n;
4.40 +
4.41 + /* Re-allocate the fragment if the capacity has been reached. */
4.42 + if (size >= capacity)
4.43 + {
4.44 + /* NOTE: Consider various restrictions on capacity increases. */
4.45 + n = data->capacity * 2;
4.46 + data = realloc(data, __FRAGMENT_SIZE(n));
4.47 + data->capacity = n;
4.48 + }
4.49 +
4.50 + /* Insert the new element and increment the list size. */
4.51 + data->attrs[size] = __value;
4.52 + data->size = size + 1;
4.53 + return __builtins___none_None;
4.54 + #undef self
4.55 + #undef __value
4.56 +}
4.57 +
4.58 +__attr __fn_native__list_concat(__attr __args[])
4.59 +{
4.60 + #define self (__args[1])
4.61 + #define __other (__args[2])
4.62 + /* self.__data__, __other.__data__ interpreted as list */
4.63 + __fragment *data = __load_via_object(self.value, __pos___data__).data;
4.64 + __fragment *other_data = __load_via_object(__other.value, __pos___data__).data;
4.65 + unsigned int size = data->size, capacity = data->capacity;
4.66 + unsigned int other_size = other_data->size;
4.67 + unsigned int i, j, n;
4.68 +
4.69 + /* Re-allocate the fragment if the capacity has been reached. */
4.70 + if (size + other_size >= capacity)
4.71 + {
4.72 + n = size + other_size;
4.73 + data = realloc(data, __FRAGMENT_SIZE(n));
4.74 + data->capacity = n;
4.75 + }
4.76 +
4.77 + /* Copy the elements from the other list and increment the list size. */
4.78 + for (i = size, j = 0; j < other_size; i++, j++)
4.79 + data->attrs[i] = other_data->attrs[j];
4.80 + data->size = n;
4.81 + return __builtins___none_None;
4.82 + #undef self
4.83 + #undef __other
4.84 }
4.85
4.86 __attr __fn_native__list_len(__attr __args[])
4.87 @@ -421,6 +481,30 @@
4.88 #undef l
4.89 }
4.90
4.91 +__attr __fn_native__buffer_str(__attr __args[])
4.92 +{
4.93 + #define self (__args[1])
4.94 + /* self.__data__ interpreted as buffer */
4.95 + __fragment *data = __load_via_object(self.value, __pos___data__).data;
4.96 + unsigned int size = 0, i, j;
4.97 + char *s;
4.98 +
4.99 + /* Calculate the size of the string. */
4.100 + for (i = 0; i < data->size; i++)
4.101 + size += strlen(data->attrs[i].strvalue);
4.102 +
4.103 + /* Reserve space for a new string. */
4.104 + s = calloc(size + 1, sizeof(char));
4.105 +
4.106 + /* Build a single string from the buffer contents. */
4.107 + for (i = 0, j = 0; i < data->size; j += strlen(data->attrs[i].strvalue), i++)
4.108 + strcpy(s + j, data->attrs[i].strvalue);
4.109 +
4.110 + /* Return a new string. */
4.111 + return __new_str(s);
4.112 + #undef self
4.113 +}
4.114 +
4.115 __attr __fn_native__tuple_init(__attr __args[])
4.116 {
4.117 #define size (__args[1])
5.1 --- a/templates/native.h Mon Nov 21 22:56:52 2016 +0100
5.2 +++ b/templates/native.h Tue Nov 22 01:28:58 2016 +0100
5.3 @@ -41,11 +41,15 @@
5.4 __attr __fn_native__str_nonempty(__attr __args[]);
5.5
5.6 __attr __fn_native__list_init(__attr __args[]);
5.7 +__attr __fn_native__list_append(__attr __args[]);
5.8 +__attr __fn_native__list_concat(__attr __args[]);
5.9 __attr __fn_native__list_len(__attr __args[]);
5.10 __attr __fn_native__list_nonempty(__attr __args[]);
5.11 __attr __fn_native__list_element(__attr __args[]);
5.12 __attr __fn_native__list_to_tuple(__attr __args[]);
5.13
5.14 +__attr __fn_native__buffer_str(__attr __args[]);
5.15 +
5.16 __attr __fn_native__tuple_init(__attr __args[]);
5.17 __attr __fn_native__tuple_len(__attr __args[]);
5.18 __attr __fn_native__tuple_element(__attr __args[]);
6.1 --- a/templates/progops.c Mon Nov 21 22:56:52 2016 +0100
6.2 +++ b/templates/progops.c Tue Nov 22 01:28:58 2016 +0100
6.3 @@ -26,8 +26,9 @@
6.4
6.5 __attr __newdata(__attr args[], unsigned int number)
6.6 {
6.7 - /* Manually calculate the size of the fragment. */
6.8 - __fragment *data = (__fragment *) calloc(1, number * sizeof(__attr) + sizeof(unsigned int));
6.9 + /* Calculate the size of the fragment. */
6.10 +
6.11 + __fragment *data = (__fragment *) calloc(1, __FRAGMENT_SIZE(number));
6.12 __attr attr = {0, .data=data};
6.13 unsigned int i, j;
6.14
6.15 @@ -37,6 +38,7 @@
6.16 data->attrs[j] = args[i];
6.17
6.18 data->size = number;
6.19 + data->capacity = number;
6.20 return attr;
6.21 }
6.22
7.1 --- a/templates/types.h Mon Nov 21 22:56:52 2016 +0100
7.2 +++ b/templates/types.h Tue Nov 22 01:28:58 2016 +0100
7.3 @@ -70,10 +70,12 @@
7.4
7.5 typedef struct __fragment
7.6 {
7.7 - unsigned int size;
7.8 + unsigned int size, capacity;
7.9 __attr attrs[];
7.10 } __fragment;
7.11
7.12 +#define __FRAGMENT_SIZE(NUMBER) (NUMBER * sizeof(__attr) + 2 * sizeof(unsigned int))
7.13 +
7.14 /* Special instance position value. The pos member of __obj refers to the
7.15 special type attribute for classes, indicating which position holds the
7.16 attribute describing the class type. For instances, it is set to zero. */
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/tests/list.py Tue Nov 22 01:28:58 2016 +0100
8.3 @@ -0,0 +1,7 @@
8.4 +l = [1, 2, 3]
8.5 +l.append(4)
8.6 +print len(l)
8.7 +print l[0]
8.8 +print l[1]
8.9 +print l[2]
8.10 +print l[3]