feat: display structures and their fields properly
parent
3adb8e71d1
commit
8a58752c56
|
@ -5,7 +5,6 @@ namespace Output
|
||||||
|
|
||||||
open scoped DocGen4.Jsx
|
open scoped DocGen4.Jsx
|
||||||
|
|
||||||
|
|
||||||
def ctorToHtml (i : NameInfo) : HtmlM Html := do
|
def ctorToHtml (i : NameInfo) : HtmlM Html := do
|
||||||
let name := i.name.components'.head!.toString
|
let name := i.name.components'.head!.toString
|
||||||
return <li «class»="constructor" id={name}>{name} : [←infoFormatToHtml i.type]</li>
|
return <li «class»="constructor" id={name}>{name} : [←infoFormatToHtml i.type]</li>
|
||||||
|
|
|
@ -5,6 +5,7 @@ Authors: Henrik Böving
|
||||||
-/
|
-/
|
||||||
import DocGen4.Output.Template
|
import DocGen4.Output.Template
|
||||||
import DocGen4.Output.Inductive
|
import DocGen4.Output.Inductive
|
||||||
|
import DocGen4.Output.Structure
|
||||||
|
|
||||||
namespace DocGen4
|
namespace DocGen4
|
||||||
namespace Output
|
namespace Output
|
||||||
|
@ -30,6 +31,19 @@ def argToHtml (arg : Arg) : HtmlM Html := do
|
||||||
else
|
else
|
||||||
html
|
html
|
||||||
|
|
||||||
|
def structureInfoHeader (s : StructureInfo) : HtmlM (Array Html) := do
|
||||||
|
let mut nodes := #[]
|
||||||
|
if s.parents.size > 0 then
|
||||||
|
nodes := nodes.push <span «class»="decl_extends">extends</span>
|
||||||
|
let mut parents := #[]
|
||||||
|
for parent in s.parents do
|
||||||
|
let link := <a «class»="break_within" href={←declNameToLink parent}>{parent.toString}</a>
|
||||||
|
let inner := Html.element "span" true #[("class", "fn")] #[link]
|
||||||
|
let html:= Html.element "span" false #[("class", "decl_parent")] #[inner]
|
||||||
|
parents := parents.push html
|
||||||
|
nodes := nodes.append (parents.toList.intersperse (Html.text ", ")).toArray
|
||||||
|
nodes
|
||||||
|
|
||||||
def docInfoHeader (doc : DocInfo) : HtmlM Html := do
|
def docInfoHeader (doc : DocInfo) : HtmlM Html := do
|
||||||
let mut nodes := #[]
|
let mut nodes := #[]
|
||||||
-- TODO: noncomputable, partial
|
-- TODO: noncomputable, partial
|
||||||
|
@ -44,14 +58,19 @@ def docInfoHeader (doc : DocInfo) : HtmlM Html := do
|
||||||
</span>
|
</span>
|
||||||
for arg in doc.getArgs do
|
for arg in doc.getArgs do
|
||||||
nodes := nodes.push (←argToHtml arg)
|
nodes := nodes.push (←argToHtml arg)
|
||||||
|
|
||||||
|
if let DocInfo.structureInfo i := doc then
|
||||||
|
nodes := nodes.append (←structureInfoHeader i)
|
||||||
|
|
||||||
nodes := nodes.push <span «class»="decl_args">:</span>
|
nodes := nodes.push <span «class»="decl_args">:</span>
|
||||||
nodes := nodes.push $ Html.element "div" true #[("class", "decl_type")] (←infoFormatToHtml doc.getType)
|
nodes := nodes.push $ Html.element "div" true #[("class", "decl_type")] (←infoFormatToHtml doc.getType)
|
||||||
-- TODO: The final type of the declaration
|
-- TODO: The final type of the declaration
|
||||||
return <div «class»="decl_header"> [nodes] </div>
|
return <div «class»="decl_header"> [nodes] </div>
|
||||||
|
|
||||||
def docInfoToHtml (doc : DocInfo) : HtmlM Html := do
|
def docInfoToHtml (doc : DocInfo) : HtmlM Html := do
|
||||||
let doc_html := match doc with
|
let doc_html ← match doc with
|
||||||
| DocInfo.inductiveInfo i => inductiveToHtml i
|
| DocInfo.inductiveInfo i => inductiveToHtml i
|
||||||
|
| DocInfo.structureInfo i => structureToHtml i
|
||||||
| _ => #[]
|
| _ => #[]
|
||||||
|
|
||||||
return <div «class»="decl" id={doc.getName.toString}>
|
return <div «class»="decl" id={doc.getName.toString}>
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import DocGen4.Output.Template
|
||||||
|
|
||||||
|
namespace DocGen4
|
||||||
|
namespace Output
|
||||||
|
|
||||||
|
open scoped DocGen4.Jsx
|
||||||
|
|
||||||
|
def fieldToHtml (f : NameInfo) : HtmlM Html := do
|
||||||
|
return <li «class»="structure_field" id={f.name.toString}>{s!"{f.name} : "} [←infoFormatToHtml f.type]</li>
|
||||||
|
|
||||||
|
def structureToHtml (i : StructureInfo) : HtmlM (Array Html) := do
|
||||||
|
#[Html.element "ul" false #[("class", "structure_fields"), ("id", s!"{i.name.toString}.mk")] (←i.fieldInfo.mapM fieldToHtml)]
|
||||||
|
|
||||||
|
end Output
|
||||||
|
end DocGen4
|
|
@ -56,13 +56,8 @@ structure InductiveInfo extends Info where
|
||||||
isUnsafe : Bool
|
isUnsafe : Bool
|
||||||
deriving Inhabited
|
deriving Inhabited
|
||||||
|
|
||||||
structure FieldInfo extends NameInfo where
|
|
||||||
projFn : Name
|
|
||||||
subobject? : Option Name
|
|
||||||
deriving Inhabited
|
|
||||||
|
|
||||||
structure StructureInfo extends Info where
|
structure StructureInfo extends Info where
|
||||||
fieldInfo : Array FieldInfo
|
fieldInfo : Array NameInfo
|
||||||
parents : Array Name
|
parents : Array Name
|
||||||
ctor : NameInfo
|
ctor : NameInfo
|
||||||
deriving Inhabited
|
deriving Inhabited
|
||||||
|
@ -162,33 +157,36 @@ def InductiveInfo.ofInductiveVal (v : InductiveVal) : MetaM InductiveInfo := do
|
||||||
let ctors ← v.ctors.mapM (λ name => do NameInfo.mk name (←getConstructorType name))
|
let ctors ← v.ctors.mapM (λ name => do NameInfo.mk name (←getConstructorType name))
|
||||||
return InductiveInfo.mk info ctors v.isUnsafe
|
return InductiveInfo.mk info ctors v.isUnsafe
|
||||||
|
|
||||||
def getFieldTypeAux (type : Expr) (vars : List Name) : (Expr × List Name) :=
|
def dropArgs (type : Expr) (n : Nat) : (Expr × List (Name × Expr)) :=
|
||||||
match type with
|
match type, n with
|
||||||
| Expr.forallE `self _ b .. => (b, (`self :: vars))
|
| e, 0 => (e, [])
|
||||||
| Expr.forallE n _ b .. => getFieldTypeAux b (n :: vars)
|
| Expr.forallE name type body _, x + 1 =>
|
||||||
| _ => (type, vars)
|
let body := body.instantiate1 $ mkFVar ⟨name⟩
|
||||||
|
let next := dropArgs body x
|
||||||
|
{ next with snd := (name, type) :: next.snd}
|
||||||
|
| e, x + 1 => panic! s!"No forallE left"
|
||||||
|
|
||||||
def getFieldType (projFn : Name) : MetaM Expr := do
|
def getFieldTypes (ctor : ConstructorVal) (parents : Nat) : MetaM (Array NameInfo) := do
|
||||||
let fn ← mkConstWithFreshMVarLevels projFn
|
let type := ctor.type
|
||||||
let type ← inferType fn
|
let (field_function, params) := dropArgs type (ctor.numParams + parents)
|
||||||
let (type, vars) := getFieldTypeAux type []
|
let (_, fields) := dropArgs field_function (ctor.numFields - parents)
|
||||||
type.instantiate $ vars.toArray.map mkConst
|
let mut field_infos := #[]
|
||||||
|
for (name, type) in fields do
|
||||||
def FieldInfo.ofStructureFieldInfo (i : StructureFieldInfo) : MetaM FieldInfo := do
|
field_infos := field_infos.push { name := name, type := ←prettyPrintTerm type}
|
||||||
let type ← getFieldType i.projFn
|
field_infos
|
||||||
let ni := NameInfo.mk i.fieldName (←prettyPrintTerm type)
|
|
||||||
FieldInfo.mk ni i.projFn i.subobject?
|
|
||||||
|
|
||||||
def StructureInfo.ofInductiveVal (v : InductiveVal) : MetaM StructureInfo := do
|
def StructureInfo.ofInductiveVal (v : InductiveVal) : MetaM StructureInfo := do
|
||||||
let info ← Info.ofConstantVal v.toConstantVal
|
let info ← Info.ofConstantVal v.toConstantVal
|
||||||
let env ← getEnv
|
let env ← getEnv
|
||||||
let parents := getParentStructures env v.name
|
let parents := getParentStructures env v.name
|
||||||
let ctor := getStructureCtor env v.name |>.name
|
let ctor := getStructureCtor env v.name
|
||||||
let ctorType ← getConstructorType ctor
|
let ctorType ← prettyPrintTerm ctor.type
|
||||||
match getStructureInfo? env v.name with
|
match getStructureInfo? env v.name with
|
||||||
| some i =>
|
| some i =>
|
||||||
let fieldInfos ← i.fieldInfo.mapM FieldInfo.ofStructureFieldInfo
|
if i.fieldNames.size - parents.size > 0 then
|
||||||
return StructureInfo.mk info fieldInfos parents ⟨ctor, ctorType⟩
|
return StructureInfo.mk info (←getFieldTypes ctor parents.size) parents ⟨ctor.name, ctorType⟩
|
||||||
|
else
|
||||||
|
return StructureInfo.mk info #[] parents ⟨ctor.name, ctorType⟩
|
||||||
| none => panic! s!"{v.name} is not a structure"
|
| none => panic! s!"{v.name} is not a structure"
|
||||||
|
|
||||||
def ClassInfo.ofInductiveVal (v : InductiveVal) : MetaM ClassInfo := do
|
def ClassInfo.ofInductiveVal (v : InductiveVal) : MetaM ClassInfo := do
|
||||||
|
|
|
@ -421,7 +421,7 @@ main h2, main h3, main h4, main h5, main h6 {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.decl_args, .decl_type {
|
.decl_args, .decl_type .decl_parent {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,7 +430,7 @@ main h2, main h3, main h4, main h5, main h6 {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.decl_kind, .decl_name {
|
.decl_kind, .decl_name, .decl_extends {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,14 +480,7 @@ pre code { padding: 0 0; }
|
||||||
|
|
||||||
.structure_field {
|
.structure_field {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
margin-left: 2ex;
|
||||||
.structure_field:before {
|
|
||||||
content: '(';
|
|
||||||
color: gray;
|
|
||||||
}
|
|
||||||
.structure_field:after {
|
|
||||||
content: ')';
|
|
||||||
color: gray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.constructor {
|
.constructor {
|
||||||
|
|
Loading…
Reference in New Issue