11/*
2- This example extends on features0 but demonstrates how to define a class.
2+ This example extends on features0 but demonstrates how to define a class,
3+ and a custom exception.
34
45 The Factorial class constructor takes an integer, and then the calculate
56 method can be called to get the factorial.
89 >>> f = features4.Factorial(4)
910 >>> f.calculate()
1011 24
12+
13+ If the argument to the Factorial class constructor is less than zero, a
14+ FactorialError is raised.
1115*/
1216
1317// Include the header file to get access to the MicroPython API
@@ -22,6 +26,8 @@ typedef struct {
2226 mp_int_t n ;
2327} mp_obj_factorial_t ;
2428
29+ mp_obj_full_type_t mp_type_FactorialError ;
30+
2531// Essentially Factorial.__new__ (but also kind of __init__).
2632// Takes a single argument (the number to find the factorial of)
2733static mp_obj_t factorial_make_new (const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * args_in ) {
@@ -30,6 +36,10 @@ static mp_obj_t factorial_make_new(const mp_obj_type_t *type, size_t n_args, siz
3036 mp_obj_factorial_t * o = mp_obj_malloc (mp_obj_factorial_t , type );
3137 o -> n = mp_obj_get_int (args_in [0 ]);
3238
39+ if (o -> n < 0 ) {
40+ mp_raise_msg ((mp_obj_type_t * )& mp_type_FactorialError , "argument must be zero or above" );
41+ }
42+
3343 return MP_OBJ_FROM_PTR (o );
3444}
3545
@@ -68,6 +78,12 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
6878 // Make the Factorial type available on the module.
6979 mp_store_global (MP_QSTR_Factorial , MP_OBJ_FROM_PTR (& mp_type_factorial ));
7080
81+ // Initialise the exception type.
82+ mp_obj_exception_init (& mp_type_FactorialError , MP_QSTR_FactorialError , & mp_type_Exception );
83+
84+ // Make the FactorialError type available on the module.
85+ mp_store_global (MP_QSTR_FactorialError , MP_OBJ_FROM_PTR (& mp_type_FactorialError ));
86+
7187 // This must be last, it restores the globals dict
7288 MP_DYNRUNTIME_INIT_EXIT
7389}
0 commit comments