lean4-htt/src/Lean/Compiler/LCNF/Simp/DefaultAlt.lean
2022-09-26 07:04:20 -07:00

65 lines
1.9 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) 2022 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
import Lean.Compiler.LCNF.Simp.SimpM
namespace Lean.Compiler.LCNF
namespace Simp
/--
Return the alternative in `alts` whose body appears in most arms,
and the number of occurrences.
We use this function to decide whether to create a `.default` case
or not.
-/
private def getMaxOccs (alts : Array Alt) : Alt × Nat := Id.run do
let mut maxAlt := alts[0]!
let mut max := getNumOccsOf alts 0
for i in [1:alts.size] do
let curr := getNumOccsOf alts i
if curr > max then
maxAlt := alts[i]!
max := curr
return (maxAlt, max)
where
/--
Return the number of occurrences of `alts[i]` in `alts`.
We use alpha equivalence.
Note that the number of occurrences can be greater than 1 only when
the alternative does not depend on field parameters
-/
getNumOccsOf (alts : Array Alt) (i : Nat) : Nat := Id.run do
let code := alts[i]!.getCode
let mut n := 1
for j in [i+1:alts.size] do
if Code.alphaEqv alts[j]!.getCode code then
n := n+1
return n
/--
Add a default case to the given `cases` alternatives if there
are alternatives with equivalent (aka alpha equivalent) right hand sides.
-/
def addDefaultAlt (alts : Array Alt) : SimpM (Array Alt) := do
if alts.size <= 1 || alts.any (· matches .default ..) then
return alts
else
let (max, noccs) := getMaxOccs alts
if noccs == 1 then
return alts
else
let mut altsNew := #[]
let mut first := true
markSimplified
for alt in alts do
if Code.alphaEqv alt.getCode max.getCode then
let .alt _ ps k := alt | unreachable!
eraseParams ps
unless first do
eraseCode k
first := false
else
altsNew := altsNew.push alt
return altsNew.push (.default max.getCode)