Source file input.ml
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
type value =
| Vsig of bool
| Vbool of bool
| Vint of int
| Vfloat of float
type input_type =
| Sig
| Bool of bool
| Int of (int * int) * int
| Float of (float * float) * float
type input_desc = string * input_type
type input_win =
| Inp of input_desc
| Frame of string * input_win
| HBox of input_win list
| VBox of input_win list
let short_string_of_input_type = function
| Sig -> "sig"
| Bool _ -> "bool"
| Int _ -> "int"
| Float _ -> "float"
let string_of_input_type = function
| Sig -> "sig"
| Bool b -> "bool (" ^ (string_of_bool b) ^ ")"
| Int ((i1, i2), default) ->
"int[" ^ (string_of_int i1) ^ ", "
^ (string_of_int i2) ^ "] "
^ "(" ^ (string_of_int default) ^ ")"
| Float ((f1, f2), default) ->
"float[" ^ (string_of_float f1) ^ ", "
^ (string_of_float f2) ^ "] "
^ "(" ^ (string_of_float default) ^ ")"
let type_of_value = function
| Vsig _ -> "sig"
| Vbool _ -> "bool"
| Vint _ -> "int"
| Vfloat _ -> "float"
let string_of_value = function
| Vsig b -> if b then "Present" else "Absent"
| Vbool b -> string_of_bool b
| Vint i -> string_of_int i
| Vfloat f -> string_of_float f
let string_of_input_desc (s, ty) = s ^ " : " ^ (short_string_of_input_type ty)
let get_inputs win =
let rec aux = function
| Inp i -> [i]
| Frame (_, w) -> aux w
| HBox w_l -> List.flatten (List.map aux w_l)
| VBox w_l -> List.flatten (List.map aux w_l)
in
aux win
class input (env : (string, value) Hashtbl.t)
(packing : GObj.widget -> unit) ((name, typ) : input_desc) =
object (self)
method private init_val v =
if Hashtbl.mem env name then begin
Printf.eprintf "Variable %s has been declared twice\n" name;
exit 1
end;
self#set_val v
method private set_val v =
ignore (match typ, v with
| Sig, Vsig _
| Bool _, Vbool _
| Int _, Vint _
| Float _, Vfloat _ -> ()
| _ -> Printf.eprintf "Variable %s has type %s but is assigned with a value of type %s."
name (short_string_of_input_type typ) (type_of_value v);
exit 1 );
Hashtbl.add env name v;
method private make_widget () =
match typ with
| Sig -> self#make_sig packing
| Bool default -> self#make_bool packing default
| Int ((i1, i2), default) -> self#make_int packing (i1, i2) default
| Float ((f1, f2), default) -> self#make_float packing (f1, f2) default
method private make_sig packing =
let widget = GButton.button ~label:("Trigger " ^ name) ~packing:packing () in
ignore (widget#connect#clicked ~callback:(fun () -> self#set_val (Vsig true)));
self#init_val (Vsig false)
method private make_bool packing default =
let widget = GButton.check_button ~label:(string_of_input_desc (name, typ))
~active:default ~packing:packing () in
ignore (widget#connect#toggled ~callback:(fun () -> self#set_val (Vbool widget#active)));
self#init_val (Vbool default)
method private make_int packing (i1, i2) default =
let get_label v = Printf.sprintf "%s = %d" name v in
let frame = GBin.frame ~label:(get_label default)
~packing:packing () in
let step_incr = 100.0 in
let lower = float_of_int (100 * i1) in
let upper = float_of_int (100 * i2 + 100) in
let value = float_of_int (100 * default) in
let adj = GData.adjustment
~lower:lower ~upper:upper ~value:value ~step_incr:step_incr () in
ignore(GRange.scale `HORIZONTAL ~adjustment:adj ~draw_value:false
~packing:frame#add ());
ignore (adj#connect#value_changed
(fun () ->
let new_val = truncate (adj#value /. 100.) in
frame#set_label (Some (get_label new_val));
self#set_val (Vint new_val)));
self#init_val (Vint default)
method private make_float packing (f1, f2) default =
let get_label v =
if (v > -10000. && v < -0.01 )
|| (v > 0.01 && v < 10000.)
|| v = 0. then
Printf.sprintf "%s = %.2f" name v
else
Printf.sprintf "%s = %.2e" name v
in
let frame = GBin.frame ~label:(get_label default)
~packing:packing () in
let step_incr = min 1. (f2 -. f1) in
let lower = 100. *. f1 in
let upper = 100. *. f2 +. 10. in
let value = 100. *. default in
let adj = GData.adjustment
~lower:lower ~upper:upper ~value:value ~step_incr:step_incr () in
ignore(GRange.scale `HORIZONTAL ~adjustment:adj ~draw_value:false
~packing:frame#add ());
ignore (adj#connect#value_changed
(fun () ->
let new_val = (adj#value /. 100.) in
frame#set_label (Some (get_label new_val));
self#set_val (Vfloat new_val)));
self#init_val (Vfloat default)
initializer
self#make_widget ()
end
class window (title : string) (win : input_win) =
let inputs = get_inputs win in
let n_inputs = List.length inputs in
let env = Hashtbl.create n_inputs in
object (self)
val w = GWindow.window ~title:title ~allow_shrink:false ()
method private make_window packing = function
| Inp i ->
ignore(new input env packing i)
| Frame (s, w) ->
let frame = GBin.frame ~label:s ~packing:packing () in
let align = GBin.alignment ~padding:(10, 10, 10, 10) ~packing:frame#add () in
self#make_window align#add w
| HBox (w_l) ->
let hbox = GPack.hbox ~homogeneous:true ~spacing:20 ~packing:packing () in
List.iter (self#make_window hbox#pack) w_l
| VBox (w_l) ->
let vbox = GPack.vbox ~spacing:20 ~packing:packing () in
List.iter (self#make_window vbox#pack) w_l
method private get_value name =
try
Hashtbl.find env name
with Not_found ->
Printf.eprintf "The value identifier %s is unbound\n"
name; exit 1
method get_sig name =
match self#get_value name with
| Vsig s ->
if s then begin Hashtbl.add env name (Vsig false); true end else false
| v ->
Printf.eprintf "Cannot access variable (%s : %s) with method get_sig\n"
name (type_of_value v); exit 1
method get_bool name =
match self#get_value name with
| Vbool b -> b
| v ->
Printf.eprintf "Cannot access variable (%s : %s) with method get_bool\n"
name (type_of_value v); exit 1
method get_int name =
match self#get_value name with
| Vint i -> i
| v ->
Printf.eprintf "Cannot access variable (%s : %s) with method get_int\n"
name (type_of_value v); exit 1
method get_float name =
match self#get_value name with
| Vfloat f -> f
| v ->
Printf.eprintf "Cannot access variable (%s : %s) with method get_float\n"
name (type_of_value v); exit 1
method resize width height =
w#resize ~width:width ~height:height
initializer
let align = GBin.alignment ~padding:(10, 10, 10, 10) ~packing:w#add () in
self#make_window align#add win;
ignore (w#connect#destroy ~callback:GMain.Main.quit);
ignore (w#misc#connect#show ~callback:w#show);
w#show ()
end
let make_sig s = Inp (s, Sig)
let make_bool s b = Inp (s, Bool b)
let make_int s (i1, i2) def = Inp (s, Int ((i1, i2), def))
let make_float s (f1, f2) def = Inp (s, Float ((f1, f2), def))
let frame s w = Frame (s, w)
let hbox w_l = HBox w_l
let vbox w_l = VBox w_l
let get_sig (w, s) = ((), w#get_sig s)
let get_bool (w, s) = w#get_bool s
let get_int (w, s) = w#get_int s
let get_float (w, s) = w#get_float s
let resize_window (w, width, height) = w#resize width height
let open_window (title, win) = new window title win