1# Copyright 2001, 2002 Dave Abrahams
2# Copyright 2002, 2003 Vladimir Prus
3# Distributed under the Boost Software License, Version 1.0.
4# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
5
6import errors ;
7
8
9rule trim-leading-zeroes ( value )
10{
11    return [ CALC $(value) + 0 ] ;
12}
13
14
15rule check ( numbers * )
16{
17    for local n in $(numbers)
18    {
19        switch $(n)
20        {
21            case *[^0-9]* :
22                errors.error $(n) "in" $(numbers) : is not a number ;
23        }
24    }
25}
26
27
28rule increment ( number )
29{
30    return [ CALC $(number) + 1 ] ;
31}
32
33
34rule decrement ( number )
35{
36    return [ CALC $(number) - 1 ] ;
37}
38
39
40rule range ( start finish ? : step ? )
41{
42    if ! $(finish)
43    {
44        finish = $(start) ;
45        start = 1 ;
46    }
47    step ?= 1 ;
48
49    check $(start) $(finish) $(step) ;
50
51    if $(finish) != 0
52    {
53        local result ;
54        while [ less $(start) $(finish) ] || $(start) = $(finish)
55        {
56            result += $(start) ;
57            start = [ CALC $(start) + $(step) ] ;
58        }
59        return $(result) ;
60    }
61}
62
63
64rule less ( n1 n2 )
65{
66    switch [ CALC $(n2) - $(n1) ]
67    {
68        case [1-9]* : return true ;
69    }
70}
71
72
73rule log10 ( number )
74{
75    switch $(number)
76    {
77        case *[^0-9]* : errors.error $(number) is not a number ;
78        case 0 : errors.error can't take log of zero ;
79        case [1-9] : return 0 ;
80        case [1-9]? : return 1 ;
81        case [1-9]?? : return 2 ;
82        case [1-9]??? : return 3 ;
83        case [1-9]???? : return 4 ;
84        case [1-9]????? : return 5 ;
85        case [1-9]?????? : return 6 ;
86        case [1-9]??????? : return 7 ;
87        case [1-9]???????? : return 8 ;
88        case [1-9]????????? : return 9 ;
89        case * :
90        {
91            import sequence ;
92            import string ;
93            local chars = [ string.chars $(number) ] ;
94            while $(chars[1]) = 0
95            {
96                chars = $(chars[2-]) ;
97            }
98            if ! $(chars)
99            {
100                errors.error can't take log of zero ;
101            }
102            else
103            {
104                return [ decrement [ sequence.length $(chars) ] ] ;
105            }
106        }
107    }
108}
109
110
111rule __test__ ( )
112{
113    import assert ;
114
115    assert.result 1 : increment 0 ;
116    assert.result 2 : increment 1 ;
117    assert.result 1 : decrement 2 ;
118    assert.result 0 : decrement 1 ;
119    assert.result 50 : increment 49 ;
120    assert.result 49 : decrement 50 ;
121    assert.result 99 : increment 98 ;
122    assert.result 99 : decrement 100 ;
123    assert.result 100 : increment 99 ;
124    assert.result 999 : decrement 1000 ;
125    assert.result 1000 : increment 999 ;
126
127    assert.result 1 2 3 : range 3 ;
128    assert.result 1 2 3 4 5 6 7 8 9 10 11 12 : range 12 ;
129    assert.result 3 4 5 6 7 8 9 10 11 : range 3 11 ;
130    assert.result : range 0 ;
131    assert.result 1 4 7 10 : range 10 : 3 ;
132    assert.result 2 4 6 8 10 : range 2 10 : 2 ;
133    assert.result 25 50 75 100 : range 25 100 : 25 ;
134
135    assert.result 0           : trim-leading-zeroes 0           ;
136    assert.result 1234        : trim-leading-zeroes 1234        ;
137    assert.result 123456      : trim-leading-zeroes 0000123456  ;
138    assert.result 1000123456  : trim-leading-zeroes 1000123456  ;
139    assert.result 10000       : trim-leading-zeroes 10000       ;
140    assert.result 10000       : trim-leading-zeroes 00010000    ;
141
142    assert.true  less 1 2 ;
143    assert.true  less 1 12 ;
144    assert.true  less 1 21 ;
145    assert.true  less 005 217 ;
146    assert.false less 0 0 ;
147    assert.false less 03 3 ;
148    assert.false less 3 03 ;
149    assert.true  less 005 217 ;
150    assert.true  less 0005 217 ;
151    assert.true  less 5 00217 ;
152
153    # TEMPORARY disabled, because nested "try"/"catch" do not work and I do no
154    # have the time to fix that right now.
155    if $(0)
156    {
157    try ;
158    {
159        decrement 0 ;
160    }
161    catch can't decrement zero! ;
162
163    try ;
164    {
165        check foo ;
166    }
167    catch : not a number ;
168
169    try ;
170    {
171        increment foo ;
172    }
173    catch : not a number ;
174
175    try ;
176    {
177        log10 0 ;
178    }
179    catch can't take log of zero ;
180
181    try ;
182    {
183        log10 000 ;
184    }
185    catch can't take log of zero ;
186
187    }
188
189    assert.result 0 : log10 1 ;
190    assert.result 0 : log10 9 ;
191    assert.result 1 : log10 10 ;
192    assert.result 1 : log10 99 ;
193    assert.result 2 : log10 100 ;
194    assert.result 2 : log10 101 ;
195    assert.result 2 : log10 125 ;
196    assert.result 2 : log10 999 ;
197    assert.result 3 : log10 1000 ;
198    assert.result 10 : log10 12345678901 ;
199
200    for local x in [ range 75 110 : 5 ]
201    {
202        for local y in [ range $(x) 111 : 3 ]
203        {
204            if $(x) != $(y)
205            {
206                assert.true less $(x) $(y) ;
207            }
208        }
209    }
210
211    for local x in [ range 90 110 : 2 ]
212    {
213        for local y in [ range 80 $(x) : 4 ]
214        {
215            assert.false less $(x) $(y) ;
216        }
217    }
218}
219