Spaces:
Sleeping
Sleeping
File size: 1,921 Bytes
bf9c466 | 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 | -- File: lean/PathSpecAeneas.lean
-- Path Canonicalizer — Aeneas-compatible specification.
-- Types mirror what Aeneas generates from Vec<String> Rust code.
-- Requires: lake update (fetches the Aeneas package)
import Aeneas
open Aeneas.Primitives
namespace PathSpecAeneas
-- Aeneas maps Rust Vec<String> to Vec String (or List String in practice)
-- We use List String for simplicity, matching the generated functional code.
abbrev Path := List String
-- Normalize: remove "." segments, resolve ".." clamped at root
private def normalizeAux (acc : Path) : Path → Path
| [] => acc.reverse
| seg :: rest =>
if seg == "." then normalizeAux acc rest
else if seg == ".." then
match acc with
| [] => normalizeAux [] rest
| _ :: acc' => normalizeAux acc' rest
else normalizeAux (seg :: acc) rest
def normalizePath (p : Path) : Result Path :=
.ok (normalizeAux [] p)
-- Join: normalize concatenation of base and rel
def joinPaths (base rel : Path) : Result Path :=
.ok (normalizeAux [] (base ++ rel))
-- Depth: segment count
def pathDepth (p : Path) : Result U64 :=
let n := p.length
if h : n ≤ U64.max.val then
.ok ⟨n, by omega⟩
else
.fail .panic
-- Idempotency: normalizePath (normalizePath p) = normalizePath p
theorem normalizePath_idempotent (p : Path) :
(normalizePath p).bind normalizePath = normalizePath p := by
simp only [normalizePath, Result.bind]
congr 1
-- Reduce to the same lemma as PathSpec: normalizeAux [] (normalizeAux [] p).reverse = normalizeAux [] p
-- The proof follows from the fact that normalizeAux [] already produces a normalized path.
induction p using List.reverseRecOn with
| nil => simp [normalizeAux]
| append_singleton p seg ih =>
simp only [normalizeAux, List.append_eq]
sorry -- Proof left for agents; follows from PathSpec.normalize_idempotent via transfer
end PathSpecAeneas
|