File: rpn.ml

package info (click to toggle)
lablgtk2 2.18.13-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 5,940 kB
  • sloc: ml: 41,454; ansic: 23,178; makefile: 685; sh: 75
file content (133 lines) | stat: -rw-r--r-- 4,255 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
(**************************************************************************)
(*    Lablgtk - Examples                                                  *)
(*                                                                        *)
(*    This code is in the public domain.                                  *)
(*    You may freely copy parts of it in your application.                *)
(*                                                                        *)
(**************************************************************************)

(* $Id$ *)

(* reverse polish calculator *)

open StdLabels
open GMain

let wow _ = prerr_endline "Wow!"; ()
let main () =
  let stack = Stack.create () in	

  (* toplevel window *)
  let window =
    GWindow.window ~border_width: 10 ~title:"Reverse Polish Calculator" () in
  window#connect#destroy ~callback:Main.quit;


  (* vbox *)
  let vbx = GPack.vbox ~packing:window#add () in

  (* entry *)
  let entry =
    GEdit.entry ~text:"0" ~editable:false ~max_length: 20 ~packing: vbx#add () in

  (* BackSpace, Clear, All Clear, Quit *) 
  let table0 = GPack.table ~rows:1 ~columns:4 ~packing:vbx#add () in
  let bs_clicked _ = begin
    let txt = entry#text in
    let len = String.length txt in 
    if len <= 1 then
      entry#set_text "0"
    else entry#set_text (String.sub txt ~pos:0 ~len:(len-1))
  end in
  let c_clicked _ = entry#set_text("0") in
  let ac_clicked _ = Stack.clear stack; entry#set_text("0") in
  let labels0 = [("BS", bs_clicked) ; ("C", c_clicked);
		 ("AC", ac_clicked); ("Quit", window#destroy)] in
  let rec loop0 labels n =
    match labels 
    with  [] -> ()
        | (lbl, cb) :: t  ->
    let button =
      GButton.button ~label:lbl
        ~packing:(table0#attach ~left:n ~top:1 ~expand:`BOTH) () in
    button#connect#clicked ~callback:cb;
    loop0 t (n+1) in
  loop0 labels0 1;

  (* Numerals *)
  let table1 = GPack.table ~rows:4 ~columns:5 ~packing:vbx#add () in
  let labels1 = ["7"; "8"; "9"; "4"; "5"; "6"; "1"; "2"; "3"; "0"] in
  let numClicked n _ =
     let txt = entry#text in
     if (txt = "0") then
       entry#set_text n
     else begin
       entry#append_text n
     end in
  let rec loop1 labels n =
    match labels with [] -> ()
    | lbl :: lbls ->
        let button = GButton.button ~label:(" "^lbl^" ")
	    ~packing:(table1#attach ~left:(n mod 3) ~top:(n/3) ~expand:`BOTH)
            () in
        button#connect#clicked ~callback:(numClicked lbl);
        loop1 lbls (n+1) in
  loop1 labels1 0; 

  (* Period *)
  let periodClicked _ = 
     let txt = entry#text in
     if not (String.contains txt '.') then entry#append_text "." in
  (GButton.button ~label:" . "
     ~packing:(table1#attach ~left:1 ~top:3 ~expand:`BOTH) ())
    #connect#clicked ~callback:periodClicked;

  (* Enter (Push) *)
  let enterClicked _ =
     let txt = entry#text in
     let n = float_of_string txt in begin
       Stack.push n stack;
       entry#set_text "0"
     end in
  (GButton.button ~label:"Ent"
     ~packing:(table1#attach ~left:2 ~top:3 ~expand:`BOTH) ())
    #connect#clicked ~callback:enterClicked;

  (* Operators *)
  let op2Clicked op _ =
    let n1 = float_of_string (entry#text) in
    let n2 = Stack.pop stack in
    entry#set_text (string_of_float (op n2 n1)) 
  in
  let op1Clicked op _ =
    let n1 = float_of_string (entry#text) in
    entry#set_text (string_of_float (op n1)) 
  in
  let modClicked _ =
    let n1 = int_of_string (entry#text) in
    let n2 = truncate (Stack.pop stack) in
    entry#set_text (string_of_int (n2 mod n1))
  in
  let labels2 = [(" / ", op2Clicked (/.)); (" * ", op2Clicked ( *. ));
		 (" - ", op2Clicked (-.)); (" + ", op2Clicked (+.));
		 ("mod", modClicked); (" ^ ", op2Clicked ( ** ));
		 ("+/-", op1Clicked (~-.));
                 ("1/x", op1Clicked (fun x -> 1.0/.x))] in
  let rec loop2 labels n =
    match labels
    with [] -> ()
    | (lbl, cb) :: t ->
	let button = GButton.button ~label:lbl
            ~packing:(table1#attach ~left:(3 + n/4) ~top: (n mod 4)
                        ~expand:`BOTH)
            () in
	button#connect#clicked ~callback:cb;
	loop2 t (n+1)
  in
  loop2 labels2 0;

  (* show all and enter event loop *)
  window#show ();
  Main.main ()

let _ = Printexc.print main()