sealed trait Term case class Var(n: String) extends Term case class App(h: String, args: List[Term]) extends Term case class Ctr(name: String, args: List[Term]) extends Term case class Case(selector: Term, branches: List[Branch]) extends Term case class Branch(pat: Pat, body: Term) case class Pat(name: String, params: List[String])
Untersuchende Sprache • MuTTI (Munich Type Theory Implementation) • Agda Termination checker основан на Foetus • Andreas Abel. foetus – termination checker for simple functional programs. Programming Lab Report (1998) • Andreas Abel and Thorsten Altenkirch. A predicative analysis of structural recursion. JFP 12.1 (2002)
При рекурсивном вызове аргументы должны уменьшаться. • Анализ “уменьшаемости” просходит внутри одного метода (интрапроцедурный анализ) • Затем результаты комбинируются с учетом зависимостей между методами (граф вызовов)
x match { case Z() => y case S(x1) => S(add(x1, y)) } def mult(x: Nat, y: Nat): Nat = x match { case Z() => Z() case S(x1) => add(y, mult(x1, y)) } add add mult add mult 1 2 3
Nat = x match { case Z() => y case S(x1) => S(add(x1, y)) } def mult(x: Nat, y: Nat): Nat = x match { case Z() => Z() case S(x1) => add(y, mult(x1, y)) } add add mult add mult 1 2 3 < ? ? = 1 ? = ? ? 2 < ? ? = 3 На диагонали есть <
= x match { case Z() => S(y) case S(x1) => y match { case Z() => ack(x1, S(Z())) case S(y1) => ack(x1, ack(S(x1), y1)) } } 1) < ? 2) < ? 3) = < 1 2 3 Лексикографический порядок
x match { case Z() => S(y) case S(x1) => ack(x1, ack1(y, S(x1))) } def ack1(y: Nat, x: Nat): Nat = y match { case Z() => S(Z()) case S(y1) => ack(x, y1) } ack ack1 m1 m3 m2
??? • Перемножаем матрицы!! (Док-во корректности в статьях) • Матрицы перемножаются обычным образом, нужно лишь определить * и + для =, <, ?. ack ack1 m1 m3 m2
строится матрица вызова – как соотносятся параметры/аргументы через <,=,?. • Матрицами помечаем дуги в графе вызовов. • Насыщаем граф вызовов. • Для каждого набора дуг/матриц f → f проверяем наличие лексикографического порядка.
строится матрица вызова – как соотносятся параметры/аргументы через <,=,?. • Матрицами помечаем дуги в графе вызовов. • Насыщаем граф вызовов. • Для каждого набора дуг/матриц f → f проверяем наличие лексикографического порядка.
Nat, y: Nat): Nat = x match { case Z() => S(y) case S(x1) => y match { case Z() => ack(x1, S(Z())) case S(y1) => ack(x1, ack(S(x1), y1)) } } }) should equal { List("ack" -> Some(List(0, 1))) } }