packages feed

phino-0.0.155: test-resources/evaluate-packs/stops-an-accumulator-recursion-under-plausible.yaml

# SPDX-FileCopyrightText: Copyright (c) 2025 Objectionary.com
# SPDX-License-Identifier: MIT
---
# yamllint disable rule:line-length
# A factorial with an accumulator, under '--acyclic=plausible'. Every round
# wraps the accumulator in one more 'pair' and the counter in one more 'dec',
# so no two rounds are ever the same formation up to a renaming of symbols and
# '--acyclic=proven' never cuts it. The body of 'fact' dispatches 'Ο†' off its
# 'if', so 'ml' fires it, and the 'morph' operand of 'L_if' reduces the
# recursive call the same way. The 'if' it reaches on the second round holds
# the one fired on the first, under the wrappers it gained, which is what the
# plausible guard compares by, so the second firing is cut before it opens and
# its 'looped' line names the mode that cut it (#1451). The operand hands back
# the term the cut left, which no 'join' can pair with the datum of the other
# branch, so the first 'L_if' gets stuck and '--partial' parks it.
symbolic: |
  - Ξ»: L_zero
    dataize:
      𝛿1: $.x
    𝑛: ⟦ Ξ» ‍ 𝜎 ⟧
  - Ξ»: L_dec
    dataize:
      𝛿1: $.x
    𝑛: ⟦ Ξ» ‍ 𝜎 ⟧
  - Ξ»: L_if
    dataize:
      𝛿1: $.c
    morph:
      𝑛1: $.left
      𝑛2: $.right
    symbolize:
      𝑛3: 𝑛1
      𝑛4: 𝑛2
    join:
      𝑛5: [𝑛3, 𝑛4]
    𝑛: 𝑛5
location: 'Q.x'
acyclic: plausible
partial: true
input: >
  ⟦ if ↦ ⟦ c ↦ βˆ…, left ↦ βˆ…, right ↦ βˆ…, Ξ» ‍ L_if ⟧,
    zero ↦ ⟦ x ↦ βˆ…, Ξ» ‍ L_zero ⟧,
    dec ↦ ⟦ x ↦ βˆ…, Ξ» ‍ L_dec ⟧,
    pair ↦ ⟦ head ↦ βˆ…, tail ↦ βˆ… ⟧,
    fact ↦ ⟦ n ↦ βˆ…, acc ↦ βˆ…, Ο† ↦ Ξ¦.if( c ↦ Ξ¦.zero( x ↦ ΞΎ.n ), left ↦ ΞΎ.acc, right ↦ Ξ¦.fact( n ↦ Ξ¦.dec( x ↦ ΞΎ.n ), acc ↦ Ξ¦.pair( head ↦ ΞΎ.n, tail ↦ ΞΎ.acc ) ).Ο† ).Ο† ⟧,
    x ↦ Ξ¦.fact( n ↦ ⟦ Ξ» ‍ 𝜎1 ⟧, acc ↦ ⟦ Ξ” ‍ 00- ⟧ ).Ο† ⟧
result: 'Ξ¦.if( c ↦ Ξ¦.zero( x ↦ 𝜎1:Ξ» ), left ↦ 00-:Ξ”, right ↦ Ξ¦.fact( n ↦ Ξ¦.dec( x ↦ 𝜎1:Ξ» ), acc ↦ Ξ¦.pair( head ↦ 𝜎1:Ξ», tail ↦ 00-:Ξ” ) ).Ο† ).Ο†'
protocol: |
  𝕄(Ξ¦.x):
    𝑛·0Β·1 := Ξ¦.fact( n ↦ 𝜎1:Ξ» )
    𝑛·0Β·2 := 𝑛·0Β·1( acc ↦ 00-:Ξ” )
    𝑛·0Β·3 := Ξ¦.if( c ↦ Ξ¦.zero( x ↦ 𝜎1:Ξ» ) )
    𝑛·0Β·4 := 𝑛·0Β·3( left ↦ 00-:Ξ” )
    𝑛·0Β·5 := 𝑛·0Β·4( right ↦ Ξ¦.fact( n ↦ Ξ¦.dec( x ↦ 𝜎1:Ξ» ), acc ↦ Ξ¦.pair( head ↦ 𝜎1:Ξ», tail ↦ 00-:Ξ” ) ).Ο† )
    𝔼(L_if):
      𝔻(Ξ¦.a🌡0):
        𝕄(Ξ¦.a🌡0):
          𝑛·1Β·1 := Ξ¦.zero( x ↦ 𝜎1:Ξ» )
        𝔼(L_zero):
          𝛿1Β·2 := 𝔻(𝜎1:Ξ»)  # 𝔻(ΞΎ.x)
          𝑛·2Β·1 := 𝜎2:Ξ»  # 𝑛
          𝑛·2Β·2 := 𝜎2:Ξ»  # 𝕄(𝑛·2Β·1)
      𝛿1Β·1 := 𝔻(𝜎2:Ξ»)  # 𝔻(ΞΎ.c)
      𝑛1Β·1 := 00-:Ξ”  # 𝕄(ΞΎ.left)
      𝕄(Ξ¦.a🌡3):
        𝑛·1Β·2 := Ξ¦.fact( n ↦ Ξ¦.dec( x ↦ 𝜎1:Ξ» ) )
        𝑛·1Β·3 := 𝑛·1Β·2( acc ↦ Ξ¦.pair( head ↦ 𝜎1:Ξ», tail ↦ 00-:Ξ” ) )
        𝑛·1Β·4 := Ξ¦.if( c ↦ Ξ¦.zero( x ↦ Ξ¦.dec( x ↦ 𝜎1:Ξ» ) ) )
        𝑛·1Β·5 := 𝑛·1Β·4( left ↦ Ξ¦.pair( head ↦ 𝜎1:Ξ», tail ↦ 00-:Ξ” ) )
        𝑛·1Β·6 := 𝑛·1Β·5( right ↦ Ξ¦.fact( n ↦ Ξ¦.dec( x ↦ Ξ¦.dec( x ↦ 𝜎1:Ξ» ) ), acc ↦ Ξ¦.pair( head ↦ Ξ¦.dec( x ↦ 𝜎1:Ξ» ), tail ↦ Ξ¦.pair( head ↦ 𝜎1:Ξ», tail ↦ 00-:Ξ” ) ) ).Ο† )
        looped(𝑛·0Β·5)  # plausible
      𝑛2Β·1 := 𝑛·1Β·3.Ο†  # 𝕄(ΞΎ.right)
      𝔻(𝜎3:Ξ») == 00-
      𝑛3Β·1 := 𝜎3:Ξ»  # 𝑛1
      𝔻(𝜎4:Ξ») == 00-
      𝑛4Β·1 := 𝑛·1Β·2( acc ↦ Ξ¦.pair( head ↦ 𝜎1:Ξ», tail ↦ 𝜎4:Ξ» ) ).Ο†  # 𝑛2
      unjoined(L_if)  # 𝜎3:Ξ» vs 𝑛·1Β·2( acc ↦ Ξ¦.pair( head ↦ 𝜎1:Ξ», tail ↦ 𝜎4:Ξ» ) ).Ο†