lean4-htt/library/init/lean/level.lean
2019-05-03 13:57:21 +02:00

132 lines
4.5 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2018 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
prelude
import init.data.option.basic init.lean.name init.lean.format
namespace Lean
inductive Level
| zero : Level
| succ : Level → Level
| max : Level → Level → Level
| imax : Level → Level → Level
| Param : Name → Level
| mvar : Name → Level
attribute [extern "level_mk_succ"] Level.succ
attribute [extern "level_mk_max"] Level.max
attribute [extern "level_mk_imax"] Level.imax
attribute [extern "level_mk_param"] Level.Param
attribute [extern "level_mk_mvar"] Level.mvar
instance levelIsInhabited : Inhabited Level :=
⟨Level.zero⟩
def Level.one : Level := Level.succ Level.zero
def Level.hasParam : Level → Bool
| (Level.Param _) := true
| (Level.succ l) := Level.hasParam l
| (Level.max l₁ l₂) := Level.hasParam l₁ || Level.hasParam l₂
| (Level.imax l₁ l₂) := Level.hasParam l₁ || Level.hasParam l₂
| _ := false
def Level.hasMvar : Level → Bool
| (Level.mvar _) := true
| (Level.succ l) := Level.hasParam l
| (Level.max l₁ l₂) := Level.hasParam l₁ || Level.hasParam l₂
| (Level.imax l₁ l₂) := Level.hasParam l₁ || Level.hasParam l₂
| _ := false
def Level.ofNat : Nat → Level
| 0 := Level.zero
| (n+1) := Level.succ (Level.ofNat n)
def Nat.imax (n m : Nat) : Nat :=
if m = 0 then 0 else Nat.max n m
def Level.toNat : Level → Option Nat
| Level.zero := some 0
| (Level.succ l) := Nat.succ <$> Level.toNat l
| (Level.max l₁ l₂) := Nat.max <$> Level.toNat l₁ <*> Level.toNat l₂
| (Level.imax l₁ l₂) := Nat.imax <$> Level.toNat l₁ <*> Level.toNat l₂
| _ := none
def Level.toOffset : Level → Level × Nat
| Level.zero := (Level.zero, 0)
| (Level.succ l) := let (l', k) := Level.toOffset l in (l', k+1)
| l := (l, 0)
def Level.instantiate (s : Name → Option Level) : Level → Level
| Level.zero := Level.zero
| (Level.succ l) := Level.succ (Level.instantiate l)
| (Level.max l₁ l₂) := Level.max (Level.instantiate l₁) (Level.instantiate l₂)
| (Level.imax l₁ l₂) := Level.imax (Level.instantiate l₁) (Level.instantiate l₂)
| l@(Level.Param n) :=
match s n with
| some l' := l'
| none := l
| l := l
@[extern "lean_level_hash"]
constant Level.hash (n : @& Level) : USize := default USize
/- Level to Format -/
namespace LevelToFormat
inductive Result
| leaf : Format → Result
| num : Nat → Result
| offset : Result → Nat → Result
| maxNode : List Result → Result
| imaxNode : List Result → Result
def Result.succ : Result → Result
| (Result.offset f k) := Result.offset f (k+1)
| (Result.num k) := Result.num (k+1)
| f := Result.offset f 1
def Result.max : Result → Result → Result
| f (Result.maxNode Fs) := Result.maxNode (f::Fs)
| f₁ f₂ := Result.maxNode [f₁, f₂]
def Result.imax : Result → Result → Result
| f (Result.imaxNode Fs) := Result.imaxNode (f::Fs)
| f₁ f₂ := Result.imaxNode [f₁, f₂]
def parenIfFalse : Format → Bool → Format
| f true := f
| f false := f.paren
@[specialize] private def formatLst (fmt : Result → Format) : List Result → Format
| [] := Format.nil
| (r::rs) := Format.line ++ fmt r ++ formatLst rs
partial def Result.format : Result → Bool → Format
| (Result.leaf f) _ := f
| (Result.num k) _ := toString k
| (Result.offset f 0) r := Result.format f r
| (Result.offset f (k+1)) r :=
let f' := Result.format f false in
parenIfFalse (f' ++ "+" ++ fmt (k+1)) r
| (Result.maxNode fs) r := parenIfFalse (Format.group $ "max" ++ formatLst (λ r, Result.format r false) fs) r
| (Result.imaxNode fs) r := parenIfFalse (Format.group $ "imax" ++ formatLst (λ r, Result.format r false) fs) r
def Level.toResult : Level → Result
| Level.zero := Result.num 0
| (Level.succ l) := Result.succ (Level.toResult l)
| (Level.max l₁ l₂) := Result.max (Level.toResult l₁) (Level.toResult l₂)
| (Level.imax l₁ l₂) := Result.imax (Level.toResult l₁) (Level.toResult l₂)
| (Level.Param n) := Result.leaf (fmt n)
| (Level.mvar n) := Result.leaf (fmt n)
def Level.format (l : Level) : Format :=
(Level.toResult l).format true
instance levelHasFormat : HasFormat Level := ⟨Level.format⟩
instance levelHasToString : HasToString Level := ⟨Format.pretty ∘ Level.format⟩
end LevelToFormat
end Lean