1.1 --- a/lib/__builtins__/sequence.py Thu Dec 01 19:09:28 2016 +0100
1.2 +++ b/lib/__builtins__/sequence.py Thu Dec 01 19:48:31 2016 +0100
1.3 @@ -21,9 +21,9 @@
1.4
1.5 from native import _isinstance
1.6
1.7 -class sequence:
1.8 +class itemaccess:
1.9
1.10 - "A common base class for sequence types."
1.11 + "An abstract class providing item access."
1.12
1.13 def _check_index(self, index):
1.14
1.15 @@ -35,56 +35,6 @@
1.16 if index < 0 or index >= len(self):
1.17 raise IndexError(index)
1.18
1.19 - def _str(self, opening, closing):
1.20 -
1.21 - "Serialise this object with the given 'opening' and 'closing' strings."
1.22 -
1.23 - b = buffer()
1.24 - i = 0
1.25 - l = self.__len__()
1.26 - first = True
1.27 -
1.28 - b.append(opening)
1.29 - while i < l:
1.30 - if first:
1.31 - first = False
1.32 - else:
1.33 - b.append(", ")
1.34 - b.append(repr(self.__get_single_item__(i)))
1.35 - i += 1
1.36 - b.append(closing)
1.37 -
1.38 - return str(b)
1.39 -
1.40 - def __contains__(self, value):
1.41 -
1.42 - "Return whether the list contains 'value'."
1.43 -
1.44 - # Perform a linear search of the sequence contents.
1.45 -
1.46 - for v in self:
1.47 -
1.48 - # Return True if the current value is equal to the specified one.
1.49 - # Note that this is not an identity test, but an equality test.
1.50 -
1.51 - if v == value:
1.52 - return True
1.53 -
1.54 - return False
1.55 -
1.56 - def index(self, value):
1.57 -
1.58 - "Return the index of 'value' or raise ValueError."
1.59 -
1.60 - i = 0
1.61 - l = len(self)
1.62 - while i < l:
1.63 - if self[i] == value:
1.64 - return i
1.65 - i += 1
1.66 -
1.67 - raise ValueError(value)
1.68 -
1.69 def __getitem__(self, index):
1.70
1.71 "Return the item or slice specified by 'index'."
1.72 @@ -157,6 +107,60 @@
1.73
1.74 return result
1.75
1.76 +class sequence(itemaccess):
1.77 +
1.78 + "A common base class for sequence types."
1.79 +
1.80 + def _str(self, opening, closing):
1.81 +
1.82 + "Serialise this object with the given 'opening' and 'closing' strings."
1.83 +
1.84 + b = buffer()
1.85 + i = 0
1.86 + l = self.__len__()
1.87 + first = True
1.88 +
1.89 + b.append(opening)
1.90 + while i < l:
1.91 + if first:
1.92 + first = False
1.93 + else:
1.94 + b.append(", ")
1.95 + b.append(repr(self.__get_single_item__(i)))
1.96 + i += 1
1.97 + b.append(closing)
1.98 +
1.99 + return str(b)
1.100 +
1.101 + def __contains__(self, value):
1.102 +
1.103 + "Return whether the list contains 'value'."
1.104 +
1.105 + # Perform a linear search of the sequence contents.
1.106 +
1.107 + for v in self:
1.108 +
1.109 + # Return True if the current value is equal to the specified one.
1.110 + # Note that this is not an identity test, but an equality test.
1.111 +
1.112 + if v == value:
1.113 + return True
1.114 +
1.115 + return False
1.116 +
1.117 + def index(self, value):
1.118 +
1.119 + "Return the index of 'value' or raise ValueError."
1.120 +
1.121 + i = 0
1.122 + l = len(self)
1.123 + while i < l:
1.124 + if self[i] == value:
1.125 + return i
1.126 + i += 1
1.127 +
1.128 + raise ValueError(value)
1.129 +
1.130 def __eq__(self, other):
1.131
1.132 "Return whether this sequence is equal to 'other'."
1.133 @@ -211,6 +215,4 @@
1.134 else:
1.135 return y
1.136
1.137 -def _tuple(l): pass
1.138 -
1.139 # vim: tabstop=4 expandtab shiftwidth=4
2.1 --- a/lib/__builtins__/str.py Thu Dec 01 19:09:28 2016 +0100
2.2 +++ b/lib/__builtins__/str.py Thu Dec 01 19:48:31 2016 +0100
2.3 @@ -20,9 +20,10 @@
2.4 """
2.5
2.6 from __builtins__.operator import _binary_op, _negate
2.7 +from __builtins__.sequence import itemaccess
2.8 import native
2.9
2.10 -class basestring:
2.11 +class basestring(itemaccess):
2.12
2.13 "The base class for all strings."
2.14
2.15 @@ -121,6 +122,15 @@
2.16 def strip(self, chars=None): pass
2.17 def upper(self): pass
2.18
2.19 + # Special implementation methods.
2.20 +
2.21 + def __get_single_item__(self, index):
2.22 +
2.23 + "Return the item at the normalised (positive) 'index'."
2.24 +
2.25 + self._check_index(index)
2.26 + return native._str_substr(self, index, 1)
2.27 +
2.28 class string(basestring):
2.29 pass
2.30
3.1 --- a/lib/native.py Thu Dec 01 19:09:28 2016 +0100
3.2 +++ b/lib/native.py Thu Dec 01 19:48:31 2016 +0100
3.3 @@ -60,6 +60,7 @@
3.4 def _str_eq(self, other): pass
3.5 def _str_len(self): pass
3.6 def _str_nonempty(self): pass
3.7 +def _str_substr(self, start, size): pass
3.8
3.9 # List operations.
3.10
4.1 --- a/templates/native.c Thu Dec 01 19:09:28 2016 +0100
4.2 +++ b/templates/native.c Thu Dec 01 19:48:31 2016 +0100
4.3 @@ -302,7 +302,7 @@
4.4 char *r = (char *) __ALLOCATE(n, sizeof(char));
4.5
4.6 strncpy(r, s, n);
4.7 - strncpy(r + strlen(s), o, n - strlen(s));
4.8 + strncpy(r + strlen(s), o, n - strlen(s)); /* should null terminate */
4.9
4.10 /* Return a new string. */
4.11 return __new_str(r);
4.12 @@ -363,6 +363,24 @@
4.13 return strlen(s) ? __builtins___boolean_True : __builtins___boolean_False;
4.14 }
4.15
4.16 +__attr __fn_native__str_substr(__attr __args[])
4.17 +{
4.18 + __attr * const self = &__args[1];
4.19 + __attr * const start = &__args[2];
4.20 + __attr * const size = &__args[3];
4.21 + /* self.__data__ interpreted as string */
4.22 + char *s = __load_via_object(self->value, __pos___data__).strvalue, *sub;
4.23 + /* start.__data__ interpreted as int */
4.24 + int i = __load_via_object(start->value, __pos___data__).intvalue;
4.25 + /* size.__data__ interpreted as int */
4.26 + int l = __load_via_object(size->value, __pos___data__).intvalue;
4.27 +
4.28 + /* Reserve space for a new string. */
4.29 + sub = (char *) __ALLOCATE(l + 1, sizeof(char));
4.30 + strncpy(sub, s + i, l); /* does not null terminate but final byte should be zero */
4.31 + return __new_str(sub);
4.32 +}
4.33 +
4.34 __attr __fn_native__list_init(__attr __args[])
4.35 {
4.36 __attr * const size = &__args[1];
4.37 @@ -649,7 +667,7 @@
4.38 {
4.39 o = __load_via_object(data->attrs[i].value, __pos___data__).strvalue;
4.40 n = strlen(o);
4.41 - strncpy(s + j, o, n);
4.42 + strncpy(s + j, o, n); /* does not null terminate but final byte should be zero */
4.43 j += n;
4.44 }
4.45
5.1 --- a/templates/native.h Thu Dec 01 19:09:28 2016 +0100
5.2 +++ b/templates/native.h Thu Dec 01 19:48:31 2016 +0100
5.3 @@ -40,6 +40,7 @@
5.4 __attr __fn_native__str_eq(__attr __args[]);
5.5 __attr __fn_native__str_len(__attr __args[]);
5.6 __attr __fn_native__str_nonempty(__attr __args[]);
5.7 +__attr __fn_native__str_substr(__attr __args[]);
5.8
5.9 __attr __fn_native__list_init(__attr __args[]);
5.10 __attr __fn_native__list_setsize(__attr __args[]);
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/tests/string.py Thu Dec 01 19:48:31 2016 +0100
6.3 @@ -0,0 +1,15 @@
6.4 +s = "Hello"
6.5 +s += " world!"
6.6 +print s # Hello world!
6.7 +
6.8 +s2 = "Hello worlds!"
6.9 +print s2 # Hello worlds!
6.10 +print s < s2 # True
6.11 +print s <= s2 # True
6.12 +print s == s2 # False
6.13 +print s != s2 # True
6.14 +print s >= s2 # False
6.15 +print s > s2 # False
6.16 +
6.17 +print s[0] # H
6.18 +print s[-1] # !