/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2022 Justine Alexandra Roberts Tunney │ │ │ │ Permission to use, copy, modify, and/or distribute this software for │ │ any purpose with or without fee is hereby granted, provided that the │ │ above copyright notice and this permission notice appear in all copies. │ │ │ │ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ │ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ │ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ │ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ │ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ │ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #ifndef __COSMOPOLITAN__ #include #include #endif #include "blc.h" #define FREEBIES L"ɐqɔpǝɟƃɥıɾʞןɯuodbɹsʇnʌʍxʎz" /* clang-format off */ #define ALPHABET \ L"abcdefghijklmnopqrsuvwxyz" \ L"αβγδεζηθιμξπρςστυφχψϑϕ" \ L"ℵℶℷℸ" \ L"идџжлђ" \ L"⅄ℏ℘þæߧ£¥₿" \ L"𝘢𝘣𝘤𝘥𝘦𝘧𝘨𝘩𝘪𝘫𝘬𝘭𝘮𝘯𝘰𝘱𝘲𝘳𝘴𝘵𝘶𝘷𝘸𝘹𝘺𝘻" \ L"𝕒𝕓𝕔𝕕𝕖𝕗𝕘𝕙𝕚𝕛𝕜𝕝𝕞𝕟𝕠𝕡𝕢𝕣𝕤𝕥𝕦𝕧𝕨𝕩𝕪𝕫" \ L"𝗮𝗯𝗰𝗱𝗲𝗳𝗴𝗵𝗶𝗷𝗸𝗹𝗺𝗻𝗼𝗽𝗾𝗿𝘀𝘁𝘂𝘃𝘄𝘅𝘆𝘇" /* clang-format on */ static int kFalse[] = { ABS, // 0: false ABS, // 1: (λ 0) VAR, 0, // 2: 0 }; static int kTrue[] = { ABS, // 0: true ABS, // 1: (λ 1) VAR, 1, // 2: 1 }; static int kOne[] = { ABS, // 4: (λab.ab) ABS, // 5: (λa.ɐa) APP, 2, // 6: qɐ VAR, 1, // 8: q VAR, 0, // 10: ɐ }; static int kTwo[] = { ABS, // 12: (λab.a(ab)) ABS, // 13: (λa.ɐ(ɐa)) APP, 2, // 14: q(qɐ) VAR, 1, // 16: q APP, 2, // 18: qɐ VAR, 1, // 20: q VAR, 0, // 22: ɐ }; static int kThree[] = { ABS, // 24: (λab.a(a(ab))) ABS, // 25: (λa.ɐ(ɐ(ɐa))) APP, 2, // 26: q(q(qɐ)) VAR, 1, // 28: q APP, 2, // 30: q(qɐ) VAR, 1, // 32: q APP, 2, // 34: qɐ VAR, 1, // 36: q VAR, 0, // 38: ɐ }; static int kFour[] = { ABS, // 40: (λab.a(a(a(ab)))) ABS, // 41: (λa.ɐ(ɐ(ɐ(ɐa)))) APP, 2, // 42: q(q(q(qɐ))) VAR, 1, // 44: q APP, 2, // 46: q(q(qɐ)) VAR, 1, // 48: q APP, 2, // 50: q(qɐ) VAR, 1, // 52: q APP, 2, // 54: qɐ VAR, 1, // 56: q VAR, 0, // 58: ɐ }; static int kFive[] = { ABS, // 60: (λab.a(a(a(a(ab))))) ABS, // 61: (λa.ɐ(ɐ(ɐ(ɐ(ɐa))))) APP, 2, // 62: q(q(q(q(qɐ)))) VAR, 1, // 64: q APP, 2, // 66: q(q(q(qɐ))) VAR, 1, // 68: q APP, 2, // 70: q(q(qɐ)) VAR, 1, // 72: q APP, 2, // 74: q(qɐ) VAR, 1, // 76: q APP, 2, // 78: qɐ VAR, 1, // 80: q VAR, 0, // 82: ɐ }; static int kSix[] = { ABS, // 84: (λab.a(a(a(a(a(ab)))))) ABS, // 85: (λa.ɐ(ɐ(ɐ(ɐ(ɐ(ɐa)))))) APP, 2, // 86: q(q(q(q(q(qɐ))))) VAR, 1, // 88: q APP, 2, // 90: q(q(q(q(qɐ)))) VAR, 1, // 92: q APP, 2, // 94: q(q(q(qɐ))) VAR, 1, // 96: q APP, 2, // 98: q(q(qɐ)) VAR, 1, // 100: q APP, 2, // 102: q(qɐ) VAR, 1, // 104: q APP, 2, // 106: qɐ VAR, 1, // 108: q VAR, 0, // 110: ɐ }; static int kSeven[] = { ABS, // 112: (λab.a(a(a(a(a(a(ab))))))) ABS, // 113: (λa.ɐ(ɐ(ɐ(ɐ(ɐ(ɐ(ɐa))))))) APP, 2, // 114: q(q(q(q(q(q(qɐ)))))) VAR, 1, // 116: q APP, 2, // 118: q(q(q(q(q(qɐ))))) VAR, 1, // 120: q APP, 2, // 122: q(q(q(q(qɐ)))) VAR, 1, // 124: q APP, 2, // 126: q(q(q(qɐ))) VAR, 1, // 128: q APP, 2, // 130: q(q(qɐ)) VAR, 1, // 132: q APP, 2, // 134: q(qɐ) VAR, 1, // 136: q APP, 2, // 138: qɐ VAR, 1, // 140: q VAR, 0, // 142: ɐ }; static int kEight[] = { ABS, // 144: (λab.a(a(a(a(a(a(a(ab)))))))) ABS, // 145: (λa.ɐ(ɐ(ɐ(ɐ(ɐ(ɐ(ɐ(ɐa)))))))) APP, 2, // 146: q(q(q(q(q(q(q(qɐ))))))) VAR, 1, // 148: q APP, 2, // 150: q(q(q(q(q(q(qɐ)))))) VAR, 1, // 152: q APP, 2, // 154: q(q(q(q(q(qɐ))))) VAR, 1, // 156: q APP, 2, // 158: q(q(q(q(qɐ)))) VAR, 1, // 160: q APP, 2, // 162: q(q(q(qɐ))) VAR, 1, // 164: q APP, 2, // 166: q(q(qɐ)) VAR, 1, // 168: q APP, 2, // 170: q(qɐ) VAR, 1, // 172: q APP, 2, // 174: qɐ VAR, 1, // 176: q VAR, 0, // 178: ɐ }; static int kNine[] = { ABS, // 180: (λab.a(a(a(a(a(a(a(a(ab))))))))) ABS, // 181: (λa.ɐ(ɐ(ɐ(ɐ(ɐ(ɐ(ɐ(ɐ(ɐa))))))))) APP, 2, // 182: q(q(q(q(q(q(q(q(qɐ)))))))) VAR, 1, // 184: q APP, 2, // 186: q(q(q(q(q(q(q(qɐ))))))) VAR, 1, // 188: q APP, 2, // 190: q(q(q(q(q(q(qɐ)))))) VAR, 1, // 192: q APP, 2, // 194: q(q(q(q(q(qɐ))))) VAR, 1, // 196: q APP, 2, // 198: q(q(q(q(qɐ)))) VAR, 1, // 200: q APP, 2, // 202: q(q(q(qɐ))) VAR, 1, // 204: q APP, 2, // 206: q(q(qɐ)) VAR, 1, // 208: q APP, 2, // 210: q(qɐ) VAR, 1, // 212: q APP, 2, // 214: qɐ VAR, 1, // 216: q VAR, 0, // 218: ɐ }; static int kSelf[] = { ABS, // 0: λa.aa APP, 2, // 1: ɐɐ VAR, 0, // 3: ɐ VAR, 0, // 5: ɐ }; static int kOmega[] = { APP, 7, // 0: ω ω ABS, // 2: ω APP, 2, // 3: ɐ ɐ VAR, 0, // 5: ɐ VAR, 0, // 7: ɐ ABS, // 9: ω APP, 2, // 10: ɐ ɐ VAR, 0, // 12: ɐ VAR, 0, // 14: ɐ }; static int kIf[] = { ABS, // 0: if ABS, // 1: (λλ 2 1 0) ABS, // 2: (λ 2 1 0) APP, 6, // 3: 2 1 0 APP, 2, // 5: 2 1 VAR, 2, // 7: 2 VAR, 1, // 9: 1 VAR, 0, // 11: 0 }; static int kOr[] = { ABS, // 0: (λλ 1 1 0) ABS, // 1: (λ 1 1 0) APP, 6, // 2: 1 1 0 APP, 2, // 4: 1 1 VAR, 1, // 6: 1 VAR, 1, // 8: 1 VAR, 0, // 10: 0 }; static int kAnd[] = { ABS, // 0: (λλ 1 0 1) ABS, // 1: (λ 1 0 1) APP, 6, // 2: 1 0 1 APP, 2, // 4: 1 0 VAR, 1, // 6: 1 VAR, 0, // 8: 0 VAR, 1, // 10: 1 }; static int kNot[] = { ABS, // 0: (λ 0 false true) APP, 8, // 1: 0 false true APP, 2, // 3: 0 false VAR, 0, // 5: 0 ABS, // 7: false ABS, // 8: (λ 0) VAR, 0, // 9: 0 ABS, // 11: true ABS, // 12: (λ 1) VAR, 1, // 13: 1 }; static int kPair[] = { ABS, // 0: (λλλ 0 2 1) ABS, // 1: (λλ 0 2 1) ABS, // 2: (λ 0 2 1) APP, 6, // 3: 0 2 1 APP, 2, // 5: 0 2 VAR, 0, // 7: 0 VAR, 2, // 9: 2 VAR, 1, // 11: 1 }; static int kFirst[] = { ABS, // 0: (λ 0 false) APP, 2, // 1: 0 false VAR, 0, // 3: 0 ABS, // 5: false ABS, // 6: (λ 0) VAR, 0, // 7: 0 }; static int kSecond[] = { ABS, // 0: (λ 0 true) APP, 2, // 1: 0 true VAR, 0, // 3: 0 ABS, // 5: true ABS, // 6: (λ 1) VAR, 1, // 7: 1 }; static int kSucc[] = { ABS, // 0: (λλλ 1 (2 1 0)) ABS, // 1: (λλ 1 (2 1 0)) ABS, // 2: (λ 1 (2 1 0)) APP, 2, // 3: 1 (2 1 0) VAR, 1, // 5: 1 APP, 6, // 7: 2 1 0 APP, 2, // 9: 2 1 VAR, 2, // 11: 2 VAR, 1, // 13: 1 VAR, 0, // 15: 0 }; static int kCompose[] = { ABS, // 0: (λλλ 2 (1 0)) ABS, // 1: (λλ 2 (1 0)) ABS, // 2: (λ 2 (1 0)) APP, 2, // 3: 2 (1 0) VAR, 2, // 5: 2 APP, 2, // 7: 1 0 VAR, 1, // 9: 1 VAR, 0, // 11: 0 }; static int kMap[] = { ABS, // 0: (λλλλ 2 (compose 1 3) 0) ABS, // 1: (λλλ 2 (compose 1 3) 0) ABS, // 2: (λλ 2 (compose 1 3) 0) ABS, // 3: (λ 2 (compose 1 3) 0) APP, 25, // 4: 2 (compose 1 3) 0 APP, 2, // 6: 2 (compose 1 3) VAR, 2, // 8: 2 APP, 17, // 10: compose 1 3 APP, 13, // 12: compose 1 ABS, // 14: compose ABS, // 15: (λλ 2 (1 0)) ABS, // 16: (λ 2 (1 0)) APP, 2, // 17: 2 (1 0) VAR, 2, // 19: 2 APP, 2, // 21: 1 0 VAR, 1, // 23: 1 VAR, 0, // 25: 0 VAR, 1, // 27: 1 VAR, 3, // 29: 3 VAR, 0, // 31: 0 }; static int kCons[] = { ABS, // 0: (λλλλ 1 3 (2 1 0)) ABS, // 1: (λλλ 1 3 (2 1 0)) ABS, // 2: (λλ 1 3 (2 1 0)) ABS, // 3: (λ 1 3 (2 1 0)) APP, 6, // 4: 1 3 (2 1 0) APP, 2, // 6: 1 3 VAR, 1, // 8: 1 VAR, 3, // 10: 3 APP, 6, // 12: 2 1 0 APP, 2, // 14: 2 1 VAR, 2, // 16: 2 VAR, 1, // 18: 1 VAR, 0, // 20: 0 }; static int kY[] = { ABS, // 0: (λ (λ 1 (0 0)) (λ 1 (0 0))) APP, 11, // 1: (λ 1 (0 0)) (λ 1 (0 0)) ABS, // 3: (λ 1 (0 0)) APP, 2, // 4: 1 (0 0) VAR, 1, // 6: 1 APP, 2, // 8: 0 0 VAR, 0, // 10: 0 VAR, 0, // 12: 0 ABS, // 14: (λ 1 (0 0)) APP, 2, // 15: 1 (0 0) VAR, 1, // 17: 1 APP, 2, // 19: 0 0 VAR, 0, // 21: 0 VAR, 0, // 23: 0 }; static int kIszero[] = { ABS, // 0: λ [[0 λλλ 0] ⊤] APP, 9, // 1: [[0 λλλ 0] ⊤] APP, 2, // 3: [0 λλλ 0] VAR, 0, // 5: 0 ABS, // 7: λλλ 0 ABS, // 8: ⊥ ABS, // 9: λ 0 VAR, 0, // 10: 0 ABS, // 12: ⊤ ABS, // 13: λ 1 VAR, 1, // 14: 1 }; static int kPred[] = { ABS, // 0: λabc.a(λde.e(db))(λd.c)(λd.d) ABS, // 1: λab.ɐ(λcd.d(ca))(λc.b)(λc.c) ABS, // 2: λa.q(λbc.c(bɐ))(λb.a)(λb.b) APP, 21, // 3: ɔ(λab.b(aq))(λa.ɐ)(λa.a) APP, 16, // 5: ɔ(λab.b(aq))(λa.ɐ) APP, 2, // 7: ɔ(λab.b(aq)) VAR, 2, // 9: ɔ ABS, // 11: λab.b(aq) ABS, // 12: λa.a(ɐɔ) APP, 2, // 13: ɐ(qp) VAR, 0, // 15: ɐ APP, 2, // 17: qp VAR, 1, // 19: q VAR, 3, // 21: p ABS, // 23: λa.ɐ VAR, 1, // 24: q ABS, // 26: λa.a VAR, 0, // 27: ɐ }; static int kXor[] = { ABS, // 0: λab.a((λc.c(λde.e)(λde.d))b)b ABS, // 1: λa.ɐ((λb.b(λcd.d)(λcd.c))a)a APP, 23, // 2: q((λa.a(λbc.c)(λbc.b))ɐ)ɐ APP, 2, // 4: q((λa.a(λbc.c)(λbc.b))ɐ) VAR, 1, // 6: q APP, 15, // 8: (λa.a(λbc.c)(λbc.b))ɐ ABS, // 10: λa.a(λbc.c)(λbc.b) APP, 8, // 11: ɐ(λab.b)(λab.a) APP, 2, // 13: ɐ(λab.b) VAR, 0, // 15: ɐ ABS, // 17: λab.b ABS, // 18: λa.a VAR, 0, // 19: ɐ ABS, // 21: λab.a ABS, // 22: λa.ɐ VAR, 1, // 23: q VAR, 0, // 25: ɐ VAR, 0, // 27: ɐ }; static int kAdd[] = { ABS, // 29: λabcd.ac(bcd) ABS, // 30: λabc.ɐb(abc) ABS, // 31: λab.qa(ɐab) ABS, // 32: λa.ɔɐ(qɐa) APP, 6, // 33: pq(ɔqɐ) APP, 2, // 35: pq VAR, 3, // 37: p VAR, 1, // 39: q APP, 6, // 41: ɔqɐ APP, 2, // 43: ɔq VAR, 2, // 45: ɔ VAR, 1, // 47: q VAR, 0, // 49: ɐ }; static int kSub[] = { ABS, // 51: λab.b(λcde.c(λfg.g(fd))(λf.e)(λf.f))a ABS, // 52: λa.a(λbcd.b(λef.f(ec))(λe.d)(λe.e))ɐ APP, 33, // 53: ɐ(λabc.a(λde.e(db))(λd.c)(λd.d))q APP, 2, // 55: ɐ(λabc.a(λde.e(db))(λd.c)(λd.d)) VAR, 0, // 57: ɐ ABS, // 59: λabc.a(λde.e(db))(λd.c)(λd.d) ABS, // 60: λab.ɐ(λcd.d(ca))(λc.b)(λc.c) ABS, // 61: λa.q(λbc.c(bɐ))(λb.a)(λb.b) APP, 21, // 62: ɔ(λab.b(aq))(λa.ɐ)(λa.a) APP, 16, // 64: ɔ(λab.b(aq))(λa.ɐ) APP, 2, // 66: ɔ(λab.b(aq)) VAR, 2, // 68: ɔ ABS, // 70: λab.b(aq) ABS, // 71: λa.a(ɐɔ) APP, 2, // 72: ɐ(qp) VAR, 0, // 74: ɐ APP, 2, // 76: qp VAR, 1, // 78: q VAR, 3, // 80: p ABS, // 82: λa.ɐ VAR, 1, // 83: q ABS, // 85: λa.a VAR, 0, // 86: ɐ VAR, 1, // 88: q }; static int kLe[] = { ABS, // 0: λab.iszero(- a b) ABS, // 1: λa.iszero(- ɐ a) APP, 16, // 2: iszero(- q ɐ) ABS, // 4: iszero APP, 9, // 5: ɐ (λabc.c) ⊤ APP, 2, // 7: ɐ (λabc.c) VAR, 0, // 9: ɐ ABS, // 11: λabc.c ABS, // 12: ⊥ ABS, // 13: λa.a VAR, 0, // 14: ɐ ABS, // 16: ⊤ ABS, // 17: λa.ɐ VAR, 1, // 18: q APP, 43, // 20: - q ɐ APP, 39, // 22: - q ABS, // 24: - ABS, // 25: λa.a dec ɐ APP, 33, // 26: ɐ dec q APP, 2, // 28: ɐ dec VAR, 0, // 30: ɐ ABS, // 32: dec ABS, // 33: λab.ɐ (λcd.d(c a)) (λc.b) (λc.c) ABS, // 34: λa.q (λbc.c(b ɐ)) (λb.a) (λb.b) APP, 21, // 35: ɔ (λab.b(a q)) (λa.ɐ) (λa.a) APP, 16, // 37: ɔ (λab.b(a q)) (λa.ɐ) APP, 2, // 39: ɔ (λab.b(a q)) VAR, 2, // 41: ɔ ABS, // 43: λab.b(a q) ABS, // 44: λa.a(ɐ ɔ) APP, 2, // 45: ɐ(q p) VAR, 0, // 47: ɐ APP, 2, // 49: q p VAR, 1, // 51: q VAR, 3, // 53: p ABS, // 55: λa.ɐ VAR, 1, // 56: q ABS, // 58: λa.a VAR, 0, // 59: ɐ VAR, 1, // 61: q VAR, 1, // 63: q VAR, 0, // 65: ɐ }; static int kEq[] = { ABS, // 0: λab.∧(≤ a b)(≤ b a) ABS, // 1: λa.∧(≤ ɐ a)(≤ a ɐ) APP, 89, // 2: ∧(≤ q ɐ)(≤ ɐ q) APP, 12, // 4: ∧(≤ q ɐ) ABS, // 6: ∧ ABS, // 7: λa.ɐ a ɐ APP, 6, // 8: q ɐ q APP, 2, // 10: q ɐ VAR, 1, // 12: q VAR, 0, // 14: ɐ VAR, 1, // 16: q APP, 71, // 18: ≤ q ɐ APP, 67, // 20: ≤ q ABS, // 22: ≤ ABS, // 23: λa.iszero(- ɐ a) APP, 16, // 24: iszero(- q ɐ) ABS, // 26: iszero APP, 9, // 27: ɐ (λabc.c) ⊤ APP, 2, // 29: ɐ (λabc.c) VAR, 0, // 31: ɐ ABS, // 33: λabc.c ABS, // 34: ⊥ ABS, // 35: λa.a VAR, 0, // 36: ɐ ABS, // 38: ⊤ ABS, // 39: λa.ɐ VAR, 1, // 40: q APP, 43, // 42: - q ɐ APP, 39, // 44: - q ABS, // 46: - ABS, // 47: λa.a dec ɐ APP, 33, // 48: ɐ dec q APP, 2, // 50: ɐ dec VAR, 0, // 52: ɐ ABS, // 54: dec ABS, // 55: λab.ɐ (λcd.d(c a)) (λc.b) (λc.c) ABS, // 56: λa.q (λbc.c(b ɐ)) (λb.a) (λb.b) APP, 21, // 57: ɔ (λab.b(a q)) (λa.ɐ) (λa.a) APP, 16, // 59: ɔ (λab.b(a q)) (λa.ɐ) APP, 2, // 61: ɔ (λab.b(a q)) VAR, 2, // 63: ɔ ABS, // 65: λab.b(a q) ABS, // 66: λa.a(ɐ ɔ) APP, 2, // 67: ɐ(q p) VAR, 0, // 69: ɐ APP, 2, // 71: q p VAR, 1, // 73: q VAR, 3, // 75: p ABS, // 77: λa.ɐ VAR, 1, // 78: q ABS, // 80: λa.a VAR, 0, // 81: ɐ VAR, 1, // 83: q VAR, 1, // 85: q VAR, 0, // 87: ɐ VAR, 1, // 89: q VAR, 0, // 91: ɐ APP, 71, // 93: ≤ ɐ q APP, 67, // 95: ≤ ɐ ABS, // 97: ≤ ABS, // 98: λa.iszero(- ɐ a) APP, 16, // 99: iszero(- q ɐ) ABS, // 101: iszero APP, 9, // 102: ɐ (λabc.c) ⊤ APP, 2, // 104: ɐ (λabc.c) VAR, 0, // 106: ɐ ABS, // 108: λabc.c ABS, // 109: ⊥ ABS, // 110: λa.a VAR, 0, // 111: ɐ ABS, // 113: ⊤ ABS, // 114: λa.ɐ VAR, 1, // 115: q APP, 43, // 117: - q ɐ APP, 39, // 119: - q ABS, // 121: - ABS, // 122: λa.a dec ɐ APP, 33, // 123: ɐ dec q APP, 2, // 125: ɐ dec VAR, 0, // 127: ɐ ABS, // 129: dec ABS, // 130: λab.ɐ (λcd.d(c a)) (λc.b) (λc.c) ABS, // 131: λa.q (λbc.c(b ɐ)) (λb.a) (λb.b) APP, 21, // 132: ɔ (λab.b(a q)) (λa.ɐ) (λa.a) APP, 16, // 134: ɔ (λab.b(a q)) (λa.ɐ) APP, 2, // 136: ɔ (λab.b(a q)) VAR, 2, // 138: ɔ ABS, // 140: λab.b(a q) ABS, // 141: λa.a(ɐ ɔ) APP, 2, // 142: ɐ(q p) VAR, 0, // 144: ɐ APP, 2, // 146: q p VAR, 1, // 148: q VAR, 3, // 150: p ABS, // 152: λa.ɐ VAR, 1, // 153: q ABS, // 155: λa.a VAR, 0, // 156: ɐ VAR, 1, // 158: q VAR, 1, // 160: q VAR, 0, // 162: ɐ VAR, 0, // 164: ɐ VAR, 1, // 166: q }; void PrintVar(int i, FILE* f) { switch (style) { case 0: fprintf(f, "%d", i); break; case 1: if (0 <= i && i < sizeof(ALPHABET) / sizeof(*ALPHABET) - 1) { fputwc(ALPHABET[i], f); } else if (i < 0 && ~i < sizeof(FREEBIES) / sizeof(*FREEBIES) - 1) { fputwc(FREEBIES[~i], f); } else { fprintf(f, "?%d", i); } break; default: do { fputc('1', f); } while (i-- > 0); fputc('0', f); break; } } void PrintDebruijn(int x, int head, int depth, FILE* f) { if (0 <= x && x < TERMS) { if (mem[x] == ABS) { if (!noname) { if (x == 14) { fputs("put", f); return; } if (x + sizeof(kTrue) / sizeof(*kTrue) <= end && !memcmp(mem + x, kTrue, sizeof(kTrue))) { if (asciiname) { fputs("true", f); } else { fputs("⊤", f); } return; } if (x + sizeof(kFalse) / sizeof(*kFalse) <= end && !memcmp(mem + x, kFalse, sizeof(kFalse))) { if (asciiname) { fputs("false", f); } else { fputs("⊥", f); } return; } if (x + sizeof(kOmega) / sizeof(*kOmega) <= end && !memcmp(mem + x, kOmega, sizeof(kOmega))) { if (asciiname) { fputs("omega", f); } else { fputs("Ω", f); } return; } if (x + sizeof(kSelf) / sizeof(*kSelf) <= end && !memcmp(mem + x, kSelf, sizeof(kSelf))) { if (asciiname) { fputs("omega", f); } else { fputs("ω", f); } return; } if (x + sizeof(kY) / sizeof(*kY) <= end && !memcmp(mem + x, kY, sizeof(kY))) { fputs("Y", f); return; } if (x + sizeof(kIf) / sizeof(*kIf) <= end && !memcmp(mem + x, kIf, sizeof(kIf))) { fputs("if", f); return; } if (x + sizeof(kPair) / sizeof(*kPair) <= end && !memcmp(mem + x, kPair, sizeof(kPair))) { fputs("pair", f); return; } if (x + sizeof(kNot) / sizeof(*kNot) <= end && !memcmp(mem + x, kNot, sizeof(kNot))) { if (asciiname) { fputs("not", f); } else { fputwc(L'¬', f); } return; } if (x + sizeof(kOr) / sizeof(*kOr) <= end && !memcmp(mem + x, kOr, sizeof(kOr))) { if (asciiname) { fputs("or", f); } else { fputwc(L'∨', f); } return; } if (x + sizeof(kAnd) / sizeof(*kAnd) <= end && !memcmp(mem + x, kAnd, sizeof(kAnd))) { if (asciiname) { fputs("and", f); } else { fputwc(L'∧', f); } return; } if (x + sizeof(kXor) / sizeof(*kXor) <= end && !memcmp(mem + x, kXor, sizeof(kXor))) { if (asciiname) { fputs("xor", f); } else { fputwc(L'⊻', f); } return; } if (x + sizeof(kLe) / sizeof(*kLe) <= end && !memcmp(mem + x, kLe, sizeof(kLe))) { if (asciiname) { fputs("le", f); } else { fputwc(L'≤', f); } return; } if (x + sizeof(kEq) / sizeof(*kEq) <= end && !memcmp(mem + x, kEq, sizeof(kEq))) { fputwc(L'=', f); return; } if (x + sizeof(kAdd) / sizeof(*kAdd) <= end && !memcmp(mem + x, kAdd, sizeof(kAdd))) { fputs("+", f); return; } if (x + sizeof(kSub) / sizeof(*kSub) <= end && !memcmp(mem + x, kSub, sizeof(kSub))) { fputs("-", f); return; } if (x + sizeof(kCompose) / sizeof(*kCompose) <= end && !memcmp(mem + x, kCompose, sizeof(kCompose))) { fputs("∘", f); return; } if (x + sizeof(kSucc) / sizeof(*kSucc) <= end && !memcmp(mem + x, kSucc, sizeof(kSucc))) { fputs("inc", f); return; } if (x + sizeof(kPred) / sizeof(*kPred) <= end && !memcmp(mem + x, kPred, sizeof(kPred))) { fputs("dec", f); return; } if (x + sizeof(kSecond) / sizeof(*kSecond) <= end && !memcmp(mem + x, kSecond, sizeof(kSecond))) { fputs("second", f); return; } if (x + sizeof(kFirst) / sizeof(*kFirst) <= end && !memcmp(mem + x, kFirst, sizeof(kFirst))) { fputs("first", f); return; } if (x + sizeof(kMap) / sizeof(*kMap) <= end && !memcmp(mem + x, kMap, sizeof(kMap))) { fputs("map", f); return; } if (x + sizeof(kIszero) / sizeof(*kIszero) <= end && !memcmp(mem + x, kIszero, sizeof(kIszero))) { fputs("iszero", f); return; } if (x + sizeof(kCons) / sizeof(*kCons) <= end && !memcmp(mem + x, kCons, sizeof(kCons))) { fputs("cons", f); return; } if (x + sizeof(kOne) / sizeof(*kOne) <= end && !memcmp(mem + x, kOne, sizeof(kOne))) { fputs("one", f); return; } if (x + sizeof(kTwo) / sizeof(*kTwo) <= end && !memcmp(mem + x, kTwo, sizeof(kTwo))) { fputs("two", f); return; } if (x + sizeof(kThree) / sizeof(*kThree) <= end && !memcmp(mem + x, kThree, sizeof(kThree))) { fputs("three", f); return; } if (x + sizeof(kFour) / sizeof(*kFour) <= end && !memcmp(mem + x, kFour, sizeof(kFour))) { fputs("four", f); return; } if (x + sizeof(kFive) / sizeof(*kFive) <= end && !memcmp(mem + x, kFive, sizeof(kFive))) { fputs("five", f); return; } if (x + sizeof(kSix) / sizeof(*kSix) <= end && !memcmp(mem + x, kSix, sizeof(kSix))) { fputs("six", f); return; } if (x + sizeof(kSeven) / sizeof(*kSeven) <= end && !memcmp(mem + x, kSeven, sizeof(kSeven))) { fputs("seven", f); return; } if (x + sizeof(kEight) / sizeof(*kEight) <= end && !memcmp(mem + x, kEight, sizeof(kEight))) { fputs("eight", f); return; } if (x + sizeof(kNine) / sizeof(*kNine) <= end && !memcmp(mem + x, kNine, sizeof(kNine))) { fputs("nine", f); return; } } do { ++x; if (asciiname) { fputc('\\', f); } else { fputwc(L'λ', f); } if (!(0 <= x && x < TERMS)) goto Overflow; } while (mem[x] == ABS); fputc(' ', f); } if (!(0 <= (x + 1) && (x + 1) < TERMS)) goto Overflow; if (mem[x] == APP) { fputc('[', f); PrintDebruijn(x + 2, 1, depth, f); fputc(' ', f); PrintDebruijn(x + 2 + mem[x + 1], 0, depth, f); fputc(']', f); } else if (mem[x] == VAR) { if (0 <= x + 1 && x + 1 < TERMS) { PrintVar(mem[x + 1], f); } else { fprintf(f, "‼%d", x); } } else if (mem[x] == IOP) { if (x < 22) { if (mem[x + 1] & 1) { fputs("put", f); } else if (x & 1) { fputs("wr1", f); } else { fputs("wr0", f); } } else if (x == end) { fputs(asciiname ? "gro" : "⋯", f); } else { fprintf(f, "!%d", x); } } else { fprintf(f, "!%d", x); } return; } Overflow: fprintf(f, "‼%d", x); } void PrintLambda(int x, int head, int depth, int apps, FILE* f) { int close = 0; if (0 <= x && x < TERMS) { if (mem[x] == ABS) { if (!noname) { if (x == 14) { if (asciiname) { fputs("put", f); } else { fputs("⍆", f); } return; } if (x + sizeof(kTrue) / sizeof(*kTrue) <= end && !memcmp(mem + x, kTrue, sizeof(kTrue))) { if (asciiname) { fputs("true", f); } else { fputs("⊤", f); } return; } if (x + sizeof(kFalse) / sizeof(*kFalse) <= end && !memcmp(mem + x, kFalse, sizeof(kFalse))) { if (asciiname) { fputs("false", f); } else { fputs("⊥", f); } return; } if (x + sizeof(kY) / sizeof(*kY) <= end && !memcmp(mem + x, kY, sizeof(kY))) { fputs("Y", f); return; } if (x + sizeof(kOmega) / sizeof(*kOmega) <= end && !memcmp(mem + x, kOmega, sizeof(kOmega))) { if (asciiname) { fputs("OMEGA", f); } else { fputs("Ω", f); } return; } if (x + sizeof(kSelf) / sizeof(*kSelf) <= end && !memcmp(mem + x, kSelf, sizeof(kSelf))) { if (asciiname) { fputs("omega", f); } else { fputs("ω", f); } return; } if (x + sizeof(kNot) / sizeof(*kNot) <= end && !memcmp(mem + x, kNot, sizeof(kNot))) { if (asciiname) { fputs("not", f); } else { fputwc(L'¬', f); } return; } if (x + sizeof(kOr) / sizeof(*kOr) <= end && !memcmp(mem + x, kOr, sizeof(kOr))) { if (asciiname) { fputs("or", f); } else { fputwc(L'∨', f); } return; } if (x + sizeof(kXor) / sizeof(*kXor) <= end && !memcmp(mem + x, kXor, sizeof(kXor))) { if (asciiname) { fputs("xor", f); } else { fputwc(L'⊻', f); } return; } if (x + sizeof(kLe) / sizeof(*kLe) <= end && !memcmp(mem + x, kLe, sizeof(kLe))) { if (asciiname) { fputs("le", f); } else { fputwc(L'≤', f); } return; } if (x + sizeof(kEq) / sizeof(*kEq) <= end && !memcmp(mem + x, kEq, sizeof(kEq))) { fputwc(L'=', f); return; } if (x + sizeof(kAnd) / sizeof(*kAnd) <= end && !memcmp(mem + x, kAnd, sizeof(kAnd))) { if (asciiname) { fputs("and", f); } else { fputwc(L'∧', f); } return; } if (x + sizeof(kAdd) / sizeof(*kAdd) <= end && !memcmp(mem + x, kAdd, sizeof(kAdd))) { fputs("+", f); return; } if (x + sizeof(kSub) / sizeof(*kSub) <= end && !memcmp(mem + x, kSub, sizeof(kSub))) { fputs("-", f); return; } if (x + sizeof(kCompose) / sizeof(*kCompose) <= end && !memcmp(mem + x, kCompose, sizeof(kCompose))) { if (asciiname) { fputs("compose", f); } else { fputs("∘", f); } return; } if (x + sizeof(kOne) / sizeof(*kOne) <= end && !memcmp(mem + x, kOne, sizeof(kOne))) { fputc('1', f); return; } if (x + sizeof(kTwo) / sizeof(*kTwo) <= end && !memcmp(mem + x, kTwo, sizeof(kTwo))) { fputc('2', f); return; } if (x + sizeof(kThree) / sizeof(*kThree) <= end && !memcmp(mem + x, kThree, sizeof(kThree))) { fputc('3', f); return; } if (x + sizeof(kFour) / sizeof(*kFour) <= end && !memcmp(mem + x, kFour, sizeof(kFour))) { fputc('4', f); return; } if (x + sizeof(kFive) / sizeof(*kFive) <= end && !memcmp(mem + x, kFive, sizeof(kFive))) { fputc('5', f); return; } if (x + sizeof(kSix) / sizeof(*kSix) <= end && !memcmp(mem + x, kSix, sizeof(kSix))) { fputc('6', f); return; } if (x + sizeof(kSeven) / sizeof(*kSeven) <= end && !memcmp(mem + x, kSeven, sizeof(kSeven))) { fputc('7', f); return; } if (x + sizeof(kEight) / sizeof(*kEight) <= end && !memcmp(mem + x, kEight, sizeof(kEight))) { fputc('8', f); return; } if (x + sizeof(kNine) / sizeof(*kNine) <= end && !memcmp(mem + x, kNine, sizeof(kNine))) { fputc('9', f); return; } if (x + sizeof(kIf) / sizeof(*kIf) <= end && !memcmp(mem + x, kIf, sizeof(kIf))) { fputs("if", f); return; } if (x + sizeof(kPair) / sizeof(*kPair) <= end && !memcmp(mem + x, kPair, sizeof(kPair))) { fputs("pair", f); return; } if (x + sizeof(kSucc) / sizeof(*kSucc) <= end && !memcmp(mem + x, kSucc, sizeof(kSucc))) { fputs("inc", f); return; } if (x + sizeof(kPred) / sizeof(*kPred) <= end && !memcmp(mem + x, kPred, sizeof(kPred))) { fputs("dec", f); return; } if (x + sizeof(kSecond) / sizeof(*kSecond) <= end && !memcmp(mem + x, kSecond, sizeof(kSecond))) { fputs("second", f); return; } if (x + sizeof(kFirst) / sizeof(*kFirst) <= end && !memcmp(mem + x, kFirst, sizeof(kFirst))) { fputs("first", f); return; } if (x + sizeof(kMap) / sizeof(*kMap) <= end && !memcmp(mem + x, kMap, sizeof(kMap))) { fputs("map", f); return; } if (x + sizeof(kIszero) / sizeof(*kIszero) <= end && !memcmp(mem + x, kIszero, sizeof(kIszero))) { fputs("iszero", f); return; } if (x + sizeof(kCons) / sizeof(*kCons) <= end && !memcmp(mem + x, kCons, sizeof(kCons))) { fputs("cons", f); return; } } if (apps) { fputc('(', f); close = 1; } if (asciiname) { fputc('\\', f); } else { fputwc(L'λ', f); } if (safer) { fputwc(ALPHABET[depth++], f); fputc('.', f); PrintLambda(x + 1, head, depth, apps + 1, f); if (close) { fputc(')', f); } return; } do { ++x; fputwc(ALPHABET[depth++], f); if (!(0 <= x && x < TERMS)) goto Overflow; } while (mem[x] == ABS); fputc('.', f); } if (!(0 <= (x + 1) && (x + 1) < TERMS)) goto Overflow; if (mem[x] == VAR) { if (0 <= x + 1 && x + 1 < TERMS) { PrintVar(depth - 1 - mem[x + 1], f); } else { fprintf(f, "‼%d", x); } } else if (mem[x] == APP) { if (!close && !head) { fputc('(', f); close = 1; } PrintLambda(x + 2, 1, depth, apps + 1, f); if (!(x + 2 + mem[x + 1] < TERMS && mem[x + 2 + mem[x + 1]] == APP)) { if (safer || !noname) fputc(' ', f); } PrintLambda(x + 2 + mem[x + 1], 0, depth, apps + 1, f); } else if (mem[x] == IOP) { if (x < 22) { if (mem[x + 1] & 1) { fputs(asciiname ? "put" : "⍆", f); } else if (x & 1) { fputs(asciiname ? "wr1" : "⍆₁", f); } else { fputs(asciiname ? "wr0" : "⍆₀", f); } } else if (x == end) { fputs(asciiname ? "gro" : "⋯", f); } else { fprintf(f, "!%d", x); } } else { fprintf(f, "!%d", x); } if (close) { fputc(')', f); } return; } Overflow: fprintf(f, "‼%d", x); } void PrintBinary(int x, int head, int depth, FILE* f) { if (0 <= x && x < TERMS) { if (mem[x] == ABS) { if (x == 14) { fputs("⍆", f); return; } do { ++x; ++depth; fputc('0', f); fputc('0', f); if (!(0 <= x && x < TERMS)) goto Overflow; } while (mem[x] == ABS); } if (!(0 <= (x + 1) && (x + 1) < TERMS)) goto Overflow; if (mem[x] == VAR) { if (0 <= x + 1 && x + 1 < TERMS) { PrintVar(mem[x + 1], f); } else { fprintf(f, "‼%d", x); } } else if (mem[x] == APP) { fputc('0', f); fputc('1', f); PrintBinary(x + 2, 0, 0, f); PrintBinary(x + 2 + mem[x + 1], 0, 0, f); } else if (mem[x] == IOP) { if (x < 22) { if (mem[x + 1] & 1) { fputs("⍆", f); } else if (x & 1) { fputs("⍆₁", f); } else { fputs("⍆₀", f); } } else { fputwc(L'⋯', f); } } else if (mem[x] == -1) { fputwc(L'⋯', f); } else { fprintf(f, "!%d", x); } return; } Overflow: fprintf(f, "‼%d", x); } void Print(int x, int head, int depth, FILE* f) { switch (style) { case 0: PrintDebruijn(x, head, depth, f); break; case 1: PrintLambda(x, head, depth, 0, f); break; default: PrintBinary(x, head, depth, f); break; } }