232 lines
4.5 KiB
OCaml
232 lines
4.5 KiB
OCaml
(** Overview *)
|
|
|
|
let x = 10 + 10
|
|
|
|
let y = x * 3
|
|
|
|
let c = String.make x 'a'
|
|
|
|
let sin1 = sin 1.
|
|
|
|
let rec fact n = if n = 0 then 1. else float n *. fact (n - 1)
|
|
|
|
let _ = Printf.printf "fact 20 = %f\n" (fact 20)
|
|
|
|
let _ = "abc" < "def"
|
|
|
|
(** Mutually recursive function *)
|
|
|
|
let rec even n =
|
|
match n with
|
|
| 0 -> true
|
|
| x -> odd (x - 1)
|
|
|
|
and odd n =
|
|
match n with
|
|
| 0 -> false
|
|
| x -> even (x - 1)
|
|
|
|
(** Mutually recursive module *)
|
|
|
|
module rec Odd : sig
|
|
val odd : int -> bool
|
|
end = struct
|
|
let odd x = if x = 0 then false else Even.even (pred x)
|
|
end
|
|
|
|
and Even : sig
|
|
val even : int -> bool
|
|
end = struct
|
|
let even x = if x = 0 then true else Odd.odd (pred x)
|
|
end
|
|
|
|
(** Reactive dom *)
|
|
|
|
open Js_of_ocaml
|
|
open Js_of_ocaml_lwt
|
|
open Js_of_ocaml_tyxml
|
|
|
|
let display x =
|
|
Dom.appendChild (Dom_html.getElementById "output") (Tyxml_js.To_dom.of_element x)
|
|
|
|
module RList = ReactiveData.RList
|
|
|
|
let rl, rhandle = RList.create []
|
|
|
|
let li_rl = RList.map (fun x -> Tyxml_js.Html.(li [ txt x ])) rl
|
|
|
|
let ul_elt = Tyxml_js.R.Html.ul li_rl
|
|
|
|
let init =
|
|
let _ = RList.snoc "# cons \"some string\"" rhandle in
|
|
let _ = RList.snoc "# snoc \"some other\"" rhandle in
|
|
let _ = RList.snoc "# insert \"anywhere\" 1" rhandle in
|
|
let _ = RList.snoc "# remove 1" rhandle in
|
|
()
|
|
|
|
let snoc s = RList.snoc s rhandle
|
|
|
|
let cons s = RList.cons s rhandle
|
|
|
|
let insert s pos = RList.insert s pos rhandle
|
|
|
|
let remove pos = RList.remove pos rhandle
|
|
|
|
let time_signal =
|
|
let s, set = React.S.create (Sys.time ()) in
|
|
let rec loop () : unit Lwt.t =
|
|
set (Sys.time ());
|
|
Lwt.bind (Lwt_js.sleep 1.) loop
|
|
in
|
|
Lwt.async loop;
|
|
s
|
|
|
|
let div_elt =
|
|
Tyxml_js.(
|
|
Html.(
|
|
div
|
|
[ h4
|
|
[ txt "Uptime is "
|
|
; R.Html.txt
|
|
(React.S.map (fun s -> string_of_int (int_of_float s)) time_signal)
|
|
; txt " s"
|
|
]
|
|
; ul_elt
|
|
]))
|
|
|
|
let _ = display div_elt
|
|
|
|
(** Graphics: Draw *)
|
|
|
|
open Graphics_js
|
|
|
|
let () =
|
|
loop [ Mouse_motion ] (function { mouse_x = x; mouse_y = y } -> fill_circle x y 5)
|
|
|
|
(** Graphics: Draw chars*)
|
|
|
|
open Graphics_js
|
|
|
|
let () =
|
|
loop [ Mouse_motion; Key_pressed ] (function
|
|
| { key = '\000'; _ } -> ()
|
|
| { mouse_x = x; mouse_y = y; key } ->
|
|
moveto x y;
|
|
draw_char key)
|
|
|
|
(** Graphics: PingPong *)
|
|
|
|
open Js_of_ocaml_lwt
|
|
open Graphics_js
|
|
|
|
let c = 3
|
|
|
|
let x0 = 0
|
|
|
|
and x1 = size_x ()
|
|
|
|
and y0 = 0
|
|
|
|
and y1 = size_y ()
|
|
|
|
let draw_ball x y =
|
|
set_color foreground;
|
|
fill_circle x y c
|
|
|
|
let state = ref (Lwt.task ())
|
|
|
|
let wait () = fst !state
|
|
|
|
let rec pong_aux x y dx dy =
|
|
draw_ball x y;
|
|
let new_x = x + dx and new_y = y + dy in
|
|
let new_dx = if new_x - c <= x0 || new_x + c >= x1 then -dx else dx
|
|
and new_dy = if new_y - c <= y0 || new_y + c >= y1 then -dy else dy in
|
|
Lwt.bind (wait ()) (fun () -> pong_aux new_x new_y new_dx new_dy)
|
|
|
|
let rec start () =
|
|
let t = Lwt.task () in
|
|
let _, w = !state in
|
|
state := t;
|
|
clear_graph ();
|
|
Lwt.wakeup w ();
|
|
Lwt.bind (Lwt_js.sleep (1. /. 60.)) start
|
|
|
|
let pong x y dx dy = pong_aux x y dx dy
|
|
|
|
let _ = pong 111 87 2 3
|
|
|
|
let _ = pong 28 57 5 3
|
|
|
|
let _ = start ()
|
|
|
|
(** Effect handler *)
|
|
|
|
module Txn : sig
|
|
type 'a t
|
|
|
|
val atomically : (unit -> unit) -> unit
|
|
|
|
val ref : 'a -> 'a t
|
|
|
|
val ( ! ) : 'a t -> 'a
|
|
|
|
val ( := ) : 'a t -> 'a -> unit
|
|
end = struct
|
|
open Effect
|
|
open Effect.Deep
|
|
|
|
type 'a t = 'a ref
|
|
|
|
type _ Effect.t += Update : 'a t * 'a -> unit Effect.t
|
|
|
|
let atomically f =
|
|
let comp =
|
|
match_with
|
|
f
|
|
()
|
|
{ retc = (fun x _ -> x)
|
|
; exnc =
|
|
(fun e rb ->
|
|
rb ();
|
|
raise e)
|
|
; effc =
|
|
(fun (type a) (e : a Effect.t) ->
|
|
match e with
|
|
| Update (r, v) ->
|
|
Some
|
|
(fun (k : (a, _) continuation) rb ->
|
|
let old_v = !r in
|
|
r := v;
|
|
continue k () (fun () ->
|
|
r := old_v;
|
|
rb ()))
|
|
| _ -> None)
|
|
}
|
|
in
|
|
comp (fun () -> ())
|
|
|
|
let ref = ref
|
|
|
|
let ( ! ) = ( ! )
|
|
|
|
let ( := ) r v = perform (Update (r, v))
|
|
end
|
|
|
|
let example () =
|
|
let open Txn in
|
|
let exception Res of int in
|
|
let r = ref 10 in
|
|
Printf.printf "T0: %d\n" !r;
|
|
try
|
|
atomically (fun () ->
|
|
r := 20;
|
|
r := 21;
|
|
Printf.printf "T1: Before abort %d\n" !r;
|
|
raise (Res !r) |> ignore;
|
|
Printf.printf "T1: After abort %d\n" !r;
|
|
r := 30)
|
|
with Res v ->
|
|
Printf.printf "T0: T1 aborted with %d\n" v;
|
|
Printf.printf "T0: %d\n" !r
|