@@ -30,7 +30,7 @@ public def Arg := String
3030public abbrev MonadArg (m) := MonadReaderOf Arg m
3131
3232/-- A List of command line arguments. -/
33- @[expose] public def ArgList := List Arg
33+ @[expose] public def ArgList := List String
3434
3535public noncomputable instance : SizeOf ArgList := inferInstanceAs (SizeOf (List String))
3636
@@ -56,7 +56,37 @@ public instance [MonadStateOf ArgList m] : MonadArgs m where
5656 takeArg? := modifyGet fun | [] => (none, []) | arg :: args => (some arg, args)
5757 takeArgs := modifyGet fun args => (args, [])
5858
59- /-- A monad transformer to equip a monad with a state that monotonically decreasing in size. -/
59+ /-- A monad transformer to equip a monad with a command-line argument list. -/
60+ @[expose] -- for codegen
61+ public abbrev ArgsT := StateT ArgList
62+
63+ namespace ArgsT
64+
65+ /--
66+ Executes an action in the underlying monad {lean}`m` with the added state of a command-line
67+ argument list. It returns the monadic value paired with the final argument list.
68+ -/
69+ public abbrev run (self : ArgsT m α) (args : List String) : m (α × List String) :=
70+ StateT.run self args
71+
72+ /--
73+ Executes an action in the underlying monad {lean}`m` with the added state of a command-line
74+ argument list. It returns the monadic value, discarding any remaining arguments list.
75+ -/
76+ public abbrev run' [Functor m] (self : ArgsT m α) (args : List String) : m α :=
77+ StateT.run' self args
78+
79+ @[simp] public theorem run_getArgs {as : List String} [Monad m] :
80+ StateT.run (σ := ArgList) (m := m) getArgs as = pure (as, as)
81+ := by rfl
82+
83+ @[simp] public theorem run_takeArgs {as : List String} [Monad m] :
84+ StateT.run (σ := ArgList) (m := m) takeArgs as = pure (as, [])
85+ := by rfl
86+
87+ end ArgsT
88+
89+ /-- A monad transformer to equip a monad with a state that monotonically non-increasing in size. -/
6090@[expose] -- for codegen
6191public def MonoStateT (σ : Type u) [SizeOf σ] (m : Type max u v → Type w) (α : Type v) :=
6292 (s : σ) → m (α × {s' : σ // sizeOf s' ≤ sizeOf s})
@@ -120,25 +150,25 @@ public protected def get [SizeOf σ] [Pure m] : MonoStateT σ m σ :=
120150
121151end MonoStateT
122152
123- /-- A monad transformer to equip a monad with an argument list. -/
124- public abbrev ArgsT (m : Type → Type v) := MonoStateT ArgList m
153+ /-- A monad transformer to equip a monad with a monotonically non-increasing argument list. -/
154+ public abbrev MonoArgsT (m : Type → Type v) := MonoStateT ArgList m
125155
126- namespace ArgsT
156+ namespace MonoArgsT
127157
128158@[inline, always_inline, inherit_doc MonadArgs.getArgs]
129- public protected def get [Pure m] : ArgsT m (List String) :=
159+ public protected def get [Pure m] : MonoArgsT m (List String) :=
130160 MonoStateT.get
131161
132162@[inline, always_inline, inherit_doc MonadArgs.takeArg?]
133- public protected def takeArg? [Monad m] : ArgsT m (Option String) :=
163+ public protected def takeArg? [Monad m] : MonoArgsT m (Option String) :=
134164 MonoStateT.modifyGet fun
135165 | [] => (none, ⟨[], Nat.le_refl _⟩)
136166 | arg :: args => (some arg, ⟨args, mono_cons⟩)
137167where
138168 mono_cons {a} {as : List String} : sizeOf as ≤ sizeOf (a :: as) := by simp
139169
140170@[inline, always_inline, inherit_doc MonadArgs.takeArgs]
141- public protected def takeArgs [Monad m] : ArgsT m (List String) :=
171+ public protected def takeArgs [Monad m] : MonoArgsT m (List String) :=
142172 MonoStateT.modifyGet fun args => (args, ⟨[], mono_nil⟩)
143173where
144174 mono_nil {as : List String} : sizeOf ([] : List String) ≤ sizeOf as := by
@@ -147,12 +177,12 @@ where
147177 · simp only [List.nil.sizeOf_spec, List.cons.sizeOf_spec]
148178 omega
149179
150- public instance [Monad m] : MonadArgs (ArgsT m) where
151- getArgs := ArgsT .get
152- takeArg? := ArgsT .takeArg?
153- takeArgs := ArgsT .takeArgs
180+ public instance [Monad m] : MonadArgs (MonoArgsT m) where
181+ getArgs := MonoArgsT .get
182+ takeArg? := MonoArgsT .takeArg?
183+ takeArgs := MonoArgsT .takeArgs
154184
155- end ArgsT
185+ end MonoArgsT
156186
157187/-! ## Monadic Argument Parsing Utilities -/
158188
@@ -192,6 +222,17 @@ If no argument is available, returns {lean}`none`.
192222 else
193223 return none
194224
225+ @[simp] public theorem ArgsT.run_takeArg?_nil
226+ [Monad m] [LawfulMonad m] {_ : MonadParseArg α (ArgsT m)} :
227+ StateT.run (σ := ArgList) (m := m) takeArg? [] = pure ((none : Option α), [])
228+ := by simp [takeArg?, MonadArgs.takeArg?]
229+
230+ @[simp] public theorem ArgsT.run_takeArg?_cons
231+ [Monad m] [LawfulMonad m] [MonadParseArg α (ArgsT m)] :
232+ StateT.run (σ := ArgList) (m := m) (α := Option α) takeArg? (a :: as) =
233+ StateT.run (σ := ArgList) (some <$> parseArg a) as
234+ := by simp [takeArg?, MonadArgs.takeArg?]
235+
195236/--
196237Removes and returns the head of the remaining argument list, parsing the argument into {lean}`α`.
197238
@@ -201,6 +242,11 @@ If no argument is available, returns {lean}`default`.
201242 [Monad m] [MonadArgs m] [MonadParseArg α m] (default : α)
202243: m α := return (← takeArg?).getD default
203244
245+ @[simp] public theorem takeArgD_eq_getD_takeArg?
246+ [Monad m] [LawfulMonad m] [MonadArgs m] [MonadParseArg α m] :
247+ takeArgD (α := α) (m := m) d = (·.getD d) <$> takeArg?
248+ := by simp [takeArgD]
249+
204250/--
205251Removes and returns the head of the remaining argument list, parsing the argument into {lean}`α`.
206252
@@ -209,11 +255,23 @@ If no argument is available,, errors using {name}`throwExpectedArg` with {lean}`
209255@[inline] public def takeArg
210256 [Monad m] [MonadArgs m] [MonadParseArg α m] [MonadThrowExpectedArg m] (descr : String)
211257: m α := do
212- if let some arg ← takeArg? then
258+ if let some arg ← MonadArgs. takeArg? then
213259 parseArg arg
214260 else
215261 throwExpectedArg descr
216262
263+ @[simp] public theorem ArgsT.run_takeArg_nil
264+ [Monad m] [LawfulMonad m] [MonadParseArg α (ArgsT m)] [MonadThrowExpectedArg m] :
265+ StateT.run (σ := ArgList) (m := m) (α := α) (takeArg d) [] =
266+ ((·, [])) <$> throwExpectedArg (m := m) d
267+ := by simp [takeArg, MonadArgs.takeArg?, throwExpectedArg]
268+
269+ @[simp] public theorem ArgsT.run_takeArg_cons
270+ [Monad m] [LawfulMonad m] [MonadParseArg α (ArgsT m)] {_ : MonadThrowExpectedArg m} :
271+ StateT.run (σ := ArgList) (m := m) (α := α) (takeArg d) (a :: as) =
272+ StateT.run (σ := ArgList) (parseArg a) as
273+ := by simp [takeArg, MonadArgs.takeArg?]
274+
217275/-! ## Argument Handler Type -/
218276
219277/-- A monadic callback for an arbitrary command line argument. -/
@@ -226,7 +284,7 @@ public def ArgHandler (m : Type → Type v) :=
226284 read
227285
228286/-- A monad transformer to equip a monad with a command line argument. -/
229- public abbrev ArgT (m) := ReaderT Arg <| ArgsT m
287+ public abbrev ArgT (m) := ReaderT Arg <| MonoArgsT m
230288
231289/--
232290Construct an argument handler from a monadic action.
@@ -260,7 +318,7 @@ public structure IsArg (arg : String) : Prop where
260318namespace IsOpt
261319
262320/-- A decision procedure for determining if {lean}`arg` is an option. -/
263- public def dec (arg : String) : Decidable (IsOpt arg) :=
321+ @[reducible, expose] public def dec (arg : String) : Decidable (IsOpt arg) :=
264322 if h0 : arg.startPos = arg.endPos then
265323 isFalse fun ⟨_, _, _⟩ => by contradiction
266324 else
@@ -274,11 +332,14 @@ public def dec (arg : String) : Decidable (IsOpt arg) :=
274332
275333public instance instDecidable {arg : String} : Decidable (IsOpt arg) := dec arg
276334
335+ public theorem ne_empty {arg} (h : IsOpt arg) : arg ≠ "" :=
336+ String.startPos_eq_endPos_iff.subst h.startPos_ne_endPos
337+
277338public theorem not_isArg {arg} (h : IsOpt arg) : ¬ IsArg arg :=
278339 fun h' => h'.not_isOpt h
279340
280- public theorem ne_empty {arg} (h : IsOpt arg) : arg ≠ "" :=
281- String.startPos_eq_endPos_iff.subst h.startPos_ne_endPos
341+ public theorem ne_of_isArg (ha : IsOpt a) (hb : IsArg b) : a ≠ b :=
342+ fun heq => ha.not_isArg.elim (heq ▸ hb)
282343
283344public theorem offset_next_startPos (h : IsOpt a) :
284345 (a.startPos.next h.startPos_ne_endPos).offset = ⟨1 ⟩
@@ -334,7 +395,7 @@ end IsOpt
334395namespace IsArg
335396
336397/-- A decision procedure for determining if {lean}`arg` is an non-option command line argument. -/
337- public def dec (arg : String) : Decidable (IsArg arg) :=
398+ @[reducible, expose] public def dec (arg : String) : Decidable (IsArg arg) :=
338399 if h0 : arg.startPos = arg.endPos then
339400 isFalse fun h => h.ne_empty (String.startPos_eq_endPos_iff.mp h0)
340401 else
@@ -349,6 +410,9 @@ public def dec (arg : String) : Decidable (IsArg arg) :=
349410
350411public instance instDecidable {arg : String} : Decidable (IsArg arg) := dec arg
351412
413+ public theorem ne_of_isOpt (ha : IsArg a) (hb : IsOpt b) : a ≠ b :=
414+ fun heq => ha.not_isOpt.elim (heq ▸ hb)
415+
352416public theorem startPos_ne_endPos (h : IsArg a) : a.startPos ≠ a.endPos :=
353417 String.startPos_eq_endPos_iff.symm.subst h.ne_empty
354418
@@ -378,7 +442,7 @@ public def OptArg := Option String.Slice
378442public abbrev MonadOptArg (m) := MonadReaderOf OptArg m
379443
380444/-- A monad transformer to equip a monad with a command line option and optional argument. -/
381- public abbrev OptT (m) := ReaderT Opt <| ReaderT OptArg <| ArgsT m
445+ public abbrev OptT (m) := ReaderT Opt <| ReaderT OptArg <| MonoArgsT m
382446
383447/-- The character of a command line short option (e.g., {lit}`x` of {lit}`-x`). -/
384448@[expose] -- for codegen
@@ -636,11 +700,11 @@ public def processLeadingOptions
636700 return args
637701termination_by args
638702
639- public theorem processLeadingOptions_nil [Monad m] :
703+ @[simp] public theorem processLeadingOptions_nil [Monad m] :
640704 processLeadingOptions (m := m) [] f = pure []
641705:= by unfold processLeadingOptions; simp
642706
643- public theorem processLeadingOptions_cons_empty [Monad m] :
707+ @[simp] public theorem processLeadingOptions_cons_empty [Monad m] :
644708 processLeadingOptions (m := m) ("" :: as) f = processLeadingOptions as f
645709:= by conv => {lhs; unfold processLeadingOptions}; simp
646710
@@ -674,11 +738,11 @@ public theorem processLeadingOptions_cons_of_isArg [Monad m] (h : IsArg a) :
674738 termination_by args
675739 loop args
676740
677- public theorem processArgs_nil [Monad m] :
741+ @[simp] public theorem processArgs_nil [Monad m] :
678742 processArgs (m := m) [] optH argH = pure ()
679743:= by unfold processArgs processArgs.loop; simp
680744
681- public theorem processArgs_cons_empty [Monad m] :
745+ @[simp] public theorem processArgs_cons_empty [Monad m] :
682746 processArgs (m := m) ("" :: as) optH argH = processArgs as optH argH
683747:= by
684748 unfold processArgs
0 commit comments