Dsl
I define a DSL to convert human-readable input with named variable to De Bruijn indexed AST expressions.
import SkLean.Ast
De Bruijn and "named variable" expresions are mixed in the same tree.
inductive NamedSkExpr where
| k : NamedSkExpr
| s : NamedSkExpr
| prp : NamedSkExpr
| ty : ℕ → NamedSkExpr
| fall : String → NamedSkExpr → NamedSkExpr → NamedSkExpr
| call : NamedSkExpr → NamedSkExpr → NamedSkExpr
| var : String → NamedSkExpr
| e : SkExpr → NamedSkExpr
namespace NamedSkExpr
De Bruijn indices are assigned greedily based on the location of the nearest bound matching variable.
def to_sk_expr (names : List String) : NamedSkExpr → SkExpr
| .k => .k .mk
| .e e' => e'
| .s => .s .mk
| .prp => .prp .mk
| .ty n => .ty (.mk n)
| .call lhs rhs => .call (.mk (to_sk_expr names lhs) (to_sk_expr names rhs))
| .var name => .var $ (.mk ⟨Nat.succ <| (names.findIdx? (. = name)).getD 0⟩)
| .fall name bind_ty body => .fall (.mk
(to_sk_expr (name :: names) bind_ty)
(to_sk_expr (name :: names) body))
end NamedSkExpr
The DSL is used like so:
SK[K]
SK[(K (Type 0))]
SK[∀ α : Type 0, ∀ β : Type 0, ∀ x : α, ∀ y : β, α]
declare_syntax_cat skexpr
syntax "K" : skexpr
syntax "S" : skexpr
syntax "Prop" : skexpr
syntax "Type" num : skexpr
syntax "Type" ident : skexpr
syntax "∀" ident ":" skexpr "," skexpr : skexpr
syntax "(" skexpr skexpr ")" : skexpr
syntax "(" skexpr ")" : skexpr
syntax ident : skexpr
syntax "#" ident : skexpr
syntax skexpr "→" skexpr : skexpr
syntax " ⟪ " skexpr " ⟫ " : term
macro_rules
| `(⟪ ($e:skexpr) ⟫) => `(⟪ $e ⟫)
| `(⟪ K ⟫) => `(NamedSkExpr.k)
| `(⟪ S ⟫) => `(NamedSkExpr.s)
| `(⟪ Prop ⟫) => `(NamedSkExpr.prp)
| `(⟪ Type $n:num ⟫) => `(NamedSkExpr.ty $n)
| `(⟪ Type $v:ident ⟫) => `(NamedSkExpr.ty $v)
| `(⟪ #$var:ident ⟫) =>
`(NamedSkExpr.var $(Lean.quote var.getId.toString))
| `(⟪ $var:ident ⟫) => `(NamedSkExpr.e $var)
| `(⟪ $e₁:skexpr → $e₂:skexpr ⟫) => `(⟪ ∀ x : $e₁, $e₂ ⟫)
| `(⟪ ∀ $var:ident : $e_ty:skexpr , $body:skexpr ⟫) =>
`(NamedSkExpr.fall $(Lean.quote var.getId.toString) (⟪ $e_ty ⟫) (⟪ $body ⟫))
| `(⟪ ($e₁:skexpr $e₂:skexpr)⟫) => `(NamedSkExpr.call ⟪ $e₁ ⟫ ⟪ $e₂ ⟫)
syntax "SK[ " skexpr " ] " : term
macro_rules
| `(SK[ $e:skexpr ]) => `(NamedSkExpr.to_sk_expr [] ⟪ $e ⟫)
Variables in body position must be prefixed with # so as not to collide with definitions in scope.
#eval SK[∀ α : Type 0, ∀ β : Type 0, ∀ x : #α, ∀ y : #β, #α]
Made by Dowland Aiello.