Merge: lib/string: some cleaning, doc and unit tests
authorJean Privat <jean@pryen.org>
Fri, 4 Apr 2014 20:26:42 +0000 (16:26 -0400)
committerJean Privat <jean@pryen.org>
Fri, 4 Apr 2014 20:26:42 +0000 (16:26 -0400)
An important point is the generalization of services from
StringCharView to Sequences, and the privatization of StringCharView.

Closes #144
Closes #140
Pull-Request: #383
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>

21 files changed:
contrib/nitcc/src/nitcc_lexer0.nit
contrib/nitcc/src/nitcc_semantic.nit
contrib/nitcc/src/re2nfa.nit
examples/calculator.nit
lib/json_serialization.nit
lib/mpd.nit
lib/nitcc_runtime.nit
lib/opts.nit
lib/simple_json_reader/simple_json_reader.nit
lib/standard/collection/abstract_collection.nit
lib/standard/collection/array.nit
lib/standard/collection/list.nit
lib/standard/file.nit
lib/standard/string.nit
src/debugger.nit
src/modelize_class.nit
src/modelize_property.nit
src/nitdoc.nit
src/nitni/nitni_base.nit
src/serialization_phase.nit
tests/base_iterator1.nit

index 6f12765..7fa876f 100644 (file)
@@ -25,14 +25,14 @@ import nitcc_parser
 class Lexer_nitcc
        var text: String
 
-       var iter: Iterator[Char] = "".iterator
+       var iter: Iterator[Char] = "".chars.iterator
        var pos = 0
 
        var tokens = new Array[NToken]
 
        fun lex: Array[NToken]
        do
-               iter = text.iterator
+               iter = text.chars.iterator
                while iter.is_ok do
                        trim
                        if not iter.is_ok then break
index 02aea35..b723c1a 100644 (file)
@@ -454,7 +454,7 @@ redef class Token
                var text = self.text
                if text != null then
                        var nfa = new Automaton.epsilon
-                       for c in text.as(not null) do
+                       for c in text.chars do
                                nfa.concat(new Automaton.atom(c.ascii))
                        end
                        return nfa
index da66d9f..d381fe1 100644 (file)
@@ -38,7 +38,7 @@ redef class Nstr
        do
                var a = new Automaton.epsilon
                var val
-               for c in self.value do
+               for c in self.value.chars do
                        var b = new Automaton.atom(c.ascii)
                        a.concat(b)
                end
@@ -50,7 +50,7 @@ redef class Nch_dec
        redef fun value: String do return text.substring_from(1).to_i.ascii.to_s
        redef fun make_rfa: Automaton
        do
-               var a = new Automaton.atom(self.value.first.ascii)
+               var a = new Automaton.atom(self.value.chars.first.ascii)
                return a
        end
 end
@@ -219,7 +219,7 @@ redef class Nre_class
                        exit(1)
                        abort
                end
-               var a = new Automaton.cla(c1.first.ascii, c2.first.ascii)
+               var a = new Automaton.cla(c1.chars.first.ascii, c2.chars.first.ascii)
                return a
        end
 end
index 35ed125..541f4d2 100644 (file)
@@ -123,7 +123,7 @@ class CalculatorGui
                                var s = context.result.to_precision_native(6)
                                var index : nullable Int = null
                                for i in s.length.times do
-                                   var chiffre = s[i]
+                                   var chiffre = s.chars[i]
                                    if chiffre == '0' and index == null then
                                        index = i
                                    else if chiffre != '0' then
@@ -132,7 +132,7 @@ class CalculatorGui
                                end
                                if index != null then
                                        s = s.substring(0, index)
-                                       if s[s.length-1] == ',' then s = s.substring(0, s.length-1)
+                                       if s.chars[s.length-1] == ',' then s = s.substring(0, s.length-1)
                                end
                                lbl_disp.text = s
                        end
index fd04d62..b361f88 100644 (file)
@@ -154,7 +154,7 @@ class JsonDeserializer
 
                                if val.length != 1 then print "Error: expected a single char when deserializing '{val}'."
                                
-                               return val.first
+                               return val.chars.first
                        end
 
                        print "Malformed Json string: unexpected Json Object kind '{kind}'"
index 9383934..fd8fa5d 100644 (file)
@@ -87,7 +87,7 @@ class MPDConnection
                        var words = l.split_with(" ")
                        if words.length > 1 then
                                var key = words[0].to_lower
-                               var first_space = l.index_of(' ')
+                               var first_space = l.chars.index_of(' ')
                                var rest = l.substring_from(first_space+1)
                                if  key == "volume:" then
                                        volume = rest.to_i
@@ -158,7 +158,7 @@ class MPDConnection
                        var words = l.split_with(" ")
                        if words.length > 1 then
                                var key = words[0].to_lower
-                               var first_space = l.index_of(' ')
+                               var first_space = l.chars.index_of(' ')
                                var rest = l.substring_from(first_space+1)
                                if key == "album:" then
                                        album = rest
index 1342c59..5f05815 100644 (file)
@@ -191,7 +191,7 @@ abstract class Lexer
                                c = '\0'
                                next = null
                        else
-                               c = text[pos]
+                               c = text.chars[pos]
                                next = state.trans(c)
                        end
                        if next == null then
@@ -467,7 +467,7 @@ end
 class NLexerError
        super NError
 
-       redef fun unexpected do return "character '{text.first}'"
+       redef fun unexpected do return "character '{text.chars.first}'"
 end
 
 # A parser error linked to a unexpected token
index 14e28fa..0ef02ad 100644 (file)
@@ -270,7 +270,7 @@ class OptionContext
                                parseargs = false
                        else
                                # We're looking for packed short options
-                               if str.last_index_of('-') == 0 and str.length > 2 then
+                               if str.chars.last_index_of('-') == 0 and str.length > 2 then
                                        var next_called = false
                                        for i in [1..str.length] do
                                                var short_opt = "-" + str.chars[i].to_s
index 3fd3d22..e9f8426 100644 (file)
@@ -27,7 +27,7 @@ redef class Nvalue_number
        redef fun to_nit_object
        do
                var text = n_number.text
-               if text.has('.') or text.has('e') or text.has('E') then return text.to_f
+               if text.chars.has('.') or text.chars.has('e') or text.chars.has('E') then return text.to_f
                return text.to_i
        end
 end
index f693ac1..20be476 100644 (file)
@@ -653,8 +653,6 @@ interface SequenceRead[E]
                return res
        end
 
-       redef fun iterator: IndexedIterator[E] is abstract
-
        # Two sequences are equals if they have the same items in the same order.
        #
        #     var a = new List[Int]
@@ -683,6 +681,42 @@ interface SequenceRead[E]
                for e in self do res += res.hash
                return res
        end
+
+       redef fun iterator: IndexedIterator[E] is abstract
+
+       # Gets a new Iterator starting at position `pos`
+       #
+       #     var iter = [10,20,30,40,50].iterator_from(2)
+       #     assert iter.to_a == [30, 40, 50]
+       fun iterator_from(pos: Int): IndexedIterator[E]
+       do
+               var res = iterator
+               while pos > 0 and res.is_ok do
+                       res.next
+                       pos -= 1
+               end
+               return res
+       end
+
+       # Gets an iterator starting at the end and going backwards
+       #
+       #     var reviter = [1,2,3].reverse_iterator
+       #     assert reviter.to_a == [3,2,1]
+       fun reverse_iterator: IndexedIterator[E] is abstract
+
+       # Gets an iterator on the chars of self starting from `pos`
+       #
+       #     var reviter = [10,20,30,40,50].reverse_iterator_from(2)
+       #     assert reviter.to_a == [30,20,10]
+       fun reverse_iterator_from(pos: Int): IndexedIterator[E]
+       do
+               var res = reverse_iterator
+               while pos > 0 and res.is_ok do
+                       res.next
+                       pos -= 1
+               end
+               return res
+       end
 end
 
 # Sequence are indexed collection.
index f6511be..6fe304e 100644 (file)
@@ -131,6 +131,7 @@ abstract class AbstractArrayRead[E]
        end
 
        redef fun iterator: ArrayIterator[E] do return new ArrayIterator[E](self)
+       redef fun reverse_iterator do return new ArrayReverseIterator[E](self)
 end
 
 # Resizable one dimension array of objects.
@@ -364,6 +365,20 @@ private class ArrayIterator[E]
        var _array: AbstractArrayRead[E]
 end
 
+private class ArrayReverseIterator[E]
+       super ArrayIterator[E]
+
+       redef fun is_ok do return _index >= 0
+
+       redef fun next do _index -= 1
+
+       init(a: AbstractArrayRead[E])
+       do
+               _array = a
+               _index = a.length - 1
+       end
+end
+
 # Others collections ##########################################################
 
 # A set implemented with an Array.
index c9a7155..0c5ce5f 100644 (file)
@@ -201,6 +201,7 @@ class List[E]
 
 
        redef fun iterator: ListIterator[E] do return new ListIterator[E](self)
+       redef fun reverse_iterator: ListIterator[E] do return new ListReverseIterator[E](self)
 
        # Build an empty list.
        init do end
@@ -315,6 +316,23 @@ class ListIterator[E]
        end
 end
 
+private class ListReverseIterator[E]
+       super ListIterator[E]
+
+       redef fun next
+       do
+               _node = _node.prev
+               _index -= 1
+       end
+
+       private init(list: List[E])
+       do
+               _list = list
+               _node = list._tail
+               _index = list.length
+       end
+end
+
 # Linked nodes that constitute a linked list.
 private class ListNode[E]
        super Container[E]
index b851876..f2653d1 100644 (file)
@@ -277,7 +277,7 @@ redef class String
                var l = length - 1 # Index of the last char
                while l > 0 and self.chars[l] == '/' do l -= 1 # remove all trailing `/`
                if l == 0 then return "/"
-               var pos = last_index_of_from('/', l)
+               var pos = chars.last_index_of_from('/', l)
                var n = self
                if pos >= 0 then
                        n = substring(pos+1, l-pos)
@@ -299,7 +299,7 @@ redef class String
        do
                var l = length - 1 # Index of the last char
                while l > 0 and self.chars[l] == '/' do l -= 1 # remove all trailing `/`
-               var pos = last_index_of_from('/', l)
+               var pos = chars.last_index_of_from('/', l)
                if pos > 0 then
                        return substring(0, pos)
                else if pos == 0 then
@@ -419,7 +419,7 @@ redef class String
        #     assert ".file".file_extension         == null
        fun file_extension: nullable String
        do
-               var last_slash = last_index_of('.')
+               var last_slash = chars.last_index_of('.')
                if last_slash > 0 then
                        return substring( last_slash+1, length )
                else
index 29a25ff..e1efccd 100644 (file)
@@ -32,18 +32,18 @@ abstract class Text
 
        redef type OTHER: Text
 
-       # Type of the view on self (.chars)
-       type SELFVIEW: StringCharView
-
        # Type of self (used for factorization of several methods, ex : substring_from, empty...)
        type SELFTYPE: Text
 
-       var hash_cache: nullable Int = null
-
        # Gets a view on the chars of the Text object
-       fun chars: SELFVIEW is abstract
+       #
+       #     assert "hello".chars.to_a == ['h', 'e', 'l', 'l', 'o']
+       fun chars: SequenceRead[Char] is abstract
 
        # Number of characters contained in self.
+       #
+       #     assert "12345".length == 5
+       #     assert "".length == 0
        fun length: Int is abstract
 
        # Create a substring.
@@ -59,18 +59,29 @@ abstract class Text
        fun substring(from: Int, count: Int): SELFTYPE is abstract
 
        # Concatenates `o` to `self`
+       #
+       #     assert "hello" + "world"  == "helloworld"
+       #     assert "" + "hello" + ""  == "hello"
        fun +(o: Text): SELFTYPE is abstract
 
        # Auto-concatenates self `i` times
+       #
+       #     assert "abc" * 4 == "abcabcabcabc"
+       #     assert "abc" * 1 == "abc"
+       #     assert "abc" * 0 == ""
        fun *(i: Int): SELFTYPE is abstract
 
        # Is the current Text empty (== "")
-       #       assert "".is_empty
-       #       assert not "foo".is_empty
+       #
+       #     assert "".is_empty
+       #     assert not "foo".is_empty
        fun is_empty: Bool do return self.length == 0
 
        # Returns an empty Text of the right type
-       fun empty: SELFTYPE is abstract
+       #
+       # This method is used internally to get the right
+       # implementation of an empty string.
+       protected fun empty: SELFTYPE is abstract
 
        # Gets the first char of the Text
        #
@@ -127,9 +138,10 @@ abstract class Text
        fun to_cstring: NativeString do return flatten.to_cstring
 
        # The index of the last occurrence of an element starting from pos (in reverse order).
-       # Example :
-       #               assert "/etc/bin/test/test.nit".last_index_of_from('/', length-1) == 13
-       #               assert "/etc/bin/test/test.nit".last_index_of_from('/', 12) == 8
+       #
+       #     var s = "/etc/bin/test/test.nit"
+       #     assert s.last_index_of_from('/', s.length-1) == 13
+       #     assert s.last_index_of_from('/', 12)         == 8
        #
        # Returns -1 if not found
        #
@@ -180,6 +192,10 @@ abstract class Text
        end
 
        # Returns a reversed version of self
+       #
+       #     assert "hello".reversed  == "olleh"
+       #     assert "bob".reversed    == "bob"
+       #     assert "".reversed       == ""
        fun reversed: SELFTYPE is abstract
 
        # Does self have a substring `str` starting from position `pos`?
@@ -189,7 +205,7 @@ abstract class Text
        fun has_substring(str: String, pos: Int): Bool
        do
                var myiter = self.chars.iterator_from(pos)
-               var itsiter = str.iterator
+               var itsiter = str.chars.iterator
                while myiter.is_ok and itsiter.is_ok do
                        if myiter.item != itsiter.item then return false
                        myiter.next
@@ -234,6 +250,8 @@ abstract class Text
        end
 
        # If `self` contains only digits and alpha <= 'f', return the corresponding integer.
+       #
+       #     assert "ff".to_hex == 255
        fun to_hex: Int do return a_to(16)
 
        # If `self` contains only digits and letters, return the corresponding integer in a given base
@@ -301,6 +319,10 @@ abstract class Text
        fun to_lower : SELFTYPE is abstract
 
        # Removes the whitespaces at the beginning of self
+       #
+       #     assert " \n\thello \n\t".l_trim == "hello \n\t"
+       #
+       # A whitespace is defined as any character which ascii value is less than or equal to 32
        fun l_trim: SELFTYPE
        do
                var iter = self.chars.iterator
@@ -313,6 +335,10 @@ abstract class Text
        end
 
        # Removes the whitespaces at the end of self
+       #
+       #     assert " \n\thello \n\t".r_trim == " \n\thello"
+       #
+       # A whitespace is defined as any character which ascii value is less than or equal to 32
        fun r_trim: SELFTYPE
        do
                var iter = self.chars.reverse_iterator
@@ -396,7 +422,7 @@ abstract class Text
        fun escape_more_to_c(chars: String): String
        do
                var b = new FlatBuffer
-               for c in escape_to_c do
+               for c in escape_to_c.chars do
                        if chars.chars.has(c) then
                                b.add('\\')
                        end
@@ -405,24 +431,23 @@ abstract class Text
                return b.to_s
        end
 
-       # Escape to c plus braces
+       # Escape to C plus braces
        #
        #     assert "\n\"'\\\{\}".escape_to_nit      == "\\n\\\"\\'\\\\\\\{\\\}"
        fun escape_to_nit: String do return escape_more_to_c("\{\}")
 
        # Return a string where Nit escape sequences are transformed.
        #
-       # Example:
        #     var s = "\\n"
        #     assert s.length        ==  2
        #     var u = s.unescape_nit
        #     assert u.length        ==  1
-       #     assert u[0].ascii      ==  10 # (the ASCII value of the "new line" character)
+       #     assert u.chars[0].ascii      ==  10 # (the ASCII value of the "new line" character)
        fun unescape_nit: String
        do
                var res = new FlatBuffer.with_capacity(self.length)
                var was_slash = false
-               for c in self do
+               for c in chars do
                        if not was_slash then
                                if c == '\\' then
                                        was_slash = true
@@ -447,6 +472,22 @@ abstract class Text
                return res.to_s
        end
 
+       # Equality of text
+       # Two pieces of text are equals if thez have the same characters in the same order.
+       #
+       #     assert "hello" == "hello"
+       #     assert "hello" != "HELLO"
+       #     assert "hello" == "hel"+"lo"
+       #
+       # Things that are not Text are not equal.
+       #
+       #     assert "9" != '9'
+       #     assert "9" != ['9']
+       #     assert "9" != 9
+       #
+       #     assert "9".chars.first == '9'   # equality of Char
+       #     assert "9".chars       == ['9'] # equality of Sequence
+       #     assert "9".to_i        == 9     # equality of Int
        redef fun ==(o)
        do
                if o == null then return false
@@ -456,14 +497,34 @@ abstract class Text
                return self.chars == o.chars
        end
 
-       redef fun <(o)
+       # Lexicographical comparaison
+       #
+       #     assert "abc" < "xy"
+       #     assert "ABC" < "abc"
+       redef fun <(other)
        do
-               return self.chars < o.chars
+               var self_chars = self.chars.iterator
+               var other_chars = other.chars.iterator
+
+               while self_chars.is_ok and other_chars.is_ok do
+                       if self_chars.item < other_chars.item then return true
+                       if self_chars.item > other_chars.item then return false
+                       self_chars.next
+                       other_chars.next
+               end
+
+               if self_chars.is_ok then
+                       return false
+               else
+                       return true
+               end
        end
 
        # Flat representation of self
        fun flatten: FlatText is abstract
 
+       private var hash_cache: nullable Int = null
+
        redef fun hash
        do
                if hash_cache == null then
@@ -510,14 +571,11 @@ end
 
 # Abstract class for the SequenceRead compatible
 # views on String and Buffer objects
-abstract class StringCharView
+private abstract class StringCharView
        super SequenceRead[Char]
-       super Comparable
 
        type SELFTYPE: Text
 
-       redef type OTHER: StringCharView
-
        private var target: SELFTYPE
 
        private init(tgt: SELFTYPE)
@@ -531,85 +589,12 @@ abstract class StringCharView
 
        redef fun iterator: IndexedIterator[Char] do return self.iterator_from(0)
 
-       # Gets a new Iterator starting at position `pos`
-       #
-       # Ex :
-       #       var iter = "abcd".iterator_from(2)
-       #       while iter.is_ok do
-       #               printn iter.item
-       #               iter.next
-       #       end
-       #
-       # Outputs : cd
-       fun iterator_from(pos: Int): IndexedIterator[Char] is abstract
-
-       # Gets an iterator starting at the end and going backwards
-       #
-       # Ex :
-       #       var reviter = "now step live...".reverse_iterator
-       #       while reviter.is_ok do
-       #               printn reviter.item
-       #               reviter.next
-       #       end
-       #
-       # Outputs : ...evil pets won
-       fun reverse_iterator: IndexedIterator[Char] do return self.reverse_iterator_from(self.length - 1)
-
-       # Gets an iterator on the chars of self starting from `pos`
-       #
-       # Ex :
-       #       var iter = "abcd".reverse_iterator_from(1)
-       #       while iter.is_ok do
-       #               printn iter.item
-       #               iter.next
-       #       end
-       #
-       # Outputs : ba
-       fun reverse_iterator_from(pos: Int): IndexedIterator[Char] is abstract
-
-       redef fun has(c: Char): Bool
-       do
-               for i in self do
-                       if i == c then return true
-               end
-               return false
-       end
-
-       redef fun ==(other)
-       do
-               if other == null then return false
-               if not other isa StringCharView then return false
-               var other_chars = other.iterator
-               for i in self do
-                       if i != other_chars.item then return false
-                       other_chars.next
-               end
-               return true
-       end
-
-       redef fun <(other)
-       do
-               var self_chars = self.iterator
-               var other_chars = other.iterator
-
-               while self_chars.is_ok and other_chars.is_ok do
-                       if self_chars.item < other_chars.item then return true
-                       if self_chars.item > other_chars.item then return false
-                       self_chars.next
-                       other_chars.next
-               end
-
-               if self_chars.is_ok then
-                       return false
-               else
-                       return true
-               end
-       end
+       redef fun reverse_iterator do return self.reverse_iterator_from(self.length - 1)
 end
 
 # View on Buffer objects, extends Sequence
 # for mutation operations
-abstract class BufferCharView
+private abstract class BufferCharView
        super StringCharView
        super Sequence[Char]
 
@@ -639,29 +624,23 @@ class FlatString
        # Indes in _items of the last item of the string
        private var index_to: Int
 
-       redef var chars: SELFVIEW = new FlatStringCharView(self)
+       redef var chars: SequenceRead[Char] = new FlatStringCharView(self)
 
        ################################################
        #       AbstractString specific methods        #
        ################################################
 
-       redef fun [](index) do
-               assert index >= 0
-               # Check that the index (+ index_from) is not larger than indexTo
-               # In other terms, if the index is valid
-               assert (index + index_from) <= index_to
-               return items[index + index_from]
-       end
-
        redef fun reversed
        do
                var native = calloc_string(self.length + 1)
-               var reviter = chars.reverse_iterator
+               var length = self.length
+               var items = self.items
                var pos = 0
-               while reviter.is_ok do
-                       native[pos] = reviter.item
+               var ipos = length-1
+               while pos < length do
+                       native[pos] = items[ipos]
                        pos += 1
-                       reviter.next
+                       ipos -= 1
                end
                return native.to_s_with_length(self.length)
        end
@@ -751,7 +730,6 @@ class FlatString
                index_to = to
        end
 
-       # Return a null terminated char *
        redef fun to_cstring: NativeString
        do
                if real_items != null then return real_items.as(not null)
@@ -792,9 +770,6 @@ class FlatString
                return true
        end
 
-       # The comparison between two strings is done on a lexicographical basis
-       #
-       #     assert ("aa" < "b")      ==  true
        redef fun <(other)
        do
                if not other isa FlatString then return super
@@ -831,9 +806,6 @@ class FlatString
                return my_length < its_length
        end
 
-       # The concatenation of `self` with `s`
-       #
-       #     assert "hello " + "world!"         == "hello world!"
        redef fun +(s)
        do
                var my_length = self.length
@@ -861,9 +833,6 @@ class FlatString
                return target_string.to_s_with_length(total_length)
        end
 
-       #     assert "abc"*3           == "abcabcabc"
-       #     assert "abc"*1           == "abc"
-       #     assert "abc"*0           == ""
        redef fun *(i)
        do
                assert i >= 0
@@ -974,6 +943,7 @@ private class FlatStringCharView
                # Check that the index (+ index_from) is not larger than indexTo
                # In other terms, if the index is valid
                assert index >= 0
+               var target = self.target
                assert (index + target.index_from) <= target.index_to
                return target.items[index + target.index_from]
        end
@@ -987,10 +957,10 @@ end
 abstract class Buffer
        super Text
 
-       redef type SELFVIEW: BufferCharView
        redef type SELFTYPE: Buffer
 
-       var is_dirty = true
+       # Specific implementations MUST set this to `true` in order to invalidate caches
+       protected var is_dirty = true
 
        # Modifies the char contained at pos `index`
        #
@@ -1003,12 +973,23 @@ abstract class Buffer
        fun add(c: Char) is abstract
 
        # Clears the buffer
+       #
+       #     var b = new FlatBuffer
+       #     b.append "hello"
+       #     assert not b.is_empty
+       #     b.clear
+       #     assert b.is_empty
        fun clear is abstract
 
        # Enlarges the subsequent array containing the chars of self
        fun enlarge(cap: Int) is abstract
 
        # Adds the content of text `s` at the end of self
+       #
+       #     var b = new FlatBuffer
+       #     b.append "hello"
+       #     b.append "world"
+       #     assert b == "helloworld"
        fun append(s: Text) is abstract
 
        redef fun hash
@@ -1017,6 +998,9 @@ abstract class Buffer
                return super
        end
 
+       # In Buffers, the internal sequence of character is mutable
+       # Thus, `chars` can be used to modify the buffer.
+       redef fun chars: Sequence[Char] is abstract
 end
 
 # Mutable strings of characters.
@@ -1026,9 +1010,9 @@ class FlatBuffer
 
        redef type SELFTYPE: FlatBuffer
 
-       redef var chars: SELFVIEW = new FlatBufferCharView(self)
+       redef var chars: Sequence[Char] = new FlatBufferCharView(self)
 
-       var capacity: Int
+       private var capacity: Int
 
        redef fun []=(index, item)
        do
@@ -1343,7 +1327,7 @@ end
 redef class Int
        # Fill `s` with the digits in base `base` of `self` (and with the '-' sign if 'signed' and negative).
        # assume < to_c max const of char
-       fun fill_buffer(s: Buffer, base: Int, signed: Bool)
+       private fun fill_buffer(s: Buffer, base: Int, signed: Bool)
        do
                var n: Int
                # Sign
@@ -1377,7 +1361,10 @@ redef class Int
                return native_int_to_s(len).to_s_with_length(len)
        end
 
-       # return displayable int in hexadecimal (unsigned (not now))
+       # return displayable int in hexadecimal
+       #
+       #     assert 1.to_hex  == "1"
+       #     assert (-255).to_hex  == "-ff"
        fun to_hex: String do return to_base(16,false)
 
        # return displayable int in base base and signed
@@ -1392,6 +1379,11 @@ end
 
 redef class Float
        # Pretty print self, print needoed decimals up to a max of 3.
+       #
+       #     assert 12.34.to_s        == "12.34"
+       #     assert (-0120.03450).to_s  == "-120.035"
+       #
+       # see `to_precision` for a different precision.
        redef fun to_s do
                var str = to_precision( 3 )
                if is_inf != 0 or is_nan then return str
@@ -1411,6 +1403,11 @@ redef class Float
        end
 
        # `self` representation with `nb` digits after the '.'.
+       #
+       #     assert 12.345.to_precision(1) == "12.3"
+       #     assert 12.345.to_precision(2) == "12.35"
+       #     assert 12.345.to_precision(3) == "12.345"
+       #     assert 12.345.to_precision(4) == "12.3450"
        fun to_precision(nb: Int): String
        do
                if is_nan then return "nan"
@@ -1443,6 +1440,12 @@ redef class Float
                end
        end
 
+       # `self` representation with `nb` digits after the '.'.
+       #
+       #     assert 12.345.to_precision_native(1) == "12.3"
+       #     assert 12.345.to_precision_native(2) == "12.35"
+       #     assert 12.345.to_precision_native(3) == "12.345"
+       #     assert 12.345.to_precision_native(4) == "12.3450"
        fun to_precision_native(nb: Int): String import NativeString.to_s `{
                int size;
                char *str;
@@ -1465,27 +1468,37 @@ redef class Char
        end
 
        # Returns true if the char is a numerical digit
+       #
+       #      assert '0'.is_numeric
+       #      assert '9'.is_numeric
+       #      assert not 'a'.is_numeric
+       #      assert not '?'.is_numeric
        fun is_numeric: Bool
        do
-               if self >= '0' and self <= '9'
-               then
-                       return true
-               end
-               return false
+               return self >= '0' and self <= '9'
        end
 
        # Returns true if the char is an alpha digit
+       #
+       #      assert 'a'.is_alpha
+       #      assert 'Z'.is_alpha
+       #      assert not '0'.is_alpha
+       #      assert not '?'.is_alpha
        fun is_alpha: Bool
        do
-               if (self >= 'a' and self <= 'z') or (self >= 'A' and self <= 'Z') then return true
-               return false
+               return (self >= 'a' and self <= 'z') or (self >= 'A' and self <= 'Z')
        end
 
        # Returns true if the char is an alpha or a numeric digit
+       #
+       #      assert 'a'.is_alphanumeric
+       #      assert 'Z'.is_alphanumeric
+       #      assert '0'.is_alphanumeric
+       #      assert '9'.is_alphanumeric
+       #      assert not '?'.is_alphanumeric
        fun is_alphanumeric: Bool
        do
-               if self.is_numeric or self.is_alpha then return true
-               return false
+               return self.is_numeric or self.is_alpha
        end
 end
 
index a73bab5..08befc6 100644 (file)
@@ -639,7 +639,7 @@ class Debugger
        # Processes an array print command
        fun process_array_command(parts_of_command: Array[String])
        do
-               var index_of_first_brace = parts_of_command[1].index_of('[')
+               var index_of_first_brace = parts_of_command[1].chars.index_of('[')
                var variable_name = get_real_variable_name(parts_of_command[1].substring(0,index_of_first_brace))
                var braces = parts_of_command[1].substring_from(index_of_first_brace)
 
@@ -1095,8 +1095,8 @@ class Debugger
        # Returns an array containing all the indexes demanded
        fun process_index(index_string: String): nullable Array[Int]
        do
-               var from_end_index = index_string.index_of('.')
-               var to_start_index = index_string.last_index_of('.')
+               var from_end_index = index_string.chars.index_of('.')
+               var to_start_index = index_string.chars.last_index_of('.')
 
                if from_end_index != -1 and to_start_index != -1 then
                        var index_from_string = index_string.substring(0,from_end_index)
index 34b5c28..2d1dc58 100644 (file)
@@ -120,7 +120,7 @@ redef class ModelBuilder
                                        error(nfd, "Error: A formal parameter type `{ptname}' already exists")
                                        return
                                end
-                               for c in ptname do if c >= 'a' and c<= 'z' then
+                               for c in ptname.chars do if c >= 'a' and c<= 'z' then
                                        warning(nfd, "Warning: lowercase in the formal parameter type {ptname}")
                                        break
                                end
index 9667d77..9425fcf 100644 (file)
@@ -934,7 +934,7 @@ redef class ATypePropdef
                if mprop == null then
                        var mvisibility = new_property_visibility(modelbuilder, nclassdef, self.n_visibility)
                        mprop = new MVirtualTypeProp(mclassdef, name, mvisibility)
-                       for c in name do if c >= 'a' and c<= 'z' then
+                       for c in name.chars do if c >= 'a' and c<= 'z' then
                                modelbuilder.warning(n_id, "Warning: lowercase in the virtual type {name}")
                                break
                        end
index 4715068..abcc91f 100644 (file)
@@ -1785,7 +1785,7 @@ redef class ADoc
                for t in n_comment do
                        var text = t.text
                        text = text.substring_from(1)
-                       if text.first == ' ' then text = text.substring_from(1)
+                       if text.chars.first == ' ' then text = text.substring_from(1)
                        res.append(text.html_escape)
                end
                var str = res.to_s
index 69f64f3..896b579 100644 (file)
@@ -45,7 +45,7 @@ redef class MMethod
                if nit_name == ">>" then return "_right"
                if nit_name == "<=>" then return "_starship"
 
-               if nit_name.last == '=' then return "{nit_name.substring(0, nit_name.length-1)}__assign"
+               if nit_name.chars.last == '=' then return "{nit_name.substring(0, nit_name.length-1)}__assign"
                return nit_name
        end
 end
index 73ce377..f565f56 100644 (file)
@@ -135,7 +135,7 @@ private class SerializationPhase
 
                for nclassdef in nclassdefs do
                        var name = nclassdef.n_id.text
-                       if not name.has('[') then # FIXME this is a temporary hack
+                       if not name.chars.has('[') then # FIXME this is a temporary hack
                                code.add "              if name == \"{name}\" then return new {name}.from_deserializer(self)"
                        end
                end
index ceec37d..aa06403 100644 (file)
@@ -31,8 +31,8 @@ for v in col do print v
 
 # ok
 var map = new MapIterable
-map.map["Riri"] = "Riri".to_a
-map.map["Fifi"] = "Fifi".to_a
-map.map["Loulou"] = "Loulou".to_a
+map.map["Riri"] = "Riri".chars.to_a
+map.map["Fifi"] = "Fifi".chars.to_a
+map.map["Loulou"] = "Loulou".chars.to_a
 for k, v in map do print "{k}: {v.join(",")}"