PreviousUpNext

15.4.1337  src/lib/x-kit/tut/calculator/accumulator.pkg

## accumulator.pkg

# Compiled by:
#     src/lib/x-kit/tut/calculator/calculator-app.lib


# The accumulator of the calculator.

#DO set_control "compiler::trap_int_overflow" "TRUE";


stipulate
    include threadkit;                                  # threadkit     is from   src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg
    #
    package xtr =  xlogger;                             # xlogger       is from   src/lib/x-kit/xclient/src/stuff/xlogger.pkg
    #
    trace       =  xtr::log_if  xtr::io_logging 0;      # Conditionally write strings to tracing.log or whatever.
        #
        # To debug via tracelogging, annotate the code with lines like
        #
        #       trace .{ sprintf "foo/top: bar d=%d" bar; };
        #
herein

    package   accumulator
    :         Accumulator                               # Accumulator   is from   src/lib/x-kit/tut/calculator/accumulator.api
    {
        Op_T = PLUS | MINUS | DIVIDE | TIMES;
        Plea_Mail = OP Op_T | CLEAR | EQUAL | DIGIT Int;
        Out_Val = OVAL Int | OINFINITY | OOVERFLOW;

        Accumulator = ACCUMULATOR (Mailslot(Plea_Mail), Mailslot(Out_Val) );

        fun math_op_of PLUS   => int::(+);
            math_op_of MINUS  => int::(-);
            math_op_of TIMES  => int::(*);
            math_op_of DIVIDE => int::(/);
        end;

        fun op_to_string PLUS   => "+";
            op_to_string MINUS  => "-";
            op_to_string TIMES  => "*";
            op_to_string DIVIDE => "/";
        end;

        fun make_accumulator ()
            =
            {
                plea_slot   =  make_mailslot ();
                result_slot =  make_mailslot ();

                fun get_plea ()  =  take_from_mailslot  plea_slot;

                # We use these three functions to
                # update the value displayed in the
                # GUI number window:
                #
                fun display v           =  put_in_mailslot (result_slot, OVAL v);
                fun display_infinity () =  put_in_mailslot (result_slot, OINFINITY);
                fun display_overflow () =  put_in_mailslot (result_slot, OOVERFLOW);


                fun add_digit_to_operand (operand, digit)
                    =
                    {   operand = 10*operand + digit;
                        #
                        display operand;
                        operand;
                    }
                    except OVERFLOW = operand;

                fun do_err DIVIDE_BY_ZERO =>  display_infinity ();
                    do_err OVERFLOW       =>  display_overflow ();
                    do_err a              =>  raise exception a;
                end;


                # We have four major states:
                #
                #    Reading_First_Digit_Of_First_Operand
                #    Reading_Rest_Of_First_Operand
                #    Reading_First_Digit_Of_Second_Operand
                #    Reading_Rest_Of_Second_Operand
                #
                # We represent these states with one loop fn each,
                # and implement transitions between the
                # states via calls from one to another.

                fun read_first_digit_of_first_operand ()
                    =
                    {   
                        case (get_plea ())
                            #
                            OP op => {
                                       read_first_digit_of_first_operand ();
                                     };
                            CLEAR => {
                                       do_clear   ();
                                     };
                            EQUAL => {
                                       read_first_digit_of_first_operand ();
                                     }; 
                            DIGIT digit => {
                                       display digit;
                                       read_rest_of_first_operand  digit;
                                     };
                        esac;
                    }

                also
                fun read_rest_of_first_operand  first_operand
                    =
                    {
                        case (get_plea ())
                            #
                            OP operator => {
                                            read_first_digit_of_second_operand (first_operand, operator);
                                           };
                            CLEAR       => {
                                            do_clear ();
                                           };
                            EQUAL       => {
                                            read_first_digit_of_first_operand ();
                                           };
                            DIGIT digit => {
                                            read_rest_of_first_operand (add_digit_to_operand (first_operand, digit));
                                           };
                         esac;
                    }

                also
                fun read_first_digit_of_second_operand (first_operand, operator)
                    =
                    {
                        display 0;

                        case (get_plea ())
                            #
                            OP operator => {
                                            read_first_digit_of_second_operand (first_operand, operator);
                                           };
                            CLEAR       => {
                                            do_clear ();
                                           };
                            EQUAL       => {
                                             read_first_digit_of_first_operand ();
                                           };   
                            DIGIT digit => {
                                             display digit;
                                             read_rest_of_second_operand (first_operand, operator, digit);
                                           };
                         esac;
                    }

                also
                fun read_rest_of_second_operand (first_operand, operator, second_operand)
                    =
                    {
                        case (get_plea ())
                            #
                            CLEAR       => {
                                            do_clear ();
                                           };
                            EQUAL       => {
                                            do_equal (first_operand, operator, second_operand);
                                           };
                            DIGIT digit => {
                                            read_rest_of_second_operand (first_operand, operator, add_digit_to_operand (second_operand, digit));
                                           };
                            #
                            OP operator'
                                =>
                                {
                                    result = (math_op_of operator) (first_operand, second_operand);
                                    #
                                    display result;
                                    read_first_digit_of_second_operand (result, operator');
                                }
                                except
                                    err = {   do_err err;
                                              read_first_digit_of_first_operand ();
                                          };
                        esac;
                    }

                also
                fun do_clear ()
                    =
                    {   display 0;
                        read_first_digit_of_first_operand ();
                    }

                also
                fun do_equal (first_operand, operator, second_operand)
                    =
                    {   {   math_op = (math_op_of  operator);
                            result        = math_op (first_operand, second_operand);
                            display result;
                        }
                        except
                            err = do_err err;

                        read_first_digit_of_first_operand ();
                    };


                make_thread "accumulator"  read_first_digit_of_first_operand;

                ACCUMULATOR (plea_slot, result_slot);
            };

        fun send_to_accumulator  (ACCUMULATOR (plea_slot, _))  msg
            =
            put_in_mailslot (plea_slot, msg);

        fun from_accumulator_mailop_of (ACCUMULATOR(_, result_slot))
            =
            take_from_mailslot' result_slot;

    };                                  # package accumulator 
end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext