feat: allow combining private/public and protected
This commit is contained in:
parent
ad471b46b8
commit
ca43608aa0
10 changed files with 52 additions and 48 deletions
|
|
@ -49,26 +49,21 @@ def checkNotAlreadyDeclared {m} [Monad m] [MonadEnv m] [MonadError m] [MonadFina
|
|||
addInfo declName
|
||||
throwError "a non-private declaration '{.ofConstName declName true}' has already been declared"
|
||||
|
||||
/-- Declaration visibility modifier. That is, whether a declaration is regular, protected or private. -/
|
||||
/-- Declaration visibility modifier. That is, whether a declaration is public or private or inherits its visibility from the outer scope. -/
|
||||
inductive Visibility where
|
||||
| regular | «protected» | «private» | «public»
|
||||
| regular | «private» | «public»
|
||||
deriving Inhabited
|
||||
|
||||
instance : ToString Visibility where
|
||||
toString
|
||||
| .regular => "regular"
|
||||
| .private => "private"
|
||||
| .protected => "protected"
|
||||
| .public => "public"
|
||||
|
||||
def Visibility.isPrivate : Visibility → Bool
|
||||
| .private => true
|
||||
| _ => false
|
||||
|
||||
def Visibility.isProtected : Visibility → Bool
|
||||
| .protected => true
|
||||
| _ => false
|
||||
|
||||
def Visibility.isPublic : Visibility → Bool
|
||||
| .public => true
|
||||
| _ => false
|
||||
|
|
@ -92,6 +87,7 @@ structure Modifiers where
|
|||
stx : TSyntax ``Parser.Command.declModifiers := ⟨.missing⟩
|
||||
docString? : Option (TSyntax ``Parser.Command.docComment) := none
|
||||
visibility : Visibility := Visibility.regular
|
||||
isProtected : Bool := false
|
||||
computeKind : ComputeKind := .regular
|
||||
recKind : RecKind := RecKind.default
|
||||
isUnsafe : Bool := false
|
||||
|
|
@ -99,7 +95,6 @@ structure Modifiers where
|
|||
deriving Inhabited
|
||||
|
||||
def Modifiers.isPrivate (m : Modifiers) : Bool := m.visibility.isPrivate
|
||||
def Modifiers.isProtected (m : Modifiers) : Bool := m.visibility.isProtected
|
||||
def Modifiers.isPublic (m : Modifiers) : Bool := m.visibility.isPublic
|
||||
def Modifiers.isInferredPublic (env : Environment) (m : Modifiers) : Bool :=
|
||||
m.visibility.isInferredPublic env
|
||||
|
|
@ -147,8 +142,8 @@ instance : ToFormat Modifiers := ⟨fun m =>
|
|||
++ (match m.visibility with
|
||||
| .regular => []
|
||||
| .private => [f!"private"]
|
||||
| .protected => [f!"protected"]
|
||||
| .public => [f!"public"])
|
||||
++ (if m.isProtected then [f!"protected"] else [])
|
||||
++ (match m.computeKind with | .regular => [] | .meta => [f!"meta"] | .noncomputable => [f!"noncomputable"])
|
||||
++ (match m.recKind with | RecKind.partial => [f!"partial"] | RecKind.nonrec => [f!"nonrec"] | _ => [])
|
||||
++ (if m.isUnsafe then [f!"unsafe"] else [])
|
||||
|
|
@ -176,18 +171,19 @@ def elabModifiers (stx : TSyntax ``Parser.Command.declModifiers) : m Modifiers :
|
|||
let docCommentStx := stx.raw[0]
|
||||
let attrsStx := stx.raw[1]
|
||||
let visibilityStx := stx.raw[2]
|
||||
let protectedStx := stx.raw[3]
|
||||
let computeKind :=
|
||||
if stx.raw[3].isNone then
|
||||
if stx.raw[4].isNone then
|
||||
.regular
|
||||
else if stx.raw[3][0].getKind == ``Parser.Command.meta then
|
||||
else if stx.raw[4][0].getKind == ``Parser.Command.meta then
|
||||
.meta
|
||||
else
|
||||
.noncomputable
|
||||
let unsafeStx := stx.raw[4]
|
||||
let unsafeStx := stx.raw[5]
|
||||
let recKind :=
|
||||
if stx.raw[5].isNone then
|
||||
if stx.raw[6].isNone then
|
||||
RecKind.default
|
||||
else if stx.raw[5][0].getKind == ``Parser.Command.partial then
|
||||
else if stx.raw[6][0].getKind == ``Parser.Command.partial then
|
||||
RecKind.partial
|
||||
else
|
||||
RecKind.nonrec
|
||||
|
|
@ -197,14 +193,14 @@ def elabModifiers (stx : TSyntax ``Parser.Command.declModifiers) : m Modifiers :
|
|||
| some v =>
|
||||
match v with
|
||||
| `(Parser.Command.visibility| private) => pure .private
|
||||
| `(Parser.Command.visibility| protected) => pure .protected
|
||||
| `(Parser.Command.visibility| public) => pure .public
|
||||
| _ => throwErrorAt v "unexpected visibility modifier"
|
||||
let isProtected := !protectedStx.isNone
|
||||
let attrs ← match attrsStx.getOptional? with
|
||||
| none => pure #[]
|
||||
| some attrs => elabDeclAttrs attrs
|
||||
return {
|
||||
stx, docString?, visibility, computeKind, recKind, attrs,
|
||||
stx, docString?, visibility, isProtected, computeKind, recKind, attrs,
|
||||
isUnsafe := !unsafeStx.isNone
|
||||
}
|
||||
|
||||
|
|
@ -213,12 +209,12 @@ Ensure the function has not already been declared, and apply the given visibilit
|
|||
If `private`, return the updated name using our internal encoding for private names.
|
||||
If `protected`, register `declName` as protected in the environment.
|
||||
-/
|
||||
def applyVisibility (visibility : Visibility) (declName : Name) : m Name := do
|
||||
def applyVisibility (modifiers : Modifiers) (declName : Name) : m Name := do
|
||||
let mut declName := declName
|
||||
if !visibility.isInferredPublic (← getEnv) then
|
||||
if !modifiers.visibility.isInferredPublic (← getEnv) then
|
||||
declName := mkPrivateName (← getEnv) declName
|
||||
checkNotAlreadyDeclared declName
|
||||
if visibility matches .protected then
|
||||
if modifiers.isProtected then
|
||||
modifyEnv fun env => addProtected env declName
|
||||
pure declName
|
||||
|
||||
|
|
@ -246,16 +242,16 @@ def mkDeclName (currNamespace : Name) (modifiers : Modifiers) (shortName : Name)
|
|||
shortName := Name.mkSimple s
|
||||
currNamespace := p.replacePrefix `_root_ Name.anonymous
|
||||
checkIfShadowingStructureField declName
|
||||
let declName ← applyVisibility modifiers.visibility declName
|
||||
match modifiers.visibility with
|
||||
| Visibility.protected =>
|
||||
let declName ← applyVisibility modifiers declName
|
||||
if modifiers.isProtected then
|
||||
match currNamespace with
|
||||
| .str _ s => return (declName, Name.mkSimple s ++ shortName)
|
||||
| _ =>
|
||||
if shortName.isAtomic then
|
||||
throwError "protected declarations must be in a namespace"
|
||||
return (declName, shortName)
|
||||
| _ => return (declName, shortName)
|
||||
else
|
||||
return (declName, shortName)
|
||||
|
||||
/--
|
||||
`declId` is of the form
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ private def inductiveSyntaxToView (modifiers : Modifiers) (decl : Syntax) : Term
|
|||
checkValidCtorModifier ctorModifiers
|
||||
let ctorName := ctor.getIdAt 3
|
||||
let ctorName := declName ++ ctorName
|
||||
let ctorName ← withRef ctor[3] <| applyVisibility ctorModifiers.visibility ctorName
|
||||
let ctorName ← withRef ctor[3] <| applyVisibility ctorModifiers ctorName
|
||||
let (binders, type?) := expandOptDeclSig ctor[4]
|
||||
addDocString' ctorName ctorModifiers.docString?
|
||||
addDeclarationRangesFromSyntax ctorName ctor ctor[3]
|
||||
|
|
|
|||
|
|
@ -1021,8 +1021,8 @@ private def applyComputedFields (indViews : Array InductiveView) : CommandElabM
|
|||
for {ref, fieldId, type, matchAlts, modifiers, ..} in indView.computedFields do
|
||||
computedFieldDefs := computedFieldDefs.push <| ← do
|
||||
let modifiers ← match modifiers with
|
||||
| `(Lean.Parser.Command.declModifiersT| $[$doc:docComment]? $[$attrs:attributes]? $[$vis]? $[noncomputable]?) =>
|
||||
`(Lean.Parser.Command.declModifiersT| $[$doc]? $[$attrs]? $[$vis]? noncomputable)
|
||||
| `(Lean.Parser.Command.declModifiersT| $[$doc:docComment]? $[$attrs:attributes]? $[$vis]? $[protected%$protectedTk]? $[noncomputable]?) =>
|
||||
`(Lean.Parser.Command.declModifiersT| $[$doc]? $[$attrs]? $[$vis]? $[protected%$protectedTk]? noncomputable)
|
||||
| _ => do
|
||||
withRef modifiers do logError "Unsupported modifiers for computed field"
|
||||
`(Parser.Command.declModifiersT| noncomputable)
|
||||
|
|
|
|||
|
|
@ -233,11 +233,12 @@ private def expandCtor (structStx : Syntax) (structModifiers : Modifiers) (struc
|
|||
(forcePrivate : Bool) : TermElabM CtorView := do
|
||||
let useDefault := do
|
||||
let visibility := if forcePrivate then .private else .regular
|
||||
let modifiers := { (default : Modifiers) with visibility }
|
||||
let declName := structDeclName ++ defaultCtorName
|
||||
let declName ← applyVisibility visibility declName
|
||||
let declName ← applyVisibility modifiers declName
|
||||
let ref := structStx[1].mkSynthetic
|
||||
addDeclarationRangesFromSyntax declName ref
|
||||
pure { ref, declId := ref, modifiers := { (default : Modifiers) with visibility }, declName }
|
||||
pure { ref, declId := ref, modifiers, declName }
|
||||
if structStx[4].isNone then
|
||||
useDefault
|
||||
else
|
||||
|
|
@ -273,7 +274,7 @@ private def expandCtor (structStx : Syntax) (structModifiers : Modifiers) (struc
|
|||
throwError m!"Constructor must be `private` because one or more of this structure's fields are `private`" ++ hint
|
||||
let name := ctor[1].getId
|
||||
let declName := structDeclName ++ name
|
||||
let declName ← applyVisibility ctorModifiers.visibility declName
|
||||
let declName ← applyVisibility ctorModifiers declName
|
||||
-- `binders` is type parameter binder overrides; this will be validated when the constructor is created in `Structure.mkCtor`.
|
||||
let binders := ctor[2]
|
||||
addDocString' declName ctorModifiers.docString?
|
||||
|
|
@ -379,7 +380,7 @@ private def expandFields (structStx : Syntax) (structModifiers : Modifiers) (str
|
|||
unless name.isAtomic do
|
||||
throwErrorAt ident "Invalid field name `{name.eraseMacroScopes}`: Field names must be atomic"
|
||||
let declName := structDeclName ++ name
|
||||
let declName ← applyVisibility fieldModifiers.visibility declName
|
||||
let declName ← applyVisibility fieldModifiers declName
|
||||
addDocString' declName fieldModifiers.docString?
|
||||
return views.push {
|
||||
ref := ident
|
||||
|
|
@ -611,13 +612,11 @@ private def getFieldDefault? (structName : Name) (params : Array Expr) (fieldNam
|
|||
else
|
||||
return none
|
||||
|
||||
private def toVisibility (fieldInfo : StructureFieldInfo) : CoreM Visibility := do
|
||||
if isProtected (← getEnv) fieldInfo.projFn then
|
||||
return Visibility.protected
|
||||
else if isPrivateName fieldInfo.projFn then
|
||||
return Visibility.private
|
||||
else
|
||||
return Visibility.regular
|
||||
private def toModifiers (fieldInfo : StructureFieldInfo) : CoreM Modifiers := do
|
||||
return {
|
||||
isProtected := isProtected (← getEnv) fieldInfo.projFn
|
||||
visibility := if isPrivateName fieldInfo.projFn then .private else .regular
|
||||
}
|
||||
|
||||
mutual
|
||||
|
||||
|
|
@ -654,7 +653,7 @@ private partial def withStructField (view : StructView) (sourceStructNames : Lis
|
|||
its default value is overridden, otherwise the `declName` is irrelevant, except to ensure a declaration is not already declared. -/
|
||||
let mut declName := view.declName ++ fieldName
|
||||
if inSubobject?.isNone then
|
||||
declName ← applyVisibility (← toVisibility fieldInfo) declName
|
||||
declName ← applyVisibility (← toModifiers fieldInfo) declName
|
||||
-- No need to validate links because this docstring was already added to the environment previously
|
||||
addDocStringCore' declName (← findDocString? (← getEnv) fieldInfo.projFn)
|
||||
addDeclarationRangesFromSyntax declName (← getRef)
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ builtin_initialize addBuiltinUnusedVariablesIgnoreFn (fun _ stack _ =>
|
|||
stx.isOfKind ``Lean.Parser.Command.optDeclSig ||
|
||||
stx.isOfKind ``Lean.Parser.Command.declSig) &&
|
||||
(stack[5]? |>.any fun (stx, _) => match stx[0] with
|
||||
| `(Lean.Parser.Command.declModifiersT| $[$_:docComment]? @[$[$attrs:attr],*] $[$vis]? $[noncomputable]?) =>
|
||||
| `(Lean.Parser.Command.declModifiersT| $[$_:docComment]? @[$[$attrs:attr],*] $[$vis]? $[protected]? $[noncomputable]?) =>
|
||||
attrs.any (fun attr => attr.raw.isOfKind ``Parser.Attr.extern || attr matches `(attr| implemented_by $_))
|
||||
| _ => false))
|
||||
|
||||
|
|
|
|||
|
|
@ -62,11 +62,11 @@ def namedPrio := leading_parser
|
|||
def optNamedPrio := optional namedPrio
|
||||
|
||||
def «private» := leading_parser "private "
|
||||
def «protected» := leading_parser "protected "
|
||||
def «public» := leading_parser "public "
|
||||
def visibility :=
|
||||
withAntiquot (mkAntiquot "visibility" decl_name% (isPseudoKind := true)) <|
|
||||
«private» <|> «protected» <|> «public»
|
||||
«private» <|> «public»
|
||||
def «protected» := leading_parser "protected "
|
||||
def «meta» := leading_parser "meta "
|
||||
def «noncomputable» := leading_parser "noncomputable "
|
||||
def «unsafe» := leading_parser "unsafe "
|
||||
|
|
@ -76,7 +76,8 @@ def «nonrec» := leading_parser "nonrec "
|
|||
/-- `declModifiers` is the collection of modifiers on a declaration:
|
||||
* a doc comment `/-- ... -/`
|
||||
* a list of attributes `@[attr1, attr2]`
|
||||
* a visibility specifier, `private`, `protected`, or `public`
|
||||
* a visibility specifier, `private` or `public`
|
||||
* `protected`
|
||||
* `noncomputable`
|
||||
* `unsafe`
|
||||
* `partial` or `nonrec`
|
||||
|
|
@ -90,6 +91,7 @@ such as inductive constructors, structure projections, and `let rec` / `where` d
|
|||
optional docComment >>
|
||||
optional (Term.«attributes» >> if inline then skip else ppDedent ppLine) >>
|
||||
optional visibility >>
|
||||
optional «protected» >>
|
||||
optional («meta» <|> «noncomputable») >>
|
||||
optional «unsafe» >>
|
||||
optional («partial» <|> «nonrec»)
|
||||
|
|
|
|||
|
|
@ -347,6 +347,12 @@ instance : DecodeToml Dependency := ⟨fun v => do Dependency.decodeToml (← v.
|
|||
|
||||
/-! ## Package & Target Configuration Decoders -/
|
||||
|
||||
section
|
||||
-- We automatically disable the following option for `macro`s but the subsequent `def` both contains
|
||||
-- a quotation and is called only by `macro`s, so we disable the option for it manually. Note that
|
||||
-- we can't use `in` as it is parsed as a single command and so the option would not influence the
|
||||
-- parser.
|
||||
set_option internal.parseQuotWithCurrentStage false
|
||||
private def genDecodeToml
|
||||
(cmds : Array Command)
|
||||
(tyName : Name) [info : ConfigInfo tyName] (takesName : Bool)
|
||||
|
|
@ -366,6 +372,7 @@ private def genDecodeToml
|
|||
let instId ← mkIdentFromRef <| `_root_ ++ tyName.str "instDecodeToml"
|
||||
let cmds ← cmds.push <$> `(instance $instId:ident : DecodeToml $ty := ⟨decodeTableValue $decId⟩)
|
||||
return cmds
|
||||
end
|
||||
|
||||
local macro "gen_toml_decoders%" : command => do
|
||||
let cmds := #[]
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ StxQuot.lean:8:12-8:13: error: unexpected token ')'; expected identifier or term
|
|||
"(«term_+_» (num \"1\") \"+\" (num \"1\"))"
|
||||
StxQuot.lean:19:15-19:16: error: unexpected token ']'; expected term
|
||||
"(Term.fun \"fun\" (Term.basicFun [`a._@.UnhygienicMain._hyg.1] [] \"=>\" `a._@.UnhygienicMain._hyg.1))"
|
||||
"(Command.declaration\n (Command.declModifiers [] [] [] [] [] [])\n (Command.definition\n \"def\"\n (Command.declId `foo._@.UnhygienicMain._hyg.1 [])\n (Command.optDeclSig [] [])\n (Command.declValSimple \":=\" (num \"1\") (Termination.suffix [] []) [])\n []))"
|
||||
"[(Command.declaration\n (Command.declModifiers [] [] [] [] [] [])\n (Command.definition\n \"def\"\n (Command.declId `foo._@.UnhygienicMain._hyg.1 [])\n (Command.optDeclSig [] [])\n (Command.declValSimple \":=\" (num \"1\") (Termination.suffix [] []) [])\n []))\n (Command.declaration\n (Command.declModifiers [] [] [] [] [] [])\n (Command.definition\n \"def\"\n (Command.declId `bar._@.UnhygienicMain._hyg.1 [])\n (Command.optDeclSig [] [])\n (Command.declValSimple \":=\" (num \"2\") (Termination.suffix [] []) [])\n []))]"
|
||||
"(Command.declaration\n (Command.declModifiers [] [] [] [] [] [] [])\n (Command.definition\n \"def\"\n (Command.declId `foo._@.UnhygienicMain._hyg.1 [])\n (Command.optDeclSig [] [])\n (Command.declValSimple \":=\" (num \"1\") (Termination.suffix [] []) [])\n []))"
|
||||
"[(Command.declaration\n (Command.declModifiers [] [] [] [] [] [] [])\n (Command.definition\n \"def\"\n (Command.declId `foo._@.UnhygienicMain._hyg.1 [])\n (Command.optDeclSig [] [])\n (Command.declValSimple \":=\" (num \"1\") (Termination.suffix [] []) [])\n []))\n (Command.declaration\n (Command.declModifiers [] [] [] [] [] [] [])\n (Command.definition\n \"def\"\n (Command.declId `bar._@.UnhygienicMain._hyg.1 [])\n (Command.optDeclSig [] [])\n (Command.declValSimple \":=\" (num \"2\") (Termination.suffix [] []) [])\n []))]"
|
||||
"`Nat.one._@.UnhygienicMain._hyg.1"
|
||||
"`Nat.one._@.UnhygienicMain._hyg.1"
|
||||
"(Term.app `f._@.UnhygienicMain._hyg.1 [`Nat.one._@.UnhygienicMain._hyg.1 `Nat.one._@.UnhygienicMain._hyg.1])"
|
||||
|
|
@ -18,8 +18,8 @@ StxQuot.lean:19:15-19:16: error: unexpected token ']'; expected term
|
|||
"(Term.proj `Nat.one._@.UnhygienicMain._hyg.1 \".\" `b._@.UnhygienicMain._hyg.1)"
|
||||
"(«term_+_» (num \"2\") \"+\" (num \"1\"))"
|
||||
"(«term_+_» («term_+_» (num \"1\") \"+\" (num \"2\")) \"+\" (num \"1\"))"
|
||||
"(Command.declaration\n (Command.declModifiers [] [] [] [] [] [])\n (Command.definition\n \"def\"\n (Command.declId `foo._@.UnhygienicMain._hyg.1 [])\n (Command.optDeclSig [] [])\n (Command.declValSimple \":=\" (num \"1\") (Termination.suffix [] []) [])\n []))"
|
||||
"[(Command.declaration\n (Command.declModifiers [] [] [] [] [] [])\n (Command.definition\n \"def\"\n (Command.declId `bar._@.UnhygienicMain._hyg.1 [])\n (Command.optDeclSig [] [])\n (Command.declValSimple \":=\" (num \"2\") (Termination.suffix [] []) [])\n []))\n (Command.declaration\n (Command.declModifiers [] [] [] [] [] [])\n (Command.definition\n \"def\"\n (Command.declId `foo._@.UnhygienicMain._hyg.1 [])\n (Command.optDeclSig [] [])\n (Command.declValSimple \":=\" (num \"1\") (Termination.suffix [] []) [])\n []))]"
|
||||
"(Command.declaration\n (Command.declModifiers [] [] [] [] [] [] [])\n (Command.definition\n \"def\"\n (Command.declId `foo._@.UnhygienicMain._hyg.1 [])\n (Command.optDeclSig [] [])\n (Command.declValSimple \":=\" (num \"1\") (Termination.suffix [] []) [])\n []))"
|
||||
"[(Command.declaration\n (Command.declModifiers [] [] [] [] [] [] [])\n (Command.definition\n \"def\"\n (Command.declId `bar._@.UnhygienicMain._hyg.1 [])\n (Command.optDeclSig [] [])\n (Command.declValSimple \":=\" (num \"2\") (Termination.suffix [] []) [])\n []))\n (Command.declaration\n (Command.declModifiers [] [] [] [] [] [] [])\n (Command.definition\n \"def\"\n (Command.declId `foo._@.UnhygienicMain._hyg.1 [])\n (Command.optDeclSig [] [])\n (Command.declValSimple \":=\" (num \"1\") (Termination.suffix [] []) [])\n []))]"
|
||||
"0"
|
||||
0
|
||||
1
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
partialSyntaxTraces.lean:6:0: error: unexpected end of input; expected ':=', 'where' or '|'
|
||||
[Elab.command] [Error pretty printing syntax: parenthesize: uncaught backtrack exception. Falling back to raw printer.]
|
||||
(Command.declaration
|
||||
(Command.declModifiers [] [] [] [] [] [])
|
||||
(Command.declModifiers [] [] [] [] [] [] [])
|
||||
(Command.definition "def" (Command.declId `f []) (Command.optDeclSig [] []) (Command.whereStructInst <missing>)))
|
||||
[Elab.command]
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ necessary correction is reasonably unambiguous.
|
|||
error: Constructor must be `private` because one or more of this structure's fields are `private`
|
||||
|
||||
Hint: Mark constructor as `private`
|
||||
p̵r̵o̵t̵e̵c̵t̵e̵d̵p̲r̲i̲v̲a̲t̲e̲ mk ::
|
||||
p̲r̲i̲v̲a̲t̲e̲ ̲protected mk ::
|
||||
-/
|
||||
#guard_msgs in
|
||||
structure Foo where
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue