Cairn · module

Cairn.Runtime.Proofs

lean/Cairn/Runtime/Proofs.lean

Theorems about the runtime: actions name controls on screen, interaction state stays sound, and a click at a reachable control presses it.

Imports Cairn.Runtime.Step

Order

Definitions 7

def

Cairn.Runtime.Sound

lean/Cairn/Runtime/Proofs.lean:78
Sound {S : Type} (s : State S) : Prop

Focus is a focusable control of the tree on screen; hover and press are controls of it.

def

Cairn.Runtime.Names

lean/Cairn/Runtime/Proofs.lean:252
Names (laid : Laid) (acts : List Action) : Prop

Every action names a control of laid.

def

Cairn.Runtime.Untouched

lean/Cairn/Runtime/Proofs.lean:448
Untouched {S : Type} (a0 : S) (c : Ctx S) : Prop

Nothing delivered means the app state is the one it started from.

def

Cairn.Runtime.Quiet

lean/Cairn/Runtime/Proofs.lean:537
Quiet {S : Type} (app : App S) : Prop

An app that ignores the world: receive never changes its state (the default, and every M1 app's).

def

Cairn.Runtime.feed

lean/Cairn/Runtime/Proofs.lean:594
feed {S : Type} (app : App S) (st : S) : Action ⊕ Msg → S

One input to an app: an action to update or a message to receive.

def

Cairn.Runtime.Fed

lean/Cairn/Runtime/Proofs.lean:599
Fed {S : Type} (app : App S) (a b : S) : Prop

b is a after some actions and messages.

def

Cairn.Runtime.Kept

lean/Cairn/Runtime/Proofs.lean:1078
Kept {S : Type} (a : S) (c : Ctx S) : Prop

A context that delivered nothing still holds the app state a.

Theorems 111

theorem

Cairn.Runtime.tab_fst

provedlean/Cairn/Runtime/Proofs.lean:12
tab_fst {S : Type} (s : State S) (back : Bool) :
  (tab s back).fst.laid = s.laid ∧ (tab s back).fst.app = s.app
theorem

Cairn.Runtime.wheel_eq

provedlean/Cairn/Runtime/Proofs.lean:17
wheel_eq {S : Type} (s : State S) (p : Point) (dx dy : Int) :
  ∃ ui,
    wheel s p dx dy =
      { app := s.app, ui := ui, clicks := s.clicks, pointer := s.pointer, scale := s.scale,
        laid := s.laid, effects := s.effects, world := s.world, subCmds := s.subCmds,
        surfaces := s.surfaces, seen := s.seen }

Scrolling changes only the UI.

theorem

Cairn.Runtime.keyScrollState_eq

provedlean/Cairn/Runtime/Proofs.lean:22
keyScrollState_eq {S : Type} (s : State S) (k : Key) (mods : Mods) :
  ∃ ui,
    keyScrollState s k mods =
      { app := s.app, ui := ui, clicks := s.clicks, pointer := s.pointer, scale := s.scale,
        laid := s.laid, effects := s.effects, world := s.world, subCmds := s.subCmds,
        surfaces := s.surfaces, seen := s.seen }
theorem

Cairn.Runtime.wheel_fst

provedlean/Cairn/Runtime/Proofs.lean:33
wheel_fst {S : Type} (s : State S) (p : Point) (dx dy : Int) :
  (wheel s p dx dy).laid = s.laid ∧
    (wheel s p dx dy).app = s.app ∧ (wheel s p dx dy).surfaces = s.surfaces
theorem

Cairn.Runtime.keyScrollState_fst

provedlean/Cairn/Runtime/Proofs.lean:39
keyScrollState_fst {S : Type} (s : State S) (k : Key) (mods : Mods) :
  (keyScrollState s k mods).laid = s.laid ∧
    (keyScrollState s k mods).app = s.app ∧ (keyScrollState s k mods).surfaces = s.surfaces
theorem

Cairn.Runtime.openAt_fst

provedlean/Cairn/Runtime/Proofs.lean:45
openAt_fst {S : Type} (s : State S) (r : ControlRef) :
  (openAt s r).laid = s.laid ∧ (openAt s r).app = s.app ∧ (openAt s r).surfaces = s.surfaces
theorem

Cairn.Runtime.secondaryDown_fst

provedlean/Cairn/Runtime/Proofs.lean:49
secondaryDown_fst {S : Type} (s : State S) (p : Point) :
  (secondaryDown s p).laid = s.laid ∧
    (secondaryDown s p).app = s.app ∧ (secondaryDown s p).surfaces = s.surfaces
theorem

Cairn.Runtime.keyRoute_fst

provedlean/Cairn/Runtime/Proofs.lean:54
keyRoute_fst {S : Type} (s : State S) (k : Key) (mods : Mods) :
  (keyRoute s k mods).fst.laid = s.laid ∧
    (keyRoute s k mods).fst.app = s.app ∧ (keyRoute s k mods).fst.surfaces = s.surfaces
theorem

Cairn.Runtime.textRoute_fst

provedlean/Cairn/Runtime/Proofs.lean:61
textRoute_fst {S : Type} (s : State S) (str : String)
  (rep : Option (Nat × Nat)) :
  (textRoute s str rep).fst.laid = s.laid ∧
    (textRoute s str rep).fst.app = s.app ∧ (textRoute s str rep).fst.surfaces = s.surfaces
theorem

Cairn.Runtime.route_laid

provedlean/Cairn/Runtime/Proofs.lean:66
route_laid {S : Type} (m : TextMetrics) (s : State S) (e : Event) :
  (route m s e).fst.laid = s.laid ∧ (route m s e).fst.app = s.app
theorem

Cairn.Runtime.fixUI_sound

provedlean/Cairn/Runtime/Proofs.lean:83
fixUI_sound (laid : Laid) (pointer : Option Point) (ui : UI)
  (keep : List ControlRef) :
  (∀ (r : ControlRef),
      (fixUI laid pointer ui keep).focus = some r →
        ∃ t, t ∈ targets laid ∧ t.ref = r ∧ t.focusable = true) ∧
    (∀ (r : ControlRef), (fixUI laid pointer ui keep).hover = some r → r ∈ refs laid) ∧
      ∀ (r : ControlRef), (fixUI laid pointer ui keep).pressed = some r → r ∈ refs laid
theorem

Cairn.Runtime.settle_spec

provedlean/Cairn/Runtime/Proofs.lean:104
settle_spec {S : Type} (app : App S) (cfg : Config) (st : S)
  (pointer : Option Point) (ui0 : UI) (fuel : Nat) (ui : UI) :
  ∃ l, settle app cfg st pointer ui0 fuel ui = (fixUI l pointer ui0 (app.keepScroll st), l)

settle always returns ui0 repaired against the tree it returns.

theorem

Cairn.Runtime.resettle_spec

provedlean/Cairn/Runtime/Proofs.lean:114
resettle_spec {S : Type} (app : App S) (cfg : Config) (st : S)
  (pointer : Option Point) (ui0 : UI) (fuel : Nat) (x : UI × Laid) :
  (∃ l, x = (fixUI l pointer ui0 (app.keepScroll st), l)) →
    ∃ l,
      resettle app cfg st pointer ui0 fuel x = (fixUI l pointer ui0 (app.keepScroll st), l)

So does resettle, from a UI and tree of that form.

theorem

Cairn.Runtime.settleAll_spec

provedlean/Cairn/Runtime/Proofs.lean:125
settleAll_spec {S : Type} (app : App S) (cfg : Config) (st : S)
  (pointer : Option Point) (ui0 ui : UI) :
  ∃ l, settleAll app cfg st pointer ui0 ui = (fixUI l pointer ui0 (app.keepScroll st), l)

settleAll always returns ui0 repaired against the tree it returns.

theorem

Cairn.Runtime.repeat_comm

provedlean/Cairn/Runtime/Proofs.lean:130
repeat_comm {α : Type} (f : α → α) (n : Nat) (a : α) :
  Nat.repeat f n (f a) = f (Nat.repeat f n a)
theorem

Cairn.Runtime.resettle_stops

provedlean/Cairn/Runtime/Proofs.lean:138
resettle_stops {S : Type} (app : App S) (cfg : Config) (st : S)
  (pointer : Option Point) (ui0 : UI) (fuel : Nat) (x : UI × Laid) :
  unsettled (resettle app cfg st pointer ui0 fuel x).snd = false ∨
    resettle app cfg st pointer ui0 fuel x =
      Nat.repeat (fun y => settle app cfg st pointer ui0 0 y.fst) fuel x

A list settles, or the fuel ran out. resettle returns a tree in which no virtual list laid a row at a height other than the one it was laid out by (unsettled), unless it took every one of its fuel layouts.

theorem

Cairn.Runtime.aim_spec

provedlean/Cairn/Runtime/Proofs.lean:157
aim_spec {S : Type} (app : App S) (cfg : Config) (st : S)
  (pointer : Option Point) (ui1 : UI) (goals : List (ControlRef × ScrollTarget))
  (fuel : Nat) (x : UI × Laid) :
  (∃ l u,
      x = (fixUI l pointer u (app.keepScroll st), l) ∧
        u.focus = ui1.focus ∧ u.pressed = ui1.pressed) →
    ∃ l u,
      aim app cfg st pointer ui1 goals fuel x = (fixUI l pointer u (app.keepScroll st), l) ∧
        u.focus = ui1.focus ∧ u.pressed = ui1.pressed

What aim returns is still a UI repaired against the tree returned with it, from one with ui1's focus and press.

theorem

Cairn.Runtime.lay_spec

provedlean/Cairn/Runtime/Proofs.lean:174
lay_spec {S : Type} (app : App S) (cfg : Config) (st : S)
  (pointer : Option Point) (goals : List (ControlRef × ScrollTarget)) (ui1 : UI) :
  ∃ l u,
    lay app cfg st pointer goals ui1 = (fixUI l pointer u (app.keepScroll st), l) ∧
      u.focus = ui1.focus ∧ u.pressed = ui1.pressed

lay returns a UI repaired against the tree returned with it, from one with ui1's focus and press (ui1 itself, unless a scroll request moved an offset).

theorem

Cairn.Runtime.sound_settle

provedlean/Cairn/Runtime/Proofs.lean:187
sound_settle {S : Type} (app : App S) (cfg : Config) (st : S)
  (pointer : Option Point) (ui0 : UI) (fuel : Nat) (ui : UI) (s : State S)
  (h : (s.ui, s.laid) = settle app cfg st pointer ui0 fuel ui) : Sound s
theorem

Cairn.Runtime.sound_lay

provedlean/Cairn/Runtime/Proofs.lean:196
sound_lay {S : Type} (app : App S) (cfg : Config) (st : S)
  (pointer : Option Point) (goals : List (ControlRef × ScrollTarget)) (ui1 : UI)
  (s : State S) (h : (s.ui, s.laid) = lay app cfg st pointer goals ui1) : Sound s
theorem

Cairn.Runtime.sound_settleAll

provedlean/Cairn/Runtime/Proofs.lean:205
sound_settleAll {S : Type} (app : App S) (cfg : Config) (st : S)
  (pointer : Option Point) (ui0 ui : UI) (s : State S)
  (h : (s.ui, s.laid) = settleAll app cfg st pointer ui0 ui) : Sound s
theorem

Cairn.Runtime.start_sound

provedlean/Cairn/Runtime/Proofs.lean:215
start_sound {S : Type} (app : App S) (cfg : Config) (size : Size)
  (scale : Nat) : Sound (start app cfg size scale)

Focus is sound at start.

theorem

Cairn.Runtime.step_sound

provedlean/Cairn/Runtime/Proofs.lean:221
step_sound {S : Type} (app : App S) (cfg : Config) (s : State S) (e : Event)
  (h : Sound s) : Sound (step app cfg s e).fst

Focus is sound after every step: focus is none or a focusable control of the tree on screen, and hover and press are none or controls of it.

theorem

Cairn.Runtime.steps_sound

provedlean/Cairn/Runtime/Proofs.lean:236
steps_sound {S : Type} (app : App S) (cfg : Config) (s : State S)
  (es : List Event) (h : Sound s) : Sound (steps app cfg s es).fst
theorem

Cairn.Runtime.names_nil

provedlean/Cairn/Runtime/Proofs.lean:254
names_nil (laid : Laid) : Names laid []
theorem

Cairn.Runtime.names_append

provedlean/Cairn/Runtime/Proofs.lean:256
names_append {laid : Laid} {a b : List Action} (ha : Names laid a)
  (hb : Names laid b) : Names laid (a ++ b)
theorem

Cairn.Runtime.names_of

provedlean/Cairn/Runtime/Proofs.lean:263
names_of {laid : Laid} {t : Target} (ht : t ∈ targets laid)
  {acts : List Action} (h : ∀ (a : Action), a ∈ acts → a.control = t.ref) : Names laid acts

Actions all about one control of the tree.

theorem

Cairn.Runtime.focused_mem

provedlean/Cairn/Runtime/Proofs.lean:267
focused_mem {S : Type} {s : State S} {t : Target} (h : focused s = some t) :
  t ∈ targets s.laid
theorem

Cairn.Runtime.leave_names

provedlean/Cairn/Runtime/Proofs.lean:272
leave_names {S : Type} (s : State S) (n : Option ControlRef) :
  Names s.laid (leave s n)
theorem

Cairn.Runtime.leave_blurs

provedlean/Cairn/Runtime/Proofs.lean:281
leave_blurs {S : Type} (s : State S) (n : Option ControlRef) (a : Action) :
  a ∈ leave s n → ∃ c, a = Action.blur c
theorem

Cairn.Runtime.onField_names

provedlean/Cairn/Runtime/Proofs.lean:287
onField_names {S : Type} (s : State S) (ops : Target → List TextOp) :
  Names s.laid (onField s ops)
theorem

Cairn.Runtime.keyActions_names

provedlean/Cairn/Runtime/Proofs.lean:296
keyActions_names {S : Type} (s : State S) (k : Key) (mods : Mods) :
  Names s.laid (keyActions s k mods)
theorem

Cairn.Runtime.textActions_names

provedlean/Cairn/Runtime/Proofs.lean:304
textActions_names {S : Type} (s : State S) (str : String)
  (rep : Option (Nat × Nat)) : Names s.laid (textActions s str rep)
theorem

Cairn.Runtime.keyRoute_names

provedlean/Cairn/Runtime/Proofs.lean:314
keyRoute_names {S : Type} (s : State S) (k : Key) (mods : Mods) :
  Names s.laid (keyRoute s k mods).snd
theorem

Cairn.Runtime.textRoute_names

provedlean/Cairn/Runtime/Proofs.lean:320
textRoute_names {S : Type} (s : State S) (str : String)
  (rep : Option (Nat × Nat)) : Names s.laid (textRoute s str rep).snd
theorem

Cairn.Runtime.tabTarget_mem

provedlean/Cairn/Runtime/Proofs.lean:326
tabTarget_mem {S : Type} (s : State S) (back : Bool) {t : Target}
  (h : tabTarget s back = some t) : t ∈ targets s.laid
theorem

Cairn.Runtime.mem_appearRefs

provedlean/Cairn/Runtime/Proofs.lean:338
mem_appearRefs {laid : Laid} {r : ControlRef} :
  r ∈ appearRefs laid ↔
    ∃ t, t ∈ targets laid ∧ t.control.appear = true ∧ t.visible.nonempty ∧ t.ref = r
theorem

Cairn.Runtime.mem_appearing

provedlean/Cairn/Runtime/Proofs.lean:357
mem_appearing {laid : Laid} {seen : List ControlRef} {a : Action} :
  a ∈ appearing laid seen ↔
    ∃ c,
      a = Action.appear c ∧
        ¬c ∈ seen ∧
          ∃ t, t ∈ targets laid ∧ t.control.appear = true ∧ t.visible.nonempty ∧ t.ref = c

Appear, exactly. The frame event delivers appear c exactly when c is a control of the tree on screen marked appear with a visible part, and isn't among the controls seen at the last frame.

theorem

Cairn.Runtime.appearing_names

provedlean/Cairn/Runtime/Proofs.lean:370
appearing_names (laid : Laid) (seen : List ControlRef) :
  Names laid (appearing laid seen)
theorem

Cairn.Runtime.tab_names

provedlean/Cairn/Runtime/Proofs.lean:376
tab_names {S : Type} (s : State S) (back : Bool) :
  Names s.laid (tab s back).snd
theorem

Cairn.Runtime.route_names

provedlean/Cairn/Runtime/Proofs.lean:387
route_names {S : Type} (m : TextMetrics) (s : State S) (e : Event)
  (hm : e.isMenu = false) : Names s.laid (route m s e).snd

No action without a control. Every action the runtime passes to update names a control of the laid tree on screen when the event arrived, unless the event is a menu event (those name the menu's items: menu_route_names). (step delivers exactly (route cfg.metrics s e).2.)

theorem

Cairn.Runtime.release_app

provedlean/Cairn/Runtime/Proofs.lean:439
release_app {S : Type} (c : Ctx S) (w : World) : (release c w).app = c.app
theorem

Cairn.Runtime.release_delivered

provedlean/Cairn/Runtime/Proofs.lean:440
release_delivered {S : Type} (c : Ctx S) (w : World) :
  (release c w).delivered = c.delivered
theorem

Cairn.Runtime.ack_app

provedlean/Cairn/Runtime/Proofs.lean:442
ack_app {S : Type} (c : Ctx S) (id : Nat) : (ack c id).app = c.app
theorem

Cairn.Runtime.ack_delivered

provedlean/Cairn/Runtime/Proofs.lean:444
ack_delivered {S : Type} (c : Ctx S) (id : Nat) :
  (ack c id).delivered = c.delivered
theorem

Cairn.Runtime.give_untouched

provedlean/Cairn/Runtime/Proofs.lean:450
give_untouched {S : Type} (app : App S) (a0 : S) (c : Ctx S) (m : Msg) :
  Untouched a0 (give app c m)
theorem

Cairn.Runtime.hear_untouched

provedlean/Cairn/Runtime/Proofs.lean:454
hear_untouched {S : Type} (app : App S) {a0 : S} {c : Ctx S}
  (h : Untouched a0 c) : Untouched a0 (hear app c)
theorem

Cairn.Runtime.fire_untouched

provedlean/Cairn/Runtime/Proofs.lean:460
fire_untouched {S : Type} (app : App S) {a0 : S} {c : Ctx S} (n : String)
  (h : Untouched a0 c) : Untouched a0 (fire app c n)
theorem

Cairn.Runtime.foldl_fire_untouched

provedlean/Cairn/Runtime/Proofs.lean:466
foldl_fire_untouched {S : Type} (app : App S) {a0 : S} (ns : List String)
  {c : Ctx S} : Untouched a0 c → Untouched a0 (List.foldl (fire app) c ns)
theorem

Cairn.Runtime.boot_untouched

provedlean/Cairn/Runtime/Proofs.lean:472
boot_untouched {S : Type} (app : App S) {a0 : S} {c : Ctx S}
  (h : Untouched a0 c) : Untouched a0 (boot app c)
theorem

Cairn.Runtime.admit_untouched

provedlean/Cairn/Runtime/Proofs.lean:478
admit_untouched {S : Type} (app : App S) (s : State S) (e : Event) :
  Untouched s.app (admit app s e)
theorem

Cairn.Runtime.admit_input

provedlean/Cairn/Runtime/Proofs.lean:498
admit_input {S : Type} (app : App S) (s : State S) {e : Event}
  (h : e.isWorld = false) : admit app s e = { app := s.app, world := s.world }
theorem

Cairn.Runtime.step_app

provedlean/Cairn/Runtime/Proofs.lean:505
step_app {S : Type} (app : App S) (cfg : Config) (s : State S) (e : Event) :
  (step app cfg s e).fst.app = (act app (admit app s e) (route cfg.metrics s e).snd).app

step passes update exactly the routed actions, in order, after telling the app the time if it hasn't heard it: the app state after a step is act over (route cfg.metrics s e).2 from what the world events delivered.

theorem

Cairn.Runtime.step_delivers

provedlean/Cairn/Runtime/Proofs.lean:524
step_delivers {S : Type} (app : App S) (cfg : Config) (s : State S)
  (e : Event) (hw : e.isWorld = false) (hh : s.world.heard = some s.world.clock) :
  (step app cfg s e).fst.app = (deliver app.update s.app (route cfg.metrics s e).snd).fst

For input events (not from the world), when the app has heard the current time, the app state after a step is update folded over exactly the routed actions: M1's statement.

theorem

Cairn.Runtime.give_app

provedlean/Cairn/Runtime/Proofs.lean:539
give_app {S : Type} {app : App S} (h : Quiet app) (c : Ctx S) (m : Msg) :
  (give app c m).app = c.app
theorem

Cairn.Runtime.hear_app

provedlean/Cairn/Runtime/Proofs.lean:542
hear_app {S : Type} {app : App S} (h : Quiet app) (c : Ctx S) :
  (hear app c).app = c.app
theorem

Cairn.Runtime.fire_app

provedlean/Cairn/Runtime/Proofs.lean:547
fire_app {S : Type} {app : App S} (h : Quiet app) (c : Ctx S) (n : String) :
  (fire app c n).app = c.app
theorem

Cairn.Runtime.foldl_fire_app

provedlean/Cairn/Runtime/Proofs.lean:553
foldl_fire_app {S : Type} {app : App S} (h : Quiet app) (ns : List String)
  (c : Ctx S) : (List.foldl (fire app) c ns).app = c.app
theorem

Cairn.Runtime.boot_app

provedlean/Cairn/Runtime/Proofs.lean:559
boot_app {S : Type} {app : App S} (h : Quiet app) (c : Ctx S) :
  (boot app c).app = c.app
theorem

Cairn.Runtime.admit_app

provedlean/Cairn/Runtime/Proofs.lean:564
admit_app {S : Type} {app : App S} (h : Quiet app) (s : State S) (e : Event) :
  (admit app s e).app = s.app
theorem

Cairn.Runtime.act_app

provedlean/Cairn/Runtime/Proofs.lean:583
act_app {S : Type} {app : App S} (h : Quiet app) (c : Ctx S)
  (acts : List Action) : (act app c acts).app = (deliver app.update c.app acts).fst
theorem

Cairn.Runtime.Fed.refl

provedlean/Cairn/Runtime/Proofs.lean:601
refl {S : Type} (app : App S) (a : S) : Fed app a a
theorem

Cairn.Runtime.Fed.trans

provedlean/Cairn/Runtime/Proofs.lean:603
trans {S : Type} {app : App S} {a b c : S} (h1 : Fed app a b)
  (h2 : Fed app b c) : Fed app a c
theorem

Cairn.Runtime.give_fed

provedlean/Cairn/Runtime/Proofs.lean:607
give_fed {S : Type} (app : App S) (c : Ctx S) (m : Msg) :
  Fed app c.app (give app c m).app
theorem

Cairn.Runtime.hear_fed

provedlean/Cairn/Runtime/Proofs.lean:610
hear_fed {S : Type} (app : App S) (c : Ctx S) : Fed app c.app (hear app c).app
theorem

Cairn.Runtime.fire_fed

provedlean/Cairn/Runtime/Proofs.lean:615
fire_fed {S : Type} (app : App S) (c : Ctx S) (n : String) :
  Fed app c.app (fire app c n).app
theorem

Cairn.Runtime.foldl_fire_fed

provedlean/Cairn/Runtime/Proofs.lean:620
foldl_fire_fed {S : Type} (app : App S) (ns : List String) (c : Ctx S) :
  Fed app c.app (List.foldl (fire app) c ns).app
theorem

Cairn.Runtime.boot_fed

provedlean/Cairn/Runtime/Proofs.lean:626
boot_fed {S : Type} (app : App S) (c : Ctx S) : Fed app c.app (boot app c).app
theorem

Cairn.Runtime.admit_fed

provedlean/Cairn/Runtime/Proofs.lean:631
admit_fed {S : Type} (app : App S) (s : State S) (e : Event) :
  Fed app s.app (admit app s e).app
theorem

Cairn.Runtime.deliver_fed

provedlean/Cairn/Runtime/Proofs.lean:648
deliver_fed {S : Type} (u : S → Action → S × List Effect) (acts : List Action)
  (st : S) (effs : List Effect) :
  (List.foldl
        (fun p a =>
          match u p.fst a with
          | (st', e) => (st', p.snd ++ e))
        (st, effs) acts).fst =
    List.foldl (fun s a => (u s a).fst) st acts
theorem

Cairn.Runtime.foldl_feed_inl

provedlean/Cairn/Runtime/Proofs.lean:656
foldl_feed_inl {S : Type} (app : App S) (acts : List Action) (st : S) :
  List.foldl (fun s a => (app.update s a).fst) st acts =
    List.foldl (feed app) st (List.map Sum.inl acts)
theorem

Cairn.Runtime.act_fed

provedlean/Cairn/Runtime/Proofs.lean:662
act_fed {S : Type} (app : App S) (c : Ctx S) (acts : List Action) :
  Fed app c.app (act app c acts).app
theorem

Cairn.Runtime.step_fed

provedlean/Cairn/Runtime/Proofs.lean:673
step_fed {S : Type} (app : App S) (cfg : Config) (s : State S) (e : Event) :
  Fed app s.app (step app cfg s e).fst.app

Any app. The app state after a step is the one before after some updates and messages (the routed actions, the clock, due timers, a reply or a subscription event).

theorem

Cairn.Runtime.step_delivers_quiet

provedlean/Cairn/Runtime/Proofs.lean:680
step_delivers_quiet {S : Type} {app : App S} (h : Quiet app) (cfg : Config)
  (s : State S) (e : Event) :
  (step app cfg s e).fst.app = (deliver app.update s.app (route cfg.metrics s e).snd).fst

For an app that ignores the world, the app state after any step is update folded over exactly the routed actions.

theorem

Cairn.Runtime.applyFocus_pressed

provedlean/Cairn/Runtime/Proofs.lean:688
applyFocus_pressed (effs : List Effect) (ui : UI) :
  (applyFocus effs ui).pressed = ui.pressed

A focus request changes only the focus.

theorem

Cairn.Runtime.step_down_pressed

provedlean/Cairn/Runtime/Proofs.lean:695
step_down_pressed {S : Type} (app : App S) (cfg : Config) (s : State S)
  (t : Target) (p : Point) (clicks : Nat) (mods : Mods) (hhit : hitTarget s.laid p = some t)
  (hf : t.isField = false) (hb : t.menuButton = false)
  (hpres :
    t.ref ∈
      refs (step app cfg s (Event.pointerDown p Button.primary clicks mods)).fst.laid) :
  (step app cfg s (Event.pointerDown p Button.primary clicks mods)).fst.ui.pressed =
      some t.ref ∧
    (step app cfg s (Event.pointerDown p Button.primary clicks mods)).fst.clicks = clicks

After a pointerDown on a non-field control t, the press is recorded on t with the down's click count, whatever the update and relayout did, provided t's ref is still in the new tree.

theorem

Cairn.Runtime.down_actions

provedlean/Cairn/Runtime/Proofs.lean:723
down_actions {S : Type} (m : TextMetrics) (s : State S) (t : Target)
  (p : Point) (clicks : Nat) (mods : Mods) (hhit : hitTarget s.laid p = some t)
  (hf : t.isField = false) (hb : t.menuButton = false) :
  (route m s (Event.pointerDown p Button.primary clicks mods)).snd = leave s none

The actions of a pointerDown on a non-field control that isn't a menu button: at most a blur of the field that loses focus. No press happens on the way down.

theorem

Cairn.Runtime.click_presses

provedlean/Cairn/Runtime/Proofs.lean:734
click_presses {S : Type} (app : App S) (cfg : Config) (s : State S)
  (t : Target) (p : Point) (mods mods' : Mods) (h0 : Reaches s.laid t p)
  (hf : t.isField = false) (hb : t.menuButton = false)
  (h1 :
    ∃ t1,
      Reaches (step app cfg s (Event.pointerDown p Button.primary 1 mods)).fst.laid t1 p ∧
        t1.ref = t.ref ∧ t1.isField = false) :
  (∀ (a : Action),
      a ∈ (route cfg.metrics s (Event.pointerDown p Button.primary 1 mods)).snd →
        ∃ c, a = Action.blur c) ∧
    (route cfg.metrics (step app cfg s (Event.pointerDown p Button.primary 1 mods)).fst
          (Event.pointerUp p Button.primary mods')).snd =
      [Action.press t.ref]

Pressable, step level. If a pointer at p reaches non-field control t that isn't a menu button (a menu button's click opens its menu instead), and after the pointerDown (and whatever update and relayout it caused) p still reaches a non-field control with the same ref, then the pointerUp at p delivers exactly press t.ref, and the pointerDown delivered nothing but blurs.

theorem

Cairn.Runtime.click_center_presses

provedlean/Cairn/Runtime/Proofs.lean:752
click_center_presses {S : Type} (app : App S) (cfg : Config) (s : State S)
  (t : Target) (mods mods' : Mods) (h0 : LayoutFacts s.laid t) (hf : t.isField = false)
  (hb : t.menuButton = false)
  (h1 :
    ∃ t1,
      Reaches
          (step app cfg s
                (Event.pointerDown t.visible.center Button.primary 1 mods)).fst.laid
          t1 t.visible.center ∧
        t1.ref = t.ref ∧ t1.isField = false) :
  (∀ (a : Action),
      a ∈
          (route cfg.metrics s
              (Event.pointerDown t.visible.center Button.primary 1 mods)).snd →
        ∃ c, a = Action.blur c) ∧
    (route cfg.metrics
          (step app cfg s (Event.pointerDown t.visible.center Button.primary 1 mods)).fst
          (Event.pointerUp t.visible.center Button.primary mods')).snd =
      [Action.press t.ref]

Pressable at the centre: under LayoutFacts, a click at the centre of the control's visible rect presses it.

theorem

Cairn.Runtime.menu_route_names

provedlean/Cairn/Runtime/Proofs.lean:773
menu_route_names {S : Type} (m : TextMetrics) (s : State S) :
  (∀ (p : ClaimId) (a : Action),
      a ∈ (route m s (Event.menuOpen p)).snd →
        ∃ it, Shown.statusOf p s.surfaces = some it ∧ a = Action.press it.control) ∧
    (∀ (p : ClaimId) (r : ControlRef) (a : Action),
        a ∈ (route m s (Event.menuSelect p r)).snd →
          ∃ ms,
            selectMenu s p = some ms ∧ r ∈ MenuItem.enabledRefs ms ∧ a = Action.press r) ∧
      ∀ (p : ClaimId), (route m s (Event.menuClose p)).snd = []

Menu actions name menu items. Opening a status item's menu presses only its control; a selection presses only an enabled item of the menu it is checked against now; closing presses nothing.

theorem

Cairn.Runtime.selectMenu_window

provedlean/Cairn/Runtime/Proofs.lean:797
selectMenu_window {S : Type} {s : State S} {p : ClaimId}
  (h : Shown.windowPlace s.surfaces = some p) :
  selectMenu s p = Option.map (fun x => x.snd.items) (openMenu s)

For the window's place, a selection is checked against the control menu open now.

theorem

Cairn.Runtime.control_menu_select_names

provedlean/Cairn/Runtime/Proofs.lean:805
control_menu_select_names {S : Type} (m : TextMetrics) (s : State S)
  {p : ClaimId} {r : ControlRef} (hw : Shown.windowPlace s.surfaces = some p) (a : Action) :
  a ∈ (route m s (Event.menuSelect p r)).snd →
    ∃ o cm,
      openMenu s = some (o, cm) ∧ r ∈ MenuItem.enabledRefs cm.items ∧ a = Action.press r

A control menu's choice is an item of the menu open now. Every action a selection addressed to the window delivers is a press of an enabled item of the control menu open now (openMenu: UI.menu's control, its menu in the tree on screen); with no menu open, or an item that isn't an enabled item of it, nothing.

theorem

Cairn.Runtime.menu_select_presses

provedlean/Cairn/Runtime/Proofs.lean:818
menu_select_presses {S : Type} (m : TextMetrics) (s : State S) {p : ClaimId}
  {ms : List MenuItem} {r : ControlRef} (h : selectMenu s p = some ms)
  (hr : r ∈ MenuItem.enabledRefs ms) :
  route m s (Event.menuSelect p r) = (s, [Action.press r])

A menu selection presses its item. If r is an enabled item of the menu a selection for p is checked against, choosing it delivers exactly press r (the menu's click_presses, with no layout in between).

theorem

Cairn.Runtime.menu_open_presses

provedlean/Cairn/Runtime/Proofs.lean:824
menu_open_presses {S : Type} (m : TextMetrics) (s : State S) {p : ClaimId}
  {it : StatusItem} (h : Shown.statusOf p s.surfaces = some it) :
  route m s (Event.menuOpen p) = (s, [Action.press it.control])

Opening a shown status item's menu presses its control.

theorem

Cairn.Runtime.UI.same_self

provedlean/Cairn/Runtime/Proofs.lean:829
same_self (a : UI) : same a a = true
theorem

Cairn.Runtime.menu_select_stale

provedlean/Cairn/Runtime/Proofs.lean:836
menu_select_stale {S : Type} (app : App S) (cfg : Config) (s : State S)
  {p : ClaimId} {r : ControlRef}
  (h : ∀ (ms : List MenuItem), selectMenu s p = some ms → ¬r ∈ MenuItem.enabledRefs ms) :
  step app cfg s (Event.menuSelect p r) = (s, [])

A stale menu selection is ignored. If the chosen ref is not an enabled item of the menu the selection is checked against now (the menu changed while it was open, the item was disabled, the status item or the control is gone, or no control menu is open), the step changes nothing at all: same app state, same runtime state, no effects.

theorem

Cairn.Runtime.menu_select_absent

provedlean/Cairn/Runtime/Proofs.lean:851
menu_select_absent {S : Type} (app : App S) (cfg : Config) (s : State S)
  {p : ClaimId} {r : ControlRef}
  (h : ∀ (ms : List MenuItem), selectMenu s p = some ms → ¬r ∈ MenuItem.refs ms) :
  step app cfg s (Event.menuSelect p r) = (s, [])

A selection addressed to an item not in the menu is ignored (a special case of menu_select_stale): nothing outside the description can be pressed through the menu.

theorem

Cairn.Runtime.menuHitsOf_owner

provedlean/Cairn/Runtime/Proofs.lean:860
menuHitsOf_owner (o : Option Target) (l : Laid) (h : Hit) :
  h ∈ menuHitsOf o l →
    h.owner = o ∨ ∃ t, t ∈ targetsOf l ∧ h.owner = some t ∧ t.node.menu?.isSome = true
theorem

Cairn.Runtime.menuHitsList_owner

provedlean/Cairn/Runtime/Proofs.lean:898
menuHitsList_owner (o : Option Target) (ls : List Laid) (h : Hit) :
  h ∈ menuHitsList o ls →
    h.owner = o ∨ ∃ t, t ∈ targetsList ls ∧ h.owner = some t ∧ t.node.menu?.isSome = true
theorem

Cairn.Runtime.menuTarget_mem

provedlean/Cairn/Runtime/Proofs.lean:914
menuTarget_mem {laid : Laid} {p : Point} {t : Target}
  (h : menuTarget laid p = some t) : t ∈ targets laid ∧ t.node.menu?.isSome = true

The control a secondary click opens is a control of the tree that has a menu.

theorem

Cairn.Runtime.secondary_no_menu

provedlean/Cairn/Runtime/Proofs.lean:929
secondary_no_menu {S : Type} (m : TextMetrics) (s : State S) {p : Point}
  (clicks : Nat) (mods : Mods) (h : menuTarget s.laid p = none) :
  route m s (Event.pointerDown p Button.secondary clicks mods) = (withPointer s p, [])

A secondary click on a control without a menu changes nothing but hover: with no control with a menu at or above the point, the runtime moves the pointer (and so hover) and delivers nothing, as before menus on controls.

theorem

Cairn.Runtime.secondary_opens

provedlean/Cairn/Runtime/Proofs.lean:936
secondary_opens {S : Type} (m : TextMetrics) (s : State S) {p : Point}
  {t : Target} (clicks : Nat) (mods : Mods) (h : menuTarget s.laid p = some t) :
  route m s (Event.pointerDown p Button.secondary clicks mods) =
    (openAt (withPointer s p) t.ref, [])

A secondary click on a control with a menu (or inside one) opens that menu and delivers nothing.

theorem

Cairn.Runtime.setScroll_menu

provedlean/Cairn/Runtime/Proofs.lean:941
setScroll_menu (ui : UI) (r : ControlRef) (o : Int) :
  (ui.setScroll r o).menu = ui.menu
theorem

Cairn.Runtime.revealIn_menu

provedlean/Cairn/Runtime/Proofs.lean:944
revealIn_menu (chain : List Scroller) (ui : UI) (q : Rect) :
  (revealIn chain ui q).menu = ui.menu
theorem

Cairn.Runtime.tab_menu

provedlean/Cairn/Runtime/Proofs.lean:960
tab_menu {S : Type} (s : State S) (back : Bool) :
  (tab s back).fst.ui.menu = s.ui.menu
theorem

Cairn.Runtime.wheel_menu

provedlean/Cairn/Runtime/Proofs.lean:965
wheel_menu {S : Type} (s : State S) (p : Point) (dx dy : Int) :
  (wheel s p dx dy).ui.menu = s.ui.menu
theorem

Cairn.Runtime.keyScrollState_menu

provedlean/Cairn/Runtime/Proofs.lean:971
keyScrollState_menu {S : Type} (s : State S) (k : Key) (mods : Mods) :
  (keyScrollState s k mods).ui.menu = s.ui.menu
theorem

Cairn.Runtime.route_open_quiet

provedlean/Cairn/Runtime/Proofs.lean:985
route_open_quiet {S : Type} (m : TextMetrics) (s : State S) (e : Event)
  {r : ControlRef} (h : (route m s e).fst.ui.menu = some r) (hne : s.ui.menu ≠ some r) :
  (route m s e).snd = []

Opening a menu reaches no update. Whenever routing an event opens a control menu (the menu open after it is one that wasn't open before: a secondary click, a menu button's primary click, Space or Return on a focused menu button, the context-menu key), it delivers no action.

theorem

Cairn.Runtime.step_open_quiet

provedlean/Cairn/Runtime/Proofs.lean:1038
step_open_quiet {S : Type} (app : App S) (cfg : Config) (s : State S)
  (e : Event) {r : ControlRef} (h : (route cfg.metrics s e).fst.ui.menu = some r)
  (hne : s.ui.menu ≠ some r) (hw : e.isWorld = false) :
  (step app cfg s e).fst.app = s.app ∧ (step app cfg s e).snd = []

Opening a menu changes no app state. A step whose routing opens a control menu (for instance a secondary click on a control with a menu, secondary_opens) leaves the app state as it was and asks the host for nothing; only choosing an item (menuSelect) reaches update.

theorem

Cairn.Runtime.route_surface_other

provedlean/Cairn/Runtime/Proofs.lean:1059
route_surface_other {S : Type} (m : TextMetrics) (s : State S) {p : ClaimId}
  (e : Event) (h : Shown.windowPlace s.surfaces ≠ some p) :
  route m s (Event.surface p e) = (s, [])

Events addressed to a surface other than the window (a panel, a status item) do nothing.

theorem

Cairn.Runtime.tab_surfaces

provedlean/Cairn/Runtime/Proofs.lean:1065
tab_surfaces {S : Type} (s : State S) (back : Bool) :
  (tab s back).fst.surfaces = s.surfaces
theorem

Cairn.Runtime.route_surfaces

provedlean/Cairn/Runtime/Proofs.lean:1068
route_surfaces {S : Type} (m : TextMetrics) (s : State S) (e : Event) :
  (route m s e).fst.surfaces = s.surfaces
theorem

Cairn.Runtime.give_kept

provedlean/Cairn/Runtime/Proofs.lean:1080
give_kept {S : Type} (app : App S) (a : S) (c : Ctx S) (m : Msg) :
  Kept a (give app c m)
theorem

Cairn.Runtime.hear_kept

provedlean/Cairn/Runtime/Proofs.lean:1083
hear_kept {S : Type} (app : App S) (a : S) (c : Ctx S) (h : Kept a c) :
  Kept a (hear app c)
theorem

Cairn.Runtime.fire_kept

provedlean/Cairn/Runtime/Proofs.lean:1088
fire_kept {S : Type} (app : App S) (a : S) (c : Ctx S) (n : String)
  (h : Kept a c) : Kept a (fire app c n)
theorem

Cairn.Runtime.boot_kept

provedlean/Cairn/Runtime/Proofs.lean:1094
boot_kept {S : Type} (app : App S) (a : S) (c : Ctx S) (h : Kept a c) :
  Kept a (boot app c)
theorem

Cairn.Runtime.foldl_fire_kept

provedlean/Cairn/Runtime/Proofs.lean:1099
foldl_fire_kept {S : Type} (app : App S) (a : S) (ns : List String)
  (c : Ctx S) : Kept a c → Kept a (List.foldl (fire app) c ns)
theorem

Cairn.Runtime.admit_kept

provedlean/Cairn/Runtime/Proofs.lean:1106
admit_kept {S : Type} (app : App S) (s : State S) (e : Event) :
  Kept s.app (admit app s e)

admit changes the app state only by delivering something.

theorem

Cairn.Runtime.step_surfaces

provedlean/Cairn/Runtime/Proofs.lean:1126
step_surfaces {S : Type} (app : App S) (cfg : Config) (s : State S)
  (e : Event) (h : s.surfaces = shows app cfg s.app) :
  (step app cfg s e).fst.surfaces = shows app cfg (step app cfg s e).fst.app

Each step keeps the runtime's surfaces equal to what the app's surfaces show for its state: the menu menuSelect is checked against is the menu of the current app state.

theorem

Cairn.Runtime.start_surfaces

provedlean/Cairn/Runtime/Proofs.lean:1155
start_surfaces {S : Type} (app : App S) (cfg : Config) (size : Size)
  (scale : Nat) :
  (start app cfg size scale).surfaces = shows app cfg (start app cfg size scale).app
theorem

Cairn.Runtime.steps_surfaces

provedlean/Cairn/Runtime/Proofs.lean:1159
steps_surfaces {S : Type} (app : App S) (cfg : Config) (es : List Event)
  (s : State S) :
  s.surfaces = shows app cfg s.app →
    (steps app cfg s es).fst.surfaces = shows app cfg (steps app cfg s es).fst.app

In every state the running app reaches, the surfaces show the current app state.