open Bogue module W = Widget module L = Layout let calculator () = let stack = Stack.create () in Stack.push "0" stack ; let stack_show () = Stack.fold (fun acc number -> number ^ " " ^ acc) "" stack in let display = W.label "" in let update_display () = W.set_text display (stack_show ()) in let digit_pressed digit = match Stack.pop stack with | "0" -> Stack.push digit stack ; | number -> Stack.push (number ^ digit) stack ; update_display () in let push_clicked _ = Stack.push "0" stack ; update_display () in let swap_clicked _ = match Stack.length stack with | n when n >= 2 -> let y = Stack.pop stack in let x = Stack.pop stack in Stack.push y stack ; Stack.push x stack ; update_display () | _ -> () in let pop_clicked _ = match Stack.length stack with | 1 -> Stack.pop stack |> ignore ; Stack.push "0" stack ; update_display () | _ -> Stack.pop stack |> ignore ; update_display () in let digit_clicked digit = fun _ -> digit_pressed digit ; update_display () in let op_clicked op = fun _ -> match Stack.length stack with | n when n >= 2 -> let y = Stack.pop stack |> int_of_string in let x = Stack.pop stack |> int_of_string in Stack.push (op x y |> string_of_int) stack ; update_display () | _ -> () in let make_button name action = let button = W.button name in W.on_click ~click:action button ; button in let op_button name op = make_button name @@ op_clicked op in let push_button = make_button "PSH" push_clicked in let swap_button = make_button "SWP" swap_clicked in let pop_button = make_button "POP" pop_clicked in let digit_button digit = make_button digit @@ digit_clicked digit in let (//) x y = match x, y with | (_, 0) -> 0 | (x, y) -> x / y in let layout = L.tower ~align:Draw.Center [ L.resident ~w:400 display ; L.flat_of_w [ digit_button "1" ; digit_button "2" ; digit_button "3" ] ; L.flat_of_w [ digit_button "4" ; digit_button "5" ; digit_button "6" ] ; L.flat_of_w [ digit_button "7" ; digit_button "8" ; digit_button "9" ] ; L.flat_of_w [ digit_button "0" ] ; L.flat_of_w [ push_button; swap_button; pop_button] ; L.flat_of_w [ op_button "ADD" (+) ; op_button "MUL" ( * ) ; op_button "SUB" (-) ; op_button "DIV" (//) ] ; ] in let calculator = Bogue.make [] [layout] in update_display () ; Bogue.run calculator ;; let _ = calculator () ; Draw.quit()