Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lambda support #16

Merged
merged 40 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
828b7d0
First trial
utkn Nov 15, 2024
d8daaa1
`Omni.newLambda`, `Omni.callLambda` omni rule
utkn Nov 15, 2024
dd05821
lambda syntax first iteration
utkn Nov 15, 2024
ed4204e
Lambda parsing complete. Intro rules (first iteration)
utkn Nov 15, 2024
6c41c45
minor updates
utkn Nov 16, 2024
9c21543
Introduced a new state that also contains closures
utkn Nov 21, 2024
588ebe3
Proof fixes
utkn Nov 21, 2024
2b29e38
Lambda semantics
utkn Nov 21, 2024
5741a35
various changes
utkn Nov 21, 2024
f488e5e
SLH typeclass
utkn Nov 21, 2024
5d1cc68
Steps tactic fixed to use SLP (State _). Broken proof steps replaced …
utkn Nov 22, 2024
19e84de
Some proofs completed
utkn Nov 22, 2024
ba1211a
Omni frame proven
utkn Nov 22, 2024
ea4166c
omni frame proof simplified (a bit)
utkn Nov 22, 2024
9abf997
Proof simplifications. Tactics work over heaps
utkn Nov 23, 2024
b90ad54
Renamed `SLH` to `LawfulHeap`
utkn Nov 23, 2024
5aa0fdd
Disjoint_union_right is now proven automatically with disjoint_union_…
utkn Nov 23, 2024
a5b6342
some tactic fixes
utkn Nov 23, 2024
e3b2604
Tactics fixed. Build passing
utkn Nov 24, 2024
944def9
callLambda intro
utkn Nov 25, 2024
cf80adb
newLambda Omni frame proven, callLambda intro rule added
utkn Nov 25, 2024
7bc25ac
callLambda intro rule
utkn Nov 25, 2024
6305337
Lambda structure created. Parsing fixed. `clsSingleton` SLTerm integr…
utkn Nov 25, 2024
4d067d0
"Closure" renamed to "lambda" across the project for precision
utkn Nov 26, 2024
fbca229
Renamed newLambda to lam
utkn Nov 26, 2024
427f728
callLambda intro updated and proven
utkn Nov 26, 2024
d0dab1b
steps tactic can now work with callLambda intro rule
utkn Nov 26, 2024
da4de6f
updates in the steps tactic
utkn Nov 27, 2024
284c344
Merge branch 'main' of https://github.com/reilabs/lampe into us/lambdas
utkn Nov 27, 2024
0edfe4b
renamed utkans_thm to nested_triple
utkn Nov 27, 2024
30aeae3
lambda singleton notation changed
utkn Nov 28, 2024
fca5580
variable p reintroduced to semantics. functionident's rep parameter i…
utkn Nov 28, 2024
31217dd
Lambda syntax updated
utkn Nov 28, 2024
0c6af88
lawfulheap lemmas moved into namespace. class props now have a "thm_"…
utkn Nov 28, 2024
4b38719
Function and lambda types combined. `Rep` is now a parameter of funct…
utkn Nov 29, 2024
00f335f
nested_triple theorem moved to the tactic code
utkn Nov 29, 2024
5e0c712
nrfn! now returns (rep -> Function)
utkn Nov 29, 2024
d3a8441
small changes
utkn Nov 30, 2024
4feede0
Lambda is now parametrized over "rep" instead of having "rep" as its …
utkn Dec 2, 2024
6c7d4f5
small fix in the proof in the main
utkn Dec 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 32 additions & 10 deletions Lampe/Lampe.lean
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ nr_def simple_muts<>(x : Field) -> Field {
y
}

example : STHoare p Γ ⟦⟧ (simple_muts.fn.body _ h![] h![x]) fun v => v = x := by
example : STHoare p Γ ⟦⟧ (simple_muts.fn.body _ h![] |>.body h![x]) fun v => v = x := by
simp only [simple_muts]
steps
try (exact _)
utkn marked this conversation as resolved.
Show resolved Hide resolved
simp_all

nr_def weirdEq<I>(x : I, y : I) -> Unit {
Expand All @@ -21,7 +22,7 @@ nr_def weirdEq<I>(x : I, y : I) -> Unit {
#assert(#eq(a, y) : bool) : Unit;
}

example {P} {x y : Tp.denote P .field} : STHoare P Γ ⟦⟧ (weirdEq.fn.body _ h![.field] h![x, y]) fun _ => x = y := by
example {x y : Tp.denote p .field} : STHoare p Γ ⟦⟧ (weirdEq.fn.body _ h![.field] |>.body h![x, y]) fun _ => x = y := by
simp only [weirdEq]
steps
simp_all
Expand All @@ -39,7 +40,7 @@ lemma BitVec.add_toNat_of_lt_max {a b : BitVec w} (h: a.toNat + b.toNat < 2^w) :
rw [Nat.mod_eq_of_lt]
assumption

example {self that : Tp.denote P (.slice tp)} : STHoare P Γ ⟦⟧ (sliceAppend.fn.body _ h![tp] h![self, that]) fun v => v = self ++ that := by
example {self that : Tp.denote p (.slice tp)} : STHoare p Γ ⟦⟧ (sliceAppend.fn.body _ h![tp] |>.body h![self, that]) fun v => v = self ++ that := by
simp only [sliceAppend]
steps
rename Tp.denote _ tp.slice.ref => selfRef
Expand All @@ -48,7 +49,7 @@ example {self that : Tp.denote P (.slice tp)} : STHoare P Γ ⟦⟧ (sliceAppend
steps
have : (i + 1).toNat = i.toNat + 1 := by
apply BitVec.add_toNat_of_lt_max
casesm* (Tp.denote P (.u 32)), (U _), Fin _
casesm* (Tp.denote p (.u 32)), (U _), Fin _
simp at *
linarith
simp only [this, List.take_succ]
Expand All @@ -66,7 +67,7 @@ nr_def simple_if<>(x : Field, y : Field) -> Field {
z
}

example {p Γ x y}: STHoare p Γ ⟦⟧ (simple_if.fn.body (Tp.denote p) h![] h![x, y])
example {p Γ x y}: STHoare p Γ ⟦⟧ (simple_if.fn.body _ h![] |>.body h![x, y])
fun v => v = y := by
simp only [simple_if]
steps <;> tauto
Expand All @@ -82,14 +83,35 @@ nr_def simple_if_else<>(x : Field, y : Field) -> Field {
z
}

example {p Γ x y}: STHoare p Γ ⟦⟧ (simple_if_else.fn.body (Tp.denote p) h![] h![x, y])
example {p Γ x y}: STHoare p Γ ⟦⟧ (simple_if_else.fn.body _ h![] |>.body h![x, y])
fun v => v = x := by
simp only [simple_if_else]
steps
. simp only [decide_True, exists_const]
sl
contradiction
. simp_all
. aesop

nr_def simple_lambda<>(x : Field, y : Field) -> Field {
let add = |a : Field, b : Field| -> Field { #add(a, b) : Field };
^add(x, y) : Field;
}

example {p Γ} {x y : Tp.denote p Tp.field} :
STHoare p Γ ⟦⟧ (simple_lambda.fn.body _ h![] |>.body h![x, y])
fun v => v = (x + y) := by
simp only [simple_lambda]
steps
simp_all
steps
simp_all
rotate_left 2
simp_all [SLP.entails_self]
exact (fun v => v = x + y)
sl
aesop
sl
aesop

def bulbulizeField : TraitImpl := {
traitGenericKinds := [],
Expand All @@ -100,7 +122,7 @@ def bulbulizeField : TraitImpl := {
impl := fun _ => [("bulbulize", nrfn![
fn bulbulize<>(x : Field) -> Field {
#add(x, x) : Field
}].2
}]
)]
}

Expand All @@ -111,9 +133,9 @@ def bulbulizeU32 : TraitImpl := {
constraints := fun _ => [],
self := fun _ => .u 32,
impl := fun _ => [("bulbulize", nrfn![
fn bulbulize<>(x : u32) -> u32 {
fn bulbulize<>(_x : u32) -> u32 {
69 : u32
}].2
}]
)]
}

Expand Down
39 changes: 23 additions & 16 deletions Lampe/Lampe/Ast.lean
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import Mathlib

import Lampe.Tp
import Lampe.Data.HList
import Lampe.State
import Lampe.SeparationLogic.ValHeap
import Lampe.Builtin

namespace Lampe

abbrev Ident := String

/-- A reference to a lambda is represented as a reference to a unit type -/
abbrev Tp.lambdaRef := Tp.ref .unit

structure TraitRef where
name : Ident
traitGenericKinds : List Kind
Expand All @@ -21,44 +25,47 @@ structure TraitMethodImplRef where
trait : TraitImplRef
method : Ident

inductive FunctionIdent : Type where
| builtin : Builtin → FunctionIdent
| decl : Ident → FunctionIdent
| trait : TraitMethodImplRef → FunctionIdent
inductive FunctionIdent (rep : Tp → Type) : Type where
| builtin : Builtin → FunctionIdent rep
| decl : Ident → FunctionIdent rep
| lambda : rep .lambdaRef → FunctionIdent rep
| trait : TraitMethodImplRef → FunctionIdent rep

inductive Member : Tp → List Tp → Type where
| head : Member tp (tp :: tps)
| tail : Member tp tps → Member tp (tp' :: tps)

inductive Expr (rep : Tp → Type): Tp → Type where
inductive Expr (rep : Tp → Type) : Tp → Type where
| lit : (tp : Tp) → Nat → Expr rep tp
| var : rep tp → Expr rep tp
| letIn : Expr rep t₁ → (rep t₁ → Expr rep t₂) → Expr rep t₂
| call : HList Kind.denote tyKinds → (argTypes : List Tp) → (res : Tp) → FunctionIdent → HList rep argTypes → Expr rep res
| call : HList Kind.denote tyKinds → (argTypes : List Tp) → (res : Tp) → FunctionIdent rep → HList rep argTypes → Expr rep res
| ite : rep .bool → Expr rep a → Expr rep a → Expr rep a
| skip : Expr rep .unit
| loop : rep (.u s) → rep (.u s) → (rep (.u s) → Expr rep r) → Expr rep .unit
| lambda : (argTps : List Tp) → (outTp : Tp) → (HList rep argTps → Expr rep outTp) → Expr rep .lambdaRef

structure Lambda (rep : Tp → Type) where
argTps : List Tp
outTp : Tp
body : HList rep argTps → Expr rep outTp

structure Function : Type _ where
generics : List Kind
inTps : HList Kind.denote generics → List Tp
outTp : HList Kind.denote generics → Tp
body : ∀ rep, (gs : HList Kind.denote generics) → HList rep (inTps gs) → Expr rep (outTp gs)
body : ∀ (rep : Tp → Type), (HList Kind.denote generics) → Lambda rep

/-- Polymorphic identity -/
example : Function := {
generics := [.type]
inTps := fun h![x] => [x]
outTp := fun h![x] => x
body := fun _ h![_] h![x] => .var x
body := fun _ h![tp] => ⟨[tp], tp, fun h![x] => .var x⟩
}

structure FunctionDecl where
name : Ident
fn : Function
name : Ident
fn : Function

structure Module where
decls : List FunctionDecl
decls : List FunctionDecl

structure Struct where
name : String
Expand Down
1 change: 0 additions & 1 deletion Lampe/Lampe/Basic.lean
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Lampe.Semantics
import Lampe.SeparationLogic
import Lampe.Syntax
import Lampe.Ast
import Lampe.Tp
Expand Down
22 changes: 12 additions & 10 deletions Lampe/Lampe/Builtin/Basic.lean
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
import Lampe.State
import Lampe.SeparationLogic.ValHeap
import Lampe.Data.Field
import Lampe.Data.HList
import Lampe.SeparationLogic
import Lampe.Builtin.Helpers
import Mathlib

namespace Lampe

abbrev Builtin.Omni := ∀(P:Prime),
State P →
ValHeap P →
(argTps : List Tp) →
(outTp : Tp) →
HList (Tp.denote P) argTps →
(Option (State P × Tp.denote P outTp) → Prop) →
(Option (ValHeap P × Tp.denote P outTp) → Prop) →
Prop

def Builtin.omni_conseq (omni : Builtin.Omni) : Prop :=
∀{P st argTps outTp args Q Q'}, omni P st argTps outTp args Q → (∀ r, Q r → Q' r) → omni P st argTps outTp args Q'
∀ {P st argTps outTp args Q Q'},
omni P st argTps outTp args Q → (∀ r, Q r → Q' r) → omni P st argTps outTp args Q'

def Builtin.omni_frame (omni : Builtin.Omni) : Prop :=
∀{P st₁ st₂ argTps outTp args Q}, omni P st₁ argTps outTp args Q → st₁.Disjoint st₂ →
omni P (st₁ ∪ st₂) argTps outTp args (fun r => match r with
| some (st, v) => ((fun st => Q (some (st, v))) ⋆ (fun st => st = st₂)) st
| none => Q none
)
∀ {P st₁ st₂ argTps outTp args Q},
omni P st₁ argTps outTp args Q →
st₁.Disjoint st₂ →
omni P (st₁ ∪ st₂) argTps outTp args (fun r => match r with
| some (st, v) => ((fun st => Q (some (st, v))) ⋆ (fun st => st = st₂)) st
| none => Q none
)

structure Builtin where
omni : Builtin.Omni
Expand Down
2 changes: 1 addition & 1 deletion Lampe/Lampe/Builtin/Memory.lean
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def ref : Builtin := {
simp_all
rfl
simp [Finmap.insert_union]
simp_all [Finmap.insert_eq_singleton_union, Finmap.disjoint_union_left]
simp_all [Finmap.insert_eq_singleton_union, LawfulHeap.disjoint, Finmap.disjoint_union_left]
}

inductive readRefOmni : Omni where
Expand Down
Loading
Loading