Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
41d1d54
Add tester functions and tests
Nov 25, 2025
2a34f02
Add destructors
Nov 25, 2025
e089b37
Adding datatypes to Boogie AST, in progress
Nov 26, 2025
dd94853
Add datatypes to LContext
Nov 26, 2025
43b18dc
Add datatype to Boogie typing and merge LContext change
Nov 26, 2025
74edfb7
Add datatypes to SMTContext and thread through LMonoTy.toSMTType
Nov 28, 2025
5cf2834
Add declare-datatypes and derived functions through verif pipeline
Nov 28, 2025
cab23ef
Store generated ADT functions in map
Nov 28, 2025
34ef206
Fix Boogie datatype tests
Nov 28, 2025
9f0b2f9
Minor cleanup
Dec 1, 2025
50a747f
Improve tests and remove some useless code
Dec 1, 2025
d1987e3
Merge branch 'main' into josh/declare-datatype
Dec 1, 2025
146a0ec
A few formatting fixes
Dec 1, 2025
c1b7ac0
Merge branch 'main' into josh/declare-datatype
Dec 3, 2025
535d56a
Merge branch 'main' into josh/declare-datatype
Dec 4, 2025
9a1c3eb
Merge branch 'main' into josh/declare-datatype
Dec 4, 2025
b101d94
Allow different names for testers/destructors, change Boogie prelude …
Dec 5, 2025
db33fba
Fix bug with datatypes using sorts or nested types in constructors
Dec 24, 2025
691e9f5
Add test case for datatype dependencies
Dec 24, 2025
9a9b45a
Add topological sorting for datatype dependencies and tests
Dec 24, 2025
75d47fb
Merge branch 'main' into josh/declare-datatype
Dec 24, 2025
319790f
Formatting changes from comments
Dec 24, 2025
6e66c65
Minor formatting fixes
Dec 24, 2025
2f007d7
Formatting fixes and limit comment length in TypeFactory.lean
Dec 26, 2025
d60e0d2
Fix formatting in SMT datatype tests
Dec 26, 2025
8ee229a
Merge branch 'main' into josh/declare-datatype
Dec 30, 2025
b73b779
New version of datatypes in Boogie with tests
Dec 30, 2025
52efb63
Add Other datatype dialect and fix references to Boogie in Ast.lean
Dec 30, 2025
8e718cb
Change BoogiePrelude to use datatypes
Dec 31, 2025
5f28b43
Merge branch 'main' into josh/declare-datatype
shigoel Dec 31, 2025
5ea7442
Merge branch 'main' into concrete-ast-ddm-2
Dec 31, 2025
53239fc
Add default tester names and better comments for datatype tests
Dec 31, 2025
2779c63
Merge branch 'josh/declare-datatype' into concrete-ast-ddm-2
Dec 31, 2025
4b56c58
Add missing file
Dec 31, 2025
fcb138c
Add constructor annotations
Dec 31, 2025
1e3e48a
Add field list annotations, remove hard-coded names
Dec 31, 2025
e35e74e
Clean up some Translate code to reduce duplication
Dec 31, 2025
292db8b
Add documentation to new AST declarations
Dec 31, 2025
13a3895
Move parts of datatype AST and add datatype docs
Dec 31, 2025
e3fcc87
Remove Boogie Minimal example
Dec 31, 2025
28d0932
Clean up code and documentation
Jan 2, 2026
d3099dd
Fix BoogiePrelude destructor names
Jan 2, 2026
0a6a00c
Clean up Boogie Parse.lean
Jan 2, 2026
885d6b3
Make None datatype in BoogiePrelude for computation
Jan 2, 2026
58c44b2
Update expected output with newly passing tests
Jan 2, 2026
5a5b75b
Remove perConstructorField and fieldIndex
Jan 2, 2026
5a89311
Trying again incrementally - add tvar
Jan 6, 2026
90db0c6
Poly implementation v2
Jan 6, 2026
fc4bc1c
Merge branch 'main' into josh/concrete-ast-ddm-2
Jan 6, 2026
959ec14
Fix minor bugs and add tests for polymorphic DDM definitions
Jan 7, 2026
ddedf98
Merge branch 'main' into josh/ddm-poly-2
Jan 7, 2026
b13ebd6
Add polymorphic datatype support with tests
Jan 7, 2026
ba8478f
Update Python Boogie prelude with polymorphic type
Jan 7, 2026
b455a1b
Merge branch 'main' into josh/concrete-ast-ddm-2
Jan 7, 2026
375de36
Merge branch 'josh/concrete-ast-ddm-2' into josh/ddm-poly-2
Jan 7, 2026
f2b6aae
Remove unecessary scope annotations from fields
Jan 8, 2026
57ee2ed
Update datatype documentation, add to DDM manual
Jan 8, 2026
e18d13f
Merge branch 'main' into josh/concrete-ast-ddm-2
Jan 8, 2026
6e1b98c
Add small clarification about fields
Jan 8, 2026
2d82afd
Remove special handling for fields, replace with generic Bindings
Jan 9, 2026
d603ed9
Merge branch 'main' into josh/concrete-ast-ddm-2
Jan 9, 2026
6498223
Merge branch 'main' into josh/concrete-ast-ddm-2
Jan 9, 2026
a75f32a
Merge branch 'main' into josh/concrete-ast-ddm-2
Jan 12, 2026
1b72d26
Merge branch 'main' into josh/ddm-poly-2
Jan 12, 2026
44141bd
Merge branch 'josh/concrete-ast-ddm-2' into josh/ddm-poly-2
Jan 12, 2026
ab33f31
Fix error message on tests
Jan 12, 2026
e43524e
Clean up comments
Jan 12, 2026
edfd3bd
Remove unecessary tests and test comments in polymorphic tests
Jan 12, 2026
b9f174c
Merge branch 'main' into josh/concrete-ast-ddm-2
Jan 12, 2026
99d2640
Merge branch 'josh/concrete-ast-ddm-2' into josh/ddm-poly-2
Jan 12, 2026
07c87f8
Update Verso documentation
Jan 13, 2026
89e45bd
Merge branch 'main' into josh/ddm-poly-2
Jan 13, 2026
26f12be
Merge branch 'main' into josh/concrete-ast-ddm-2
Jan 13, 2026
abfbd94
Update Python expected README
Jan 13, 2026
6c3abfe
Merge branch 'main' into josh/concrete-ast-ddm-2
Jan 13, 2026
3740d73
Merge branch 'josh/concrete-ast-ddm-2' into josh/ddm-poly-2
Jan 13, 2026
e4c025f
Merge branch 'main' into josh/ddm-poly-2
Jan 14, 2026
f488fa9
Uncomment test
Jan 14, 2026
61adec2
Merge branch 'main' into josh/ddm-poly-2
joscoh Jan 14, 2026
fb8592d
Merge branch 'main' into josh/ddm-poly-2
Jan 14, 2026
086ebaf
Merge branch 'main' into josh/ddm-poly-2
Jan 15, 2026
47379b1
Update test output
Jan 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions Strata/DDM/AST.lean
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ inductive TypeExprF (α : Type) where
| ident (ann : α) (name : QualifiedIdent) (args : Array (TypeExprF α))
/-- A bound type variable at the given deBruijn index in the context. -/
| bvar (ann : α) (index : Nat)
/-- A polymorphic type variable (universally quantified).
Used for polymorphic function type parameters -/
| tvar (ann : α) (name : String)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use String for type variable names rather than deBrujin indices as in bvar? It seems like bvar could refer to either a type variable or "expression" variable.

/-- A reference to a global variable along with any arguments to ensure it is well-typed. -/
| fvar (ann : α) (fvar : FreeVarIndex) (args : Array (TypeExprF α))
/-- A function type. -/
Expand All @@ -101,6 +104,7 @@ namespace TypeExprF
def ann {α} : TypeExprF α → α
| .ident ann _ _ => ann
| .bvar ann _ => ann
| .tvar ann _ => ann
| .fvar ann _ _ => ann
| .arrow ann _ _ => ann

Expand All @@ -112,13 +116,15 @@ protected def incIndices {α} (tp : TypeExprF α) (count : Nat) : TypeExprF α :
| .ident n i args => .ident n i (args.attach.map fun ⟨e, _⟩ => e.incIndices count)
| .fvar n f args => .fvar n f (args.attach.map fun ⟨e, _⟩ => e.incIndices count)
| .bvar n idx => .bvar n (idx + count)
| .tvar n name => .tvar n name -- tvar doesn't use indices
| .arrow n a r => .arrow n (a.incIndices count) (r.incIndices count)

/-- Return true if type expression has a bound variable. -/
protected def hasUnboundVar {α} (bindingCount : Nat := 0) : TypeExprF α → Bool
| .ident _ _ args => args.attach.any (fun ⟨e, _⟩ => e.hasUnboundVar bindingCount)
| .fvar _ _ args => args.attach.any (fun ⟨e, _⟩ => e.hasUnboundVar bindingCount)
| .bvar _ idx => idx ≥ bindingCount
| .tvar _ _ => true
| .arrow _ a r => a.hasUnboundVar bindingCount || r.hasUnboundVar bindingCount
termination_by e => e

Expand All @@ -135,6 +141,7 @@ protected def instTypeM {m α} [Monad m] (d : TypeExprF α) (bindings : α → N
| .ident n i a =>
.ident n i <$> a.attach.mapM (fun ⟨e, _⟩ => e.instTypeM bindings)
| .bvar n idx => bindings n idx
| .tvar n name => pure (.tvar n name)
| .fvar n idx a => .fvar n idx <$> a.attach.mapM (fun ⟨e, _⟩ => e.instTypeM bindings)
| .arrow n a b => .arrow n <$> a.instTypeM bindings <*> b.instTypeM bindings
termination_by d
Expand Down Expand Up @@ -472,6 +479,15 @@ def scopeDatatypeIndex (metadata : Metadata) : Option (Nat × Nat) :=
| some #[.catbvar nameIdx, .catbvar typeParamsIdx] => some (nameIdx, typeParamsIdx)
| some _ => panic! s!"Unexpected argument count to scopeDatatype"

/-- Returns the typeArgs index if @[scopeTypeVars] is present.
Used for polymorphic function declarations where type parameters should be
added as .tvar bindings. -/
def scopeTypeVarsIndex (metadata : Metadata) : Option Nat :=
match metadata[q`StrataDDL.scopeTypeVars]? with
| none => none
| some #[.catbvar typeArgsIdx] => some typeArgsIdx
| some _ => panic! s!"Unexpected argument count to scopeTypeVars"

/-- Returns the index of the value in the binding for the given variable of the scope to use. -/
private def resultIndex (metadata : Metadata) : Option Nat :=
match metadata[MetadataAttr.scopeName]? with
Expand Down Expand Up @@ -510,8 +526,12 @@ generate types.
inductive PreType where
/-- A dialect defined type. -/
| ident (ann : SourceRange) (name : QualifiedIdent) (args : Array PreType)
/-- A bound type variable at the given deBruijn index in the context. -/
/-- A bound type variable at the given deBruijn index in the context.
Used for type alias parameters -/
| bvar (ann : SourceRange) (index : Nat)
/-- A polymorphic type variable (universally quantified).
Used for polymorphic function type parameters -/
| tvar (ann : SourceRange) (name : String)
/-- A reference to a global variable along with any arguments to ensure it is well-typed. -/
| fvar (ann : SourceRange) (fvar : FreeVarIndex) (args : Array PreType)
/-- A function type. -/
Expand All @@ -526,13 +546,15 @@ namespace PreType
def ann : PreType → SourceRange
| .ident ann _ _ => ann
| .bvar ann _ => ann
| .tvar ann _ => ann
| .fvar ann _ _ => ann
| .arrow ann _ _ => ann
| .funMacro ann _ _ => ann

def ofType : TypeExprF SourceRange → PreType
| .ident loc name args => .ident loc name (args.map fun a => .ofType a)
| .bvar loc idx => .bvar loc idx
| .tvar loc name => .tvar loc name
| .fvar loc idx args => .fvar loc idx (args.map fun a => .ofType a)
| .arrow loc a r => .arrow loc (.ofType a) (.ofType r)
termination_by tp => tp
Expand Down Expand Up @@ -696,6 +718,18 @@ def argScopeDatatypeLevel (argDecls : ArgDecls) (level : Fin argDecls.size) : Op
else
panic! s!"scopeDatatype name index {nameIdx} out of bounds ({level.val})"

/-- Returns the typeArgs level if @[scopeTypeVars] is present.
This is used for polymorphic function declarations where type parameters like `<a, b>`
should be added as .tvar bindings when parsing parameter types and return type. -/
def argScopeTypeVarsLevel (argDecls : ArgDecls) (level : Fin argDecls.size) : Option (Fin level.val) :=
match argDecls[level].metadata.scopeTypeVarsIndex with
| none => none
| some typeArgsIdx =>
if h : typeArgsIdx < level.val then
some ⟨level.val - (typeArgsIdx + 1), by omega⟩
else
panic! s!"scopeTypeVars typeArgs index {typeArgsIdx} out of bounds ({level.val})"

end ArgDecls

/--
Expand Down Expand Up @@ -752,10 +786,10 @@ structure ConstructorInfo where

/--
Build a TypeExpr reference to the datatype with type parameters, using
`.fvar` for the datatype's GlobalContext index.
`.fvar` for the datatype's GlobalContext index and `.tvar` for type parameters.
-/
def mkDatatypeTypeRef (ann : SourceRange) (datatypeIndex : FreeVarIndex) (typeParams : Array String) : TypeExpr :=
let typeArgs := typeParams.mapIdx fun i _ => TypeExprF.bvar ann i
let typeArgs := typeParams.map fun name => TypeExprF.tvar ann name
TypeExprF.fvar ann datatypeIndex typeArgs

/--
Expand Down
2 changes: 2 additions & 0 deletions Strata/DDM/BuiltinDialects/StrataDDL.lean
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ def StrataDDL : Dialect := BuiltinM.create! "StrataDDL" #[initDialect] do
used for recursive datatype definitions where the datatype name must be visible when parsing constructor field types (e.g., `tail: List` in
`Cons(head: int, tail: List)`) -/
declareMetadata { name := "scopeDatatype", args := #[.mk "name" .ident, .mk "typeParams" .ident] }
-- Metadata for bringing type variable names into scope as .tvar bindings.
declareMetadata { name := "scopeTypeVars", args := #[.mk "typeArgs" .ident] }

end Strata
end
101 changes: 88 additions & 13 deletions Strata/DDM/Elab/Core.lean
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ partial def expandMacros (m : DialectMap) (f : PreType) (args : Nat → Option A
| .arrow loc a b => .arrow loc <$> expandMacros m a args <*> expandMacros m b args
| .fvar loc i a => .fvar loc i <$> a.mapM fun e => expandMacros m e args
| .bvar loc idx => pure (.bvar loc idx)
| .tvar loc name => pure (.tvar loc name)
| .funMacro loc i r => do
let r ← expandMacros m r args
match args i with
Expand All @@ -77,7 +78,7 @@ the head is in a normal form.
-/
partial def hnf (tctx : TypingContext) (e : TypeExpr) : TypeExpr :=
match e with
| .arrow .. | .ident .. => e
| .arrow .. | .ident .. | .tvar .. => e
| .fvar _ idx args =>
let gctx := tctx.globalContext
match gctx.kindOf! idx with
Expand All @@ -94,6 +95,7 @@ partial def hnf (tctx : TypingContext) (e : TypeExpr) : TypeExpr :=
assert! d.isGround
hnf (tctx.drop (idx + 1)) d
| .type _ _ none => e
| .tvar _ _ => e
| _ => panic! "Expected a type"

/--
Expand Down Expand Up @@ -176,6 +178,9 @@ def resolveTypeBinding (tctx : TypingContext) (loc : SourceRange) (name : String
if let .type loc [] _ := k then
let info : TypeInfo := { inputCtx := tctx, loc := loc, typeExpr := .bvar loc idx, isInferred := false }
return .node (.ofTypeInfo info) #[]
else if let .tvar loc tvarName := k then
let info : TypeInfo := { inputCtx := tctx, loc := loc, typeExpr := .tvar loc tvarName, isInferred := false }
return .node (.ofTypeInfo info) #[]
else
logErrorMF loc mf!"Expected a type instead of {k}"
return default
Expand Down Expand Up @@ -326,7 +331,7 @@ N.B. This expects that macros have already been expanded in e.
-/
partial def headExpandTypeAlias (gctx : GlobalContext) (e : TypeExpr) : TypeExpr :=
match e with
| .arrow .. | .ident .. | .bvar .. => e
| .arrow .. | .ident .. | .bvar .. | .tvar .. => e
| .fvar _ idx args =>
match gctx.kindOf! idx with
| .expr _ => panic! "Type free variable bound to expression."
Expand All @@ -347,6 +352,10 @@ partial def checkExpressionType (tctx : TypingContext) (itype rtype : TypeExpr)
let itype := tctx.hnf itype
let rtype := tctx.hnf rtype
match itype, rtype with
-- tvar matches anything (dialect responsible for typechecking)
| .tvar _ n1, .tvar _ n2 => return n1 == n2
| .tvar _ _, _ => return true
| _, .tvar _ _ => return true
| .ident _ iq ia, .ident _ rq ra =>
if p : iq = rq ∧ ia.size = ra.size then do
for i in Fin.range ia.size do
Expand Down Expand Up @@ -468,9 +477,12 @@ partial def unifyTypes
if !(← checkExpressionType tctx inferredType info.typeExpr) then
logErrorMF exprLoc mf!"Expression has type {withBindings tctx.bindings (mformat inferredType)} when {withBindings tctx.bindings (mformat info.typeExpr)} expected."
pure args
| .tvar _ _ =>
-- tvar nodes are passed through without attempting unification
pure args
| .arrow _ ea er =>
match inferredType with
| .ident .. | .bvar .. | .fvar .. =>
| .ident .. | .bvar .. | .fvar .. | .tvar .. =>
logErrorMF exprLoc mf!"Expected {expectedType} when {inferredType} found"
pure args
| .arrow _ ia ir =>
Expand Down Expand Up @@ -752,6 +764,12 @@ def translateBindingKind (tree : Tree) : ElabM BindingKind := do
else
logErrorMF nameLoc mf!"Unexpected arguments to type variable {name}."
return default
else if let .tvar loc tvarName := k then
if tpArgs.isEmpty then
return .expr (.tvar loc tvarName)
else
logErrorMF nameLoc mf!"Unexpected arguments to type variable {name}."
return default
else
logErrorMF nameLoc mf!"Expected a type instead of {k}"
return default
Expand Down Expand Up @@ -795,12 +813,15 @@ def evalBindingSpec
let (bindings, success) ← runChecked <| elabArgIndex initSize args b.argsIndex fun argLoc b =>
match b.kind with
| .expr tp =>
pure (b.ident, tp)
pure (some (b.ident, tp))
| .tvar .. =>
pure none
| .type .. | .cat _ => do
logError argLoc "Expecting expressions in variable binding"
pure default
pure none
if !success then
return default
let bindings := bindings.filterMap id
let typeTree := args[b.typeIndex.toLevel]
let kind ←
match typeTree.info with
Expand All @@ -827,6 +848,8 @@ def evalBindingSpec
match b.kind with
| .type _ [] _ =>
pure ()
| .tvar _ _ =>
pure ()
| .type .. | .expr _ | .cat _ => do
logError argLoc s!"{b.ident} must be have type Type instead of {repr b.kind}."
return b.ident
Expand Down Expand Up @@ -955,6 +978,33 @@ def unwrapTree (tree : Tree) (unwrap : Bool) : Arg :=
| .ofBytesInfo info => .bytes info.loc info.val
| _ => tree.arg -- Fallback for non-unwrappable types

/--
Extract type variable names from a TypeArgs tree (or Option TypeArgs).
TypeArgs is an operation `type_args` with one child that is `CommaSepBy Ident`.
Option TypeArgs wraps this in an OptionInfo node.
-/
def extractTypeVarNames (tree : Tree) : Array String :=
let innerTree :=
match tree.info with
| .ofOptionInfo _ =>
match tree.children[0]? with
| none => none
| some t => some t
| _ => some tree
match innerTree with
| none => #[]
| some typeArgsTree =>
-- typeArgsTree should be the type_args operation
-- Its first child should be CommaSepBy Ident
match typeArgsTree.children[0]? with
| none => #[]
| some commaSepTree =>
-- commaSepTree has CommaSepInfo with children that are Ident trees
commaSepTree.children.filterMap fun identTree =>
match identTree.info with
| .ofIdentInfo info => some info.val
| _ => none

mutual

partial def elabOperation (tctx : TypingContext) (stx : Syntax) : ElabM Tree := do
Expand Down Expand Up @@ -1017,21 +1067,43 @@ partial def runSyntaxElaborator
| .ofIdentInfo info => info.val
| _ => panic! "Expected identifier for datatype name"
let baseCtx := typeParamsT.resultContext
-- Extract type parameter names from the bindings
let typeParamNames := baseCtx.bindings.toArray.filterMap fun b =>
match b.kind with
| .type _ [] _ => some b.ident
| _ => none
-- Add the datatype name to the GlobalContext as a type
let gctx := baseCtx.globalContext
let gctx :=
if datatypeName ∈ gctx then gctx
else gctx.push datatypeName (GlobalKind.type [] none)
-- Create a new typing context with the updated GlobalContext
pure (baseCtx.withGlobalContext gctx)
else gctx.push datatypeName (GlobalKind.type typeParamNames.toList none)
-- Add .tvar bindings for type parameters
let loc := typeParamsT.info.loc
let tctx := typeParamNames.foldl (init := baseCtx.withGlobalContext gctx) fun ctx name =>
ctx.push { ident := name, kind := .tvar loc name }
pure tctx
| _, _ => continue
| none =>
match ae.contextLevel with
| some idx =>
match trees[idx] with
| some t => pure t.resultContext
-- Check for typeVarsScope (polymorphic function type parameters)
match ae.typeVarsScope with
| some typeArgsLevel =>
match trees[typeArgsLevel] with
| some typeArgsTree =>
-- Extract identifiers from TypeArgs and add as .tvar bindings
let baseCtx := typeArgsTree.resultContext
let typeVarNames := extractTypeVarNames typeArgsTree
let tctx := typeVarNames.foldl (init := baseCtx) fun ctx name =>
let loc := typeArgsTree.info.loc
ctx.push { ident := name, kind := .tvar loc name }
pure tctx
| none => continue
| none => pure tctx0
| none =>
match ae.contextLevel with
| some idx =>
match trees[idx] with
| some t => pure t.resultContext
| none => continue
| none => pure tctx0
let astx := args[ae.syntaxLevel]
let expectedKind := argDecls[argLevel].kind
match expectedKind with
Expand Down Expand Up @@ -1209,6 +1281,9 @@ partial def elabExpr (tctx : TypingContext) (stx : Syntax) : ElabM Tree := do
| .type _ _params _ =>
logErrorMF loc mf!"{name} is a type when an expression is required."
return default
| .tvar _ _ =>
logErrorMF loc mf!"{name} is a type variable when an expression is required."
return default
| .cat c =>
logErrorMF loc mf!"{name} has category {c} when an expression is required."
return default
Expand Down
1 change: 1 addition & 0 deletions Strata/DDM/Elab/DialectM.lean
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ private def foldBoundTypeVars {α} (tp : PreType) (init : α) (f : α → Nat
| .ident _ _ a => a.attach.foldl (init := init) fun r ⟨e, _⟩ => e.foldBoundTypeVars r f
| .fvar _ _ a => a.attach.foldl (init := init) fun r ⟨e, _⟩ => e.foldBoundTypeVars r f
| .bvar _ i => f init i
| .tvar _ _ => init
| .arrow _ a r => r.foldBoundTypeVars (a.foldBoundTypeVars init f) f
| .funMacro _ _ r => r.foldBoundTypeVars init f

Expand Down
5 changes: 5 additions & 0 deletions Strata/DDM/Elab/SyntaxElab.lean
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ structure ArgElaborator where
-- Datatype scope: (nameLevel, typeParamsLevel) for recursive datatype definitions
-- When set, the datatype name is added to the typing context as a type
datatypeScope : Option (Fin argLevel × Fin argLevel) := .none
-- Type vars scope: level of TypeArgs argument for polymorphic function declarations
-- When set, identifiers from TypeArgs are added as .tvar bindings
typeVarsScope : Option (Fin argLevel) := .none
-- Whether to unwrap this argument
unwrap : Bool := false
deriving Inhabited, Repr
Expand Down Expand Up @@ -65,6 +68,7 @@ private def push (as : ArgElaborators)
argLevel := argLevel.val
contextLevel := argDecls.argScopeLevel argLevel
datatypeScope := argDecls.argScopeDatatypeLevel argLevel
typeVarsScope := argDecls.argScopeTypeVarsLevel argLevel
}
have scp : sc < sc + 1 := by grind
{ as with argElaborators := as.argElaborators.push ⟨newElab, scp⟩ }
Expand All @@ -81,6 +85,7 @@ private def pushWithUnwrap
argLevel := argLevel.val
contextLevel := argDecls.argScopeLevel argLevel
datatypeScope := argDecls.argScopeDatatypeLevel argLevel
typeVarsScope := argDecls.argScopeTypeVarsLevel argLevel
unwrap := unwrap
}
have scp : sc < sc + 1 := by grind
Expand Down
7 changes: 7 additions & 0 deletions Strata/DDM/Elab/Tree.lean
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ over the parameters.
Variable belongs to the particular category below.
-/
| cat (k : SyntaxCat)
/--
Variable is a polymorphic type variable (for function type parameters).
These are passed through to the dialect's typechecker for inference.
-/
| tvar (ann : SourceRange) (name : String)
deriving Inhabited, Repr

namespace BindingKind
Expand All @@ -48,13 +53,15 @@ def ofCat (c : SyntaxCat) : BindingKind :=
def categoryOf : BindingKind → SyntaxCat
| .expr tp => .atom tp.ann q`Init.Expr
| .type loc _ _ => .atom loc q`Init.Type
| .tvar loc _ => .atom loc q`Init.Type
| .cat c => c

instance : ToStrataFormat BindingKind where
mformat bk := private
match bk with
| .expr tp => mformat tp
| .type _ params _ => mformat (params.foldr (init := f!"Type") (fun a f => f!"({a} : Type) -> {f}"))
| .tvar _ name => mformat f!"tvar({name})"
| .cat c => mformat c

end BindingKind
Expand Down
Loading
Loading