# HG changeset patch # User Paul Boddie # Date 1480618111 -3600 # Node ID 436d7832ca668981de36b898881695cd8d4d5c30 # Parent afa2a255d1e58ef3aa5f95806af77b759fe4148d Introduced the itemaccess class as the base of sequence types and strings. Added support for obtaining substrings from strings. Added tests of string operations. Removed the superfluous _tuple function from the sequence module. diff -r afa2a255d1e5 -r 436d7832ca66 lib/__builtins__/sequence.py --- a/lib/__builtins__/sequence.py Thu Dec 01 19:09:28 2016 +0100 +++ b/lib/__builtins__/sequence.py Thu Dec 01 19:48:31 2016 +0100 @@ -21,9 +21,9 @@ from native import _isinstance -class sequence: +class itemaccess: - "A common base class for sequence types." + "An abstract class providing item access." def _check_index(self, index): @@ -35,56 +35,6 @@ if index < 0 or index >= len(self): raise IndexError(index) - def _str(self, opening, closing): - - "Serialise this object with the given 'opening' and 'closing' strings." - - b = buffer() - i = 0 - l = self.__len__() - first = True - - b.append(opening) - while i < l: - if first: - first = False - else: - b.append(", ") - b.append(repr(self.__get_single_item__(i))) - i += 1 - b.append(closing) - - return str(b) - - def __contains__(self, value): - - "Return whether the list contains 'value'." - - # Perform a linear search of the sequence contents. - - for v in self: - - # Return True if the current value is equal to the specified one. - # Note that this is not an identity test, but an equality test. - - if v == value: - return True - - return False - - def index(self, value): - - "Return the index of 'value' or raise ValueError." - - i = 0 - l = len(self) - while i < l: - if self[i] == value: - return i - i += 1 - - raise ValueError(value) - def __getitem__(self, index): "Return the item or slice specified by 'index'." @@ -157,6 +107,60 @@ return result +class sequence(itemaccess): + + "A common base class for sequence types." + + def _str(self, opening, closing): + + "Serialise this object with the given 'opening' and 'closing' strings." + + b = buffer() + i = 0 + l = self.__len__() + first = True + + b.append(opening) + while i < l: + if first: + first = False + else: + b.append(", ") + b.append(repr(self.__get_single_item__(i))) + i += 1 + b.append(closing) + + return str(b) + + def __contains__(self, value): + + "Return whether the list contains 'value'." + + # Perform a linear search of the sequence contents. + + for v in self: + + # Return True if the current value is equal to the specified one. + # Note that this is not an identity test, but an equality test. + + if v == value: + return True + + return False + + def index(self, value): + + "Return the index of 'value' or raise ValueError." + + i = 0 + l = len(self) + while i < l: + if self[i] == value: + return i + i += 1 + + raise ValueError(value) + def __eq__(self, other): "Return whether this sequence is equal to 'other'." @@ -211,6 +215,4 @@ else: return y -def _tuple(l): pass - # vim: tabstop=4 expandtab shiftwidth=4 diff -r afa2a255d1e5 -r 436d7832ca66 lib/__builtins__/str.py --- a/lib/__builtins__/str.py Thu Dec 01 19:09:28 2016 +0100 +++ b/lib/__builtins__/str.py Thu Dec 01 19:48:31 2016 +0100 @@ -20,9 +20,10 @@ """ from __builtins__.operator import _binary_op, _negate +from __builtins__.sequence import itemaccess import native -class basestring: +class basestring(itemaccess): "The base class for all strings." @@ -121,6 +122,15 @@ def strip(self, chars=None): pass def upper(self): pass + # Special implementation methods. + + def __get_single_item__(self, index): + + "Return the item at the normalised (positive) 'index'." + + self._check_index(index) + return native._str_substr(self, index, 1) + class string(basestring): pass diff -r afa2a255d1e5 -r 436d7832ca66 lib/native.py --- a/lib/native.py Thu Dec 01 19:09:28 2016 +0100 +++ b/lib/native.py Thu Dec 01 19:48:31 2016 +0100 @@ -60,6 +60,7 @@ def _str_eq(self, other): pass def _str_len(self): pass def _str_nonempty(self): pass +def _str_substr(self, start, size): pass # List operations. diff -r afa2a255d1e5 -r 436d7832ca66 templates/native.c --- a/templates/native.c Thu Dec 01 19:09:28 2016 +0100 +++ b/templates/native.c Thu Dec 01 19:48:31 2016 +0100 @@ -302,7 +302,7 @@ char *r = (char *) __ALLOCATE(n, sizeof(char)); strncpy(r, s, n); - strncpy(r + strlen(s), o, n - strlen(s)); + strncpy(r + strlen(s), o, n - strlen(s)); /* should null terminate */ /* Return a new string. */ return __new_str(r); @@ -363,6 +363,24 @@ return strlen(s) ? __builtins___boolean_True : __builtins___boolean_False; } +__attr __fn_native__str_substr(__attr __args[]) +{ + __attr * const self = &__args[1]; + __attr * const start = &__args[2]; + __attr * const size = &__args[3]; + /* self.__data__ interpreted as string */ + char *s = __load_via_object(self->value, __pos___data__).strvalue, *sub; + /* start.__data__ interpreted as int */ + int i = __load_via_object(start->value, __pos___data__).intvalue; + /* size.__data__ interpreted as int */ + int l = __load_via_object(size->value, __pos___data__).intvalue; + + /* Reserve space for a new string. */ + sub = (char *) __ALLOCATE(l + 1, sizeof(char)); + strncpy(sub, s + i, l); /* does not null terminate but final byte should be zero */ + return __new_str(sub); +} + __attr __fn_native__list_init(__attr __args[]) { __attr * const size = &__args[1]; @@ -649,7 +667,7 @@ { o = __load_via_object(data->attrs[i].value, __pos___data__).strvalue; n = strlen(o); - strncpy(s + j, o, n); + strncpy(s + j, o, n); /* does not null terminate but final byte should be zero */ j += n; } diff -r afa2a255d1e5 -r 436d7832ca66 templates/native.h --- a/templates/native.h Thu Dec 01 19:09:28 2016 +0100 +++ b/templates/native.h Thu Dec 01 19:48:31 2016 +0100 @@ -40,6 +40,7 @@ __attr __fn_native__str_eq(__attr __args[]); __attr __fn_native__str_len(__attr __args[]); __attr __fn_native__str_nonempty(__attr __args[]); +__attr __fn_native__str_substr(__attr __args[]); __attr __fn_native__list_init(__attr __args[]); __attr __fn_native__list_setsize(__attr __args[]); diff -r afa2a255d1e5 -r 436d7832ca66 tests/string.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/string.py Thu Dec 01 19:48:31 2016 +0100 @@ -0,0 +1,15 @@ +s = "Hello" +s += " world!" +print s # Hello world! + +s2 = "Hello worlds!" +print s2 # Hello worlds! +print s < s2 # True +print s <= s2 # True +print s == s2 # False +print s != s2 # True +print s >= s2 # False +print s > s2 # False + +print s[0] # H +print s[-1] # !