-
Notifications
You must be signed in to change notification settings - Fork 98
feat: elaborate block structures as concrete elements #693
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
base: concrete-block
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -799,11 +799,27 @@ public abbrev DirectiveExpander := Array Arg → TSyntaxArray `block → DocElab | |||||
|
|
||||||
| public abbrev DirectiveExpanderOf α := α → TSyntaxArray `block → DocElabM Term | ||||||
|
|
||||||
| public abbrev DirectiveElaborator := Array Arg → TSyntaxArray `block → DocElabM (Array Target.Block) | ||||||
|
|
||||||
| /-- | ||||||
| The type of directive elaborators. In order to give a declaration of type {lean}`DirectiveElabOf α` | ||||||
| the {lit}`@[directive]` annotation, it must be possible to synthesize {lean}`FromArgs α DocElabM`. | ||||||
| -/ | ||||||
| public abbrev DirectiveElabOf (α : Type) := α → TSyntaxArray `block → DocElabM Target.Block | ||||||
|
|
||||||
| public def directiveExpanderToElaborator (expander : DirectiveExpander) : DirectiveElaborator | ||||||
| | args, contents => do return (← expander args contents).map (.stx ·) | ||||||
|
|
||||||
|
|
||||||
| initialize directiveExpanderAttr : KeyedDeclsAttribute DirectiveExpander ← | ||||||
| mkDocExpanderAttribute `directive_expander ``DirectiveExpander "Indicates that this function is used to implement a given directive" `directiveExpanderAttr | ||||||
|
|
||||||
| public def toDirective {α : Type} [FromArgs α DocElabM] (expander : α → TSyntaxArray `block → DocElabM Term) : DirectiveExpander := | ||||||
| public def toDirectiveTerm {α : Type} [FromArgs α DocElabM] (expander : α → TSyntaxArray `block → DocElabM Term) : DirectiveElaborator := | ||||||
| fun args blocks => do | ||||||
| let v ← ArgParse.parse args | ||||||
| return #[.stx (← expander v blocks)] | ||||||
|
|
||||||
| public def toDirective {α : Type} [FromArgs α DocElabM] (expander : α → TSyntaxArray `block → DocElabM Target.Block) : DirectiveElaborator := | ||||||
| fun args blocks => do | ||||||
| let v ← ArgParse.parse args | ||||||
| return #[← expander v blocks] | ||||||
|
|
@@ -838,14 +854,29 @@ unsafe initialize registerBuiltinAttribute { | |||||
|
|
||||||
| let n ← mkFreshUserName <| declName ++ `directive | ||||||
|
|
||||||
| -- Find the appropriate adapter for both new (`DirectiveElabOf`) and legacy (`DirectiveExpanderOf`) declarations | ||||||
| let constructor ← match (← getEnv).find? declName |>.map (·.type.getAppFn) with | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is probably correct, but I figured I'd flag it up just to be sure. Right now, this will reject user-written
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||
| | some (Expr.const ``DirectiveExpanderOf _) => pure ``toDirectiveTerm | ||||||
| | some (Expr.const ``DirectiveElabOf _) => pure ``toDirective | ||||||
| | some e => | ||||||
| logWarning m!"Declaration tagged with `@[directive]` has type{indentD e}\nwhich is not in \ | ||||||
| one of the expected forms `{.ofConstName ``DirectiveExpanderOf} _` or \ | ||||||
| `{.ofConstName ``DirectiveElabOf} _`" | ||||||
| pure ``toDirective | ||||||
| | none => | ||||||
| logError m!"Unexpected error: definition of `{declName}` not found" | ||||||
| return | ||||||
|
|
||||||
| let ((e, t), _) ← Meta.MetaM.run (ctx := {}) (s := {}) do | ||||||
| let e ← Meta.mkAppM ``toDirective #[.const declName []] | ||||||
| let e ← Meta.mkAppM constructor #[.const declName []] | ||||||
| let e ← instantiateMVars e | ||||||
| let t ← Meta.inferType e | ||||||
|
|
||||||
|
|
||||||
| match_expr e with | ||||||
| | toDirective ty _ _ => saveSignature n ty | ||||||
| | toDirectiveTerm ty _ _ => | ||||||
| saveSignature n ty | ||||||
| | toDirective ty _ _ => | ||||||
| saveSignature n ty | ||||||
| | _ => pure () | ||||||
|
|
||||||
| pure (e, t) | ||||||
|
|
@@ -865,10 +896,10 @@ unsafe initialize registerBuiltinAttribute { | |||||
| directiveExpanderExt.addEntry env (directiveName, n) | ||||||
| } | ||||||
|
|
||||||
| private unsafe def directiveExpandersForUnsafe' (x : Name) : DocElabM (Array (DirectiveExpander × Option String × Option SigDoc)) := do | ||||||
| private unsafe def directiveExpandersForUnsafe' (x : Name) : DocElabM (Array (DirectiveElaborator × Option String × Option SigDoc)) := do | ||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't the function be renamed too?
Suggested change
|
||||||
| let expanders := directiveExpanderExt.getState (← getEnv) |>.find? x |>.getD #[] | ||||||
| expanders.mapM fun n => do | ||||||
| let e ← evalConst DirectiveExpander n | ||||||
| let e ← evalConst DirectiveElaborator n | ||||||
| let doc? ← findDocString? (← getEnv) n | ||||||
| let sig := expanderSignatureExt.getState (← getEnv) |>.find? n | ||||||
| return (e, doc?, sig) | ||||||
|
|
@@ -877,11 +908,11 @@ private unsafe def directiveExpandersForUnsafe'' (x : Name) : DocElabM (Array Di | |||||
| let expanders := directiveExpanderAttr.getEntries (← getEnv) x | ||||||
| return expanders.map (·.value) |>.toArray | ||||||
|
|
||||||
| private unsafe def directiveExpandersForUnsafe (x : Name) : DocElabM (Array (DirectiveExpander × Option String × Option SigDoc)) := do | ||||||
| return (← directiveExpandersForUnsafe' x) ++ (← directiveExpandersForUnsafe'' x).map (·, none, none) | ||||||
| private unsafe def directiveExpandersForUnsafe (x : Name) : DocElabM (Array (DirectiveElaborator × Option String × Option SigDoc)) := do | ||||||
| return (← directiveExpandersForUnsafe' x) ++ (← directiveExpandersForUnsafe'' x).map (directiveExpanderToElaborator ·, none, none) | ||||||
|
|
||||||
| @[implemented_by directiveExpandersForUnsafe] | ||||||
| public opaque directiveExpandersFor (x : Name) : DocElabM (Array (DirectiveExpander × Option String × Option SigDoc)) | ||||||
| public opaque directiveExpandersFor (x : Name) : DocElabM (Array (DirectiveElaborator × Option String × Option SigDoc)) | ||||||
|
|
||||||
|
|
||||||
| public abbrev BlockCommandExpander := Array Arg → DocElabM (Array (TSyntax `term)) | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want this old-school version to be public?