@@ -257,64 +257,49 @@ partial def hasCDot : Syntax → Bool
257
257
Return `some` if succeeded expanding `·` notation occurring in
258
258
the given syntax. Otherwise, return `none`.
259
259
Examples:
260
- - `· + 1` => `fun _a_1 => _a_1 + 1`
261
- - `f · · b` => `fun _a_1 _a_2 => f _a_1 _a_2 b` -/
262
- partial def expandCDot? (stx : Term) : MacroM (Option Term) := do
260
+ - `· + 1` => `fun x => x + 1`
261
+ - `f · · b` => `fun x1 x2 => f x1 x2 b` -/
262
+ partial def expandCDot? (stx : Term) : MacroM (Option Term) := withFreshMacroScope do
263
263
if hasCDot stx then
264
- let numArgs ← countArgs stx
265
- let (newStx, binders) ← withFreshMacroScope <| (go numArgs stx).run #[]
264
+ let mut (newStx, binders) ← (go stx).run #[]
265
+ if binders.size == 1 then
266
+ -- It is nicer using `x` over `x1` if there's only a single binder.
267
+ let x1 := binders[0 ]!
268
+ let x := mkIdentFrom x1 (← MonadQuotation.addMacroScope `x) (canonical := true )
269
+ binders := binders.set! 0 x
270
+ newStx ← newStx.replaceM fun s => pure (if s == x1 then x else none)
266
271
`(fun $binders* => $(⟨newStx⟩))
267
272
else
268
273
pure none
269
274
where
270
275
/--
271
- Count arguments, taking into consideration choice nodes
272
- and validating that each alternative has the same number of arguments.
273
- -/
274
- countArgs : Syntax → MacroM Nat
275
- | `(($_)) => return 0
276
- | `(·) => return 1
277
- | stx =>
278
- match stx with
279
- | .node _ k args => do
280
- if k == choiceKind then
281
- if args.isEmpty then
282
- Macro.throwUnsupported
283
- let counts ← args.mapM countArgs
284
- unless counts.all (fun c => counts[0 ]! == c) do
285
- Macro.throwErrorAt stx "Ambiguous notation in cdot function has different numbers of '·' arguments in each alternative."
286
- return counts[0 ]!
287
- else
288
- args.foldlM (init := 0 ) (fun acc arg => return acc + (← countArgs arg))
289
- | _ => return 0
290
- /--
291
276
Auxiliary function for expanding the `·` notation.
292
277
The extra state `Array Syntax` contains the new binder names.
293
278
If `stx` is a `·`, we create a fresh identifier, store it in the
294
279
extra state, and return it. Otherwise, we just return `stx`.
295
280
-/
296
- go (numArgs : Nat) : Syntax → StateT (Array Ident) MacroM Syntax
281
+ go : Syntax → StateT (Array Ident) MacroM Syntax
297
282
| stx@`(($(_))) => pure stx
298
283
| stx@`(·) => do
299
- let i := (← get).size
300
- let name ← MonadQuotation.addMacroScope <|
301
- if numArgs == 1 then
302
- `x
303
- else
304
- Name.mkSimple s! "x{ i + 1 } "
284
+ let name ← MonadQuotation.addMacroScope <| Name.mkSimple s! "x{ (← get).size + 1 } "
305
285
let id := mkIdentFrom stx name (canonical := true )
306
286
modify (fun s => s.push id)
307
287
pure id
308
288
| stx => match stx with
309
289
| .node _ k args => do
310
290
let args ←
311
291
if k == choiceKind then
292
+ if args.isEmpty then
293
+ return stx
312
294
let s ← get
313
- let args' ← args.mapM (fun arg => go numArgs arg |>.run s)
314
- set args'[0 ]!.2
295
+ let args' ← args.mapM (fun arg => go arg |>.run s)
296
+ let s' := args'[0 ]!.2
297
+ unless args'.all (fun (_, s'') => s''.size == s'.size) do
298
+ Macro.throwErrorAt stx "Ambiguous notation in cdot function has different numbers of '·' arguments in each alternative."
299
+ set s'
315
300
pure <| args'.map Prod.fst
316
301
else
317
- args.mapM (go numArgs)
302
+ args.mapM go
318
303
return .node (.fromRef stx (canonical := true )) k args
319
304
| _ => pure stx
320
305
0 commit comments