:- module fib.

:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.

:- implementation.
:- import_module int, list, string.

:- pred fib1(int::in, int::out) is det.
:- func fib2(int) = int.
:- func fib3(int) = int.

fib1(N, X) :-
    (  if   N =< 2
       then X = 1
       else fib1(N - 1, A), fib1(N - 2, B), X = A + B
    ).
    
fib2(N) = X :-
    (  if   N =< 2
       then X = 1
       else X = fib2(N - 1) + fib2(N - 2)
    ).
    
fib3(N) = ( if N =< 2 then 1 else fib3(N - 1) + fib3(N - 2) ).
    
main(!IO) :-
    io.write_string("Enter an integer: ", !IO),
    io.read_line_as_string(Result, !IO),
    (  
       Result = eof,
       io.nl(!IO)
    ;
       Result = ok(String),
       (   if
               string.to_int(string.strip(String), N)
           then
               fib1(N, X),
               io.format("fib1(%d, %d)\n", [i(N), i(X)], !IO),
               io.format("fib2(%d) = %d\n", [i(N), i(fib2(N))], !IO),
               io.format("fib3(%d) = %d\n", [i(N), i(fib3(N))], !IO)
           else
               io.write_string("That isn't a number!\n", !IO)
        ),
        main(!IO)
    ;
        Result = error(ErrorCode),
        io.format("%s\n", [s(io.error_message(ErrorCode))], !IO)
    ).

