Merge branch 'ht/newline-before-EOF' into maint
[shapes.git] / examples / features / error.shape
blobbdeb64cec00e546fd53ef9ffaa2ec66f49b6dfe3
1 /** This file is part of Shapes.
2  **
3  ** Shapes is free software: you can redistribute it and/or modify
4  ** it under the terms of the GNU General Public License as published by
5  ** the Free Software Foundation, either version 3 of the License, or
6  ** any later version.
7  **
8  ** Shapes is distributed in the hope that it will be useful,
9  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
10  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  ** GNU General Public License for more details.
12  **
13  ** You should have received a copy of the GNU General Public License
14  ** along with Shapes.  If not, see <http://www.gnu.org/licenses/>.
15  **
16  ** Copyright 2009, 2010 Henrik Tidefelt
17  **/
19 /** Define some function that uses the error mechanism to report bad input.
20  **
21  ** (To make it simple we avoid a helper function, but this will clearly
22  ** lead to a performance loss since the type and range of the argument will
23  ** be checked over and over again.)
24  **
25  ** By not using cond to check for the error conditions, it becomes clearer
26  ** what is error-checking and what is normal evaluation.
27  **/
28 factorial: \ i →
29   {
30     ![if [typeof i] ≠ §Integer
31          [error 'type_mismatch VARNAME §Integer.name (indexof i) i]]
32     ![if i < '0
33          [error 'out_of_range VARNAME `The factorial is not defined for negative values.´ (indexof i)]]
34     [if i = '0
35         '1
36         i * [factorial i-'1]]
37   }
39 /** Define a new function, which captures and handles one of the errors that factorial may report.
40  ** The implementation follows a pattern, so it can be learned even if it cannot be abstracted away
41  ** in a function.
42  **/
43 ext_factorial: \ i →
44   (escape_continuation return
45     (escape_continuation error
46       (escape_continue return
47         [factorial i]))
48     >>
49     \ ball →
50       [cond [cons ball.kind = 'out_of_range
51                   '~1]
52             [cons ball.kind = 'dtmin
53                   [error 'misc VARNAME `Why on earth did we get a dtmin error here?!´]]
54             [cons true
55                   (escape_continue error ball)]])
57 /** Try the new function!
58  **/
59 •stdout << [ext_factorial '10] << "{n}
60 •stdout << [ext_factorial '~10] << "{n}
62 /** But don't do this, since the type mismatch error will be re-thrown by ext_factorial:
63  **/
64 |**•stdout << [ext_factorial 10] << "{n}
66 /** Prevent empty output error. **/
67 @spot