Remove hint.html and index.html
As per discussions on GitHub the index.html and hint.html files should be deleted in favour of README.md files (from any .text/.txt/.markdown/.md files which will be turned into README.md in an upcoming commit).
This commit is contained in:
1 parent
ee8a36310f
commit
77fb0f11a2
143 files changed
-28606
No files matched your search
@@ -1,273 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta name="GENERATOR" content="mkd2html 2.2.0">
|
||||
<meta http-equiv="Content-Type"
|
||||
content="text/html; charset=utf-8"> <link rel="stylesheet"
|
||||
type="text/css"
|
||||
href="../hint.css">
|
||||
<title>Most functional interpreter</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Most functional interpreter</h1>
|
||||
|
||||
<p>Ondřej Adamovský <a href="mailto:oa@cmail.cz">oa@cmail.cz</a></p>
|
||||
|
||||
<h2>Judges' comments:</h2>
|
||||
|
||||
<h3>To use:</h3>
|
||||
|
||||
<pre><code>make prog
|
||||
./prog file.unl
|
||||
</code></pre>
|
||||
|
||||
<h3>Try:</h3>
|
||||
|
||||
<pre><code>./prog spam.unl
|
||||
|
||||
./prog sierpinski.unl | less
|
||||
|
||||
./prog advent.unl
|
||||
</code></pre>
|
||||
|
||||
<h3>Selected Judges Remarks:</h3>
|
||||
|
||||
<p>Even after pre-processing and indenting, the C code of this entry
|
||||
is about as understandable as the Unlambda code.</p>
|
||||
|
||||
<p>Pretending that we don’t know a bit of functional programming :) and lacking a better way
|
||||
to understand the entry but to fuzz it,
|
||||
we stumbled on a string of bytes which crashed it:</p>
|
||||
|
||||
<pre><code>````.0`.0`.0`c.0``sssss
|
||||
</code></pre>
|
||||
|
||||
<p>Functional programming is not a panacea against core dumps, after all.</p>
|
||||
|
||||
<h2>Author’s comments:</h2>
|
||||
|
||||
<p><strong>»A highly structured state state machine«</strong></p>
|
||||
|
||||
<h3>Purpose</h3>
|
||||
|
||||
<p>The purpose of this program is to allow you to play Colossal Cave Adventure as
|
||||
implemented by <a href="https://github.com/irori/advent-unlambda" title="Adventure">Kunihiko Sakamoto</a>. As that was written in <a href="http://www.madore.org/~david/programs/unlambda/" title="Unlambda programming language">Unlambda programming
|
||||
language</a> designed by David Alexander Madore it has to be an Unlambda interpreter.</p>
|
||||
|
||||
<h3>Aesthetics</h3>
|
||||
|
||||
<p>The program grew a bit too long so I had to use several macros to downsize it.
|
||||
That unfortunately reduced my options for program layout. I decided to separate
|
||||
it into two portions. The initial macro section where I had limited resources and
|
||||
you should disregard its shape, unless you like it, and the rest is a separator in the
|
||||
form of a single line followed by a section signifying the function of the program,
|
||||
a block with removed shape of lambda character. Even the official IOCCC size tool
|
||||
acknowledges this: When you call <code>./iocccsize -i <prog.c</code>, using the
|
||||
<a href="/2019/iocccsize.c">2019 version of iocccsize</a>,
|
||||
iocccsize returns <strong>955</strong>, which is the Unicode codepoint of the <strong>λ</strong> character.</p>
|
||||
|
||||
<p>It might be a surprise for you that according to the IOCCC size tool the program is
|
||||
actually a <em>oneliner</em>. It certainly was for me. I like to think the tool is overwhelmed
|
||||
by the sheer length of the dividing line and totally overlooks the rest of the program.</p>
|
||||
|
||||
<h3>Usage</h3>
|
||||
|
||||
<p>When built directly</p>
|
||||
|
||||
<pre><code>make
|
||||
</code></pre>
|
||||
|
||||
<p>the program (<em>prog</em>) accepts a single parameter with the name of an Unlambda program. You can
|
||||
download the <a href="https://github.com/irori/advent-unlambda" title="Adventure">Colossal Cave Adventure</a> (the <em>advent.unl</em> file) and run it like this</p>
|
||||
|
||||
<pre><code>./prog advent.unl
|
||||
</code></pre>
|
||||
|
||||
<p>You can also try other programs from the Web. Many example programs are in the official
|
||||
<a href="http://www.madore.org/~david/programs/unlambda/#distrib" title="Reference Unlambda distribution">Unlambda distribution</a> on the Unlambda homepage. The most complex programs there are
|
||||
entries from <a href="http://www.madore.org/~david/programs/unlambda/#quine" title="Unlambda quine contest">quine contest</a>.</p>
|
||||
|
||||
<p>There is an alternative build path that requires IOCCC size tool to complete. Put the tool
|
||||
source <em>iocccsize.c</em> in the project directory and call</p>
|
||||
|
||||
<pre><code>make identify
|
||||
</code></pre>
|
||||
|
||||
<p>It will build the tool and use it to build an alternative program <em>prog2</em>, which in turn will
|
||||
produce an Unlambda program <em>identify.unl</em>. <code>make identify</code> runs this program to identify
|
||||
itself.</p>
|
||||
|
||||
<p>The base program (<em>prog</em>) implements an interpreter of Unlambda 2.0. It recognises all its
|
||||
builtins (k, s, i, v, c, d, .<em>x</em>, e, @, ?<em>x</em> and |) including the syntactic sugar function
|
||||
(​r​) and formating properties in the form of ignoring whitespace and comments
|
||||
to the end of line introduced by the <em>#</em> character.</p>
|
||||
|
||||
<p>In case of wrong usage (missing Unlambda program file or missing parameter) or use of an unseekable
|
||||
Unlambda program source if it uses the <em>c</em> function, the program returns message <em>fail</em>. It
|
||||
also informs you about syntactic errors in the Unlambda program should there be any (but only
|
||||
when the execution reaches them).</p>
|
||||
|
||||
<p>The Unlambda source file may contain several Unlambda programs. The interpreter will run
|
||||
them all in sequence.</p>
|
||||
|
||||
<h3>Unlambda</h3>
|
||||
|
||||
<p>If you want to familiarise yourself with the language, visit its <a href="https://en.wikipedia.org/wiki/Unlambda" title="Unlambda on Wikipedia">Wikipedia page</a> for
|
||||
a brief introduction or its <a href="http://www.madore.org/~david/programs/unlambda/" title="Unlambda programming language">homepage</a> for an indepth discussion. For further reading you
|
||||
can visit Wikipedia pages on <a href="https://en.wikipedia.org/wiki/Lambda_calculus" title="Lambda Calculus on Wikipedia">Lambda Calculus</a> and <a href="https://en.wikipedia.org/wiki/Combinatory_logic" title="Combinatory Logic on Wikipedia">Combinatory Logic</a>.</p>
|
||||
|
||||
<p>You can also play with an <a href="https://inazz.jp/unlambda/" title="Online Unlambda interpreter">online interpreter</a> by Github user inazz. There you can
|
||||
debug one of example programs provided or try your wits in writing your own.</p>
|
||||
|
||||
<h3>Hints</h3>
|
||||
|
||||
<p>Here are some pointers where to start when trying to understand the interpreter:</p>
|
||||
|
||||
<ul>
|
||||
<li>Where is syntax error detected?</li>
|
||||
<li>How is the memory managed?</li>
|
||||
<li>How does a program character turn into a function?</li>
|
||||
<li>How does exit function <em>e</em> work?</li>
|
||||
<li>Can fD0 function be called?</li>
|
||||
<li>Are the function names familiar? (warning: some are misleading)</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h3>Obfuscation sources</h3>
|
||||
|
||||
<ul>
|
||||
<li>The elephant in the room is the Unlambda language. As we all know, functional
|
||||
programming defies sanity. Furthermore, Unlambda was specifically designed
|
||||
to be unintelligible and hard to code in. Most of its functions are quite
|
||||
simple and straightforward to implement, but two make it a mess: the promise
|
||||
operator <em>d</em> and the call with current continuation <em>c</em>.</li>
|
||||
<li>Most of the additional obfuscation is derived from basic design choices. That
|
||||
is, how the state of the program is stored and how are the Unlambda functions
|
||||
implemented.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p>More on this in the Spoilers section.</p>
|
||||
|
||||
<h3>Build notes</h3>
|
||||
|
||||
<p>The program does not require any special treatment by compilers. Some warnings
|
||||
had to be suppressed when compiling with <code>-Wall -Wextra -pedantic</code>. Those were
|
||||
produced because of the formatting of the source code, not any programming
|
||||
technique. Compilation with <code>-Weverything</code> produced many more warnings, but those
|
||||
are only relevant for multi-source-file projects and some are really questionable
|
||||
(e.g. <code>-Wdisabled-macro-expansion</code>).</p>
|
||||
|
||||
<h3>Portability</h3>
|
||||
|
||||
<p>Development was done on Debian 9 on x86-64 architecture using mainly Clang 3.8.1-24
|
||||
and GCC 6.3.0. The source is C11 compliant and does not use any special properties
|
||||
except the following:</p>
|
||||
|
||||
<ul>
|
||||
<li>The interpreter sort of relies on tail call optimization. It works well even
|
||||
without it, but the stack runs out quickly with some Unlambda programs (e.g. <em>trivial.unl</em>
|
||||
example from the <a href="http://www.madore.org/~david/programs/unlambda/#distrib" title="Reference Unlambda distribution">reference Unlambda distribution</a> produces segfault).
|
||||
Clang with <code>-O3</code> option does this optimization well and said example does
|
||||
not segfault with it. I was not able to force GCC to optimize it out (probably
|
||||
an operator fault).</li>
|
||||
<li>The only data structure of the program (the union structure) had much more
|
||||
members originally. I joined all integers to a single long long member in the name
|
||||
of obfuscation. It is used for reference counting (only 1 for every reference) among
|
||||
other uses. size_t should be used for that, but practically, I think the memory
|
||||
would run out sooner than the reference counter in any real world situation
|
||||
even when size_t is bigger than long long. It is also used for storing chars
|
||||
for later printing. This might produce some warnings, but since it was developed
|
||||
using chars it should be always used safely.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h3>Spoilers</h3>
|
||||
|
||||
<ul>
|
||||
<li><p>You can examine the <em>progSpoiler.c</em> file. It is the original final version of
|
||||
the interpreter, before I started the downsizing. It accepts one more optional
|
||||
parameter that specifies filename for the output Unlambda function (it’s the
|
||||
Unlambda function, that remains after all function applications are done).
|
||||
When no filename is provided, <em>stderr</em> is used.</p>
|
||||
|
||||
<p>The function <em>output</em> is used for this additional functionality. You can use
|
||||
it while debugging to visualise current variables.</p></li>
|
||||
<li><p>The Unlambda functions are represented by a record consisting of an array of five
|
||||
multipurpose arguments. The first one refers to the function implementing its
|
||||
application, the second and the third ones are for arguments of the function,
|
||||
the fourth one is for stack building, and the fifth one is the reference counter.</p>
|
||||
|
||||
<p>The function argument is used not only for evaluation of the functions, but also
|
||||
as a state variable to decide whether we want to call it, or do something else.</p></li>
|
||||
<li><p>The interpreter reads the Unlambda source as it interprets it, translating
|
||||
the incoming character to a function using a constructor stored in translation array <em>T</em>.</p>
|
||||
|
||||
<p>This means the interpreter must reposition in the source file whenever current
|
||||
continuation is called.</p></li>
|
||||
<li><p>The state of the interpreter is represented by trees representing evaluated
|
||||
Unlambda functions stored on the C stack as local variables, plus the source file
|
||||
position. When a current continuation is created, the stack is unwound using the
|
||||
fourth argument of the nodes, stored in the continuation, and rebuilt back resuming
|
||||
the evaluation. When its called, the stack is unwound and thrown away, and the
|
||||
stack stored in the continuation is restored.</p>
|
||||
|
||||
<p>This makes implementation of a complete debugger a bit more challenging.</p>
|
||||
|
||||
<p>For this to work, the functions that do the work (i.e. make series of applications
|
||||
and/or evaluations each of which may be a call to current continuation), the <em>s</em>
|
||||
combinator and the <em>`</em> application operation had to be broken down to pieces, one
|
||||
for each application/evaluation and corresponding helper functions for stack
|
||||
rebuilding. (the helper functions are named beginning with <em>r</em> instead of <em>f</em>)</p></li>
|
||||
<li><p>The <em>`</em> application operation does the reading of the Unlambda source when needed. It
|
||||
also implements the promise function. Whenever it would apply it, it overwrites
|
||||
the Apply constructor in translation array <em>T</em>, changing its function to build
|
||||
unevaluated subtree that is later evaluated whenever the promise is applied.</p></li>
|
||||
<li><p>To further the obfuscation, I shortened the function names while downsizing,
|
||||
but preserved their meaning (with the exception of Apply functions, which I
|
||||
renamed to Y to possibly confuse with Y combinator). Simple functions retained
|
||||
their names to misguide the reader to believe to know what is what. The names
|
||||
of continuation and exit functions were swapped. The names of S and Apply
|
||||
functions were shuffled both for S functions and Apply functions in the same way
|
||||
to hide the meaning of <em>f</em> and <em>r</em> prefixes.</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h3>Identification spoiler</h3>
|
||||
|
||||
<p>The alternative build path <code>make identify</code> output commemorates a <a href="http://ioccc.org/2014/birken/hint.html" title="Best use of port 1701">previous IOCCC winner</a> which uses
|
||||
similar methods to mess with the size tool.</p>
|
||||
|
||||
<h3>Judges remarks spoilers</h3>
|
||||
|
||||
<p>It is not a bug, it is a feature. :)</p>
|
||||
|
||||
<p>The crash is caused by a stack overflow. Conventional Unlabmda interpreters implement
|
||||
the Unlambda execution stack using data structures on the heap. This interpreter uses
|
||||
the C call stack for this purpose. In a conventional interpreter, the judges program would
|
||||
consume memory until the user (or the operating system) would lose patience. The C call stack
|
||||
is usually of a limited size and protected, so this interpreter crashes, when the judges
|
||||
program depletes the stack. You can always increase the maximal stack size through
|
||||
the system settings (on Linux) or compiler options (on Windows) if your Unlambda program
|
||||
needs it. Nevertheless, it will not help the judges program which quickly depletes any limit
|
||||
you define.</p>
|
||||
|
||||
<p>The judges, pretending not to know what they are doing, created a program that grows
|
||||
Unlambda execution stack indefinitely. You may consider it an Unlambda antipattern.
|
||||
Normally, infinite cycles in Unlambda work by creating two functions and applying one
|
||||
to the other which creates further functions to apply. The application of the function
|
||||
frees its position on the stack. This program builds one ever growing function that will
|
||||
never be complete and able to be applied.</p>
|
||||
|
||||
<hr />
|
||||
|
||||
<TABLE><TR>
|
||||
<TD><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="/png/by-sa-3.0-88x31.png" /></a></TD>
|
||||
<TD><P>© Copyright 1984-2019,
|
||||
<A HREF="/judges.html">Leo Broukhis, Simon Cooper, Landon Curt Noll</A>
|
||||
- All rights reserved<BR>
|
||||
This work is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</P></TD>
|
||||
<TD> <!--<a href="https://validator.w3.org/check?uri=referer"><img src="https://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional" height="31" width="88"></a>--></TD>
|
||||
</TR></TABLE>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user