We add an initial "_title_" and "_abstract_" to all entry `.entry.json` files. The `bin/csv2entry.sh` tool reads the `summary.csv` file and loads the "_title_" and "_abstract_" to entry `.entry.json` files. Changed `bin/csv2entry.sh` VERSION from "1.3 2024-09-23" to "1.4 2024-09-27". Perform `make csv2entry` to perform the above and test under macOS. The `bin/cvt-submission.sh` tool adds "_title_" and "_abstract_" to the .entry.json based on the `.info.json` file. Changed `bin/cvt-submission.sh` VERSION from "1.2 2024-09-23" to "1.3 2024-09-27". The `bin/entry2csv.sh` tool forms the `summary.csv` file based on the "_title_" and "_abstract_" fields found in .entry.json files. Changed `bin/entry2csv.sh` VERSION from "1.3 2024-09-23" to "1.4 2024-09-27". Perform `make entry2csv` to perform the above and test under macOS. Added `-H` and `header=with-header-3` to the `bin/md2html.cfg` for the configuration entry for `[12][0-9][0-9][0-9]/*/README.md`. Changed `bin/md2html.sh` VERSION from "1.6 2024-08-17" to "1.7 2024-09-27". All entry `index.html` files now list the "_abstract_" in a new `<h3>abstract</h3>` header. Changed `bin/subst.entry-index.sh` VERSION from "1.6 2024-09-23" to "1.7 2024-09-27". Removed `summary.csv`. Added `summary.csv` and `summary.numbers` to `.gitignore`. Sorted the result with `bin/sgi.sh`. Perform `make quick_www` to perform the above and test under macOS. Perform `make www` to perform the above and test under macOS.
813 lines
36 KiB
HTML
813 lines
36 KiB
HTML
<!DOCTYPE html>
|
||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||
<!-- START: two lines up starts content from: inc/top.default.html -->
|
||
|
||
<!-- END: this line ends content from: inc/top.default.html -->
|
||
<!-- START: this line starts content from: inc/head.default.html -->
|
||
|
||
<head>
|
||
<link rel="stylesheet" href="../../ioccc.css">
|
||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@100..900&display=swap" rel="stylesheet">
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
|
||
<title>1998/fanf - Most obfuscated translator</title>
|
||
<link rel="icon" type="image/x-icon" href="../../favicon.ico">
|
||
<meta name="description" content="1998 IOCCC entry fanf - Most obfuscated translator">
|
||
<meta name="keywords" content="IOCCC, 1998, IOCCC 1998, IOCCC entry, fanf, Most obfuscated translator">
|
||
</head>
|
||
|
||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||
<!-- !!! DO NOT MODIFY THIS FILE - This file is generated by a tool !!! -->
|
||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||
|
||
<!-- END: this line ends content from: inc/head.default.html -->
|
||
|
||
<!-- -->
|
||
<!-- This web page was formed via the tool: bin/readme2index.sh -->
|
||
<!-- The content of main section of this web page came from: 1998/fanf/README.md -->
|
||
<!-- -->
|
||
|
||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||
<!-- !!! Do not modify this web page, instead modify the file: 1998/fanf/README.md !!! -->
|
||
<!-- !!! Do not modify this web page, instead modify the file: 1998/fanf/README.md !!! -->
|
||
<!-- !!! Do not modify this web page, instead modify the file: 1998/fanf/README.md !!! -->
|
||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||
|
||
<!-- Markdown content was converted into HTML via the tool: bin/md2html.sh -->
|
||
|
||
<!-- START: this line starts content from: inc/body.default.html -->
|
||
|
||
<body>
|
||
|
||
<!-- END: this line ends content from: inc/body.default.html -->
|
||
<!-- START: this line starts content from: inc/topbar.default.html -->
|
||
|
||
<div class="theader">
|
||
<nav class="topbar">
|
||
<div class="container">
|
||
<div class="logo">
|
||
<a href="../../index.html" class="logo-link">
|
||
IOCCC
|
||
</a>
|
||
</div>
|
||
|
||
<div class="topbar-items">
|
||
<div class="item">
|
||
<span class="item-header">
|
||
Entries
|
||
</span>
|
||
|
||
<div class="sub-item">
|
||
<div class="outfit-font">
|
||
<a href="../../years.html" class="sub-item-link">
|
||
Winning Entries
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../authors.html" class="sub-item-link">
|
||
Winning Authors
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../location.html" class="sub-item-link">
|
||
Location of winning authors
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../bugs.html" class="sub-item-link">
|
||
Bugs and (mis)features
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="item">
|
||
<span class="item-header">
|
||
Status
|
||
</span>
|
||
|
||
<div class="sub-item">
|
||
<div class="outfit-font">
|
||
<a href="../../news.html" class="sub-item-link">
|
||
IOCCC News
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../status.html" class="sub-item-link">
|
||
Contest status
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../next/index.html" class="sub-item-link">
|
||
Rules and Guidelines
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="item">
|
||
<span class="item-header">
|
||
FAQ
|
||
</span>
|
||
|
||
<div class="sub-item">
|
||
<div class="outfit-font">
|
||
<a href="../../faq.html" class="sub-item-link">
|
||
FAQ
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../faq.html#submit" class="sub-item-link">
|
||
How to enter the IOCCC
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../faq.html#fix_an_entry" class="sub-item-link">
|
||
Fixing IOCCC entries
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../faq.html#fix_web_site" class="sub-item-link">
|
||
Fixing the website
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../faq.html#fix_author" class="sub-item-link">
|
||
Updating author info
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="item">
|
||
<span class="item-header">
|
||
About
|
||
</span>
|
||
|
||
<div class="sub-item">
|
||
<div class="outfit-font">
|
||
<a href="../../index.html" class="sub-item-link">
|
||
IOCCC Home
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../judges.html" class="sub-item-link">
|
||
The IOCCC Judges
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../contact.html" class="sub-item-link">
|
||
Contacting the IOCCC
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../SECURITY.html" class="sub-item-link">
|
||
IOCCC Security Policy
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../thanks-for-help.html" class="sub-item-link">
|
||
Thanks for the help
|
||
</a>
|
||
</div>
|
||
|
||
<div class="outfit-font">
|
||
<a href="../../markdown.html" class="sub-item-link">
|
||
IOCCC markdown guidelines
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
|
||
<div class="header-mobile-menu">
|
||
<noscript>
|
||
<a href="../../nojs-menu.html" class="topbar-js-label">
|
||
Please Enable JavaScript
|
||
</a>
|
||
</noscript>
|
||
|
||
<button id="header-open-menu-button" class="topbar-mobile-menu">
|
||
<img
|
||
src="../../png/hamburger-icon-open.png"
|
||
alt="hamburger style menu icon - open state"
|
||
width=48
|
||
height=48>
|
||
</button>
|
||
|
||
<button id="header-close-menu-button" class="hide-content">
|
||
<img
|
||
src="../../png/hamburger-icon-closed.png"
|
||
alt="hamburger style menu icon - closed state"
|
||
width=48
|
||
height=48>
|
||
</button>
|
||
|
||
<div id="mobile-menu-panel" class="hide-content">
|
||
<div class="mobile-menu-container">
|
||
|
||
<div class="mobile-menu-wrapper">
|
||
<div class="mobile-menu-item">
|
||
Entries
|
||
</div>
|
||
<div class="mobile-submenu-wrapper">
|
||
|
||
<a class="mobile-submenu-item" href="../../years.html">
|
||
Winning Entries
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../authors.html">
|
||
Authors of winning IOCCC entries
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../location.html">
|
||
Location of authors
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../bugs.html">
|
||
Bugs and (mis)features
|
||
</a>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mobile-menu-wrapper">
|
||
|
||
<div class="mobile-menu-item">
|
||
Status
|
||
</div>
|
||
<div class="mobile-submenu-wrapper">
|
||
|
||
<a class="mobile-submenu-item" href="../../status.html">
|
||
Contest status
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../next/index.html">
|
||
Rules and Guidelines
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../news.html">
|
||
IOCCC News
|
||
</a>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mobile-menu-wrapper">
|
||
<div class="mobile-menu-item">
|
||
FAQ
|
||
</div>
|
||
<div class="mobile-submenu-wrapper">
|
||
|
||
<a class="mobile-submenu-item" href="../../faq.html">
|
||
Frequently Asked Questions
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../faq.html#submit">
|
||
How to enter the IOCCC
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../faq.html#fix_an_entry">
|
||
Fixing IOCCC entries
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../faq.html#fix_web_site">
|
||
Fixing the website
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../faq.html#fix_author">
|
||
Fixing author info
|
||
</a>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div class="mobile-menu-wrapper">
|
||
<div class="mobile-menu-item">
|
||
About
|
||
</div>
|
||
<div class="mobile-submenu-wrapper">
|
||
|
||
<a class="mobile-submenu-item" href="../../index.html">
|
||
IOCCC Home
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../judges.html">
|
||
The IOCCC Judges
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../contact.html">
|
||
Contacting the IOCCC
|
||
</a>
|
||
|
||
<a class="mobile-submenu-item" href="../../thanks-for-help.html">
|
||
Thanks for the help
|
||
</a>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<script>
|
||
var headerOpenMenuButton = document.getElementById("header-open-menu-button");
|
||
var headerCloseMenuButton = document.getElementById("header-close-menu-button");
|
||
var mobileMenuPanel = document.getElementById("mobile-menu-panel");
|
||
|
||
headerOpenMenuButton.addEventListener("click", () => {
|
||
headerOpenMenuButton.classList.remove("topbar-mobile-menu");
|
||
headerOpenMenuButton.classList.add("hide-content");
|
||
|
||
headerCloseMenuButton.classList.remove("hide-content");
|
||
headerCloseMenuButton.classList.add("topbar-mobile-menu");
|
||
|
||
mobileMenuPanel.classList.remove("hide-content");
|
||
mobileMenuPanel.classList.add("topbar-mobile-panel");
|
||
});
|
||
|
||
headerCloseMenuButton.addEventListener("click", () => {
|
||
headerCloseMenuButton.classList.remove("topbar-mobile-menu");
|
||
headerCloseMenuButton.classList.add("hide-content");
|
||
|
||
mobileMenuPanel.classList.add("hide-content");
|
||
mobileMenuPanel.classList.remove("topbar-mobile-panel");
|
||
|
||
headerOpenMenuButton.classList.add("topbar-mobile-menu");
|
||
headerOpenMenuButton.classList.remove("hide-content");
|
||
});
|
||
</script>
|
||
|
||
<!-- END: this line ends content from: inc/topbar.default.html -->
|
||
<!-- START: this line starts content from: inc/header.default.html -->
|
||
|
||
<div class="header">
|
||
<a href="../../2011/zucker/index.html">
|
||
<img src="../../png/ioccc.png"
|
||
alt="IOCCC image by Matt Zucker"
|
||
width=300
|
||
height=110>
|
||
</a>
|
||
<h1>The International Obfuscated C Code Contest</h1>
|
||
<h2>1998/fanf - Most obfuscated translator</h2>
|
||
<h3>Translates Lambda expressions into combinator expressions</h3>
|
||
</div>
|
||
|
||
<!-- END: this line ends content from: inc/header.default.html -->
|
||
<!-- START: this line starts content from: inc/navbar.mid.html -->
|
||
|
||
<div class="navbar">
|
||
<a class="Left" href="../dorssel/index.html">← 1998/dorssel</a>
|
||
<a class="Left" href="../index.html">↑ 1998 ↑</a>
|
||
<a class="Left" href="../schnitzi/index.html">1998/schnitzi →</a>
|
||
<a class="Right" href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1998/fanf/fanf.c">C code</a>
|
||
<a class="Right" href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1998/fanf/Makefile">Makefile</a>
|
||
<a class="Right" href="#inventory">Inventory</a>
|
||
<a class="Right" href="https://validator.w3.org/nu/?doc=https%3A%2F%2Fioccc-src.github.io%2Ftemp-test-ioccc%2F1998%2Ffanf%2Findex.html">✓</a>
|
||
</div>
|
||
|
||
<!-- END: this line ends content from: inc/navbar.mid.html -->
|
||
<!-- START: this line starts content from: inc/before-content.default.html -->
|
||
|
||
<div class="content" id="content">
|
||
|
||
<!-- END: this line ends content from: inc/before-content.default.html -->
|
||
<!-- START: this line starts content for HTML phase 20 by: bin/output-index-author.sh via bin/md2html.sh -->
|
||
|
||
<!-- START: this line starts content generated by: bin/output-index-author.sh -->
|
||
|
||
<h2 id="author">Author:</h2>
|
||
<ul>
|
||
<li>Name: <a href="../../authors.html#Tony_Finch">Tony Finch</a><br>
|
||
Location: <a href="../../location.html#GB">GB</a> - <em>United Kingdom of Great Britain and Northern Ireland</em> (<em>United Kingdom</em>)</li>
|
||
</ul>
|
||
|
||
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
|
||
|
||
<!-- END: this line ends content for HTML phase 20 by: bin/output-index-author.sh via bin/md2html.sh -->
|
||
<!-- START: this line starts content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
|
||
|
||
<!-- BEFORE: 1st line of markdown file: 1998/fanf/README.md -->
|
||
<h2 id="to-build">To build:</h2>
|
||
<pre><code> make all</code></pre>
|
||
<p>NOTE: this may take a while. Some systems may have problems building
|
||
this entry because of the system resources it requires.</p>
|
||
<h2 id="to-use">To use:</h2>
|
||
<pre><code> ./fanf</code></pre>
|
||
<h2 id="try">Try:</h2>
|
||
<p>Enter an expression on standard input. To try some we have selected:</p>
|
||
<pre><code> ./try.sh</code></pre>
|
||
<h2 id="judges-remarks">Judges’ remarks:</h2>
|
||
<h3 id="historical-aside">Historical aside:</h3>
|
||
<p>At a time the code in <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1998/fanf/fanf.c">fanf.c</a> was that of <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1998/fanf/fanf.orig.c">fanf.orig.c</a>
|
||
but to get this to compile in modern systems it had to be translated to what you
|
||
now see. The intermediate steps can still be performed but they might be
|
||
different from the past. This should be kept in mind as you read the below
|
||
remarks.</p>
|
||
<p>This program translates lambda expressions into combinator
|
||
expressions. But you do not need to know Lambda Calculus to be
|
||
impressed by this program!</p>
|
||
<p>See the file <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1998/fanf/fanf.lambda">fanf.lambda</a> for more examples of lambda calculus
|
||
source.</p>
|
||
<p>Notice how large the code grows from the <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1998/fanf/fanf.c">fanf.c</a> into the final
|
||
<code>fanftmp2.c</code> C program. Take a look at that final C program again,
|
||
can you begin to understand what it is doing?</p>
|
||
<p>Look at the first stage of the C pre-processing which was done like:</p>
|
||
<pre><code> cc fanf.c -E > fanftmp1.c</code></pre>
|
||
<p>Skip to the bottom of <code>fanftmp1.c</code> (after all of the C pre-processor header
|
||
stuff … look for a line of the form: <code># 38 "fanf.c"</code> near the bottom)
|
||
and look at the resulting code. This code, when C pre-processed
|
||
will expand into over 342 times the original code (ignoring <code>#include</code>
|
||
headers) to produce <code>fanftmp2.c</code>. That program in turn, when compiled
|
||
translates a single lambda expression on standard input into
|
||
combinator expressions on standard output.</p>
|
||
<h3 id="extra-credit-question">Extra credit question:</h3>
|
||
<p>What do you have to do to make this program work with an old non-ANSI C
|
||
preprocessor?</p>
|
||
<h2 id="authors-remarks">Author’s remarks:</h2>
|
||
<p>My program is a demonstration of some practical applications of
|
||
theoretical computer science. The application it implements is a program
|
||
for translating lambda expressions into combinator expressions.</p>
|
||
<h3 id="what-the-program-does">What the program does</h3>
|
||
<p>The syntax of lambda expressions recognised by the program is as
|
||
follows: The basic atoms are variables which are single characters other
|
||
than backslash or parentheses, e.g. <code>a</code> or <code>b</code> or <code>@</code>. Variables are
|
||
combined by function application which is written as e.g. <code>(f a)</code> which is
|
||
the function <code>f</code> applied to the argument <code>a</code>. Application groups to the
|
||
left, so <code>(f a b c)</code> is equivalent to <code>(((f a) b) c)</code>. Functions are
|
||
created from lambda terms which are written in the form <code>\a(expr)</code> which
|
||
is the function taking argument <code>a</code> and having value <code>expr</code>. Lambda is
|
||
spelt <code>\</code> because ASCII isn’t good enough. Lambda binds tightly, so
|
||
<code>\a\bcd</code> is equivalent to <code>((\a(\b(c))) d)</code>. Whitespace is ignored.</p>
|
||
<p>For example, the identity function, called <code>I</code>, is written <code>\x(x)</code>. A
|
||
simple expression is <code>(I a)</code> which is equivalent to <code>(\x(x) a)</code>, which
|
||
has the value <code>a</code>. Another function called <code>K</code> is defined as <code>\x\y(x)</code>
|
||
and it evaluates as follows:</p>
|
||
<pre><code> K p q
|
||
-> \x\y(x) p q
|
||
-> \y(p) q
|
||
-> p</code></pre>
|
||
<p>Another function of interest is <code>S</code>, defined as <code>\f\g\x((f x) (g x))</code>.
|
||
My program demonstrates the fact that any lambda expression can be
|
||
translated into an equivalent “combinator expression” which involves
|
||
only <code>S</code>, <code>K</code>, <code>I</code> (the combinators), and application, with no
|
||
variables or lambda abstractions. In fact, even <code>I</code> is unnecessary,
|
||
since it is equivalent to <code>S K K</code>:</p>
|
||
<pre><code> I z
|
||
-> \a(a) z
|
||
-> z
|
||
|
||
S K K z
|
||
-> \f\g\x((f x) (g x)) K K z
|
||
-> (K z) (K z)
|
||
-> \x\y(x) z (K z)
|
||
-> z</code></pre>
|
||
<p>The algorithm for translating lambda expressions into combinator
|
||
expressions works as follows. There are three forms of lambda expression
|
||
to consider: variables, applications, and abstractions.</p>
|
||
<pre><code> trans v -> v (variable)
|
||
trans a b -> (trans a) (trans b ) (application)
|
||
trans \ab -> abs a (trans b) (abstraction)</code></pre>
|
||
<p>There are a further three cases to consider for the body of lambda
|
||
expressions, where we need to do the magic that transforms away the
|
||
variables.</p>
|
||
<pre><code> abs a f x -> S (abs a f) (abs a x)
|
||
abs a b -> K b (b != a)
|
||
abs a a -> I</code></pre>
|
||
<p>E.g. suppose we had combinator expressions for <code>+</code> and <code>3</code> and we wanted
|
||
to see what the combinator expression for doubling 3 looked like:</p>
|
||
<pre><code> trans \x(+ x x) 3
|
||
-> (trans \x(+ x x)) (trans 3)
|
||
-> (abs x (trans + x x)) 3
|
||
-> (abs x + x x) 3
|
||
-> S (abs x + x) (abs x x) 3
|
||
-> S (S (abs x +) (abs x x)) I 3
|
||
-> S (S (K +) I) I 3
|
||
-> S (S (K +) I) I 3</code></pre>
|
||
<p>We can then check that this evaluates to the expected result:</p>
|
||
<pre><code> S (S (K +) I) I 3
|
||
-> S (K +) I 3 (I 3)
|
||
-> K + 3 (I 3) (I 3)
|
||
-> + (I 3) (I 3)
|
||
-> + 3 3</code></pre>
|
||
<p>It is possible to perform a slightly more compact translation with a
|
||
couple of simple optimisations. For example, note that <code>K (a b)</code> is the
|
||
same as <code>S (K a) (K b)</code>, because</p>
|
||
<pre><code> K (a b) x
|
||
-> a b</code></pre>
|
||
<p>and</p>
|
||
<pre><code> S (K a) (K b) x
|
||
-> K a x (K b x)
|
||
-> a b</code></pre>
|
||
<p>Also, <code>S (K a) I</code> is the same as just <code>a</code> because</p>
|
||
<pre><code> S (K a) I x
|
||
-> K a x (I x)
|
||
-> a x</code></pre>
|
||
<p>The program simply reads a lambda expression from the standard input,
|
||
translates it into a combinator expression using the transformation and
|
||
optimisations described above, and prints out the result.</p>
|
||
<h3 id="why-this-is-a-practical-application">Why this is a practical application</h3>
|
||
<p>Combinator expressions are easier to evaluate than lambda expressions
|
||
because there are no problems with variables. For example, if I naively
|
||
evaluated the expression <code>\x\y(x y) y</code> I might get <code>\y(y y)</code> which is
|
||
not the same as the correct result because the first <code>y</code> in the body
|
||
should refer to a global <code>y</code> rather than the local one. David Turner was
|
||
the first person to realise that because of this fact, SK combinators
|
||
provide a simple way to implement non-strict functional programming
|
||
languages, either in software or directly in hardware.</p>
|
||
<p>My program demonstrates this by being based on a combinator evaluation
|
||
engine which is used to implement a language called <code>OFL</code> (pronounced
|
||
like “offal” and short for “Obfuscated Functional Language”). I then
|
||
used <code>OFL</code> to implement all the high-level functionality described above.
|
||
This contributes a lot to the obfuscation because even small amounts of
|
||
<code>OFL</code> are quite unpalatable, and large expressions are completely
|
||
incomprehensible.</p>
|
||
<p>It is fairly well known that the lambda calculus (and hence SK
|
||
combinators) can compute anything, but mere computation is no use if you
|
||
cannot communicate with the world. This is why <code>OFL</code> includes a few
|
||
concessions to reality: a combinator <code>E</code> for representing characters and
|
||
testing them for equality, two I/O combinators, <code>G</code> and <code>P</code>, for reading
|
||
and writing characters respectively, and a combinator <code>J</code> for
|
||
representing <code>false</code>. I also implemented the <code>Y</code> combinator directly
|
||
rather than in terms of the primitive combinators, since it only
|
||
required five characters to do so (viz. <code>Y W q Q g</code>). However this code
|
||
is not enabled because the definition of <code>Y</code> in terms of other combinators
|
||
is more cute.</p>
|
||
<p>The <code>E</code> combinator comes in a large number of forms, one for each
|
||
character and one for end of file. It is written <code>E(c)</code> for the variant
|
||
of <code>E</code> corresponding to the character <code>c</code>. An expression of the form
|
||
<code>E(c) x</code> is evaluated by first evaluating <code>x</code>. If <code>x</code> doesn’t evaluate
|
||
to some form of <code>E</code>, then evaluation of the expression terminates. If
|
||
<code>x</code> evaluates to <code>E(c)</code>, then the expression evaluates to <code>K</code>. If <code>x</code>
|
||
evaluates to <code>E(d)</code> (where <code>d</code> is a different character to <code>c</code>), then
|
||
the expression evaluates to <code>J</code>.</p>
|
||
<p><code>K</code> and <code>J</code> are used to represent <code>true</code> and <code>false</code> respectively; they
|
||
correspond exactly to the standard lambda calculus representations of
|
||
<code>true</code> and <code>false</code>, viz. <code>\t\f(t)</code> and <code>\t\f(f)</code> respectively. In this way a
|
||
conditional expression can just be written <code>cond then else</code>, which is
|
||
even more terse than C <code>cond ? then : else</code>. An expression that
|
||
compares a character with <code>a</code>, say, can be written in the rather
|
||
obfuscated form <code>E('a') char then else</code>.</p>
|
||
<p>The <code>P</code> combinator, like the <code>E</code> combinator, starts off by evaluating
|
||
its first argument and checking that it is some form of <code>E</code>. It then
|
||
writes that character on <code>stdout</code>, and finally it calls its second
|
||
argument as a function with the argument <code>I</code>, i.e.</p>
|
||
<pre><code> P x f -> f I</code></pre>
|
||
<p>with a side-effect.</p>
|
||
<p>The <code>G</code> combinator just reads a character from <code>stdin</code> then calls its
|
||
argument as a function with the appropriate <code>E</code> combinator as an
|
||
argument, i.e.</p>
|
||
<pre><code> G f -> f E(c)</code></pre>
|
||
<p>with a side-effect.</p>
|
||
<p>One of the problems with non-strict languages is that it is hard to
|
||
predict in advance in which order side-effects will occur. In my program
|
||
I used a monadic I/O structure like that used by the programming language
|
||
Haskell; this allows one to write programs that manipulate external
|
||
state in a manner remarkably similar to imperative programming languages
|
||
like C. An examination of my program should provide an illustration of
|
||
how well this technique works in practice. (In particular, I used the
|
||
CPS form of the I/O monad from page 6 of “Imperative Functional
|
||
Programming”.)</p>
|
||
<p>The <code>Y</code> combinator is used for implementing recursive functions. It has
|
||
the evaluation rule</p>
|
||
<pre><code> Y f -> f (Y f)</code></pre>
|
||
<p>so that it can be used to call a function with itself as an argument.
|
||
For example, if I had the appropriate arithmetic operators defined, I
|
||
could write a factorial function in the lambda calculus like this:</p>
|
||
<pre><code> Y \f\n((= n 0) 1 (* n (f (- n 1))))</code></pre>
|
||
<p><code>OFL</code> provides a facility for naming expressions so that they can be used
|
||
more than once without writing them in full. A definition must be written
|
||
on one line in the form <code>l name b expression</code> where <code>l</code> is short for
|
||
“let” and <code>b</code> is short for “be”. Names must be more than one character
|
||
long. A complete <code>OFL</code> program starts off by defining the primitives it
|
||
will use with likes of the form <code>p (S)</code> etc., then goes on to define the
|
||
names it will use, and finishes off with the main expression followed by
|
||
a single <code>e</code> short for “end”. <code>OFL</code> expressions must use the minimum
|
||
number of brackets needed to be unambiguous, except that the whole
|
||
expression must be surrounded by brackets.</p>
|
||
<p><code>OFL</code> has a standard library which adds another five combinators to the
|
||
basic eight. These combinators provide greater scope for optimisation
|
||
when translating an expression from the lambda calculus to combinators,
|
||
and therefore more compact programs. Their evaluation rules are:</p>
|
||
<pre><code> B f g x -> f (g x)
|
||
C f g x -> (f x) g
|
||
BB c f g x -> c (f (g x))
|
||
CC c f g x -> c (f x) g
|
||
SS c f g x -> c (f x) (g x)</code></pre>
|
||
<p>I used them to help fit my program into the required space; unfortunately
|
||
I couldn’t fit the version that fully optimises the lambda expressions
|
||
it reads into the required space. The complete optimisation rules
|
||
including the ones it doesn’t use are:</p>
|
||
<pre><code> S (K p) I -> p
|
||
S (K p) (K r) -> K ( p r )
|
||
S (K p) (B r s) -> BB p r s
|
||
S (K p) r -> B p r
|
||
S (B p q) (K r) -> CC p q r
|
||
S p (K r) -> C p r
|
||
S (B p q) r -> SS p q r
|
||
S p r -> S p r</code></pre>
|
||
<h3 id="the-implementation-of-ofl">The implementation of <code>OFL</code></h3>
|
||
<p>Although <code>OFL</code> has completely different syntax and semantics to C, all you
|
||
need to compile <code>OFL</code> programs is a C compiler and a header file (which in
|
||
my entry to the competition has been included in-line). The header file
|
||
implements a two-pass optimising compiler which produces a representation
|
||
of the program that is then interpreted.</p>
|
||
<p>The first pass of the compiler is implemented via the C preprocessor. It
|
||
implements one optimisation, namely function in-lining. Unfortunately,
|
||
this optimisation always increases object code size and execution time.
|
||
The opposite optimisation, common sub-expression elimination (which
|
||
would offer improvements in code size and execution time), has not been
|
||
implemented. The output of this pass is a C program that may be compiled
|
||
by a normal C compiler.</p>
|
||
<p>The second pass is performed by the initialisation phase of the C
|
||
program. It builds a data structure representing the abstract syntax
|
||
tree of the program.</p>
|
||
<p>The program is then executed by an interpreter. This operates by
|
||
performing manipulations on the AST that correspond to the evaluation
|
||
rules of the combinators that I described above.</p>
|
||
<p>The first 54 lines of the program are mostly the interpreter; the next 8
|
||
lines are pass one of the compiler; the next nine declare the <code>OFL</code>
|
||
primitives; the next five define the <code>OFL</code> standard library; and the rest
|
||
implement the application described in the first part of this document.
|
||
This part of the program is transformed into the second pass of the
|
||
compiler by the first pass of the compiler.</p>
|
||
<p>The first pass of the compiler relies on some magic macros that expand
|
||
in a mutually-overlapping and almost recursive way in order to
|
||
perpetrate a complete change of syntax. Interestingly enough, if I
|
||
hadn’t used the same identifier for more than one thing in various
|
||
places in the program this transformation would work with old-style cpp
|
||
as well and ANSI cpp. It expands the program from about 2.2KB to about
|
||
740KB. The resulting code does some tricky stuff to build a data
|
||
structure of the same form as the code itself.</p>
|
||
<p>The interpreter is written in fairly straightforward C, although it is
|
||
highly compressed. The C itself is written in a fairly functional style,
|
||
in that every function consists of a single expression. In the tradition
|
||
of functional programming languages it assumes that memory is infinite
|
||
and so never frees anything. It also assumes that the C compiler
|
||
implements the tail recursion optimisation, which is probably not true.</p>
|
||
<h3 id="references">References</h3>
|
||
<p>I used these references in the course of writing this program and they
|
||
explain some of the ideas behind it in more detail. Arthur Norman (one
|
||
of the authors of the first paper) did a lot to enthuse me about this
|
||
topic.</p>
|
||
<p>Clarke, T. J. W., et al., 1980. SKIM - the S, K, I Reduction Machine.
|
||
Proceedings of the 1980 ACM LISP Conference, pp. 128-135.</p>
|
||
<p>Curry, H. B. and Feys, R., 1958. Combinatory Logic, Vol. 1.
|
||
North-Holland.</p>
|
||
<p>Gordon, M. J. C., 1988. Programming Language Theory and its
|
||
Implementation. Prentice-Hall.</p>
|
||
<p>Peterson, J, et al., 1997. Report on the Programming Language Haskell,
|
||
version 1.4.</p>
|
||
<p>Peyton Jones, S. L., 1987. The implementation of Functional
|
||
Programming Languages, Chapters 2, 11, 12, 16. Prentice-Hall.</p>
|
||
<p>Peyton Jones, S. L., and Wadler, P., 1992. Imperative Functional
|
||
Programming. Proceedings of the ACM Symposium on the Principles of
|
||
Programming Languages 1993, pp. 71-84.</p>
|
||
<p>Turner, D. A., 1979. A new implementation technique for applicative
|
||
languages. Software- Practice and Experience. Vol. 9, pp. 31-49.</p>
|
||
<p>Turner, D. A., 1979. Another algorithm for bracket abstraction. Journal
|
||
of Symbolic Logic. Vol. 44, no. 2, pp. 67-270.</p>
|
||
<p>Wadler, P., 1990. Comprehending Monads. Proceedings of the ACM
|
||
conference on Lisp and Functional Programming, 1990.</p>
|
||
<p>Wadler, P., 1995. How to Declare an Imperative. Proceedings of the ACM
|
||
International Logic Programming Symposium, 1995.</p>
|
||
<!--
|
||
|
||
Copyright © 1984-2024 by Landon Curt Noll. All Rights Reserved.
|
||
|
||
You are free to share and adapt this file under the terms of this license:
|
||
|
||
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
|
||
|
||
For more information, see:
|
||
|
||
https://creativecommons.org/licenses/by-sa/4.0/
|
||
|
||
-->
|
||
<!-- AFTER: last line of markdown file: 1998/fanf/README.md -->
|
||
|
||
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
|
||
<!-- START: this line starts content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
|
||
|
||
<!-- START: this line starts content generated by: bin/output-index-inventory.sh -->
|
||
|
||
<div id="inventory">
|
||
<h1 id="inventory-for-1998fanf">Inventory for 1998/fanf</h1>
|
||
</div>
|
||
<h2 id="primary-files">Primary files</h2>
|
||
<ul>
|
||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1998/fanf/fanf.c">fanf.c</a> - entry source code</li>
|
||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1998/fanf/Makefile">Makefile</a> - entry Makefile</li>
|
||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1998/fanf/fanf.orig.c">fanf.orig.c</a> - original source code</li>
|
||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1998/fanf/try.sh">try.sh</a> - script to try entry</li>
|
||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1998/fanf/fanf.lambda">fanf.lambda</a> - lambda expressions</li>
|
||
</ul>
|
||
<h2 id="secondary-files">Secondary files</h2>
|
||
<ul>
|
||
<li><a href="1998_fanf.tar.bz2">1998_fanf.tar.bz2</a> - download entry tarball</li>
|
||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1998/fanf/README.md">README.md</a> - markdown source for this web page</li>
|
||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1998/fanf/.entry.json">.entry.json</a> - entry summary and manifest in JSON</li>
|
||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1998/fanf/.gitignore">.gitignore</a> - list of files that should not be committed under git</li>
|
||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1998/fanf/.path">.path</a> - directory path from top level directory</li>
|
||
<li><a href="index.html">index.html</a> - this web page</li>
|
||
</ul>
|
||
<hr style="width:10%;text-align:left;margin-left:0">
|
||
<h4>
|
||
Jump to: <a href="#">top</a>
|
||
</h4>
|
||
|
||
<!-- END: next line ends content generated by: bin/output-index-inventory.sh -->
|
||
|
||
<!-- END: this line ends content for HTML phase 22 by: bin/output-index-inventory.sh via bin/md2html.sh -->
|
||
<!-- START: this line starts content from: inc/after-content.default.html -->
|
||
|
||
</div>
|
||
|
||
<!-- END: this line ends content from: inc/after-content.default.html -->
|
||
<!-- START: this line starts content from: inc/footer.inventory.html -->
|
||
|
||
<!--
|
||
|
||
Copyright © 1984-2024 by Landon Curt Noll. All Rights Reserved.
|
||
|
||
You are free to share and adapt this file under the terms of this license:
|
||
|
||
Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
|
||
|
||
For more information, see:
|
||
|
||
https://creativecommons.org/licenses/by-sa/4.0/
|
||
|
||
-->
|
||
|
||
<div class="footer">
|
||
|
||
<div id="copyright"><h3>Copyright © 1984-2024 by Landon Curt Noll:
|
||
<a href="https://creativecommons.org/faq/#what-does-some-rights-reserved-mean"
|
||
target="_blank"
|
||
rel="license noopener noreferrer">Some Rights Reserved</a></h3>
|
||
<p>
|
||
This work is <b>licensed by Landon Curt Noll</b> under
|
||
<b><a href="https://creativecommons.org/licenses/by-sa/4.0/?ref=chooser-v1"
|
||
target="_blank"
|
||
rel="license noopener noreferrer"
|
||
style="display:inline-block;">CC BY-SA 4.0</a></b>.
|
||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||
src="../../png/cc.png"
|
||
alt="cc inside circle symbol">
|
||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||
src="../../png/by.png"
|
||
alt="person inside circle symbol">
|
||
<img style="height:22px!important;margin-left:3px;vertical-align:text-bottom;"
|
||
src="../../png/sa.png"
|
||
alt="arrow looping back on itself inside circle symbol"><br>
|
||
You should <b>carefully review</b> the
|
||
<b><a href="https://creativecommons.org/licenses/by-sa/4.0/legalcode.en"
|
||
target="_blank"
|
||
rel="license noopener noreferrer">CC BY-SA 4.0 LEGAL CODE</a></b>
|
||
before using the licensed material.<br>
|
||
You may wish to review the
|
||
<b><a href="../../license.html"
|
||
target="_blank"
|
||
rel="license noopener noreferrer">highlights of some of the key features and terms</a></b>
|
||
of <b>CC BY-SA 4.0</b>.<br>
|
||
</p>
|
||
</div>
|
||
|
||
<div id="coda"><h3>Coda</h3>
|
||
<p>
|
||
<a href="https://validator.w3.org/nu/?doc=https%3A%2F%2Fioccc-src.github.io%2Ftemp-test-ioccc%2F1998%2Ffanf%2Findex.html" rel="nofollow">Nu HTML check this web page</a><br>
|
||
<a href="#top">Jump to top</a> <a href="#content">Jump to Content</a> <a href="#inventory">Jump to Inventory</a><br>
|
||
</p>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<!-- END: this line ends content from: inc/footer.inventory.html -->
|
||
<!-- START: this line starts content from: inc/bottom.default.html -->
|
||
|
||
</body>
|
||
</html>
|
||
|
||
<!-- END: this line ends content from: inc/bottom.default.html -->
|