(* A very first Zelus program *)
(* The Lustre counter *)
(* v(n) = if c(n) then 1 else 0
 * s(n) = if r(n) then v(n) else v(n) + s(n-1)
 * s(0) = if r(0) then v(0) else v(0) + 0 *)
let node counter(c, r) = s where
  rec v = if c then 1 else 0
  and s = if r then v else v + (0 fby s)

(* a linear filter. [y] follows [x] *)
let node filter(x) = y where
  rec y = 0.2 *. x +. 0.8 *. (0.0 fby y)

let g = 9.81

(* The ball which bounces *)
(* initial position yi; initial speed yi'
 * computes the current position y
 * z is an zero-crossing event; true when y crosses 0 (from pos to neg) *)
let hybrid bounce(yi, yi') = (y, z) where
  rec der y' = -. g init yi' reset z -> -0.8 *. last y'
  and der y = y' init yi
  and z = up(-. y)

(* A basic hybrid program which mixes a discrete-time Lustre node *)
(* and the bouncing ball. *)
let node sum() = s where rec s = (0 fby s) + 1

(* counts the number of bounces; the node application sum() is *)
(* activated every time z is true; s is initialised to 0 *)
let hybrid count_bounces(yi, yi') = s where
  rec (y, z) = bounce(yi, yi')
  and s = present z -> sum() init 0