OSDN Git Service

Type inference of Joy expressions.
authorSimon Forman <sforman@hushmail.com>
Fri, 29 Jun 2018 20:19:12 +0000 (13:19 -0700)
committerSimon Forman <sforman@hushmail.com>
Fri, 29 Jun 2018 20:19:12 +0000 (13:19 -0700)
More remains to be done but it seems to work.

25 files changed:
docs/Types.html
docs/Types.ipynb
docs/Types.md
docs/Types.rst
docs/sphinx_docs/_build/html/_modules/index.html
docs/sphinx_docs/_build/html/_modules/joy/library.html
docs/sphinx_docs/_build/html/_modules/joy/utils/stack.html
docs/sphinx_docs/_build/html/_sources/index.rst.txt
docs/sphinx_docs/_build/html/genindex.html
docs/sphinx_docs/_build/html/index.html
docs/sphinx_docs/_build/html/library.html
docs/sphinx_docs/_build/html/notebooks/Types.html
docs/sphinx_docs/_build/html/notebooks/Zipper.html
docs/sphinx_docs/_build/html/notebooks/index.html
docs/sphinx_docs/_build/html/objects.inv
docs/sphinx_docs/_build/html/py-modindex.html
docs/sphinx_docs/_build/html/searchindex.js
docs/sphinx_docs/index.rst
docs/sphinx_docs/notebooks/Types.rst
docs/sphinx_docs/types.rst [new file with mode: 0644]
joy/library.py
joy/utils/polytypes.py
joy/utils/stack.py
joy/utils/types.py
test/test_type_inference.py

index 6486b06..f4e4f6f 100644 (file)
@@ -11775,7 +11775,7 @@ div#notebook {
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h1 id="Type-Inference">Type Inference<a class="anchor-link" href="#Type-Inference">&#182;</a></h1><p>This notebook presents a simple type inferencer for Joy code.  It can infer the stack effect of most Joy expressions.  It's built largely by means of existing ideas and research.  (A great overview of the existing knowledge is a talk <a href="http://prl.ccs.neu.edu/blog/2017/03/10/type-inference-in-stack-based-programming-languages/">"Type Inference in Stack-Based Programming Languages"</a> given by Rob Kleffner on or about 2017-03-10 as part of a course on the history of programming languages.)</p>
+<h1 id="The-Blissful-Elegance-of-Typing-Joy">The Blissful Elegance of Typing Joy<a class="anchor-link" href="#The-Blissful-Elegance-of-Typing-Joy">&#182;</a></h1><p>This notebook presents a simple type inferencer for Joy code.  It can infer the stack effect of most Joy expressions.  It's built largely by means of existing ideas and research.  (A great overview of the existing knowledge is a talk <a href="http://prl.ccs.neu.edu/blog/2017/03/10/type-inference-in-stack-based-programming-languages/">"Type Inference in Stack-Based Programming Languages"</a> given by Rob Kleffner on or about 2017-03-10 as part of a course on the history of programming languages.)</p>
 <p>The notebook starts with a simple inferencer based on the work of Jaanus Pöial which we then progressively elaborate to cover more Joy semantics.  Along the way we write a simple "compiler" that emits Python code for what I like to call Yin functions.  (Yin functions are those that only rearrange values in stacks, as opposed to Yang functions that actually work on the values themselves.)</p>
 
 </div>
@@ -12342,6 +12342,8 @@ cons ( 1 [...] -- [1 ...] )</code></pre>
         <span class="n">s</span><span class="p">[</span><span class="n">u</span><span class="p">]</span> <span class="o">=</span> <span class="n">v</span>
     <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
         <span class="n">s</span><span class="p">[</span><span class="n">v</span><span class="p">]</span> <span class="o">=</span> <span class="n">u</span>
+    <span class="k">else</span><span class="p">:</span>
+        <span class="n">s</span> <span class="o">=</span> <span class="bp">False</span>
 
     <span class="k">return</span> <span class="n">s</span>
 </pre></div>
@@ -12843,6 +12845,24 @@ cons ( 1 [...] -- [1 ...] )</code></pre>
 </div>
 </div>
 
+<div class="output_wrapper">
+<div class="output">
+
+
+<div class="output_area">
+
+<div class="prompt"></div>
+
+
+<div class="output_subarea output_stream output_stdout output_text">
+<pre>Cannot unify (1, 2) and (1001, 1002).
+</pre>
+</div>
+</div>
+
+</div>
+</div>
+
 </div>
 <div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
 </div>
@@ -12881,6 +12901,8 @@ cons ( 1 [...] -- [1 ...] )</code></pre>
         <span class="n">s</span> <span class="o">=</span> <span class="n">unify</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">s</span><span class="p">)</span>
         <span class="k">if</span> <span class="n">s</span> <span class="o">!=</span> <span class="bp">False</span><span class="p">:</span>
             <span class="n">s</span> <span class="o">=</span> <span class="n">unify</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">s</span><span class="p">)</span>
+    <span class="k">else</span><span class="p">:</span>
+        <span class="n">s</span> <span class="o">=</span> <span class="bp">False</span>
 
     <span class="k">return</span> <span class="n">s</span>
 </pre></div>
@@ -14557,7 +14579,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<p>(Eventually I should come back around to this becuase it's not tooo difficult to exend this code to be able to compile e.g. <code>n3 = mul(n1, n2)</code> for <code>mul</code> and insert it in the right place with the right variable names.  It requires a little more support from the library functions, in that we need to know to call <code>mul()</code> the Python function for <code>mul</code> the Joy function, but since <em>most</em> of the math functions (at least) are already wrappers it should be straightforward.)</p>
+<p>(Eventually I should come back around to this becuase it's not tooo difficult to exend this code to be able to compile e.g. <code>n2 = mul(n1, n1)</code> for <code>mul</code> with the right variable names and insert it in the right place.  It requires a little more support from the library functions, in that we need to know to call <code>mul()</code> the Python function for <code>mul</code> the Joy function, but since <em>most</em> of the math functions (at least) are already wrappers it should be straightforward.)</p>
 
 </div>
 </div>
@@ -16335,7 +16357,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="Part-VII:-Typing-Combinators">Part VII: Typing Combinators<a class="anchor-link" href="#Part-VII:-Typing-Combinators">&#182;</a></h2><p>In order to compute the stack effect of combinators you kinda have to have the quoted programs they expect available.  In the most general case, the <code>i</code> combinator, you can't say anything about it's stack effect other than it expects one quote:</p>
+<h2 id="Part-VII:-Typing-Combinators">Part VII: Typing Combinators<a class="anchor-link" href="#Part-VII:-Typing-Combinators">&#182;</a></h2><p>In order to compute the stack effect of combinators you kinda have to have the quoted programs they expect available.  In the most general case, the <code>i</code> combinator, you can't say anything about its stack effect other than it expects one quote:</p>
 
 <pre><code>i (... [.1.] -- ... .1.)
 
@@ -16370,7 +16392,16 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<p>I think there's a way forward.  If we convert our list of terms we are composing into a stack structure we can use it as a <em>Joy expression</em>, then we can treat the <em>output half</em> of a function's stack effect comment as a Joy interpreter stack, and just execute combinators directly.  We can hybridize the compostition function with an interpreter to evaluate combinators, compose non-combinator functions, and put type variables on the stack.  For combinators like <code>branch</code> that can have more than one stack effect we have to "split universes" again and return both.</p>
+<h3 id="Hybrid-Inferencer/Interpreter">Hybrid Inferencer/Interpreter<a class="anchor-link" href="#Hybrid-Inferencer/Interpreter">&#182;</a></h3><p>I think there's a way forward.  If we convert our list (of terms we are composing) into a stack structure we can use it as a <em>Joy expression</em>, then we can treat the <em>output half</em> of a function's stack effect comment as a Joy interpreter stack, and just execute combinators directly.  We can hybridize the compostition function with an interpreter to evaluate combinators, compose non-combinator functions, and put type variables on the stack.  For combinators like <code>branch</code> that can have more than one stack effect we have to "split universes" again and return both.</p>
+
+</div>
+</div>
+</div>
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
+</div>
+<div class="inner_cell">
+<div class="text_cell_render border-box-sizing rendered_html">
+<h4 id="Joy-Types-for-Functions">Joy Types for Functions<a class="anchor-link" href="#Joy-Types-for-Functions">&#182;</a></h4><p>We need a type variable for Joy functions that can go in our expressions and be used by the hybrid inferencer/interpreter.  They have to store a name and a list of stack effects.</p>
 
 </div>
 </div>
@@ -16393,10 +16424,6 @@ uncons = ([a1 .1.] -- a1 [.1.])
 
     <span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
         <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>
-
-
-<span class="k">class</span> <span class="nc">SymbolJoyType</span><span class="p">(</span><span class="n">FunctionJoyType</span><span class="p">):</span> <span class="n">prefix</span> <span class="o">=</span> <span class="s1">&#39;F&#39;</span>
-<span class="k">class</span> <span class="nc">CombinatorJoyType</span><span class="p">(</span><span class="n">FunctionJoyType</span><span class="p">):</span> <span class="n">prefix</span> <span class="o">=</span> <span class="s1">&#39;C&#39;</span>
 </pre></div>
 
 </div>
@@ -16404,56 +16431,22 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 
 </div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[108]:</div>
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
+</div>
 <div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="k">def</span> <span class="nf">flatten</span><span class="p">(</span><span class="n">g</span><span class="p">):</span>
-    <span class="k">return</span> <span class="nb">list</span><span class="p">(</span><span class="n">chain</span><span class="o">.</span><span class="n">from_iterable</span><span class="p">(</span><span class="n">g</span><span class="p">))</span>
-
-
-<span class="n">ID</span> <span class="o">=</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>  <span class="c1"># Identity function.</span>
-
-
-<span class="k">def</span> <span class="nf">infer</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">F</span><span class="o">=</span><span class="n">ID</span><span class="p">):</span>
-    <span class="k">if</span> <span class="ow">not</span> <span class="n">e</span><span class="p">:</span>
-        <span class="k">return</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span>
-
-    <span class="n">n</span><span class="p">,</span> <span class="n">e</span> <span class="o">=</span> <span class="n">e</span>
-
-    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">SymbolJoyType</span><span class="p">):</span>
-        <span class="n">res</span> <span class="o">=</span> <span class="n">flatten</span><span class="p">(</span><span class="n">infer</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">Fn</span><span class="p">)</span> <span class="k">for</span> <span class="n">Fn</span> <span class="ow">in</span> <span class="n">MC</span><span class="p">([</span><span class="n">F</span><span class="p">],</span> <span class="n">n</span><span class="o">.</span><span class="n">stack_effects</span><span class="p">))</span>
-
-    <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">CombinatorJoyType</span><span class="p">):</span>
-        <span class="n">res</span> <span class="o">=</span> <span class="p">[]</span>
-        <span class="k">for</span> <span class="n">combinator</span> <span class="ow">in</span> <span class="n">n</span><span class="o">.</span><span class="n">stack_effects</span><span class="p">:</span>
-            <span class="n">fi</span><span class="p">,</span> <span class="n">fo</span> <span class="o">=</span> <span class="n">F</span>
-            <span class="n">new_fo</span><span class="p">,</span> <span class="n">ee</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">combinator</span><span class="p">(</span><span class="n">fo</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="p">{})</span>
-            <span class="n">ee</span> <span class="o">=</span> <span class="n">update</span><span class="p">(</span><span class="n">FUNCTIONS</span><span class="p">,</span> <span class="n">ee</span><span class="p">)</span>  <span class="c1"># Fix Symbols.</span>
-            <span class="n">new_F</span> <span class="o">=</span> <span class="n">fi</span><span class="p">,</span> <span class="n">new_fo</span>
-            <span class="n">res</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">infer</span><span class="p">(</span><span class="n">ee</span><span class="p">,</span> <span class="n">new_F</span><span class="p">))</span>
-    <span class="k">else</span><span class="p">:</span>
-        <span class="n">lit</span> <span class="o">=</span> <span class="n">s9</span><span class="p">,</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">s9</span><span class="p">)</span>
-        <span class="n">res</span> <span class="o">=</span> <span class="n">flatten</span><span class="p">(</span><span class="n">infer</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">Fn</span><span class="p">)</span> <span class="k">for</span> <span class="n">Fn</span> <span class="ow">in</span> <span class="n">MC</span><span class="p">([</span><span class="n">F</span><span class="p">],</span> <span class="p">[</span><span class="n">lit</span><span class="p">]))</span>
-
-    <span class="k">return</span> <span class="n">res</span>
-</pre></div>
+<div class="text_cell_render border-box-sizing rendered_html">
+<h4 id="Specialized-for-Simple-Functions-and-Combinators">Specialized for Simple Functions and Combinators<a class="anchor-link" href="#Specialized-for-Simple-Functions-and-Combinators">&#182;</a></h4><p>For non-combinator functions the stack effects list contains stack effect comments (represented by pairs of cons-lists as described above.)</p>
 
 </div>
 </div>
 </div>
-
-</div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[109]:</div>
+<div class="prompt input_prompt">In&nbsp;[108]:</div>
 <div class="inner_cell">
     <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">f0</span><span class="p">,</span> <span class="n">f1</span><span class="p">,</span> <span class="n">f2</span><span class="p">,</span> <span class="n">f3</span><span class="p">,</span> <span class="n">f4</span><span class="p">,</span> <span class="n">f5</span><span class="p">,</span> <span class="n">f6</span><span class="p">,</span> <span class="n">f7</span><span class="p">,</span> <span class="n">f8</span><span class="p">,</span> <span class="n">f9</span> <span class="o">=</span> <span class="n">F</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="n">FloatJoyType</span><span class="p">,</span> <span class="n">_R</span><span class="p">)</span>
-<span class="n">i0</span><span class="p">,</span> <span class="n">i1</span><span class="p">,</span> <span class="n">i2</span><span class="p">,</span> <span class="n">i3</span><span class="p">,</span> <span class="n">i4</span><span class="p">,</span> <span class="n">i5</span><span class="p">,</span> <span class="n">i6</span><span class="p">,</span> <span class="n">i7</span><span class="p">,</span> <span class="n">i8</span><span class="p">,</span> <span class="n">i9</span> <span class="o">=</span> <span class="n">I</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="n">IntJoyType</span><span class="p">,</span> <span class="n">_R</span><span class="p">)</span>
-<span class="n">n0</span><span class="p">,</span> <span class="n">n1</span><span class="p">,</span> <span class="n">n2</span><span class="p">,</span> <span class="n">n3</span><span class="p">,</span> <span class="n">n4</span><span class="p">,</span> <span class="n">n5</span><span class="p">,</span> <span class="n">n6</span><span class="p">,</span> <span class="n">n7</span><span class="p">,</span> <span class="n">n8</span><span class="p">,</span> <span class="n">n9</span> <span class="o">=</span> <span class="n">N</span>
-<span class="n">s0</span><span class="p">,</span> <span class="n">s1</span><span class="p">,</span> <span class="n">s2</span><span class="p">,</span> <span class="n">s3</span><span class="p">,</span> <span class="n">s4</span><span class="p">,</span> <span class="n">s5</span><span class="p">,</span> <span class="n">s6</span><span class="p">,</span> <span class="n">s7</span><span class="p">,</span> <span class="n">s8</span><span class="p">,</span> <span class="n">s9</span> <span class="o">=</span> <span class="n">S</span>
+<div class=" highlight hl-ipython2"><pre><span></span><span class="k">class</span> <span class="nc">SymbolJoyType</span><span class="p">(</span><span class="n">FunctionJoyType</span><span class="p">):</span>
+    <span class="n">prefix</span> <span class="o">=</span> <span class="s1">&#39;F&#39;</span>
 </pre></div>
 
 </div>
@@ -16461,80 +16454,35 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 
 </div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[110]:</div>
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
+</div>
 <div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="kn">import</span> <span class="nn">joy.library</span>
-
-<span class="n">FNs</span> <span class="o">=</span> <span class="s1">&#39;&#39;&#39;ccons cons divmod_ dup dupd first</span>
-<span class="s1">         over pm pop popd popdd popop pred</span>
-<span class="s1">         rest rolldown rollup rrest second</span>
-<span class="s1">         sqrt stack succ swaack swap swons</span>
-<span class="s1">         third tuck uncons&#39;&#39;&#39;</span>
-
-<span class="n">FUNCTIONS</span> <span class="o">=</span> <span class="p">{</span>
-    <span class="n">name</span><span class="p">:</span> <span class="n">SymbolJoyType</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="p">[</span><span class="n">NEW_DEFS</span><span class="p">[</span><span class="n">name</span><span class="p">]],</span> <span class="n">i</span><span class="p">)</span>
-    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">name</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">FNs</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">())</span>
-    <span class="p">}</span>
-<span class="n">FUNCTIONS</span><span class="p">[</span><span class="s1">&#39;sum&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">SymbolJoyType</span><span class="p">(</span><span class="s1">&#39;sum&#39;</span><span class="p">,</span> <span class="p">[(((</span><span class="n">Ns</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">s1</span><span class="p">),</span> <span class="n">s0</span><span class="p">),</span> <span class="p">(</span><span class="n">n0</span><span class="p">,</span> <span class="n">s0</span><span class="p">))],</span> <span class="mi">100</span><span class="p">)</span>
-<span class="n">FUNCTIONS</span><span class="p">[</span><span class="s1">&#39;mul&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">SymbolJoyType</span><span class="p">(</span><span class="s1">&#39;mul&#39;</span><span class="p">,</span> <span class="p">[</span>
-     <span class="p">((</span><span class="n">i2</span><span class="p">,</span> <span class="p">(</span><span class="n">i1</span><span class="p">,</span> <span class="n">s0</span><span class="p">)),</span> <span class="p">(</span><span class="n">i3</span><span class="p">,</span> <span class="n">s0</span><span class="p">)),</span>
-     <span class="p">((</span><span class="n">f2</span><span class="p">,</span> <span class="p">(</span><span class="n">i1</span><span class="p">,</span> <span class="n">s0</span><span class="p">)),</span> <span class="p">(</span><span class="n">f3</span><span class="p">,</span> <span class="n">s0</span><span class="p">)),</span>
-     <span class="p">((</span><span class="n">i2</span><span class="p">,</span> <span class="p">(</span><span class="n">f1</span><span class="p">,</span> <span class="n">s0</span><span class="p">)),</span> <span class="p">(</span><span class="n">f3</span><span class="p">,</span> <span class="n">s0</span><span class="p">)),</span>
-     <span class="p">((</span><span class="n">f2</span><span class="p">,</span> <span class="p">(</span><span class="n">f1</span><span class="p">,</span> <span class="n">s0</span><span class="p">)),</span> <span class="p">(</span><span class="n">f3</span><span class="p">,</span> <span class="n">s0</span><span class="p">)),</span>
-<span class="p">],</span> <span class="mi">101</span><span class="p">)</span>
-<span class="n">FUNCTIONS</span><span class="o">.</span><span class="n">update</span><span class="p">({</span>
-    <span class="n">combo</span><span class="o">.</span><span class="vm">__name__</span><span class="p">:</span> <span class="n">CombinatorJoyType</span><span class="p">(</span><span class="n">combo</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="p">[</span><span class="n">combo</span><span class="p">],</span> <span class="n">i</span><span class="p">)</span>
-    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">combo</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">((</span>
-        <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">i</span><span class="p">,</span>
-        <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">dip</span><span class="p">,</span>
-        <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">dipd</span><span class="p">,</span>
-        <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">dipdd</span><span class="p">,</span>
-        <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">dupdip</span><span class="p">,</span>
-        <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">b</span><span class="p">,</span>
-        <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">x</span><span class="p">,</span>
-        <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">infra</span><span class="p">,</span>
-        <span class="p">))</span>
-    <span class="p">})</span>
-
-<span class="k">def</span> <span class="nf">branch_true</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">):</span>
-    <span class="p">(</span><span class="n">then</span><span class="p">,</span> <span class="p">(</span><span class="n">else_</span><span class="p">,</span> <span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="n">stack</span><span class="p">)))</span> <span class="o">=</span> <span class="n">stack</span>
-    <span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">CONCAT</span><span class="p">(</span><span class="n">then</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span>
-
-<span class="k">def</span> <span class="nf">branch_false</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">):</span>
-    <span class="p">(</span><span class="n">then</span><span class="p">,</span> <span class="p">(</span><span class="n">else_</span><span class="p">,</span> <span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="n">stack</span><span class="p">)))</span> <span class="o">=</span> <span class="n">stack</span>
-    <span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">CONCAT</span><span class="p">(</span><span class="n">else_</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span>
-
-<span class="n">FUNCTIONS</span><span class="p">[</span><span class="s1">&#39;branch&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">CombinatorJoyType</span><span class="p">(</span><span class="s1">&#39;branch&#39;</span><span class="p">,</span> <span class="p">[</span><span class="n">branch_true</span><span class="p">,</span> <span class="n">branch_false</span><span class="p">],</span> <span class="mi">100</span><span class="p">)</span>
-</pre></div>
+<div class="text_cell_render border-box-sizing rendered_html">
+<p>For combinators the list contains Python functions.</p>
 
 </div>
 </div>
 </div>
-
-</div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[111]:</div>
+<div class="prompt input_prompt">In&nbsp;[109]:</div>
 <div class="inner_cell">
     <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="nb">globals</span><span class="p">()</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">FUNCTIONS</span><span class="p">)</span>
-</pre></div>
+<div class=" highlight hl-ipython2"><pre><span></span><span class="k">class</span> <span class="nc">CombinatorJoyType</span><span class="p">(</span><span class="n">FunctionJoyType</span><span class="p">):</span>
 
-</div>
-</div>
-</div>
+    <span class="n">prefix</span> <span class="o">=</span> <span class="s1">&#39;C&#39;</span>
 
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[112]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">chain</span>
-<span class="kn">from</span> <span class="nn">joy.utils.stack</span> <span class="kn">import</span> <span class="n">list_to_stack</span> <span class="k">as</span> <span class="n">l2s</span>
+    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">sec</span><span class="p">,</span> <span class="n">number</span><span class="p">,</span> <span class="n">expect</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+        <span class="nb">super</span><span class="p">(</span><span class="n">CombinatorJoyType</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">sec</span><span class="p">,</span> <span class="n">number</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">expect</span> <span class="o">=</span> <span class="n">expect</span>
+
+    <span class="k">def</span> <span class="nf">enter_guard</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">f</span><span class="p">):</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">expect</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
+            <span class="k">return</span> <span class="n">f</span>
+        <span class="n">g</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">expect</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">expect</span>
+        <span class="n">new_f</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">compose</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="p">()))</span>
+        <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">new_f</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">new_f</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">new_f</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span>
 </pre></div>
 
 </div>
@@ -16542,259 +16490,168 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 
 </div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[113]:</div>
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
+</div>
 <div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">expression</span> <span class="o">=</span> <span class="n">l2s</span><span class="p">([</span><span class="n">n1</span><span class="p">,</span> <span class="n">n2</span><span class="p">,</span> <span class="p">(</span><span class="n">mul</span><span class="p">,</span> <span class="n">s2</span><span class="p">),</span> <span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">s3</span><span class="p">),</span> <span class="n">dip</span><span class="p">,</span> <span class="n">infra</span><span class="p">,</span> <span class="n">first</span><span class="p">])</span>
-</pre></div>
+<div class="text_cell_render border-box-sizing rendered_html">
+<p>For simple combinators that have only one effect (like <code>dip</code>) you only need one function and it can be the combinator itself.</p>
 
 </div>
 </div>
 </div>
-
-</div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[114]:</div>
+<div class="prompt input_prompt">In&nbsp;[110]:</div>
 <div class="inner_cell">
     <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">expression</span>
+<div class=" highlight hl-ipython2"><pre><span></span><span class="kn">import</span> <span class="nn">joy.library</span>
+
+<span class="n">dip</span> <span class="o">=</span> <span class="n">CombinatorJoyType</span><span class="p">(</span><span class="s1">&#39;dip&#39;</span><span class="p">,</span> <span class="p">[</span><span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">dip</span><span class="p">],</span> <span class="mi">23</span><span class="p">)</span>
 </pre></div>
 
 </div>
 </div>
 </div>
 
-<div class="output_wrapper">
-<div class="output">
-
-
-<div class="output_area">
-
-<div class="prompt output_prompt">Out[114]:</div>
-
-
-
-
-<div class="output_text output_subarea output_execute_result">
-<pre>(n1, (n2, ((mul, s2), ((stack, s3), (dip, (infra, (first, ())))))))</pre>
 </div>
-
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
 </div>
+<div class="inner_cell">
+<div class="text_cell_render border-box-sizing rendered_html">
+<p>For combinators that can have more than one effect (like <code>branch</code>) you have to write functions that each implement the action of one of the effects.</p>
 
 </div>
 </div>
-
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[115]:</div>
+<div class="prompt input_prompt">In&nbsp;[111]:</div>
 <div class="inner_cell">
     <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">expression</span> <span class="o">=</span> <span class="n">l2s</span><span class="p">([</span><span class="n">n1</span><span class="p">,</span> <span class="n">n2</span><span class="p">,</span> <span class="n">mul</span><span class="p">])</span>
-</pre></div>
+<div class=" highlight hl-ipython2"><pre><span></span><span class="k">def</span> <span class="nf">branch_true</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">):</span>
+    <span class="p">(</span><span class="n">then</span><span class="p">,</span> <span class="p">(</span><span class="n">else_</span><span class="p">,</span> <span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="n">stack</span><span class="p">)))</span> <span class="o">=</span> <span class="n">stack</span>
+    <span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">concat</span><span class="p">(</span><span class="n">then</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span>
 
-</div>
-</div>
-</div>
+<span class="k">def</span> <span class="nf">branch_false</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">):</span>
+    <span class="p">(</span><span class="n">then</span><span class="p">,</span> <span class="p">(</span><span class="n">else_</span><span class="p">,</span> <span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="n">stack</span><span class="p">)))</span> <span class="o">=</span> <span class="n">stack</span>
+    <span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">concat</span><span class="p">(</span><span class="n">else_</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span>
 
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[116]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">expression</span>
+<span class="n">branch</span> <span class="o">=</span> <span class="n">CombinatorJoyType</span><span class="p">(</span><span class="s1">&#39;branch&#39;</span><span class="p">,</span> <span class="p">[</span><span class="n">branch_true</span><span class="p">,</span> <span class="n">branch_false</span><span class="p">],</span> <span class="mi">100</span><span class="p">)</span>
 </pre></div>
 
 </div>
 </div>
 </div>
 
-<div class="output_wrapper">
-<div class="output">
-
-
-<div class="output_area">
-
-<div class="prompt output_prompt">Out[116]:</div>
-
-
-
-
-<div class="output_text output_subarea output_execute_result">
-<pre>(n1, (n2, (mul, ())))</pre>
-</div>
-
 </div>
-
-</div>
-</div>
-
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
 </div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[117]:</div>
 <div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">infer</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
-</pre></div>
+<div class="text_cell_render border-box-sizing rendered_html">
+<p>You can also provide an optional stack effect, input-side only, that will then be used as an identity function (that accepts and returns stacks that match the "guard" stack effect) which will be used to guard against type mismatches going into the evaluation of the combinator.</p>
 
 </div>
 </div>
 </div>
-
-<div class="output_wrapper">
-<div class="output">
-
-
-<div class="output_area">
-
-<div class="prompt output_prompt">Out[117]:</div>
-
-
-
-
-<div class="output_text output_subarea output_execute_result">
-<pre>[(s1, (f1, s1)), (s1, (i1, s1))]</pre>
-</div>
-
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
 </div>
+<div class="inner_cell">
+<div class="text_cell_render border-box-sizing rendered_html">
+<h4 id="infer()"><code>infer()</code><a class="anchor-link" href="#infer()">&#182;</a></h4><p>With those in place, we can define a function that accepts a sequence of Joy type variables, including ones representing functions (not just values), and attempts to grind out all the possible stack effects of that expression.</p>
+<p>One tricky thing is that type variables <em>in the expression</em> have to be updated along with the stack effects after doing unification or we risk losing useful information.  This was a straightforward, if awkward, modification to the call structure of <code>meta_compose()</code> et. al.</p>
 
 </div>
 </div>
-
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[118]:</div>
+<div class="prompt input_prompt">In&nbsp;[112]:</div>
 <div class="inner_cell">
     <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">infer</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-<div class="output_wrapper">
-<div class="output">
-
-
-<div class="output_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="n">ID</span> <span class="o">=</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>  <span class="c1"># Identity function.</span>
 
-<div class="prompt output_prompt">Out[118]:</div>
 
+<span class="k">def</span> <span class="nf">infer</span><span class="p">(</span><span class="o">*</span><span class="n">expression</span><span class="p">):</span>
+    <span class="k">return</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">_infer</span><span class="p">(</span><span class="n">list_to_stack</span><span class="p">(</span><span class="n">expression</span><span class="p">))))</span>
 
 
+<span class="k">def</span> <span class="nf">_infer</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">F</span><span class="o">=</span><span class="n">ID</span><span class="p">):</span>
+    <span class="n">_log_it</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">F</span><span class="p">)</span>
+    <span class="k">if</span> <span class="ow">not</span> <span class="n">e</span><span class="p">:</span>
+        <span class="k">return</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span>
 
-<div class="output_text output_subarea output_execute_result">
-<pre>[(s1, (f1, s1)), (s1, (i1, s1))]</pre>
-</div>
-
-</div>
-
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[119]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="k">for</span> <span class="n">stack_effect_comment</span> <span class="ow">in</span> <span class="n">infer</span><span class="p">(</span><span class="n">expression</span><span class="p">):</span>
-    <span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">stack_effect_comment</span><span class="p">)</span>
-</pre></div>
+    <span class="n">n</span><span class="p">,</span> <span class="n">e</span> <span class="o">=</span> <span class="n">e</span>
 
-</div>
-</div>
-</div>
+    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">SymbolJoyType</span><span class="p">):</span>
+        <span class="n">eFG</span> <span class="o">=</span> <span class="n">meta_compose</span><span class="p">([</span><span class="n">F</span><span class="p">],</span> <span class="n">n</span><span class="o">.</span><span class="n">stack_effects</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span>
+        <span class="n">res</span> <span class="o">=</span> <span class="n">flatten</span><span class="p">(</span><span class="n">_infer</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">Fn</span><span class="p">)</span> <span class="k">for</span> <span class="n">e</span><span class="p">,</span> <span class="n">Fn</span> <span class="ow">in</span> <span class="n">eFG</span><span class="p">)</span>
 
-<div class="output_wrapper">
-<div class="output">
+    <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">CombinatorJoyType</span><span class="p">):</span>
+        <span class="n">fi</span><span class="p">,</span> <span class="n">fo</span> <span class="o">=</span> <span class="n">n</span><span class="o">.</span><span class="n">enter_guard</span><span class="p">(</span><span class="n">F</span><span class="p">)</span>
+        <span class="n">res</span> <span class="o">=</span> <span class="n">flatten</span><span class="p">(</span><span class="n">_interpret</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">fi</span><span class="p">,</span> <span class="n">fo</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">n</span><span class="o">.</span><span class="n">stack_effects</span><span class="p">)</span>
 
+    <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">Symbol</span><span class="p">):</span>
+        <span class="k">assert</span> <span class="n">n</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">FUNCTIONS</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
+        <span class="n">func</span> <span class="o">=</span> <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">_dictionary</span><span class="p">[</span><span class="n">n</span><span class="p">]</span>
+        <span class="n">res</span> <span class="o">=</span> <span class="n">_interpret</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">F</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">F</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">e</span><span class="p">)</span>
 
-<div class="output_area">
+    <span class="k">else</span><span class="p">:</span>
+        <span class="n">fi</span><span class="p">,</span> <span class="n">fo</span> <span class="o">=</span> <span class="n">F</span>
+        <span class="n">res</span> <span class="o">=</span> <span class="n">_infer</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="p">(</span><span class="n">fi</span><span class="p">,</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">fo</span><span class="p">)))</span>
 
-<div class="prompt"></div>
+    <span class="k">return</span> <span class="n">res</span>
 
 
-<div class="output_subarea output_stream output_stdout output_text">
-<pre>(-- f1)
-(-- i1)
-</pre>
-</div>
-</div>
+<span class="k">def</span> <span class="nf">_interpret</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">fi</span><span class="p">,</span> <span class="n">fo</span><span class="p">,</span> <span class="n">e</span><span class="p">):</span>
+    <span class="n">new_fo</span><span class="p">,</span> <span class="n">ee</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">fo</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="p">{})</span>
+    <span class="n">ee</span> <span class="o">=</span> <span class="n">update</span><span class="p">(</span><span class="n">FUNCTIONS</span><span class="p">,</span> <span class="n">ee</span><span class="p">)</span>  <span class="c1"># Fix Symbols.</span>
+    <span class="n">new_F</span> <span class="o">=</span> <span class="n">fi</span><span class="p">,</span> <span class="n">new_fo</span>
+    <span class="k">return</span> <span class="n">_infer</span><span class="p">(</span><span class="n">ee</span><span class="p">,</span> <span class="n">new_F</span><span class="p">)</span>
 
-</div>
-</div>
 
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[120]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">expression</span>
+<span class="k">def</span> <span class="nf">_log_it</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">F</span><span class="p">):</span>
+    <span class="n">_log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
+        <span class="sa">u</span><span class="s1">&#39;</span><span class="si">%3i</span><span class="s1"> </span><span class="si">%s</span><span class="s1"> ∘ </span><span class="si">%s</span><span class="s1">&#39;</span><span class="p">,</span>
+        <span class="nb">len</span><span class="p">(</span><span class="n">inspect_stack</span><span class="p">()),</span>
+        <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">F</span><span class="p">),</span>
+        <span class="n">expression_to_string</span><span class="p">(</span><span class="n">e</span><span class="p">),</span>
+        <span class="p">)</span>
 </pre></div>
 
 </div>
 </div>
 </div>
 
-<div class="output_wrapper">
-<div class="output">
-
-
-<div class="output_area">
-
-<div class="prompt output_prompt">Out[120]:</div>
-
-
-
-
-<div class="output_text output_subarea output_execute_result">
-<pre>(n1, (n2, (mul, ())))</pre>
 </div>
-
+<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
 </div>
+<div class="inner_cell">
+<div class="text_cell_render border-box-sizing rendered_html">
+<h4 id="Work-in-Progress">Work in Progress<a class="anchor-link" href="#Work-in-Progress">&#182;</a></h4><p>And that brings us to current Work-In-Progress.  The mixed-mode inferencer/interpreter <code>infer()</code> function seems to work well.  There are details I should document, and the rest of the code in the "polytypes" module (FIXME link to its docs here!) should be explained...  There is cruft to convert the definitions in <code>DEFS</code> to the new <code>SymbolJoyType</code> objects, and some combinators.  Here is an example of output from the current code :</p>
 
 </div>
 </div>
-
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[121]:</div>
+<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
 <div class="inner_cell">
     <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">infer</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-<div class="output_wrapper">
-<div class="output">
-
-
-<div class="output_area">
+<div class=" highlight hl-ipython2"><pre><span></span><span class="mi">1</span><span class="o">/</span><span class="mi">0</span>  <span class="c1"># (Don&#39;t try to run this cell!  It&#39;s not going to work.  This is &quot;read only&quot; code heh..)</span>
 
-<div class="prompt output_prompt">Out[121]:</div>
+<span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="n">format</span><span class="o">=</span><span class="s1">&#39;</span><span class="si">%(message)s</span><span class="s1">&#39;</span><span class="p">,</span> <span class="n">stream</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="p">,</span> <span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">INFO</span><span class="p">)</span>
 
+<span class="nb">globals</span><span class="p">()</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">FUNCTIONS</span><span class="p">)</span>
 
+<span class="n">h</span> <span class="o">=</span> <span class="n">infer</span><span class="p">((</span><span class="n">pred</span><span class="p">,</span> <span class="n">s2</span><span class="p">),</span> <span class="p">(</span><span class="n">mul</span><span class="p">,</span> <span class="n">s3</span><span class="p">),</span> <span class="p">(</span><span class="n">div</span><span class="p">,</span> <span class="n">s4</span><span class="p">),</span> <span class="p">(</span><span class="n">nullary</span><span class="p">,</span> <span class="p">(</span><span class="nb">bool</span><span class="p">,</span> <span class="n">s5</span><span class="p">)),</span> <span class="n">dipd</span><span class="p">,</span> <span class="n">branch</span><span class="p">)</span>
 
+<span class="k">print</span> <span class="s1">&#39;-&#39;</span> <span class="o">*</span> <span class="mi">40</span>
 
-<div class="output_text output_subarea output_execute_result">
-<pre>[(s1, (f1, s1)), (s1, (i1, s1))]</pre>
-</div>
+<span class="k">for</span> <span class="n">fi</span><span class="p">,</span> <span class="n">fo</span> <span class="ow">in</span> <span class="n">h</span><span class="p">:</span>
+    <span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="n">fi</span><span class="p">,</span> <span class="n">fo</span><span class="p">)</span>
+</pre></div>
 
 </div>
-
 </div>
 </div>
 
@@ -16803,7 +16660,45 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<p>And that brings us to current Work-In-Progress.  I'm pretty hopeful that the mixed-mode inferencer/interpreter <code>infer()</code> function along with the ability to specify multiple implementations for the combinators will permit modelling of the stack effects of e.g. <code>ifte</code>.  If I can keep up the pace I should be able to verify that conjecture by the end of June.</p>
+<p>The numbers at the start of the lines are the current depth of the Python call stack.  They're followed by the current computed stack effect (initialized to <code>ID</code>) then the pending expression (the inference of the stack effect of which is the whole object of the current example.)</p>
+<p>In this example we are implementing (and inferring) <code>ifte</code> as <code>[nullary bool] dipd branch</code> which shows off a lot of the current implementation in action.</p>
+
+<pre><code>  7 (--) ∘ [pred] [mul] [div] [nullary bool] dipd branch
+  8 (-- [pred ...2]) ∘ [mul] [div] [nullary bool] dipd branch
+  9 (-- [pred ...2] [mul ...3]) ∘ [div] [nullary bool] dipd branch
+ 10 (-- [pred ...2] [mul ...3] [div ...4]) ∘ [nullary bool] dipd branch
+ 11 (-- [pred ...2] [mul ...3] [div ...4] [nullary bool ...5]) ∘ dipd branch
+ 15 (-- [pred ...5]) ∘ nullary bool [mul] [div] branch
+ 19 (-- [pred ...2]) ∘ [stack] dinfrirst bool [mul] [div] branch
+ 20 (-- [pred ...2] [stack ]) ∘ dinfrirst bool [mul] [div] branch
+ 22 (-- [pred ...2] [stack ]) ∘ dip infra first bool [mul] [div] branch
+ 26 (--) ∘ stack [pred] infra first bool [mul] [div] branch
+ 29 (... -- ... [...]) ∘ [pred] infra first bool [mul] [div] branch
+ 30 (... -- ... [...] [pred ...1]) ∘ infra first bool [mul] [div] branch
+ 34 (--) ∘ pred s1 swaack first bool [mul] [div] branch
+ 37 (n1 -- n2) ∘ [n1] swaack first bool [mul] [div] branch
+ 38 (... n1 -- ... n2 [n1 ...]) ∘ swaack first bool [mul] [div] branch
+ 41 (... n1 -- ... n1 [n2 ...]) ∘ first bool [mul] [div] branch
+ 44 (n1 -- n1 n2) ∘ bool [mul] [div] branch
+ 47 (n1 -- n1 b1) ∘ [mul] [div] branch
+ 48 (n1 -- n1 b1 [mul ...1]) ∘ [div] branch
+ 49 (n1 -- n1 b1 [mul ...1] [div ...2]) ∘ branch
+ 53 (n1 -- n1) ∘ div
+ 56 (f2 f1 -- f3) ∘ 
+ 56 (i1 f1 -- f2) ∘ 
+ 56 (f1 i1 -- f2) ∘ 
+ 56 (i2 i1 -- f1) ∘ 
+ 53 (n1 -- n1) ∘ mul
+ 56 (f2 f1 -- f3) ∘ 
+ 56 (i1 f1 -- f2) ∘ 
+ 56 (f1 i1 -- f2) ∘ 
+ 56 (i2 i1 -- i3) ∘ 
+----------------------------------------
+(f2 f1 -- f3)
+(i1 f1 -- f2)
+(f1 i1 -- f2)
+(i2 i1 -- f1)
+(i2 i1 -- i3)</code></pre>
 
 </div>
 </div>
@@ -16812,7 +16707,7 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="Conclusion">Conclusion<a class="anchor-link" href="#Conclusion">&#182;</a></h2><p>(for now...)</p>
+<h2 id="Conclusion">Conclusion<a class="anchor-link" href="#Conclusion">&#182;</a></h2><p>We built a simple type inferencer, and a kind of crude "compiler" for a subset of Joy functions.  Then we built a more powerful inferencer that actually does some evaluation and explores branching code paths</p>
 
 </div>
 </div>
@@ -16849,32 +16744,15 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 <div class="inner_cell">
 <div class="text_cell_render border-box-sizing rendered_html">
-<p>I'm starting to realize that, with the inferencer/checker/compiler coming along, and with the UI ready to be rewritten in Joy, I'm close to a time when my ephasis is going to have to shift from crunchy code stuff to squishy human stuff.  I'm going to have to put normal people in front of this and see if, in fact, they <em>can</em> learn the basics of programming with it.</p>
-
-</div>
-</div>
-</div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
-<div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-<p>The rest of this stuff is junk and/or unfinished material.</p>
-
-</div>
-</div>
-</div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
-<div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="Appendix:-Joy-in-the-Logical-Paradigm">Appendix: Joy in the Logical Paradigm<a class="anchor-link" href="#Appendix:-Joy-in-the-Logical-Paradigm">&#182;</a></h2><p>For this to work the type label classes have to be modified to let <code>T &gt;= t</code> succeed, where e.g. <code>T</code> is <code>IntJoyType</code> and <code>t</code> is <code>int</code></p>
+<h2 id="Appendix:-Joy-in-the-Logical-Paradigm">Appendix: Joy in the Logical Paradigm<a class="anchor-link" href="#Appendix:-Joy-in-the-Logical-Paradigm">&#182;</a></h2><p>For <em>type checking</em> to work the type label classes have to be modified to let <code>T &gt;= t</code> succeed, where e.g. <code>T</code> is <code>IntJoyType</code> and <code>t</code> is <code>int</code>.  If you do that you can take advantage of the <em>logical relational</em> nature of the stack effect comments to "compute in reverse" as it were.  There's a working demo of this at the end of the <code>polytypes</code> module.  But if you're interested in all that you should just use Prolog!</p>
+<p>Anyhow, type <em>checking</em> is a few easy steps away.</p>
 
 </div>
 </div>
 </div>
 <div class="cell border-box-sizing code_cell rendered">
 <div class="input">
-<div class="prompt input_prompt">In&nbsp;[122]:</div>
+<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
 <div class="inner_cell">
     <div class="input_area">
 <div class=" highlight hl-ipython2"><pre><span></span><span class="k">def</span> <span class="nf">_ge</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
@@ -16892,864 +16770,6 @@ uncons = ([a1 .1.] -- a1 [.1.])
 </div>
 
 </div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[123]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">F</span> <span class="o">=</span> <span class="n">infer</span><span class="p">(</span><span class="n">l2s</span><span class="p">((</span><span class="n">pop</span><span class="p">,</span> <span class="n">swap</span><span class="p">,</span> <span class="n">rolldown</span><span class="p">,</span> <span class="n">rest</span><span class="p">,</span> <span class="n">rest</span><span class="p">,</span> <span class="n">cons</span><span class="p">,</span> <span class="n">cons</span><span class="p">)))</span>
-
-<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">F</span><span class="p">:</span>
-    <span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">f</span><span class="p">)</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-<div class="output_wrapper">
-<div class="output">
-
-
-<div class="output_area">
-
-<div class="prompt"></div>
-
-
-<div class="output_subarea output_stream output_stdout output_text">
-<pre>([a4 a5 .1.] a3 a2 a1 -- [a2 a3 .1.])
-</pre>
-</div>
-</div>
-
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[124]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="kn">from</span> <span class="nn">joy.parser</span> <span class="kn">import</span> <span class="n">text_to_expression</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[125]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">F</span> <span class="o">=</span> <span class="n">infer</span><span class="p">(</span><span class="n">l2s</span><span class="p">((</span><span class="n">pop</span><span class="p">,</span> <span class="n">pop</span><span class="p">,</span> <span class="n">pop</span><span class="p">)))</span>
-
-<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">F</span><span class="p">:</span>
-    <span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">f</span><span class="p">)</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-<div class="output_wrapper">
-<div class="output">
-
-
-<div class="output_area">
-
-<div class="prompt"></div>
-
-
-<div class="output_subarea output_stream output_stdout output_text">
-<pre>(a3 a2 a1 --)
-</pre>
-</div>
-</div>
-
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[126]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">s</span> <span class="o">=</span> <span class="n">text_to_expression</span><span class="p">(</span><span class="s1">&#39;0 1 2&#39;</span><span class="p">)</span>
-<span class="n">s</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-<div class="output_wrapper">
-<div class="output">
-
-
-<div class="output_area">
-
-<div class="prompt output_prompt">Out[126]:</div>
-
-
-
-
-<div class="output_text output_subarea output_execute_result">
-<pre>(0, (1, (2, ())))</pre>
-</div>
-
-</div>
-
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[127]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">F</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-<div class="output_wrapper">
-<div class="output">
-
-
-<div class="output_area">
-
-<div class="prompt output_prompt">Out[127]:</div>
-
-
-
-
-<div class="output_text output_subarea output_execute_result">
-<pre>(a1, (a2, (a3, s1)))</pre>
-</div>
-
-</div>
-
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[128]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">L</span> <span class="o">=</span> <span class="n">unify</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">F</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span>
-<span class="n">L</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-<div class="output_wrapper">
-<div class="output">
-
-
-<div class="output_area">
-
-<div class="prompt output_prompt">Out[128]:</div>
-
-
-
-
-<div class="output_text output_subarea output_execute_result">
-<pre>()</pre>
-</div>
-
-</div>
-
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[129]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">s</span> <span class="o">=</span> <span class="n">text_to_expression</span><span class="p">(</span><span class="s1">&#39;0 1 2 [3 4]&#39;</span><span class="p">)</span>
-<span class="n">s</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-<div class="output_wrapper">
-<div class="output">
-
-
-<div class="output_area">
-
-<div class="prompt output_prompt">Out[129]:</div>
-
-
-
-
-<div class="output_text output_subarea output_execute_result">
-<pre>(0, (1, (2, ((3, (4, ())), ()))))</pre>
-</div>
-
-</div>
-
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[130]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">F</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-<div class="output_wrapper">
-<div class="output">
-
-
-<div class="output_area">
-
-<div class="prompt output_prompt">Out[130]:</div>
-
-
-
-
-<div class="output_text output_subarea output_execute_result">
-<pre>(a1, (a2, (a3, s1)))</pre>
-</div>
-
-</div>
-
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[131]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">L</span> <span class="o">=</span> <span class="n">unify</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">F</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span>
-<span class="n">L</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-<div class="output_wrapper">
-<div class="output">
-
-
-<div class="output_area">
-
-<div class="prompt output_prompt">Out[131]:</div>
-
-
-
-
-<div class="output_text output_subarea output_execute_result">
-<pre>()</pre>
-</div>
-
-</div>
-
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[132]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">L</span> <span class="o">=</span> <span class="n">unify</span><span class="p">(</span><span class="n">F</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span> <span class="n">s</span><span class="p">)</span>
-<span class="n">L</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-<div class="output_wrapper">
-<div class="output">
-
-
-<div class="output_area">
-
-<div class="prompt output_prompt">Out[132]:</div>
-
-
-
-
-<div class="output_text output_subarea output_execute_result">
-<pre>()</pre>
-</div>
-
-</div>
-
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[133]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">F</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-<div class="output_wrapper">
-<div class="output">
-
-
-<div class="output_area">
-
-<div class="prompt"></div>
-
-
-<div class="output_subarea output_text output_error">
-<pre>
-<span class="ansi-red-fg">---------------------------------------------------------------------------</span>
-<span class="ansi-red-fg">IndexError</span>                                Traceback (most recent call last)
-<span class="ansi-green-fg">&lt;ipython-input-133-58a8e44e9cba&gt;</span> in <span class="ansi-cyan-fg">&lt;module&gt;</span><span class="ansi-blue-fg">()</span>
-<span class="ansi-green-fg">----&gt; 1</span><span class="ansi-red-fg"> </span>F<span class="ansi-blue-fg">[</span><span class="ansi-cyan-fg">1</span><span class="ansi-blue-fg">]</span><span class="ansi-blue-fg">[</span><span class="ansi-cyan-fg">0</span><span class="ansi-blue-fg">]</span>
-
-<span class="ansi-red-fg">IndexError</span>: list index out of range</pre>
-</div>
-</div>
-
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">s</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">A</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">23</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
-<div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="Abstract-Interpretation"><a href="https://en.wikipedia.org/wiki/Abstract_interpretation">Abstract Interpretation</a><a class="anchor-link" href="#Abstract-Interpretation">&#182;</a></h2><p>I <em>think</em> this might be sorta what I'm doing above with the <code>kav()</code> function...
-  In any event "mixed-mode" interpreters that include values and type variables and can track constraints, etc. will be, uh, super-useful.  And Abstract Interpretation should be a rich source of ideas.</p>
-
-</div>
-</div>
-</div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
-<div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-<h2 id="Junk">Junk<a class="anchor-link" href="#Junk">&#182;</a></h2>
-</div>
-</div>
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="k">class</span> <span class="nc">SymbolJoyType</span><span class="p">(</span><span class="n">AnyJoyType</span><span class="p">):</span> <span class="n">prefix</span> <span class="o">=</span> <span class="s1">&#39;F&#39;</span>
-
-<span class="n">W</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="n">SymbolJoyType</span><span class="p">,</span> <span class="n">_R</span><span class="p">)</span>
-
-<span class="n">k</span> <span class="o">=</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="p">((</span><span class="n">W</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">2</span><span class="p">]),</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
-<span class="n">Symbol</span><span class="p">(</span><span class="s1">&#39;cons&#39;</span><span class="p">)</span>
-<span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">k</span><span class="p">)</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">dip_a</span> <span class="o">=</span> <span class="p">((</span><span class="n">W</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">2</span><span class="p">]),</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">d</span> <span class="o">=</span> <span class="n">relabel</span><span class="p">(</span><span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">dip_a</span><span class="p">)</span>
-<span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">d</span><span class="p">)</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">s</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">unify</span><span class="p">(</span><span class="n">d</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">k</span><span class="p">[</span><span class="mi">1</span><span class="p">]))[</span><span class="mi">0</span><span class="p">]</span>
-<span class="n">s</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">j</span> <span class="o">=</span> <span class="n">update</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">k</span><span class="p">)</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">j</span><span class="p">)</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">j</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">cons</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">MC</span><span class="p">([</span><span class="n">k</span><span class="p">],</span> <span class="p">[</span><span class="n">dup</span><span class="p">]):</span>
-    <span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">f</span><span class="p">)</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">l</span> <span class="o">=</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="p">((</span><span class="n">cons</span><span class="p">,</span> <span class="n">S</span><span class="p">[</span><span class="mi">2</span><span class="p">]),</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">l</span><span class="p">)</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="k">def</span> <span class="nf">dip_t</span><span class="p">(</span><span class="n">F</span><span class="p">):</span>
-    <span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">sec</span><span class="p">))</span> <span class="o">=</span> <span class="n">F</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
-    <span class="n">G</span> <span class="o">=</span> <span class="n">F</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">sec</span>
-    <span class="n">P</span> <span class="o">=</span> <span class="n">S</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">S</span><span class="p">[</span><span class="mi">3</span><span class="p">])</span>
-    <span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span>
-    <span class="k">while</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
-        <span class="n">term</span><span class="p">,</span> <span class="n">quote</span> <span class="o">=</span> <span class="n">quote</span>
-        <span class="n">a</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">term</span><span class="p">)</span>
-    <span class="n">a</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">G</span><span class="p">)</span>
-    <span class="k">return</span> <span class="n">a</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="kn">from</span> <span class="nn">joy.utils.stack</span> <span class="kn">import</span> <span class="n">iter_stack</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span> <span class="o">=</span> <span class="n">dip_t</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">a</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">b</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">c</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">MC</span><span class="p">([</span><span class="n">a</span><span class="p">],</span> <span class="p">[</span><span class="n">b</span><span class="p">])</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">kjs</span> <span class="o">=</span> <span class="n">MC</span><span class="p">(</span><span class="n">MC</span><span class="p">([</span><span class="n">a</span><span class="p">],</span> <span class="p">[</span><span class="n">b</span><span class="p">]),</span> <span class="p">[</span><span class="n">c</span><span class="p">])</span>
-<span class="n">kjs</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="k">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">kjs</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
-<div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-
-<pre><code>(a0 [.0.] -- [a0 .0.] a1)
-
-   a0 [.0.] a1 [cons] dip
-----------------------------
-   [a0 .0.] a1</code></pre>
-
-</div>
-</div>
-</div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
-<div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-<h3 id="concat"><code>concat</code><a class="anchor-link" href="#concat">&#182;</a></h3><p>How to deal with <code>concat</code>?</p>
-
-<pre><code>concat ([.0.] [.1.] -- [.0. .1.])
-
-</code></pre>
-<p>We would like to represent this in Python somehow...</p>
-
-</div>
-</div>
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">concat</span> <span class="o">=</span> <span class="p">(</span><span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span> <span class="p">((</span><span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">]),)</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
-<div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-<p>But this is actually <code>cons</code> with the first argument restricted to be a stack:</p>
-
-<pre><code>([.0.] [.1.] -- [[.0.] .1.])
-
-</code></pre>
-<p>What we have implemented so far would actually only permit:</p>
-
-<pre><code>([.0.] [.1.] -- [.2.])</code></pre>
-
-</div>
-</div>
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">concat</span> <span class="o">=</span> <span class="p">(</span><span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span> <span class="p">(</span><span class="n">S</span><span class="p">[</span><span class="mi">2</span><span class="p">],)</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
-<div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-<p>Which works but can lose information.  Consider <code>cons concat</code>, this is how much information we <em>could</em> retain:</p>
-
-<pre><code>(1 [.0.] [.1.] -- [1 .0. .1.])
-
-</code></pre>
-<p>As opposed to just:</p>
-
-<pre><code>(1 [.0.] [.1.] -- [.2.])</code></pre>
-
-</div>
-</div>
-</div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
-<div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-<h3 id="represent-concat">represent <code>concat</code><a class="anchor-link" href="#represent-concat">&#182;</a></h3>
-<pre><code>([.0.] [.1.] -- [A*(.0.) .1.])
-
-</code></pre>
-<p>Meaning that <code>A*</code> on the right-hand side should all the crap from <code>.0.</code>.</p>
-
-<pre><code>([      .0.] [.1.] -- [      A* .1.])
-([a     .0.] [.1.] -- [a     A* .1.])
-([a b   .0.] [.1.] -- [a b   A* .1.])
-([a b c .0.] [.1.] -- [a b c A* .1.])</code></pre>
-
-</div>
-</div>
-</div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
-<div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-<p>or...</p>
-
-<pre><code>([       .0.] [.1.] -- [       .1.])
-([a      .0.] [.1.] -- [a      .1.])
-([a b    .0.] [.1.] -- [a b    .1.])
-([a b  c .0.] [.1.] -- [a b  c .1.])
-([a A* c .0.] [.1.] -- [a A* c .1.])</code></pre>
-
-</div>
-</div>
-</div>
-<div class="cell border-box-sizing text_cell rendered"><div class="prompt input_prompt">
-</div>
-<div class="inner_cell">
-<div class="text_cell_render border-box-sizing rendered_html">
-
-<pre><code>(a, (b, S0)) . S1 = (a, (b, (A*, S1)))</code></pre>
-
-</div>
-</div>
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="k">class</span> <span class="nc">Astar</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
-    <span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
-        <span class="k">return</span> <span class="s1">&#39;A*&#39;</span>
-
-
-<span class="k">def</span> <span class="nf">concat</span><span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="n">s1</span><span class="p">):</span>
-    <span class="n">a</span> <span class="o">=</span> <span class="p">[]</span>
-    <span class="k">while</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
-        <span class="n">term</span><span class="p">,</span> <span class="n">s0</span> <span class="o">=</span> <span class="n">s0</span>
-        <span class="n">a</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">term</span><span class="p">)</span>
-    <span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="n">StackJoyType</span><span class="p">),</span> <span class="nb">repr</span><span class="p">(</span><span class="n">s0</span><span class="p">)</span>
-    <span class="n">s1</span> <span class="o">=</span> <span class="n">Astar</span><span class="p">(),</span> <span class="n">s1</span>
-    <span class="k">for</span> <span class="n">term</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">a</span><span class="p">):</span>
-        <span class="n">s1</span> <span class="o">=</span> <span class="n">term</span><span class="p">,</span> <span class="n">s1</span>
-    <span class="k">return</span> <span class="n">s1</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
-<div class="cell border-box-sizing code_cell rendered">
-<div class="input">
-<div class="prompt input_prompt">In&nbsp;[&nbsp;]:</div>
-<div class="inner_cell">
-    <div class="input_area">
-<div class=" highlight hl-ipython2"><pre><span></span><span class="n">concat</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
-</pre></div>
-
-</div>
-</div>
-</div>
-
-</div>
     </div>
   </div>
 </body>
index a220b3f..25d7a5f 100644 (file)
@@ -4,7 +4,7 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "# Type Inference\n",
+    "# The Blissful Elegance of Typing Joy\n",
     "\n",
     "This notebook presents a simple type inferencer for Joy code.  It can infer the stack effect of most Joy expressions.  It's built largely by means of existing ideas and research.  (A great overview of the existing knowledge is a talk [\"Type Inference in Stack-Based Programming Languages\"](http://prl.ccs.neu.edu/blog/2017/03/10/type-inference-in-stack-based-programming-languages/) given by Rob Kleffner on or about 2017-03-10 as part of a course on the history of programming languages.)\n",
     "\n",
    "cell_type": "code",
    "execution_count": 20,
    "metadata": {},
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Cannot unify (1, 2) and (1001, 1002).\n"
+     ]
+    }
+   ],
    "source": [
     "try:\n",
     "    C(cons, uncons)\n",
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "(Eventually I should come back around to this becuase it's not tooo difficult to exend this code to be able to compile e.g. `n3 = mul(n1, n2)` for `mul` and insert it in the right place with the right variable names.  It requires a little more support from the library functions, in that we need to know to call `mul()` the Python function for `mul` the Joy function, but since *most* of the math functions (at least) are already wrappers it should be straightforward.)"
+    "(Eventually I should come back around to this becuase it's not tooo difficult to exend this code to be able to compile e.g. `n2 = mul(n1, n1)` for `mul` with the right variable names and insert it in the right place.  It requires a little more support from the library functions, in that we need to know to call `mul()` the Python function for `mul` the Joy function, but since *most* of the math functions (at least) are already wrappers it should be straightforward.)"
    ]
   },
   {
    "metadata": {},
    "source": [
     "### Hybrid Inferencer/Interpreter\n",
-    "I think there's a way forward.  If we convert our list of terms we are composing into a stack structure we can use it as a *Joy expression*, then we can treat the *output half* of a function's stack effect comment as a Joy interpreter stack, and just execute combinators directly.  We can hybridize the compostition function with an interpreter to evaluate combinators, compose non-combinator functions, and put type variables on the stack.  For combinators like `branch` that can have more than one stack effect we have to \"split universes\" again and return both."
+    "I think there's a way forward.  If we convert our list (of terms we are composing) into a stack structure we can use it as a *Joy expression*, then we can treat the *output half* of a function's stack effect comment as a Joy interpreter stack, and just execute combinators directly.  We can hybridize the compostition function with an interpreter to evaluate combinators, compose non-combinator functions, and put type variables on the stack.  For combinators like `branch` that can have more than one stack effect we have to \"split universes\" again and return both."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "#### Joy Types for Functions\n",
+    "We need a type variable for Joy functions that can go in our expressions and be used by the hybrid inferencer/interpreter.  They have to store a name and a list of stack effects."
    ]
   },
   {
     "    __radd__ = __add__\n",
     "\n",
     "    def __repr__(self):\n",
-    "        return self.name\n",
-    "\n",
-    "\n",
-    "class SymbolJoyType(FunctionJoyType): prefix = 'F'\n",
-    "class CombinatorJoyType(FunctionJoyType): prefix = 'C'\n",
-    "\n",
-    "\n",
-    "def flatten(g):\n",
-    "    return list(chain.from_iterable(g))\n",
-    "\n",
-    "\n",
-    "ID = S[0], S[0]  # Identity function.\n",
-    "\n",
-    "\n",
-    "def infer(e, F=ID):\n",
-    "    if not e:\n",
-    "        return [F]\n",
-    "\n",
-    "    n, e = e\n",
-    "\n",
-    "    if isinstance(n, SymbolJoyType):\n",
-    "        res = flatten(infer(e, Fn) for Fn in MC([F], n.stack_effects))\n",
-    "\n",
-    "    elif isinstance(n, CombinatorJoyType):\n",
-    "        res = []\n",
-    "        for combinator in n.stack_effects:\n",
-    "            fi, fo = F\n",
-    "            new_fo, ee, _ = combinator(fo, e, {})\n",
-    "            ee = update(FUNCTIONS, ee)  # Fix Symbols.\n",
-    "            new_F = fi, new_fo\n",
-    "            res.extend(infer(ee, new_F))\n",
-    "    else:\n",
-    "        lit = s9, (n, s9)\n",
-    "        res = flatten(infer(e, Fn) for Fn in MC([F], [lit]))\n",
-    "\n",
-    "    return res\n",
-    "\n"
+    "        return self.name"
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": 108,
+   "cell_type": "markdown",
    "metadata": {},
-   "outputs": [],
    "source": [
-    "f0, f1, f2, f3, f4, f5, f6, f7, f8, f9 = F = map(FloatJoyType, _R)\n",
-    "i0, i1, i2, i3, i4, i5, i6, i7, i8, i9 = I = map(IntJoyType, _R)\n",
-    "n0, n1, n2, n3, n4, n5, n6, n7, n8, n9 = N\n",
-    "s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 = S"
+    "#### Specialized for Simple Functions and Combinators\n",
+    "For non-combinator functions the stack effects list contains stack effect comments (represented by pairs of cons-lists as described above.)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 109,
+   "execution_count": 108,
    "metadata": {},
    "outputs": [],
    "source": [
-    "import joy.library\n",
-    "\n",
-    "FNs = '''ccons cons divmod_ dup dupd first\n",
-    "         over pm pop popd popdd popop pred\n",
-    "         rest rolldown rollup rrest second\n",
-    "         sqrt stack succ swaack swap swons\n",
-    "         third tuck uncons'''\n",
-    "\n",
-    "FUNCTIONS = {\n",
-    "    name: SymbolJoyType(name, [NEW_DEFS[name]], i)\n",
-    "    for i, name in enumerate(FNs.strip().split())\n",
-    "    }\n",
-    "FUNCTIONS['sum'] = SymbolJoyType('sum', [(((Ns[1], s1), s0), (n0, s0))], 100)\n",
-    "FUNCTIONS['mul'] = SymbolJoyType('mul', [\n",
-    "     ((i2, (i1, s0)), (i3, s0)),\n",
-    "     ((f2, (i1, s0)), (f3, s0)),\n",
-    "     ((i2, (f1, s0)), (f3, s0)),\n",
-    "     ((f2, (f1, s0)), (f3, s0)),\n",
-    "], 101)\n",
-    "FUNCTIONS.update({\n",
-    "    combo.__name__: CombinatorJoyType(combo.__name__, [combo], i)\n",
-    "    for i, combo in enumerate((\n",
-    "        joy.library.i,\n",
-    "        joy.library.dip,\n",
-    "        joy.library.dipd,\n",
-    "        joy.library.dipdd,\n",
-    "        joy.library.dupdip,\n",
-    "        joy.library.b,\n",
-    "        joy.library.x,\n",
-    "        joy.library.infra,\n",
-    "        ))\n",
-    "    })\n",
-    "\n",
-    "def branch_true(stack, expression, dictionary):\n",
-    "    (then, (else_, (flag, stack))) = stack\n",
-    "    return stack, CONCAT(then, expression), dictionary\n",
-    "\n",
-    "def branch_false(stack, expression, dictionary):\n",
-    "    (then, (else_, (flag, stack))) = stack\n",
-    "    return stack, CONCAT(else_, expression), dictionary\n",
-    "\n",
-    "FUNCTIONS['branch'] = CombinatorJoyType('branch', [branch_true, branch_false], 100)"
+    "class SymbolJoyType(FunctionJoyType):\n",
+    "    prefix = 'F'"
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": 110,
+   "cell_type": "markdown",
    "metadata": {},
-   "outputs": [],
    "source": [
-    "globals().update(FUNCTIONS)"
+    "For combinators the list contains Python functions. "
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 111,
+   "execution_count": 109,
    "metadata": {},
    "outputs": [],
    "source": [
-    "from itertools import chain\n",
-    "from joy.utils.stack import list_to_stack as l2s"
+    "class CombinatorJoyType(FunctionJoyType):\n",
+    "\n",
+    "    prefix = 'C'\n",
+    "\n",
+    "    def __init__(self, name, sec, number, expect=None):\n",
+    "        super(CombinatorJoyType, self).__init__(name, sec, number)\n",
+    "        self.expect = expect\n",
+    "\n",
+    "    def enter_guard(self, f):\n",
+    "        if self.expect is None:\n",
+    "            return f\n",
+    "        g = self.expect, self.expect\n",
+    "        new_f = list(compose(f, g, ()))\n",
+    "        assert len(new_f) == 1, repr(new_f)\n",
+    "        return new_f[0][1]"
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": 112,
+   "cell_type": "markdown",
    "metadata": {},
-   "outputs": [],
    "source": [
-    "expression = l2s([n1, n2, mul])"
+    "For simple combinators that have only one effect (like ``dip``) you only need one function and it can be the combinator itself."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 113,
+   "execution_count": 110,
    "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "(n1, (n2, (mul, ())))"
-      ]
-     },
-     "execution_count": 113,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
+   "outputs": [],
    "source": [
-    "expression"
+    "import joy.library\n",
+    "\n",
+    "dip = CombinatorJoyType('dip', [joy.library.dip], 23)"
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": 114,
+   "cell_type": "markdown",
    "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "[(s1, (f1, s1)), (s1, (i1, s1))]"
-      ]
-     },
-     "execution_count": 114,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
    "source": [
-    "infer(expression)"
+    "For combinators that can have more than one effect (like ``branch``) you have to write functions that each implement the action of one of the effects."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 115,
+   "execution_count": 111,
    "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "(-- f1)\n",
-      "(-- i1)\n"
-     ]
-    }
-   ],
+   "outputs": [],
    "source": [
-    "for stack_effect_comment in infer(expression):\n",
-    "    print doc_from_stack_effect(*stack_effect_comment)"
+    "def branch_true(stack, expression, dictionary):\n",
+    "    (then, (else_, (flag, stack))) = stack\n",
+    "    return stack, concat(then, expression), dictionary\n",
+    "\n",
+    "def branch_false(stack, expression, dictionary):\n",
+    "    (then, (else_, (flag, stack))) = stack\n",
+    "    return stack, concat(else_, expression), dictionary\n",
+    "\n",
+    "branch = CombinatorJoyType('branch', [branch_true, branch_false], 100)"
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "`nullary`, broken here but the current code handles it.  I have to \"backport\" the work I'm doing to this notebook.  I've run ahead of myself."
+    "You can also provide an optional stack effect, input-side only, that will then be used as an identity function (that accepts and returns stacks that match the \"guard\" stack effect) which will be used to guard against type mismatches going into the evaluation of the combinator."
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": 116,
+   "cell_type": "markdown",
    "metadata": {},
-   "outputs": [],
    "source": [
-    "expression = l2s([n1, n2, (mul, s2), (stack, s3), dip, infra, first])"
+    "#### `infer()`\n",
+    "With those in place, we can define a function that accepts a sequence of Joy type variables, including ones representing functions (not just values), and attempts to grind out all the possible stack effects of that expression.\n",
+    "\n",
+    "One tricky thing is that type variables *in the expression* have to be updated along with the stack effects after doing unification or we risk losing useful information.  This was a straightforward, if awkward, modification to the call structure of `meta_compose()` et. al."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 117,
+   "execution_count": 112,
    "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "(n1, (n2, ((mul, s2), ((stack, s3), (dip, (infra, (first, ())))))))"
-      ]
-     },
-     "execution_count": 117,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
+   "outputs": [],
    "source": [
-    "expression"
+    "ID = S[0], S[0]  # Identity function.\n",
+    "\n",
+    "\n",
+    "def infer(*expression):\n",
+    "    return sorted(set(_infer(list_to_stack(expression))))\n",
+    "\n",
+    "\n",
+    "def _infer(e, F=ID):\n",
+    "    _log_it(e, F)\n",
+    "    if not e:\n",
+    "        return [F]\n",
+    "\n",
+    "    n, e = e\n",
+    "\n",
+    "    if isinstance(n, SymbolJoyType):\n",
+    "        eFG = meta_compose([F], n.stack_effects, e)\n",
+    "        res = flatten(_infer(e, Fn) for e, Fn in eFG)\n",
+    "\n",
+    "    elif isinstance(n, CombinatorJoyType):\n",
+    "        fi, fo = n.enter_guard(F)\n",
+    "        res = flatten(_interpret(f, fi, fo, e) for f in n.stack_effects)\n",
+    "\n",
+    "    elif isinstance(n, Symbol):\n",
+    "        assert n not in FUNCTIONS, repr(n)\n",
+    "        func = joy.library._dictionary[n]\n",
+    "        res = _interpret(func, F[0], F[1], e)\n",
+    "\n",
+    "    else:\n",
+    "        fi, fo = F\n",
+    "        res = _infer(e, (fi, (n, fo)))\n",
+    "\n",
+    "    return res\n",
+    "\n",
+    "\n",
+    "def _interpret(f, fi, fo, e):\n",
+    "    new_fo, ee, _ = f(fo, e, {})\n",
+    "    ee = update(FUNCTIONS, ee)  # Fix Symbols.\n",
+    "    new_F = fi, new_fo\n",
+    "    return _infer(ee, new_F)\n",
+    "\n",
+    "\n",
+    "def _log_it(e, F):\n",
+    "    _log.info(\n",
+    "        u'%3i %s ∘ %s',\n",
+    "        len(inspect_stack()),\n",
+    "        doc_from_stack_effect(*F),\n",
+    "        expression_to_string(e),\n",
+    "        )"
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": 132,
+   "cell_type": "markdown",
    "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "[]"
-      ]
-     },
-     "execution_count": 132,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
    "source": [
-    "infer(expression)  # should be three numbers."
+    "#### Work in Progress\n",
+    "And that brings us to current Work-In-Progress.  The mixed-mode inferencer/interpreter `infer()` function seems to work well.  There are details I should document, and the rest of the code in the \"polytypes\" module (FIXME link to its docs here!) should be explained...  There is cruft to convert the definitions in `DEFS` to the new `SymbolJoyType` objects, and some combinators.  Here is an example of output from the current code :"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 119,
-   "metadata": {},
+   "execution_count": null,
+   "metadata": {
+    "scrolled": true
+   },
    "outputs": [],
    "source": [
-    "for stack_effect_comment in infer(expression):\n",
-    "    print doc_from_stack_effect(*stack_effect_comment)"
+    "1/0  # (Don't try to run this cell!  It's not going to work.  This is \"read only\" code heh..)\n",
+    "\n",
+    "logging.basicConfig(format='%(message)s', stream=sys.stdout, level=logging.INFO)\n",
+    "\n",
+    "globals().update(FUNCTIONS)\n",
+    "\n",
+    "h = infer((pred, s2), (mul, s3), (div, s4), (nullary, (bool, s5)), dipd, branch)\n",
+    "\n",
+    "print '-' * 40\n",
+    "\n",
+    "for fi, fo in h:\n",
+    "    print doc_from_stack_effect(fi, fo)"
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "And that brings us to current Work-In-Progress.  I'm pretty hopeful that the mixed-mode inferencer/interpreter `infer()` function along with the ability to specify multiple implementations for the combinators will permit modelling of the stack effects of e.g. `ifte`."
+    "The numbers at the start of the lines are the current depth of the Python call stack.  They're followed by the current computed stack effect (initialized to `ID`) then the pending expression (the inference of the stack effect of which is the whole object of the current example.)\n",
+    "\n",
+    "In this example we are implementing (and inferring) `ifte` as `[nullary bool] dipd branch` which shows off a lot of the current implementation in action.\n",
+    "\n",
+    "      7 (--) ∘ [pred] [mul] [div] [nullary bool] dipd branch\n",
+    "      8 (-- [pred ...2]) ∘ [mul] [div] [nullary bool] dipd branch\n",
+    "      9 (-- [pred ...2] [mul ...3]) ∘ [div] [nullary bool] dipd branch\n",
+    "     10 (-- [pred ...2] [mul ...3] [div ...4]) ∘ [nullary bool] dipd branch\n",
+    "     11 (-- [pred ...2] [mul ...3] [div ...4] [nullary bool ...5]) ∘ dipd branch\n",
+    "     15 (-- [pred ...5]) ∘ nullary bool [mul] [div] branch\n",
+    "     19 (-- [pred ...2]) ∘ [stack] dinfrirst bool [mul] [div] branch\n",
+    "     20 (-- [pred ...2] [stack ]) ∘ dinfrirst bool [mul] [div] branch\n",
+    "     22 (-- [pred ...2] [stack ]) ∘ dip infra first bool [mul] [div] branch\n",
+    "     26 (--) ∘ stack [pred] infra first bool [mul] [div] branch\n",
+    "     29 (... -- ... [...]) ∘ [pred] infra first bool [mul] [div] branch\n",
+    "     30 (... -- ... [...] [pred ...1]) ∘ infra first bool [mul] [div] branch\n",
+    "     34 (--) ∘ pred s1 swaack first bool [mul] [div] branch\n",
+    "     37 (n1 -- n2) ∘ [n1] swaack first bool [mul] [div] branch\n",
+    "     38 (... n1 -- ... n2 [n1 ...]) ∘ swaack first bool [mul] [div] branch\n",
+    "     41 (... n1 -- ... n1 [n2 ...]) ∘ first bool [mul] [div] branch\n",
+    "     44 (n1 -- n1 n2) ∘ bool [mul] [div] branch\n",
+    "     47 (n1 -- n1 b1) ∘ [mul] [div] branch\n",
+    "     48 (n1 -- n1 b1 [mul ...1]) ∘ [div] branch\n",
+    "     49 (n1 -- n1 b1 [mul ...1] [div ...2]) ∘ branch\n",
+    "     53 (n1 -- n1) ∘ div\n",
+    "     56 (f2 f1 -- f3) ∘ \n",
+    "     56 (i1 f1 -- f2) ∘ \n",
+    "     56 (f1 i1 -- f2) ∘ \n",
+    "     56 (i2 i1 -- f1) ∘ \n",
+    "     53 (n1 -- n1) ∘ mul\n",
+    "     56 (f2 f1 -- f3) ∘ \n",
+    "     56 (i1 f1 -- f2) ∘ \n",
+    "     56 (f1 i1 -- f2) ∘ \n",
+    "     56 (i2 i1 -- i3) ∘ \n",
+    "    ----------------------------------------\n",
+    "    (f2 f1 -- f3)\n",
+    "    (i1 f1 -- f2)\n",
+    "    (f1 i1 -- f2)\n",
+    "    (i2 i1 -- f1)\n",
+    "    (i2 i1 -- i3)"
    ]
   },
   {
    "metadata": {},
    "source": [
     "## Conclusion\n",
-    "(for now...)"
+    "We built a simple type inferencer, and a kind of crude \"compiler\" for a subset of Joy functions.  Then we built a more powerful inferencer that actually does some evaluation and explores branching code paths"
    ]
   },
   {
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "I'm starting to realize that, with the inferencer/checker/compiler coming along, and with the UI ready to be rewritten in Joy, I'm close to a time when my ephasis is going to have to shift from crunchy code stuff to squishy human stuff.  I'm going to have to put normal people in front of this and see if, in fact, they *can* learn the basics of programming with it."
+    "## Appendix: Joy in the Logical Paradigm\n",
+    "\n",
+    "For *type checking* to work the type label classes have to be modified to let `T >= t` succeed, where e.g. `T` is `IntJoyType` and `t` is `int`.  If you do that you can take advantage of the *logical relational* nature of the stack effect comments to \"compute in reverse\" as it were.  There's a working demo of this at the end of the `polytypes` module.  But if you're interested in all that you should just use Prolog!\n",
+    "\n",
+    "Anyhow, type *checking* is a few easy steps away."
    ]
   },
   {
    "execution_count": null,
    "metadata": {},
    "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "The rest of this stuff is junk and/or unfinished material."
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## Appendix: Joy in the Logical Paradigm\n",
-    "For this to work the type label classes have to be modified to let `T >= t` succeed, where e.g. `T` is `IntJoyType` and `t` is `int`"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 120,
-   "metadata": {},
-   "outputs": [],
    "source": [
     "def _ge(self, other):\n",
     "    return (issubclass(other.__class__, self.__class__)\n",
     "AnyJoyType.accept = tuple, int, float, long, str, unicode, bool, Symbol\n",
     "StackJoyType.accept = tuple"
    ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 121,
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "([a4 a5 .1.] a3 a2 a1 -- [a2 a3 .1.])\n"
-     ]
-    }
-   ],
-   "source": [
-    "F = infer(l2s((pop, swap, rolldown, rest, rest, cons, cons)))\n",
-    "\n",
-    "for f in F:\n",
-    "    print doc_from_stack_effect(*f)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 122,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "from joy.parser import text_to_expression"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 123,
-   "metadata": {},
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "(a3 a2 a1 --)\n"
-     ]
-    }
-   ],
-   "source": [
-    "F = infer(l2s((pop, pop, pop)))\n",
-    "\n",
-    "for f in F:\n",
-    "    print doc_from_stack_effect(*f)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 124,
-   "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "(0, (1, (2, ())))"
-      ]
-     },
-     "execution_count": 124,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "s = text_to_expression('0 1 2')\n",
-    "s"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 125,
-   "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "(a1, (a2, (a3, s1)))"
-      ]
-     },
-     "execution_count": 125,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "F[0][0]"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 126,
-   "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "()"
-      ]
-     },
-     "execution_count": 126,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "L = unify(s, F[0][0])\n",
-    "L"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 127,
-   "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "(0, (1, (2, ((3, (4, ())), ()))))"
-      ]
-     },
-     "execution_count": 127,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "s = text_to_expression('0 1 2 [3 4]')\n",
-    "s"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 128,
-   "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "(a1, (a2, (a3, s1)))"
-      ]
-     },
-     "execution_count": 128,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "F[0][0]"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 129,
-   "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "()"
-      ]
-     },
-     "execution_count": 129,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "L = unify(s, F[0][0])\n",
-    "L"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 130,
-   "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "()"
-      ]
-     },
-     "execution_count": 130,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "L = unify(F[0][0], s)\n",
-    "L"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 131,
-   "metadata": {},
-   "outputs": [
-    {
-     "ename": "IndexError",
-     "evalue": "list index out of range",
-     "output_type": "error",
-     "traceback": [
-      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
-      "\u001b[0;31mIndexError\u001b[0m                                Traceback (most recent call last)",
-      "\u001b[0;32m<ipython-input-131-58a8e44e9cba>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mF\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
-      "\u001b[0;31mIndexError\u001b[0m: list index out of range"
-     ]
-    }
-   ],
-   "source": [
-    "F[1][0]"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "s[0]"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "A[1] >= 23"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## [Abstract Interpretation](https://en.wikipedia.org/wiki/Abstract_interpretation)\n",
-    "I *think* this might be sorta what I'm doing above with the `kav()` function...\n",
-    "  In any event \"mixed-mode\" interpreters that include values and type variables and can track constraints, etc. will be, uh, super-useful.  And Abstract Interpretation should be a rich source of ideas.\n"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## Junk"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "class SymbolJoyType(AnyJoyType): prefix = 'F'\n",
-    "\n",
-    "W = map(SymbolJoyType, _R)\n",
-    "\n",
-    "k = S[0], ((W[1], S[2]), S[0])\n",
-    "Symbol('cons')\n",
-    "print doc_from_stack_effect(*k)\n"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "dip_a = ((W[1], S[2]), (A[1], S[0]))"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "d = relabel(S[0], dip_a)\n",
-    "print doc_from_stack_effect(*d)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "s = list(unify(d[1], k[1]))[0]\n",
-    "s"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {
-    "scrolled": true
-   },
-   "outputs": [],
-   "source": [
-    "j = update(s, k)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "print doc_from_stack_effect(*j)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "j"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "cons"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {
-    "scrolled": true
-   },
-   "outputs": [],
-   "source": [
-    "for f in MC([k], [dup]):\n",
-    "    print doc_from_stack_effect(*f)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "l = S[0], ((cons, S[2]), (A[1], S[0]))"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "print doc_from_stack_effect(*l)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "\n",
-    "def dip_t(F):\n",
-    "    (quote, (a1, sec)) = F[1]\n",
-    "    G = F[0], sec\n",
-    "    P = S[3], (a1, S[3])\n",
-    "    a = [P]\n",
-    "    while isinstance(quote, tuple):\n",
-    "        term, quote = quote\n",
-    "        a.append(term)\n",
-    "    a.append(G)\n",
-    "    return a[::-1]\n",
-    "\n",
-    "\n",
-    "\n"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "from joy.utils.stack import iter_stack"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "a, b, c = dip_t(l)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "a"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "b"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "c"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "MC([a], [b])"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "kjs = MC(MC([a], [b]), [c])\n",
-    "kjs"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "print doc_from_stack_effect(*kjs[0])"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "    (a0 [.0.] -- [a0 .0.] a1)\n",
-    "    \n",
-    "       a0 [.0.] a1 [cons] dip\n",
-    "    ----------------------------\n",
-    "       [a0 .0.] a1"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": []
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "### `concat`\n",
-    "\n",
-    "How to deal with `concat`?\n",
-    "\n",
-    "    concat ([.0.] [.1.] -- [.0. .1.])\n",
-    "    \n",
-    "We would like to represent this in Python somehow..."
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "concat = (S[0], S[1]), ((S[0], S[1]),)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "But this is actually `cons` with the first argument restricted to be a stack:\n",
-    "\n",
-    "    ([.0.] [.1.] -- [[.0.] .1.])\n",
-    "\n",
-    "What we have implemented so far would actually only permit:\n",
-    "\n",
-    "    ([.0.] [.1.] -- [.2.])"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "concat = (S[0], S[1]), (S[2],)"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "    \n",
-    "Which works but can lose information.  Consider `cons concat`, this is how much information we *could* retain:\n",
-    "\n",
-    "    (1 [.0.] [.1.] -- [1 .0. .1.])\n",
-    "\n",
-    "As opposed to just:\n",
-    "\n",
-    "    (1 [.0.] [.1.] -- [.2.])"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "### represent `concat`\n",
-    "\n",
-    "    ([.0.] [.1.] -- [A*(.0.) .1.])\n",
-    "\n",
-    "Meaning that `A*` on the right-hand side should all the crap from `.0.`.\n",
-    "\n",
-    "    ([      .0.] [.1.] -- [      A* .1.])\n",
-    "    ([a     .0.] [.1.] -- [a     A* .1.])\n",
-    "    ([a b   .0.] [.1.] -- [a b   A* .1.])\n",
-    "    ([a b c .0.] [.1.] -- [a b c A* .1.])\n",
-    "\n",
-    "    "
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "or...\n",
-    "\n",
-    "    ([       .0.] [.1.] -- [       .1.])\n",
-    "    ([a      .0.] [.1.] -- [a      .1.])\n",
-    "    ([a b    .0.] [.1.] -- [a b    .1.])\n",
-    "    ([a b  c .0.] [.1.] -- [a b  c .1.])\n",
-    "    ([a A* c .0.] [.1.] -- [a A* c .1.])\n",
-    "\n",
-    "    "
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "    (a, (b, S0)) . S1 = (a, (b, (A*, S1)))"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "class Astar(object):\n",
-    "    def __repr__(self):\n",
-    "        return 'A*'\n",
-    "\n",
-    "\n",
-    "def concat(s0, s1):\n",
-    "    a = []\n",
-    "    while isinstance(s0, tuple):\n",
-    "        term, s0 = s0\n",
-    "        a.append(term)\n",
-    "    assert isinstance(s0, StackJoyType), repr(s0)\n",
-    "    s1 = Astar(), s1\n",
-    "    for term in reversed(a):\n",
-    "        s1 = term, s1\n",
-    "    return s1"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "a, b = (A[1], S[0]), (A[2], S[1])"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {},
-   "outputs": [],
-   "source": [
-    "concat(a, b)"
-   ]
   }
  ],
  "metadata": {
index 9a723c0..599973e 100644 (file)
@@ -1,5 +1,5 @@
 
-# Type Inference
+# The Blissful Elegance of Typing Joy
 
 This notebook presents a simple type inferencer for Joy code.  It can infer the stack effect of most Joy expressions.  It's built largely by means of existing ideas and research.  (A great overview of the existing knowledge is a talk ["Type Inference in Stack-Based Programming Languages"](http://prl.ccs.neu.edu/blog/2017/03/10/type-inference-in-stack-based-programming-languages/) given by Rob Kleffner on or about 2017-03-10 as part of a course on the history of programming languages.)
 
@@ -345,6 +345,8 @@ def unify(u, v, s=None):
         s[u] = v
     elif isinstance(v, int):
         s[v] = u
+    else:
+        s = False
 
     return s
 ```
@@ -556,6 +558,9 @@ except Exception, e:
     print e
 ```
 
+    Cannot unify (1, 2) and (1001, 1002).
+
+
 #### `unify()` version 2
 The problem is that the `unify()` function as written doesn't handle the case when both terms are tuples.  We just have to add a clause to deal with this recursively:
 
@@ -584,6 +589,8 @@ def unify(u, v, s=None):
         s = unify(a, c, s)
         if s != False:
             s = unify(b, d, s)
+    else:
+        s = False
 
     return s
 ```
@@ -1413,7 +1420,7 @@ print compile_('sqr', C(dup, mul))
         return (n2, stack)
 
 
-(Eventually I should come back around to this becuase it's not tooo difficult to exend this code to be able to compile e.g. `n3 = mul(n1, n2)` for `mul` and insert it in the right place with the right variable names.  It requires a little more support from the library functions, in that we need to know to call `mul()` the Python function for `mul` the Joy function, but since *most* of the math functions (at least) are already wrappers it should be straightforward.)
+(Eventually I should come back around to this becuase it's not tooo difficult to exend this code to be able to compile e.g. `n2 = mul(n1, n1)` for `mul` with the right variable names and insert it in the right place.  It requires a little more support from the library functions, in that we need to know to call `mul()` the Python function for `mul` the Joy function, but since *most* of the math functions (at least) are already wrappers it should be straightforward.)
 
 #### `compilable()`
 The functions that *can* be compiled are the ones that have only `AnyJoyType` and `StackJoyType` labels in their stack effect comments.  We can write a function to check that:
@@ -2227,7 +2234,7 @@ for result in unify(a, b):
 
 ## Part VII: Typing Combinators
 
-In order to compute the stack effect of combinators you kinda have to have the quoted programs they expect available.  In the most general case, the `i` combinator, you can't say anything about it's stack effect other than it expects one quote:
+In order to compute the stack effect of combinators you kinda have to have the quoted programs they expect available.  In the most general case, the `i` combinator, you can't say anything about its stack effect other than it expects one quote:
 
     i (... [.1.] -- ... .1.)
 
@@ -2250,7 +2257,11 @@ Obviously it would be:
 
 Without any information about the contents of the quote we can't say much about the result.
 
-I think there's a way forward.  If we convert our list of terms we are composing into a stack structure we can use it as a *Joy expression*, then we can treat the *output half* of a function's stack effect comment as a Joy interpreter stack, and just execute combinators directly.  We can hybridize the compostition function with an interpreter to evaluate combinators, compose non-combinator functions, and put type variables on the stack.  For combinators like `branch` that can have more than one stack effect we have to "split universes" again and return both.
+### Hybrid Inferencer/Interpreter
+I think there's a way forward.  If we convert our list (of terms we are composing) into a stack structure we can use it as a *Joy expression*, then we can treat the *output half* of a function's stack effect comment as a Joy interpreter stack, and just execute combinators directly.  We can hybridize the compostition function with an interpreter to evaluate combinators, compose non-combinator functions, and put type variables on the stack.  For combinators like `branch` that can have more than one stack effect we have to "split universes" again and return both.
+
+#### Joy Types for Functions
+We need a type variable for Joy functions that can go in our expressions and be used by the hybrid inferencer/interpreter.  They have to store a name and a list of stack effects.
 
 
 ```python
@@ -2267,211 +2278,183 @@ class FunctionJoyType(AnyJoyType):
 
     def __repr__(self):
         return self.name
-
-
-class SymbolJoyType(FunctionJoyType): prefix = 'F'
-class CombinatorJoyType(FunctionJoyType): prefix = 'C'
-
-
-
 ```
 
-
-```python
-def flatten(g):
-    return list(chain.from_iterable(g))
-
-
-ID = S[0], S[0]  # Identity function.
-
-
-def infer(e, F=ID):
-    if not e:
-        return [F]
-
-    n, e = e
-
-    if isinstance(n, SymbolJoyType):
-        res = flatten(infer(e, Fn) for Fn in MC([F], n.stack_effects))
-
-    elif isinstance(n, CombinatorJoyType):
-        res = []
-        for combinator in n.stack_effects:
-            fi, fo = F
-            new_fo, ee, _ = combinator(fo, e, {})
-            ee = update(FUNCTIONS, ee)  # Fix Symbols.
-            new_F = fi, new_fo
-            res.extend(infer(ee, new_F))
-    else:
-        lit = s9, (n, s9)
-        res = flatten(infer(e, Fn) for Fn in MC([F], [lit]))
-
-    return res
-
-
-```
+#### Specialized for Simple Functions and Combinators
+For non-combinator functions the stack effects list contains stack effect comments (represented by pairs of cons-lists as described above.)
 
 
 ```python
-f0, f1, f2, f3, f4, f5, f6, f7, f8, f9 = F = map(FloatJoyType, _R)
-i0, i1, i2, i3, i4, i5, i6, i7, i8, i9 = I = map(IntJoyType, _R)
-n0, n1, n2, n3, n4, n5, n6, n7, n8, n9 = N
-s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 = S
+class SymbolJoyType(FunctionJoyType):
+    prefix = 'F'
 ```
 
+For combinators the list contains Python functions. 
 
-```python
-import joy.library
-
-FNs = '''ccons cons divmod_ dup dupd first
-         over pm pop popd popdd popop pred
-         rest rolldown rollup rrest second
-         sqrt stack succ swaack swap swons
-         third tuck uncons'''
 
-FUNCTIONS = {
-    name: SymbolJoyType(name, [NEW_DEFS[name]], i)
-    for i, name in enumerate(FNs.strip().split())
-    }
-FUNCTIONS['sum'] = SymbolJoyType('sum', [(((Ns[1], s1), s0), (n0, s0))], 100)
-FUNCTIONS['mul'] = SymbolJoyType('mul', [
-     ((i2, (i1, s0)), (i3, s0)),
-     ((f2, (i1, s0)), (f3, s0)),
-     ((i2, (f1, s0)), (f3, s0)),
-     ((f2, (f1, s0)), (f3, s0)),
-], 101)
-FUNCTIONS.update({
-    combo.__name__: CombinatorJoyType(combo.__name__, [combo], i)
-    for i, combo in enumerate((
-        joy.library.i,
-        joy.library.dip,
-        joy.library.dipd,
-        joy.library.dipdd,
-        joy.library.dupdip,
-        joy.library.b,
-        joy.library.x,
-        joy.library.infra,
-        ))
-    })
+```python
+class CombinatorJoyType(FunctionJoyType):
 
-def branch_true(stack, expression, dictionary):
-    (then, (else_, (flag, stack))) = stack
-    return stack, CONCAT(then, expression), dictionary
+    prefix = 'C'
 
-def branch_false(stack, expression, dictionary):
-    (then, (else_, (flag, stack))) = stack
-    return stack, CONCAT(else_, expression), dictionary
+    def __init__(self, name, sec, number, expect=None):
+        super(CombinatorJoyType, self).__init__(name, sec, number)
+        self.expect = expect
 
-FUNCTIONS['branch'] = CombinatorJoyType('branch', [branch_true, branch_false], 100)
+    def enter_guard(self, f):
+        if self.expect is None:
+            return f
+        g = self.expect, self.expect
+        new_f = list(compose(f, g, ()))
+        assert len(new_f) == 1, repr(new_f)
+        return new_f[0][1]
 ```
 
-
-```python
-globals().update(FUNCTIONS)
-```
+For simple combinators that have only one effect (like ``dip``) you only need one function and it can be the combinator itself.
 
 
 ```python
-from itertools import chain
-from joy.utils.stack import list_to_stack as l2s
-```
-
+import joy.library
 
-```python
-expression = l2s([n1, n2, (mul, s2), (stack, s3), dip, infra, first])
+dip = CombinatorJoyType('dip', [joy.library.dip], 23)
 ```
 
-
-```python
-expression
-```
-
-
-
-
-    (n1, (n2, ((mul, s2), ((stack, s3), (dip, (infra, (first, ())))))))
-
-
+For combinators that can have more than one effect (like ``branch``) you have to write functions that each implement the action of one of the effects.
 
 
 ```python
-expression = l2s([n1, n2, mul])
-```
+def branch_true(stack, expression, dictionary):
+    (then, (else_, (flag, stack))) = stack
+    return stack, concat(then, expression), dictionary
 
+def branch_false(stack, expression, dictionary):
+    (then, (else_, (flag, stack))) = stack
+    return stack, concat(else_, expression), dictionary
 
-```python
-expression
+branch = CombinatorJoyType('branch', [branch_true, branch_false], 100)
 ```
 
+You can also provide an optional stack effect, input-side only, that will then be used as an identity function (that accepts and returns stacks that match the "guard" stack effect) which will be used to guard against type mismatches going into the evaluation of the combinator.
 
+#### `infer()`
+With those in place, we can define a function that accepts a sequence of Joy type variables, including ones representing functions (not just values), and attempts to grind out all the possible stack effects of that expression.
 
-
-    (n1, (n2, (mul, ())))
-
-
+One tricky thing is that type variables *in the expression* have to be updated along with the stack effects after doing unification or we risk losing useful information.  This was a straightforward, if awkward, modification to the call structure of `meta_compose()` et. al.
 
 
 ```python
-infer(expression)
-```
-
-
+ID = S[0], S[0]  # Identity function.
 
 
-    [(s1, (f1, s1)), (s1, (i1, s1))]
+def infer(*expression):
+    return sorted(set(_infer(list_to_stack(expression))))
 
 
+def _infer(e, F=ID):
+    _log_it(e, F)
+    if not e:
+        return [F]
 
+    n, e = e
 
-```python
-infer(expression)
-```
+    if isinstance(n, SymbolJoyType):
+        eFG = meta_compose([F], n.stack_effects, e)
+        res = flatten(_infer(e, Fn) for e, Fn in eFG)
 
+    elif isinstance(n, CombinatorJoyType):
+        fi, fo = n.enter_guard(F)
+        res = flatten(_interpret(f, fi, fo, e) for f in n.stack_effects)
 
+    elif isinstance(n, Symbol):
+        assert n not in FUNCTIONS, repr(n)
+        func = joy.library._dictionary[n]
+        res = _interpret(func, F[0], F[1], e)
 
+    else:
+        fi, fo = F
+        res = _infer(e, (fi, (n, fo)))
 
-    [(s1, (f1, s1)), (s1, (i1, s1))]
+    return res
 
 
+def _interpret(f, fi, fo, e):
+    new_fo, ee, _ = f(fo, e, {})
+    ee = update(FUNCTIONS, ee)  # Fix Symbols.
+    new_F = fi, new_fo
+    return _infer(ee, new_F)
 
 
-```python
-for stack_effect_comment in infer(expression):
-    print doc_from_stack_effect(*stack_effect_comment)
+def _log_it(e, F):
+    _log.info(
+        u'%3i %s ∘ %s',
+        len(inspect_stack()),
+        doc_from_stack_effect(*F),
+        expression_to_string(e),
+        )
 ```
 
-    (-- f1)
-    (-- i1)
-
+#### Work in Progress
+And that brings us to current Work-In-Progress.  The mixed-mode inferencer/interpreter `infer()` function seems to work well.  There are details I should document, and the rest of the code in the "polytypes" module (FIXME link to its docs here!) should be explained...  There is cruft to convert the definitions in `DEFS` to the new `SymbolJoyType` objects, and some combinators.  Here is an example of output from the current code :
 
 
 ```python
-expression
-```
-
-
-
-
-    (n1, (n2, (mul, ())))
-
-
-
-
-```python
-infer(expression)
-```
-
-
-
-
-    [(s1, (f1, s1)), (s1, (i1, s1))]
+1/0  # (Don't try to run this cell!  It's not going to work.  This is "read only" code heh..)
 
+logging.basicConfig(format='%(message)s', stream=sys.stdout, level=logging.INFO)
 
+globals().update(FUNCTIONS)
 
-And that brings us to current Work-In-Progress.  I'm pretty hopeful that the mixed-mode inferencer/interpreter `infer()` function along with the ability to specify multiple implementations for the combinators will permit modelling of the stack effects of e.g. `ifte`.  If I can keep up the pace I should be able to verify that conjecture by the end of June.
+h = infer((pred, s2), (mul, s3), (div, s4), (nullary, (bool, s5)), dipd, branch)
+
+print '-' * 40
+
+for fi, fo in h:
+    print doc_from_stack_effect(fi, fo)
+```
+
+The numbers at the start of the lines are the current depth of the Python call stack.  They're followed by the current computed stack effect (initialized to `ID`) then the pending expression (the inference of the stack effect of which is the whole object of the current example.)
+
+In this example we are implementing (and inferring) `ifte` as `[nullary bool] dipd branch` which shows off a lot of the current implementation in action.
+
+      7 (--) ∘ [pred] [mul] [div] [nullary bool] dipd branch
+      8 (-- [pred ...2]) ∘ [mul] [div] [nullary bool] dipd branch
+      9 (-- [pred ...2] [mul ...3]) ∘ [div] [nullary bool] dipd branch
+     10 (-- [pred ...2] [mul ...3] [div ...4]) ∘ [nullary bool] dipd branch
+     11 (-- [pred ...2] [mul ...3] [div ...4] [nullary bool ...5]) ∘ dipd branch
+     15 (-- [pred ...5]) ∘ nullary bool [mul] [div] branch
+     19 (-- [pred ...2]) ∘ [stack] dinfrirst bool [mul] [div] branch
+     20 (-- [pred ...2] [stack ]) ∘ dinfrirst bool [mul] [div] branch
+     22 (-- [pred ...2] [stack ]) ∘ dip infra first bool [mul] [div] branch
+     26 (--) ∘ stack [pred] infra first bool [mul] [div] branch
+     29 (... -- ... [...]) ∘ [pred] infra first bool [mul] [div] branch
+     30 (... -- ... [...] [pred ...1]) ∘ infra first bool [mul] [div] branch
+     34 (--) ∘ pred s1 swaack first bool [mul] [div] branch
+     37 (n1 -- n2) ∘ [n1] swaack first bool [mul] [div] branch
+     38 (... n1 -- ... n2 [n1 ...]) ∘ swaack first bool [mul] [div] branch
+     41 (... n1 -- ... n1 [n2 ...]) ∘ first bool [mul] [div] branch
+     44 (n1 -- n1 n2) ∘ bool [mul] [div] branch
+     47 (n1 -- n1 b1) ∘ [mul] [div] branch
+     48 (n1 -- n1 b1 [mul ...1]) ∘ [div] branch
+     49 (n1 -- n1 b1 [mul ...1] [div ...2]) ∘ branch
+     53 (n1 -- n1) ∘ div
+     56 (f2 f1 -- f3) ∘ 
+     56 (i1 f1 -- f2) ∘ 
+     56 (f1 i1 -- f2) ∘ 
+     56 (i2 i1 -- f1) ∘ 
+     53 (n1 -- n1) ∘ mul
+     56 (f2 f1 -- f3) ∘ 
+     56 (i1 f1 -- f2) ∘ 
+     56 (f1 i1 -- f2) ∘ 
+     56 (i2 i1 -- i3) ∘ 
+    ----------------------------------------
+    (f2 f1 -- f3)
+    (i1 f1 -- f2)
+    (f1 i1 -- f2)
+    (i2 i1 -- f1)
+    (i2 i1 -- i3)
 
 ## Conclusion
-(for now...)
+We built a simple type inferencer, and a kind of crude "compiler" for a subset of Joy functions.  Then we built a more powerful inferencer that actually does some evaluation and explores branching code paths
 
 Work remains to be done:
 
@@ -2489,12 +2472,11 @@ Work remains to be done:
   - docstrings all around
   - improve this notebook (it kinda falls apart at the end narratively.  I went off and just started writing code to see if it would work.  It does, but now I have to come back and describe here what I did.
 
-I'm starting to realize that, with the inferencer/checker/compiler coming along, and with the UI ready to be rewritten in Joy, I'm close to a time when my ephasis is going to have to shift from crunchy code stuff to squishy human stuff.  I'm going to have to put normal people in front of this and see if, in fact, they *can* learn the basics of programming with it.
+## Appendix: Joy in the Logical Paradigm
 
-The rest of this stuff is junk and/or unfinished material.
+For *type checking* to work the type label classes have to be modified to let `T >= t` succeed, where e.g. `T` is `IntJoyType` and `t` is `int`.  If you do that you can take advantage of the *logical relational* nature of the stack effect comments to "compute in reverse" as it were.  There's a working demo of this at the end of the `polytypes` module.  But if you're interested in all that you should just use Prolog!
 
-## Appendix: Joy in the Logical Paradigm
-For this to work the type label classes have to be modified to let `T >= t` succeed, where e.g. `T` is `IntJoyType` and `t` is `int`
+Anyhow, type *checking* is a few easy steps away.
 
 
 ```python
@@ -2507,373 +2489,3 @@ AnyJoyType.__ge__ = _ge
 AnyJoyType.accept = tuple, int, float, long, str, unicode, bool, Symbol
 StackJoyType.accept = tuple
 ```
-
-
-```python
-F = infer(l2s((pop, swap, rolldown, rest, rest, cons, cons)))
-
-for f in F:
-    print doc_from_stack_effect(*f)
-```
-
-    ([a4 a5 .1.] a3 a2 a1 -- [a2 a3 .1.])
-
-
-
-```python
-from joy.parser import text_to_expression
-```
-
-
-```python
-F = infer(l2s((pop, pop, pop)))
-
-for f in F:
-    print doc_from_stack_effect(*f)
-```
-
-    (a3 a2 a1 --)
-
-
-
-```python
-s = text_to_expression('0 1 2')
-s
-```
-
-
-
-
-    (0, (1, (2, ())))
-
-
-
-
-```python
-F[0][0]
-```
-
-
-
-
-    (a1, (a2, (a3, s1)))
-
-
-
-
-```python
-L = unify(s, F[0][0])
-L
-```
-
-
-
-
-    ()
-
-
-
-
-```python
-s = text_to_expression('0 1 2 [3 4]')
-s
-```
-
-
-
-
-    (0, (1, (2, ((3, (4, ())), ()))))
-
-
-
-
-```python
-F[0][0]
-```
-
-
-
-
-    (a1, (a2, (a3, s1)))
-
-
-
-
-```python
-L = unify(s, F[0][0])
-L
-```
-
-
-
-
-    ()
-
-
-
-
-```python
-L = unify(F[0][0], s)
-L
-```
-
-
-
-
-    ()
-
-
-
-
-```python
-F[1][0]
-```
-
-
-    ---------------------------------------------------------------------------
-
-    IndexError                                Traceback (most recent call last)
-
-    <ipython-input-133-58a8e44e9cba> in <module>()
-    ----> 1 F[1][0]
-    
-
-    IndexError: list index out of range
-
-
-
-```python
-s[0]
-```
-
-
-```python
-A[1] >= 23
-```
-
-## [Abstract Interpretation](https://en.wikipedia.org/wiki/Abstract_interpretation)
-I *think* this might be sorta what I'm doing above with the `kav()` function...
-  In any event "mixed-mode" interpreters that include values and type variables and can track constraints, etc. will be, uh, super-useful.  And Abstract Interpretation should be a rich source of ideas.
-
-
-## Junk
-
-
-```python
-class SymbolJoyType(AnyJoyType): prefix = 'F'
-
-W = map(SymbolJoyType, _R)
-
-k = S[0], ((W[1], S[2]), S[0])
-Symbol('cons')
-print doc_from_stack_effect(*k)
-
-```
-
-
-```python
-dip_a = ((W[1], S[2]), (A[1], S[0]))
-```
-
-
-```python
-d = relabel(S[0], dip_a)
-print doc_from_stack_effect(*d)
-```
-
-
-```python
-s = list(unify(d[1], k[1]))[0]
-s
-```
-
-
-```python
-j = update(s, k)
-```
-
-
-```python
-print doc_from_stack_effect(*j)
-```
-
-
-```python
-j
-```
-
-
-```python
-cons
-```
-
-
-```python
-for f in MC([k], [dup]):
-    print doc_from_stack_effect(*f)
-```
-
-
-```python
-l = S[0], ((cons, S[2]), (A[1], S[0]))
-```
-
-
-```python
-print doc_from_stack_effect(*l)
-```
-
-
-```python
-
-def dip_t(F):
-    (quote, (a1, sec)) = F[1]
-    G = F[0], sec
-    P = S[3], (a1, S[3])
-    a = [P]
-    while isinstance(quote, tuple):
-        term, quote = quote
-        a.append(term)
-    a.append(G)
-    return a[::-1]
-
-
-
-
-```
-
-
-```python
-from joy.utils.stack import iter_stack
-```
-
-
-```python
-a, b, c = dip_t(l)
-```
-
-
-```python
-a
-```
-
-
-```python
-b
-```
-
-
-```python
-c
-```
-
-
-```python
-MC([a], [b])
-```
-
-
-```python
-kjs = MC(MC([a], [b]), [c])
-kjs
-```
-
-
-```python
-print doc_from_stack_effect(*kjs[0])
-```
-
-    (a0 [.0.] -- [a0 .0.] a1)
-    
-       a0 [.0.] a1 [cons] dip
-    ----------------------------
-       [a0 .0.] a1
-
-### `concat`
-
-How to deal with `concat`?
-
-    concat ([.0.] [.1.] -- [.0. .1.])
-    
-We would like to represent this in Python somehow...
-
-
-```python
-concat = (S[0], S[1]), ((S[0], S[1]),)
-```
-
-But this is actually `cons` with the first argument restricted to be a stack:
-
-    ([.0.] [.1.] -- [[.0.] .1.])
-
-What we have implemented so far would actually only permit:
-
-    ([.0.] [.1.] -- [.2.])
-
-
-```python
-concat = (S[0], S[1]), (S[2],)
-```
-
-    
-Which works but can lose information.  Consider `cons concat`, this is how much information we *could* retain:
-
-    (1 [.0.] [.1.] -- [1 .0. .1.])
-
-As opposed to just:
-
-    (1 [.0.] [.1.] -- [.2.])
-
-### represent `concat`
-
-    ([.0.] [.1.] -- [A*(.0.) .1.])
-
-Meaning that `A*` on the right-hand side should all the crap from `.0.`.
-
-    ([      .0.] [.1.] -- [      A* .1.])
-    ([a     .0.] [.1.] -- [a     A* .1.])
-    ([a b   .0.] [.1.] -- [a b   A* .1.])
-    ([a b c .0.] [.1.] -- [a b c A* .1.])
-
-    
-
-or...
-
-    ([       .0.] [.1.] -- [       .1.])
-    ([a      .0.] [.1.] -- [a      .1.])
-    ([a b    .0.] [.1.] -- [a b    .1.])
-    ([a b  c .0.] [.1.] -- [a b  c .1.])
-    ([a A* c .0.] [.1.] -- [a A* c .1.])
-
-    
-
-    (a, (b, S0)) . S1 = (a, (b, (A*, S1)))
-
-
-```python
-class Astar(object):
-    def __repr__(self):
-        return 'A*'
-
-
-def concat(s0, s1):
-    a = []
-    while isinstance(s0, tuple):
-        term, s0 = s0
-        a.append(term)
-    assert isinstance(s0, StackJoyType), repr(s0)
-    s1 = Astar(), s1
-    for term in reversed(a):
-        s1 = term, s1
-    return s1
-```
-
-
-```python
-a, b = (A[1], S[0]), (A[2], S[1])
-```
-
-
-```python
-concat(a, b)
-```
index a8084de..dc209b5 100644 (file)
@@ -1,6 +1,6 @@
 
-Type Inference
-==============
+The Blissful Elegance of Typing Joy
+===================================
 
 This notebook presents a simple type inferencer for Joy code. It can
 infer the stack effect of most Joy expressions. It's built largely by
@@ -476,6 +476,8 @@ integers or tuples of type descriptors:
             s[u] = v
         elif isinstance(v, int):
             s[v] = u
+        else:
+            s = False
     
         return s
 
@@ -709,6 +711,12 @@ work:
     except Exception, e:
         print e
 
+
+.. parsed-literal::
+
+    Cannot unify (1, 2) and (1001, 1002).
+
+
 ``unify()`` version 2
 ^^^^^^^^^^^^^^^^^^^^^
 
@@ -741,6 +749,8 @@ deal with this recursively:
             s = unify(a, c, s)
             if s != False:
                 s = unify(b, d, s)
+        else:
+            s = False
     
         return s
 
@@ -1674,8 +1684,8 @@ such. Note that this is *not* a ``sqr`` function implementation:
 
 (Eventually I should come back around to this becuase it's not tooo
 difficult to exend this code to be able to compile e.g.
-``n3 = mul(n1, n2)`` for ``mul`` and insert it in the right place with
-the right variable names. It requires a little more support from the
+``n2 = mul(n1, n1)`` for ``mul`` with the right variable names and
+insert it in the right place. It requires a little more support from the
 library functions, in that we need to know to call ``mul()`` the Python
 function for ``mul`` the Joy function, but since *most* of the math
 functions (at least) are already wrappers it should be straightforward.)
@@ -2612,7 +2622,7 @@ Part VII: Typing Combinators
 
 In order to compute the stack effect of combinators you kinda have to
 have the quoted programs they expect available. In the most general
-case, the ``i`` combinator, you can't say anything about it's stack
+case, the ``i`` combinator, you can't say anything about its stack
 effect other than it expects one quote:
 
 ::
@@ -2646,8 +2656,11 @@ Obviously it would be:
 Without any information about the contents of the quote we can't say
 much about the result.
 
-I think there's a way forward. If we convert our list of terms we are
-composing into a stack structure we can use it as a *Joy expression*,
+Hybrid Inferencer/Interpreter
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+I think there's a way forward. If we convert our list (of terms we are
+composing) into a stack structure we can use it as a *Joy expression*,
 then we can treat the *output half* of a function's stack effect comment
 as a Joy interpreter stack, and just execute combinators directly. We
 can hybridize the compostition function with an interpreter to evaluate
@@ -2655,6 +2668,13 @@ combinators, compose non-combinator functions, and put type variables on
 the stack. For combinators like ``branch`` that can have more than one
 stack effect we have to "split universes" again and return both.
 
+Joy Types for Functions
+^^^^^^^^^^^^^^^^^^^^^^^
+
+We need a type variable for Joy functions that can go in our expressions
+and be used by the hybrid inferencer/interpreter. They have to store a
+name and a list of stack effects.
+
 .. code:: ipython2
 
     class FunctionJoyType(AnyJoyType):
@@ -2670,217 +2690,212 @@ stack effect we have to "split universes" again and return both.
     
         def __repr__(self):
             return self.name
+
+Specialized for Simple Functions and Combinators
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+For non-combinator functions the stack effects list contains stack
+effect comments (represented by pairs of cons-lists as described above.)
+
+.. code:: ipython2
+
+    class SymbolJoyType(FunctionJoyType):
+        prefix = 'F'
+
+For combinators the list contains Python functions.
+
+.. code:: ipython2
+
+    class CombinatorJoyType(FunctionJoyType):
     
+        prefix = 'C'
     
-    class SymbolJoyType(FunctionJoyType): prefix = 'F'
-    class CombinatorJoyType(FunctionJoyType): prefix = 'C'
+        def __init__(self, name, sec, number, expect=None):
+            super(CombinatorJoyType, self).__init__(name, sec, number)
+            self.expect = expect
     
+        def enter_guard(self, f):
+            if self.expect is None:
+                return f
+            g = self.expect, self.expect
+            new_f = list(compose(f, g, ()))
+            assert len(new_f) == 1, repr(new_f)
+            return new_f[0][1]
+
+For simple combinators that have only one effect (like ``dip``) you only
+need one function and it can be the combinator itself.
+
+.. code:: ipython2
+
+    import joy.library
     
+    dip = CombinatorJoyType('dip', [joy.library.dip], 23)
 
+For combinators that can have more than one effect (like ``branch``) you
+have to write functions that each implement the action of one of the
+effects.
 
 .. code:: ipython2
 
-    def flatten(g):
-        return list(chain.from_iterable(g))
+    def branch_true(stack, expression, dictionary):
+        (then, (else_, (flag, stack))) = stack
+        return stack, concat(then, expression), dictionary
     
+    def branch_false(stack, expression, dictionary):
+        (then, (else_, (flag, stack))) = stack
+        return stack, concat(else_, expression), dictionary
     
+    branch = CombinatorJoyType('branch', [branch_true, branch_false], 100)
+
+You can also provide an optional stack effect, input-side only, that
+will then be used as an identity function (that accepts and returns
+stacks that match the "guard" stack effect) which will be used to guard
+against type mismatches going into the evaluation of the combinator.
+
+``infer()``
+^^^^^^^^^^^
+
+With those in place, we can define a function that accepts a sequence of
+Joy type variables, including ones representing functions (not just
+values), and attempts to grind out all the possible stack effects of
+that expression.
+
+One tricky thing is that type variables *in the expression* have to be
+updated along with the stack effects after doing unification or we risk
+losing useful information. This was a straightforward, if awkward,
+modification to the call structure of ``meta_compose()`` et. al.
+
+.. code:: ipython2
+
     ID = S[0], S[0]  # Identity function.
     
     
-    def infer(e, F=ID):
+    def infer(*expression):
+        return sorted(set(_infer(list_to_stack(expression))))
+    
+    
+    def _infer(e, F=ID):
+        _log_it(e, F)
         if not e:
             return [F]
     
         n, e = e
     
         if isinstance(n, SymbolJoyType):
-            res = flatten(infer(e, Fn) for Fn in MC([F], n.stack_effects))
+            eFG = meta_compose([F], n.stack_effects, e)
+            res = flatten(_infer(e, Fn) for e, Fn in eFG)
     
         elif isinstance(n, CombinatorJoyType):
-            res = []
-            for combinator in n.stack_effects:
-                fi, fo = F
-                new_fo, ee, _ = combinator(fo, e, {})
-                ee = update(FUNCTIONS, ee)  # Fix Symbols.
-                new_F = fi, new_fo
-                res.extend(infer(ee, new_F))
+            fi, fo = n.enter_guard(F)
+            res = flatten(_interpret(f, fi, fo, e) for f in n.stack_effects)
+    
+        elif isinstance(n, Symbol):
+            assert n not in FUNCTIONS, repr(n)
+            func = joy.library._dictionary[n]
+            res = _interpret(func, F[0], F[1], e)
+    
         else:
-            lit = s9, (n, s9)
-            res = flatten(infer(e, Fn) for Fn in MC([F], [lit]))
+            fi, fo = F
+            res = _infer(e, (fi, (n, fo)))
     
         return res
     
-
-
-.. code:: ipython2
-
-    f0, f1, f2, f3, f4, f5, f6, f7, f8, f9 = F = map(FloatJoyType, _R)
-    i0, i1, i2, i3, i4, i5, i6, i7, i8, i9 = I = map(IntJoyType, _R)
-    n0, n1, n2, n3, n4, n5, n6, n7, n8, n9 = N
-    s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 = S
-
-.. code:: ipython2
-
-    import joy.library
     
-    FNs = '''ccons cons divmod_ dup dupd first
-             over pm pop popd popdd popop pred
-             rest rolldown rollup rrest second
-             sqrt stack succ swaack swap swons
-             third tuck uncons'''
+    def _interpret(f, fi, fo, e):
+        new_fo, ee, _ = f(fo, e, {})
+        ee = update(FUNCTIONS, ee)  # Fix Symbols.
+        new_F = fi, new_fo
+        return _infer(ee, new_F)
     
-    FUNCTIONS = {
-        name: SymbolJoyType(name, [NEW_DEFS[name]], i)
-        for i, name in enumerate(FNs.strip().split())
-        }
-    FUNCTIONS['sum'] = SymbolJoyType('sum', [(((Ns[1], s1), s0), (n0, s0))], 100)
-    FUNCTIONS['mul'] = SymbolJoyType('mul', [
-         ((i2, (i1, s0)), (i3, s0)),
-         ((f2, (i1, s0)), (f3, s0)),
-         ((i2, (f1, s0)), (f3, s0)),
-         ((f2, (f1, s0)), (f3, s0)),
-    ], 101)
-    FUNCTIONS.update({
-        combo.__name__: CombinatorJoyType(combo.__name__, [combo], i)
-        for i, combo in enumerate((
-            joy.library.i,
-            joy.library.dip,
-            joy.library.dipd,
-            joy.library.dipdd,
-            joy.library.dupdip,
-            joy.library.b,
-            joy.library.x,
-            joy.library.infra,
-            ))
-        })
     
-    def branch_true(stack, expression, dictionary):
-        (then, (else_, (flag, stack))) = stack
-        return stack, CONCAT(then, expression), dictionary
-    
-    def branch_false(stack, expression, dictionary):
-        (then, (else_, (flag, stack))) = stack
-        return stack, CONCAT(else_, expression), dictionary
-    
-    FUNCTIONS['branch'] = CombinatorJoyType('branch', [branch_true, branch_false], 100)
-
-.. code:: ipython2
-
-    globals().update(FUNCTIONS)
-
-.. code:: ipython2
-
-    from itertools import chain
-    from joy.utils.stack import list_to_stack as l2s
-
-.. code:: ipython2
-
-    expression = l2s([n1, n2, (mul, s2), (stack, s3), dip, infra, first])
-
-.. code:: ipython2
-
-    expression
-
-
-
-
-.. parsed-literal::
-
-    (n1, (n2, ((mul, s2), ((stack, s3), (dip, (infra, (first, ())))))))
-
-
-
-.. code:: ipython2
-
-    expression = l2s([n1, n2, mul])
-
-.. code:: ipython2
-
-    expression
-
-
-
-
-.. parsed-literal::
-
-    (n1, (n2, (mul, ())))
-
-
-
-.. code:: ipython2
-
-    infer(expression)
-
-
-
-
-.. parsed-literal::
-
-    [(s1, (f1, s1)), (s1, (i1, s1))]
-
-
-
-.. code:: ipython2
-
-    infer(expression)
-
-
-
-
-.. parsed-literal::
-
-    [(s1, (f1, s1)), (s1, (i1, s1))]
-
-
-
-.. code:: ipython2
-
-    for stack_effect_comment in infer(expression):
-        print doc_from_stack_effect(*stack_effect_comment)
-
-
-.. parsed-literal::
-
-    (-- f1)
-    (-- i1)
-
-
-.. code:: ipython2
-
-    expression
-
-
-
-
-.. parsed-literal::
-
-    (n1, (n2, (mul, ())))
+    def _log_it(e, F):
+        _log.info(
+            u'%3i %s ∘ %s',
+            len(inspect_stack()),
+            doc_from_stack_effect(*F),
+            expression_to_string(e),
+            )
 
+Work in Progress
+^^^^^^^^^^^^^^^^
 
+And that brings us to current Work-In-Progress. The mixed-mode
+inferencer/interpreter ``infer()`` function seems to work well. There
+are details I should document, and the rest of the code in the
+"polytypes" module (FIXME link to its docs here!) should be explained...
+There is cruft to convert the definitions in ``DEFS`` to the new
+``SymbolJoyType`` objects, and some combinators. Here is an example of
+output from the current code :
 
 .. code:: ipython2
 
-    infer(expression)
-
-
-
-
-.. parsed-literal::
-
-    [(s1, (f1, s1)), (s1, (i1, s1))]
-
-
-
-And that brings us to current Work-In-Progress. I'm pretty hopeful that
-the mixed-mode inferencer/interpreter ``infer()`` function along with
-the ability to specify multiple implementations for the combinators will
-permit modelling of the stack effects of e.g. ``ifte``. If I can keep up
-the pace I should be able to verify that conjecture by the end of June.
+    1/0  # (Don't try to run this cell!  It's not going to work.  This is "read only" code heh..)
+    
+    logging.basicConfig(format='%(message)s', stream=sys.stdout, level=logging.INFO)
+    
+    globals().update(FUNCTIONS)
+    
+    h = infer((pred, s2), (mul, s3), (div, s4), (nullary, (bool, s5)), dipd, branch)
+    
+    print '-' * 40
+    
+    for fi, fo in h:
+        print doc_from_stack_effect(fi, fo)
+
+The numbers at the start of the lines are the current depth of the
+Python call stack. They're followed by the current computed stack effect
+(initialized to ``ID``) then the pending expression (the inference of
+the stack effect of which is the whole object of the current example.)
+
+In this example we are implementing (and inferring) ``ifte`` as
+``[nullary bool] dipd branch`` which shows off a lot of the current
+implementation in action.
+
+::
+
+      7 (--) ∘ [pred] [mul] [div] [nullary bool] dipd branch
+      8 (-- [pred ...2]) ∘ [mul] [div] [nullary bool] dipd branch
+      9 (-- [pred ...2] [mul ...3]) ∘ [div] [nullary bool] dipd branch
+     10 (-- [pred ...2] [mul ...3] [div ...4]) ∘ [nullary bool] dipd branch
+     11 (-- [pred ...2] [mul ...3] [div ...4] [nullary bool ...5]) ∘ dipd branch
+     15 (-- [pred ...5]) ∘ nullary bool [mul] [div] branch
+     19 (-- [pred ...2]) ∘ [stack] dinfrirst bool [mul] [div] branch
+     20 (-- [pred ...2] [stack ]) ∘ dinfrirst bool [mul] [div] branch
+     22 (-- [pred ...2] [stack ]) ∘ dip infra first bool [mul] [div] branch
+     26 (--) ∘ stack [pred] infra first bool [mul] [div] branch
+     29 (... -- ... [...]) ∘ [pred] infra first bool [mul] [div] branch
+     30 (... -- ... [...] [pred ...1]) ∘ infra first bool [mul] [div] branch
+     34 (--) ∘ pred s1 swaack first bool [mul] [div] branch
+     37 (n1 -- n2) ∘ [n1] swaack first bool [mul] [div] branch
+     38 (... n1 -- ... n2 [n1 ...]) ∘ swaack first bool [mul] [div] branch
+     41 (... n1 -- ... n1 [n2 ...]) ∘ first bool [mul] [div] branch
+     44 (n1 -- n1 n2) ∘ bool [mul] [div] branch
+     47 (n1 -- n1 b1) ∘ [mul] [div] branch
+     48 (n1 -- n1 b1 [mul ...1]) ∘ [div] branch
+     49 (n1 -- n1 b1 [mul ...1] [div ...2]) ∘ branch
+     53 (n1 -- n1) ∘ div
+     56 (f2 f1 -- f3) ∘ 
+     56 (i1 f1 -- f2) ∘ 
+     56 (f1 i1 -- f2) ∘ 
+     56 (i2 i1 -- f1) ∘ 
+     53 (n1 -- n1) ∘ mul
+     56 (f2 f1 -- f3) ∘ 
+     56 (i1 f1 -- f2) ∘ 
+     56 (f1 i1 -- f2) ∘ 
+     56 (i2 i1 -- i3) ∘ 
+    ----------------------------------------
+    (f2 f1 -- f3)
+    (i1 f1 -- f2)
+    (f1 i1 -- f2)
+    (i2 i1 -- f1)
+    (i2 i1 -- i3)
 
 Conclusion
 ----------
 
-(for now...)
+We built a simple type inferencer, and a kind of crude "compiler" for a
+subset of Joy functions. Then we built a more powerful inferencer that
+actually does some evaluation and explores branching code paths
 
 Work remains to be done:
 
@@ -2900,21 +2915,18 @@ Work remains to be done:
    went off and just started writing code to see if it would work. It
    does, but now I have to come back and describe here what I did.
 
-I'm starting to realize that, with the inferencer/checker/compiler
-coming along, and with the UI ready to be rewritten in Joy, I'm close to
-a time when my ephasis is going to have to shift from crunchy code stuff
-to squishy human stuff. I'm going to have to put normal people in front
-of this and see if, in fact, they *can* learn the basics of programming
-with it.
-
-The rest of this stuff is junk and/or unfinished material.
-
 Appendix: Joy in the Logical Paradigm
 -------------------------------------
 
-For this to work the type label classes have to be modified to let
-``T >= t`` succeed, where e.g. ``T`` is ``IntJoyType`` and ``t`` is
-``int``
+For *type checking* to work the type label classes have to be modified
+to let ``T >= t`` succeed, where e.g. ``T`` is ``IntJoyType`` and ``t``
+is ``int``. If you do that you can take advantage of the *logical
+relational* nature of the stack effect comments to "compute in reverse"
+as it were. There's a working demo of this at the end of the
+``polytypes`` module. But if you're interested in all that you should
+just use Prolog!
+
+Anyhow, type *checking* is a few easy steps away.
 
 .. code:: ipython2
 
@@ -2926,383 +2938,3 @@ For this to work the type label classes have to be modified to let
     AnyJoyType.__ge__ = _ge
     AnyJoyType.accept = tuple, int, float, long, str, unicode, bool, Symbol
     StackJoyType.accept = tuple
-
-.. code:: ipython2
-
-    F = infer(l2s((pop, swap, rolldown, rest, rest, cons, cons)))
-    
-    for f in F:
-        print doc_from_stack_effect(*f)
-
-
-.. parsed-literal::
-
-    ([a4 a5 .1.] a3 a2 a1 -- [a2 a3 .1.])
-
-
-.. code:: ipython2
-
-    from joy.parser import text_to_expression
-
-.. code:: ipython2
-
-    F = infer(l2s((pop, pop, pop)))
-    
-    for f in F:
-        print doc_from_stack_effect(*f)
-
-
-.. parsed-literal::
-
-    (a3 a2 a1 --)
-
-
-.. code:: ipython2
-
-    s = text_to_expression('0 1 2')
-    s
-
-
-
-
-.. parsed-literal::
-
-    (0, (1, (2, ())))
-
-
-
-.. code:: ipython2
-
-    F[0][0]
-
-
-
-
-.. parsed-literal::
-
-    (a1, (a2, (a3, s1)))
-
-
-
-.. code:: ipython2
-
-    L = unify(s, F[0][0])
-    L
-
-
-
-
-.. parsed-literal::
-
-    ()
-
-
-
-.. code:: ipython2
-
-    s = text_to_expression('0 1 2 [3 4]')
-    s
-
-
-
-
-.. parsed-literal::
-
-    (0, (1, (2, ((3, (4, ())), ()))))
-
-
-
-.. code:: ipython2
-
-    F[0][0]
-
-
-
-
-.. parsed-literal::
-
-    (a1, (a2, (a3, s1)))
-
-
-
-.. code:: ipython2
-
-    L = unify(s, F[0][0])
-    L
-
-
-
-
-.. parsed-literal::
-
-    ()
-
-
-
-.. code:: ipython2
-
-    L = unify(F[0][0], s)
-    L
-
-
-
-
-.. parsed-literal::
-
-    ()
-
-
-
-.. code:: ipython2
-
-    F[1][0]
-
-
-::
-
-
-    ---------------------------------------------------------------------------
-
-    IndexError                                Traceback (most recent call last)
-
-    <ipython-input-133-58a8e44e9cba> in <module>()
-    ----> 1 F[1][0]
-    
-
-    IndexError: list index out of range
-
-
-.. code:: ipython2
-
-    s[0]
-
-.. code:: ipython2
-
-    A[1] >= 23
-
-`Abstract Interpretation <https://en.wikipedia.org/wiki/Abstract_interpretation>`__
------------------------------------------------------------------------------------
-
-I *think* this might be sorta what I'm doing above with the ``kav()``
-function... In any event "mixed-mode" interpreters that include values
-and type variables and can track constraints, etc. will be, uh,
-super-useful. And Abstract Interpretation should be a rich source of
-ideas.
-
-Junk
-----
-
-.. code:: ipython2
-
-    class SymbolJoyType(AnyJoyType): prefix = 'F'
-    
-    W = map(SymbolJoyType, _R)
-    
-    k = S[0], ((W[1], S[2]), S[0])
-    Symbol('cons')
-    print doc_from_stack_effect(*k)
-
-
-.. code:: ipython2
-
-    dip_a = ((W[1], S[2]), (A[1], S[0]))
-
-.. code:: ipython2
-
-    d = relabel(S[0], dip_a)
-    print doc_from_stack_effect(*d)
-
-.. code:: ipython2
-
-    s = list(unify(d[1], k[1]))[0]
-    s
-
-.. code:: ipython2
-
-    j = update(s, k)
-
-.. code:: ipython2
-
-    print doc_from_stack_effect(*j)
-
-.. code:: ipython2
-
-    j
-
-.. code:: ipython2
-
-    cons
-
-.. code:: ipython2
-
-    for f in MC([k], [dup]):
-        print doc_from_stack_effect(*f)
-
-.. code:: ipython2
-
-    l = S[0], ((cons, S[2]), (A[1], S[0]))
-
-.. code:: ipython2
-
-    print doc_from_stack_effect(*l)
-
-.. code:: ipython2
-
-    
-    def dip_t(F):
-        (quote, (a1, sec)) = F[1]
-        G = F[0], sec
-        P = S[3], (a1, S[3])
-        a = [P]
-        while isinstance(quote, tuple):
-            term, quote = quote
-            a.append(term)
-        a.append(G)
-        return a[::-1]
-    
-    
-    
-
-
-.. code:: ipython2
-
-    from joy.utils.stack import iter_stack
-
-.. code:: ipython2
-
-    a, b, c = dip_t(l)
-
-.. code:: ipython2
-
-    a
-
-.. code:: ipython2
-
-    b
-
-.. code:: ipython2
-
-    c
-
-.. code:: ipython2
-
-    MC([a], [b])
-
-.. code:: ipython2
-
-    kjs = MC(MC([a], [b]), [c])
-    kjs
-
-.. code:: ipython2
-
-    print doc_from_stack_effect(*kjs[0])
-
-::
-
-    (a0 [.0.] -- [a0 .0.] a1)
-
-       a0 [.0.] a1 [cons] dip
-    ----------------------------
-       [a0 .0.] a1
-
-``concat``
-~~~~~~~~~~
-
-How to deal with ``concat``?
-
-::
-
-    concat ([.0.] [.1.] -- [.0. .1.])
-
-We would like to represent this in Python somehow...
-
-.. code:: ipython2
-
-    concat = (S[0], S[1]), ((S[0], S[1]),)
-
-But this is actually ``cons`` with the first argument restricted to be a
-stack:
-
-::
-
-    ([.0.] [.1.] -- [[.0.] .1.])
-
-What we have implemented so far would actually only permit:
-
-::
-
-    ([.0.] [.1.] -- [.2.])
-
-.. code:: ipython2
-
-    concat = (S[0], S[1]), (S[2],)
-
-Which works but can lose information. Consider ``cons concat``, this is
-how much information we *could* retain:
-
-::
-
-    (1 [.0.] [.1.] -- [1 .0. .1.])
-
-As opposed to just:
-
-::
-
-    (1 [.0.] [.1.] -- [.2.])
-
-represent ``concat``
-~~~~~~~~~~~~~~~~~~~~
-
-::
-
-    ([.0.] [.1.] -- [A*(.0.) .1.])
-
-Meaning that ``A*`` on the right-hand side should all the crap from
-``.0.``.
-
-::
-
-    ([      .0.] [.1.] -- [      A* .1.])
-    ([a     .0.] [.1.] -- [a     A* .1.])
-    ([a b   .0.] [.1.] -- [a b   A* .1.])
-    ([a b c .0.] [.1.] -- [a b c A* .1.])
-
-or...
-
-::
-
-    ([       .0.] [.1.] -- [       .1.])
-    ([a      .0.] [.1.] -- [a      .1.])
-    ([a b    .0.] [.1.] -- [a b    .1.])
-    ([a b  c .0.] [.1.] -- [a b  c .1.])
-    ([a A* c .0.] [.1.] -- [a A* c .1.])
-
-::
-
-    (a, (b, S0)) . S1 = (a, (b, (A*, S1)))
-
-.. code:: ipython2
-
-    class Astar(object):
-        def __repr__(self):
-            return 'A*'
-    
-    
-    def concat(s0, s1):
-        a = []
-        while isinstance(s0, tuple):
-            term, s0 = s0
-            a.append(term)
-        assert isinstance(s0, StackJoyType), repr(s0)
-        s1 = Astar(), s1
-        for term in reversed(a):
-            s1 = term, s1
-        return s1
-
-.. code:: ipython2
-
-    a, b = (A[1], S[0]), (A[2], S[1])
-
-.. code:: ipython2
-
-    concat(a, b)
index 22e2981..6ec713c 100644 (file)
 <li><a href="joy/library.html">joy.library</a></li>
 <li><a href="joy/parser.html">joy.parser</a></li>
 <li><a href="joy/utils/generated_library.html">joy.utils.generated_library</a></li>
+<li><a href="joy/utils/polytypes.html">joy.utils.polytypes</a></li>
 <li><a href="joy/utils/pretty_print.html">joy.utils.pretty_print</a></li>
 <li><a href="joy/utils/stack.html">joy.utils.stack</a></li>
+<li><a href="joy/utils/types.html">joy.utils.types</a></li>
 </ul>
 
           </div>
index 23354be..dfa9373 100644 (file)
 <span class="s1">of == swap at</span>
 <span class="s1">product == 1 swap [*] step</span>
 <span class="s1">flatten == [] swap [concat] step</span>
-<span class="s1">unit == [] cons</span>
 <span class="s1">quoted == [unit] dip</span>
 <span class="s1">unquoted == [i] dip</span>
 <span class="s1">enstacken == stack [clear] dip</span>
 <span class="s1">anamorphism == [pop []] swap [dip swons] genrec</span>
 <span class="s1">range == [0 &lt;=] [1 - dup] anamorphism</span>
 <span class="s1">while == swap [nullary] cons dup dipd concat loop</span>
-<span class="s1">dudipd == dup dipd</span>
+<span class="s1">dupdipd == dup dipd</span>
 <span class="s1">primrec == [i] genrec</span>
 <span class="s1">step_zero == 0 roll&gt; step</span>
 <span class="s1">codireco == cons dip rest cons</span>
 <span class="s1">make_generator == [codireco] ccons</span>
-<span class="s1">ccons == cons cons</span>
 <span class="s1">&#39;&#39;&#39;</span>
+<span class="c1"># ifte == [nullary not] dipd branch</span>
+<span class="c1"># ifte == [nullary] dipd swap branch</span>
+              
+<span class="c1">##ccons == cons cons</span>
+<span class="c1">##unit == [] cons</span>
 <span class="c1">##second == rest first</span>
 <span class="c1">##third == rest rest first</span>
 <span class="c1">##swons == swap cons</span>
 <span class="c1">##  return second, (tos, stack)</span>
 
 
-<div class="viewcode-block" id="swaack"><a class="viewcode-back" href="../../library.html#joy.library.swaack">[docs]</a><span class="nd">@inscribe</span>
-<span class="nd">@SimpleFunctionWrapper</span>
-<span class="k">def</span> <span class="nf">swaack</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
-  <span class="sd">&#39;&#39;&#39;swap stack&#39;&#39;&#39;</span>
-  <span class="n">old_stack</span><span class="p">,</span> <span class="n">stack</span> <span class="o">=</span> <span class="n">stack</span>
-  <span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">old_stack</span></div>
+<span class="c1">##@inscribe</span>
+<span class="c1">##@SimpleFunctionWrapper</span>
+<span class="c1">##def swaack(stack):</span>
+<span class="c1">##  &#39;&#39;&#39;swap stack&#39;&#39;&#39;</span>
+<span class="c1">##  old_stack, stack = stack</span>
+<span class="c1">##  return stack, old_stack</span>
 
 
 <span class="c1">##@inscribe</span>
index 557dd55..789b936 100644 (file)
   <span class="c1"># RuntimeError: maximum recursion depth exceeded</span>
   <span class="c1"># on quotes longer than sys.getrecursionlimit().</span>
 
-<span class="c1">##  return (quote[0], concat(quote[1], expression)) if quote else expression</span>
+  <span class="k">return</span> <span class="p">(</span><span class="n">quote</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">concat</span><span class="p">(</span><span class="n">quote</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">expression</span><span class="p">))</span> <span class="k">if</span> <span class="n">quote</span> <span class="k">else</span> <span class="n">expression</span></div>
 
   <span class="c1"># Original implementation.</span>
 
   <span class="c1"># In-lining is slightly faster (and won&#39;t break the</span>
   <span class="c1"># recursion limit on long quotes.)</span>
 
-  <span class="n">temp</span> <span class="o">=</span> <span class="p">[]</span>
-  <span class="k">while</span> <span class="n">quote</span><span class="p">:</span>
-    <span class="n">item</span><span class="p">,</span> <span class="n">quote</span> <span class="o">=</span> <span class="n">quote</span>
-    <span class="n">temp</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
-  <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">temp</span><span class="p">):</span>
-    <span class="n">expression</span> <span class="o">=</span> <span class="n">item</span><span class="p">,</span> <span class="n">expression</span>
-  <span class="k">return</span> <span class="n">expression</span></div>
+<span class="c1">##  temp = []</span>
+<span class="c1">##  while quote:</span>
+<span class="c1">##    item, quote = quote</span>
+<span class="c1">##    temp.append(item)</span>
+<span class="c1">##  for item in reversed(temp):</span>
+<span class="c1">##    expression = item, expression</span>
+<span class="c1">##  return expression</span>
 
 
 
index ab0c360..781c7ad 100644 (file)
@@ -98,6 +98,7 @@ The following is specific information for this dialect of Joy.
    pretty
    library
    lib
+   types
    notebooks/index
 
 
index 09b0294..1375dcb 100644 (file)
  | <a href="#H"><strong>H</strong></a>
  | <a href="#I"><strong>I</strong></a>
  | <a href="#J"><strong>J</strong></a>
+ | <a href="#K"><strong>K</strong></a>
  | <a href="#L"><strong>L</strong></a>
  | <a href="#M"><strong>M</strong></a>
+ | <a href="#N"><strong>N</strong></a>
  | <a href="#O"><strong>O</strong></a>
  | <a href="#P"><strong>P</strong></a>
  | <a href="#R"><strong>R</strong></a>
 </li>
       <li><a href="library.html#joy.library.DefinitionWrapper.add_definitions">add_definitions() (joy.library.DefinitionWrapper class method)</a>
 </li>
+      <li><a href="types.html#joy.utils.types.AnyJoyType">AnyJoyType (class in joy.utils.types)</a>
+</li>
   </ul></td>
   <td style="width: 33%; vertical-align: top;"><ul>
+      <li><a href="types.html#joy.utils.polytypes.AnyStarJoyType">AnyStarJoyType (class in joy.utils.polytypes)</a>
+</li>
       <li><a href="library.html#joy.library.app1">app1() (in module joy.library)</a>
 </li>
       <li><a href="library.html#joy.library.app2">app2() (in module joy.library)</a>
   <td style="width: 33%; vertical-align: top;"><ul>
       <li><a href="library.html#joy.library.b">b() (in module joy.library)</a>
 </li>
+      <li><a href="library.html#joy.library.BinaryBuiltinWrapper">BinaryBuiltinWrapper() (in module joy.library)</a>
+</li>
   </ul></td>
   <td style="width: 33%; vertical-align: top;"><ul>
-      <li><a href="library.html#joy.library.BinaryBuiltinWrapper">BinaryBuiltinWrapper() (in module joy.library)</a>
+      <li><a href="types.html#joy.utils.types.BooleanJoyType">BooleanJoyType (class in joy.utils.types)</a>
 </li>
       <li><a href="library.html#joy.library.branch">branch() (in module joy.library)</a>
 </li>
 </li>
       <li><a href="library.html#joy.library.cmp_">cmp_() (in module joy.library)</a>
 </li>
+      <li><a href="types.html#joy.utils.polytypes.CombinatorJoyType">CombinatorJoyType (class in joy.utils.polytypes)</a>
+</li>
+      <li><a href="types.html#joy.utils.types.compilable">compilable() (in module joy.utils.types)</a>
+</li>
   </ul></td>
   <td style="width: 33%; vertical-align: top;"><ul>
+      <li><a href="types.html#joy.utils.types.compile_">compile_() (in module joy.utils.types)</a>
+</li>
+      <li><a href="types.html#joy.utils.polytypes.compose">compose() (in module joy.utils.polytypes)</a>
+
+      <ul>
+        <li><a href="types.html#joy.utils.types.compose">(in module joy.utils.types)</a>
+</li>
+      </ul></li>
       <li><a href="stack.html#joy.utils.stack.concat">concat() (in module joy.utils.stack)</a>
 </li>
       <li><a href="library.html#joy.library.concat_">concat_() (in module joy.library)</a>
   <td style="width: 33%; vertical-align: top;"><ul>
       <li><a href="library.html#joy.library.DefinitionWrapper">DefinitionWrapper (class in joy.library)</a>
 </li>
+      <li><a href="types.html#joy.utils.polytypes.defs">defs() (in module joy.utils.polytypes)</a>
+
+      <ul>
+        <li><a href="types.html#joy.utils.types.defs">(in module joy.utils.types)</a>
+</li>
+      </ul></li>
+      <li><a href="types.html#joy.utils.types.delabel">delabel() (in module joy.utils.types)</a>
+</li>
       <li><a href="library.html#joy.library.dip">dip() (in module joy.library)</a>
 </li>
       <li><a href="library.html#joy.library.dipd">dipd() (in module joy.library)</a>
 </li>
       <li><a href="library.html#joy.library.dipdd">dipdd() (in module joy.library)</a>
 </li>
-      <li><a href="library.html#joy.library.divmod_">divmod_() (in module joy.library)</a>
-</li>
   </ul></td>
   <td style="width: 33%; vertical-align: top;"><ul>
+      <li><a href="library.html#joy.library.divmod_">divmod_() (in module joy.library)</a>
+</li>
+      <li><a href="types.html#joy.utils.types.doc_from_stack_effect">doc_from_stack_effect() (in module joy.utils.types)</a>
+</li>
       <li><a href="library.html#joy.library.drop">drop() (in module joy.library)</a>
 </li>
       <li><a href="library.html#joy.utils.generated_library.dup">dup() (in module joy.utils.generated_library)</a>
 </li>
       <li><a href="library.html#joy.utils.generated_library.first_two">first_two() (in module joy.utils.generated_library)</a>
 </li>
+      <li><a href="types.html#joy.utils.types.FloatJoyType">FloatJoyType (class in joy.utils.types)</a>
+</li>
   </ul></td>
   <td style="width: 33%; vertical-align: top;"><ul>
       <li><a href="library.html#joy.library.floor">floor() (in module joy.library)</a>
 </li>
       <li><a href="library.html#joy.utils.generated_library.fourth">fourth() (in module joy.utils.generated_library)</a>
 </li>
+      <li><a href="types.html#joy.utils.polytypes.FunctionJoyType">FunctionJoyType (class in joy.utils.polytypes)</a>
+</li>
       <li><a href="library.html#joy.library.FunctionWrapper">FunctionWrapper() (in module joy.library)</a>
 </li>
   </ul></td>
 </li>
       <li><a href="library.html#joy.library.ifte">ifte() (in module joy.library)</a>
 </li>
-  </ul></td>
-  <td style="width: 33%; vertical-align: top;"><ul>
+      <li><a href="types.html#joy.utils.polytypes.infer">infer() (in module joy.utils.polytypes)</a>
+</li>
       <li><a href="library.html#joy.library.infra">infra() (in module joy.library)</a>
 </li>
+  </ul></td>
+  <td style="width: 33%; vertical-align: top;"><ul>
       <li><a href="library.html#joy.library.initialize">initialize() (in module joy.library)</a>
 </li>
       <li><a href="library.html#joy.library.inscribe">inscribe() (in module joy.library)</a>
 </li>
+      <li><a href="types.html#joy.utils.polytypes.IntJoyType">IntJoyType (class in joy.utils.polytypes)</a>
+
+      <ul>
+        <li><a href="types.html#joy.utils.types.IntJoyType">(class in joy.utils.types)</a>
+</li>
+      </ul></li>
       <li><a href="stack.html#joy.utils.stack.iter_stack">iter_stack() (in module joy.utils.stack)</a>
 </li>
   </ul></td>
 </li>
       <li><a href="library.html#module-joy.library">joy.library (module)</a>
 </li>
-  </ul></td>
-  <td style="width: 33%; vertical-align: top;"><ul>
       <li><a href="parser.html#module-joy.parser">joy.parser (module)</a>
 </li>
       <li><a href="library.html#module-joy.utils.generated_library">joy.utils.generated_library (module)</a>
 </li>
+  </ul></td>
+  <td style="width: 33%; vertical-align: top;"><ul>
+      <li><a href="types.html#module-joy.utils.polytypes">joy.utils.polytypes (module)</a>
+</li>
       <li><a href="pretty.html#module-joy.utils.pretty_print">joy.utils.pretty_print (module)</a>
 </li>
       <li><a href="stack.html#module-joy.utils.stack">joy.utils.stack (module)</a>
 </li>
+      <li><a href="types.html#module-joy.utils.types">joy.utils.types (module)</a>
+</li>
+      <li><a href="types.html#joy.utils.types.JoyTypeError">JoyTypeError</a>
+</li>
+  </ul></td>
+</tr></table>
+
+<h2 id="K">K</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%; vertical-align: top;"><ul>
+      <li><a href="types.html#joy.utils.polytypes.AnyStarJoyType.kind">kind (joy.utils.polytypes.AnyStarJoyType attribute)</a>
+
+      <ul>
+        <li><a href="types.html#joy.utils.polytypes.KleeneStar.kind">(joy.utils.polytypes.KleeneStar attribute)</a>
+</li>
+        <li><a href="types.html#joy.utils.polytypes.NumberStarJoyType.kind">(joy.utils.polytypes.NumberStarJoyType attribute)</a>
+</li>
+        <li><a href="types.html#joy.utils.polytypes.StackStarJoyType.kind">(joy.utils.polytypes.StackStarJoyType attribute)</a>
+</li>
+      </ul></li>
+  </ul></td>
+  <td style="width: 33%; vertical-align: top;"><ul>
+      <li><a href="types.html#joy.utils.polytypes.KleeneStar">KleeneStar (class in joy.utils.polytypes)</a>
+</li>
   </ul></td>
 </tr></table>
 
   <td style="width: 33%; vertical-align: top;"><ul>
       <li><a href="library.html#joy.library.map_">map_() (in module joy.library)</a>
 </li>
+      <li><a href="library.html#joy.library.max_">max_() (in module joy.library)</a>
+</li>
   </ul></td>
   <td style="width: 33%; vertical-align: top;"><ul>
-      <li><a href="library.html#joy.library.max_">max_() (in module joy.library)</a>
+      <li><a href="types.html#joy.utils.polytypes.meta_compose">meta_compose() (in module joy.utils.polytypes)</a>
 </li>
       <li><a href="library.html#joy.library.min_">min_() (in module joy.library)</a>
 </li>
   </ul></td>
 </tr></table>
 
+<h2 id="N">N</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%; vertical-align: top;"><ul>
+      <li><a href="types.html#joy.utils.types.NumberJoyType">NumberJoyType (class in joy.utils.types)</a>
+</li>
+  </ul></td>
+  <td style="width: 33%; vertical-align: top;"><ul>
+      <li><a href="types.html#joy.utils.polytypes.NumberStarJoyType">NumberStarJoyType (class in joy.utils.polytypes)</a>
+</li>
+  </ul></td>
+</tr></table>
+
 <h2 id="O">O</h2>
 <table style="width: 100%" class="indextable genindextable"><tr>
   <td style="width: 33%; vertical-align: top;"><ul>
 <h2 id="R">R</h2>
 <table style="width: 100%" class="indextable genindextable"><tr>
   <td style="width: 33%; vertical-align: top;"><ul>
+      <li><a href="types.html#joy.utils.types.relabel">relabel() (in module joy.utils.types)</a>
+</li>
       <li><a href="library.html#joy.library.remove">remove() (in module joy.library)</a>
 </li>
       <li><a href="joy.html#joy.joy.repl">repl() (in module joy.joy)</a>
 </li>
       <li><a href="library.html#joy.utils.generated_library.rest">rest() (in module joy.utils.generated_library)</a>
 </li>
-      <li><a href="library.html#joy.library.reverse">reverse() (in module joy.library)</a>
-</li>
   </ul></td>
   <td style="width: 33%; vertical-align: top;"><ul>
+      <li><a href="library.html#joy.library.reverse">reverse() (in module joy.library)</a>
+</li>
       <li><a href="library.html#joy.utils.generated_library.rolldown">rolldown() (in module joy.utils.generated_library)</a>
 </li>
       <li><a href="library.html#joy.utils.generated_library.rollup">rollup() (in module joy.utils.generated_library)</a>
 </li>
       <li><a href="library.html#joy.library.sqrt">sqrt() (in module joy.library)</a>
 </li>
+      <li><a href="types.html#joy.utils.polytypes.Ss">Ss (in module joy.utils.polytypes)</a>
+</li>
       <li><a href="library.html#joy.utils.generated_library.stack">stack() (in module joy.utils.generated_library)</a>
 </li>
       <li><a href="stack.html#joy.utils.stack.stack_to_string">stack_to_string() (in module joy.utils.stack)</a>
 </li>
+      <li><a href="types.html#joy.utils.types.StackJoyType">StackJoyType (class in joy.utils.types)</a>
+</li>
   </ul></td>
   <td style="width: 33%; vertical-align: top;"><ul>
+      <li><a href="types.html#joy.utils.polytypes.StackStarJoyType">StackStarJoyType (class in joy.utils.polytypes)</a>
+</li>
       <li><a href="library.html#joy.library.step">step() (in module joy.library)</a>
 </li>
       <li><a href="library.html#joy.utils.generated_library.stuncons">stuncons() (in module joy.utils.generated_library)</a>
 </li>
       <li><a href="library.html#joy.library.sum_">sum_() (in module joy.library)</a>
 </li>
-      <li><a href="library.html#joy.library.swaack">swaack() (in module joy.library)</a>
+      <li><a href="library.html#joy.utils.generated_library.swaack">swaack() (in module joy.utils.generated_library)</a>
 </li>
       <li><a href="library.html#joy.utils.generated_library.swap">swap() (in module joy.utils.generated_library)</a>
 </li>
 </li>
       <li><a href="parser.html#joy.parser.Symbol">Symbol (class in joy.parser)</a>
 </li>
+      <li><a href="types.html#joy.utils.polytypes.SymbolJoyType">SymbolJoyType (class in joy.utils.polytypes)</a>
+</li>
   </ul></td>
 </tr></table>
 
 </li>
       <li><a href="library.html#joy.utils.generated_library.uncons">uncons() (in module joy.utils.generated_library)</a>
 </li>
+      <li><a href="types.html#joy.utils.polytypes.unify">unify() (in module joy.utils.polytypes)</a>
+
+      <ul>
+        <li><a href="types.html#joy.utils.types.unify">(in module joy.utils.types)</a>
+</li>
+      </ul></li>
   </ul></td>
   <td style="width: 33%; vertical-align: top;"><ul>
       <li><a href="library.html#joy.library.unique">unique() (in module joy.library)</a>
 </li>
+      <li><a href="library.html#joy.utils.generated_library.unit">unit() (in module joy.utils.generated_library)</a>
+</li>
       <li><a href="library.html#joy.library.unstack">unstack() (in module joy.library)</a>
 </li>
       <li><a href="library.html#joy.utils.generated_library.unswons">unswons() (in module joy.utils.generated_library)</a>
 </li>
+      <li><a href="types.html#joy.utils.types.update">update() (in module joy.utils.types)</a>
+</li>
   </ul></td>
 </tr></table>
 
index b130956..65c6c76 100644 (file)
@@ -131,6 +131,11 @@ interesting aspects.  It’s quite a treasure trove.</p>
 <li class="toctree-l2"><a class="reference internal" href="lib.html#void"><code class="docutils literal notranslate"><span class="pre">void</span></code></a></li>
 </ul>
 </li>
+<li class="toctree-l1"><a class="reference internal" href="types.html">Type Inference of Joy Expressions</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="types.html#joy-utils-types"><code class="docutils literal notranslate"><span class="pre">joy.utils.types</span></code></a></li>
+<li class="toctree-l2"><a class="reference internal" href="types.html#joy-utils-polytypes"><code class="docutils literal notranslate"><span class="pre">joy.utils.polytypes</span></code></a></li>
+</ul>
+</li>
 <li class="toctree-l1"><a class="reference internal" href="notebooks/index.html">Essays about Programming in Joy</a><ul>
 <li class="toctree-l2"><a class="reference internal" href="notebooks/Developing.html">Developing a Program in Joy</a></li>
 <li class="toctree-l2"><a class="reference internal" href="notebooks/Quadratic.html">Quadratic formula</a></li>
@@ -141,7 +146,7 @@ interesting aspects.  It’s quite a treasure trove.</p>
 <li class="toctree-l2"><a class="reference internal" href="notebooks/Generator_Programs.html">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
 <li class="toctree-l2"><a class="reference internal" href="notebooks/Newton-Raphson.html">Newton’s method</a></li>
 <li class="toctree-l2"><a class="reference internal" href="notebooks/Zipper.html">Traversing Datastructures with Zippers</a></li>
-<li class="toctree-l2"><a class="reference internal" href="notebooks/Types.html">Type Inference</a></li>
+<li class="toctree-l2"><a class="reference internal" href="notebooks/Types.html">The Blissful Elegance of Typing Joy</a></li>
 <li class="toctree-l2"><a class="reference internal" href="notebooks/NoUpdates.html">No Updates</a></li>
 <li class="toctree-l2"><a class="reference internal" href="notebooks/Categorical.html">Categorical Programming</a></li>
 </ul>
index 86ff1a4..bf08515 100644 (file)
@@ -613,12 +613,6 @@ on top of the stack.</p>
 </dd></dl>
 
 <dl class="function">
-<dt id="joy.library.swaack">
-<code class="descclassname">joy.library.</code><code class="descname">swaack</code><span class="sig-paren">(</span><em>stack</em>, <em>expression</em>, <em>dictionary</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/library.html#swaack"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.library.swaack" title="Permalink to this definition">¶</a></dt>
-<dd><p>swap stack</p>
-</dd></dl>
-
-<dl class="function">
 <dt id="joy.library.take">
 <code class="descclassname">joy.library.</code><code class="descname">take</code><span class="sig-paren">(</span><em>stack</em>, <em>expression</em>, <em>dictionary</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/library.html#take"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.library.take" title="Permalink to this definition">¶</a></dt>
 <dd><p>Expects an integer and a quote on the stack and returns the quote with
@@ -708,7 +702,7 @@ from each list.  The smallest list sets the length of the result list.</p>
 <dl class="function">
 <dt id="joy.utils.generated_library.ccons">
 <code class="descclassname">joy.utils.generated_library.</code><code class="descname">ccons</code><span class="sig-paren">(</span><em>stack</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/generated_library.html#ccons"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.generated_library.ccons" title="Permalink to this definition">¶</a></dt>
-<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">a1</span> <span class="n">a0</span> <span class="p">[</span><span class="o">...</span><span class="mi">0</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="n">a1</span> <span class="n">a0</span> <span class="o">...</span><span class="mi">0</span><span class="p">])</span>
+<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">a2</span> <span class="n">a1</span> <span class="p">[</span><span class="o">...</span><span class="mi">1</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="n">a2</span> <span class="n">a1</span> <span class="o">...</span><span class="mi">1</span><span class="p">])</span>
 </pre></div>
 </div>
 </dd></dl>
@@ -756,7 +750,7 @@ from each list.  The smallest list sets the length of the result list.</p>
 <dl class="function">
 <dt id="joy.utils.generated_library.first_two">
 <code class="descclassname">joy.utils.generated_library.</code><code class="descname">first_two</code><span class="sig-paren">(</span><em>stack</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/generated_library.html#first_two"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.generated_library.first_two" title="Permalink to this definition">¶</a></dt>
-<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="n">a0</span> <span class="n">a1</span> <span class="o">...</span><span class="mi">0</span><span class="p">]</span> <span class="o">--</span> <span class="n">a0</span> <span class="n">a1</span><span class="p">)</span>
+<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="n">a1</span> <span class="n">a2</span> <span class="o">...</span><span class="mi">1</span><span class="p">]</span> <span class="o">--</span> <span class="n">a1</span> <span class="n">a2</span><span class="p">)</span>
 </pre></div>
 </div>
 </dd></dl>
@@ -764,7 +758,7 @@ from each list.  The smallest list sets the length of the result list.</p>
 <dl class="function">
 <dt id="joy.utils.generated_library.fourth">
 <code class="descclassname">joy.utils.generated_library.</code><code class="descname">fourth</code><span class="sig-paren">(</span><em>stack</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/generated_library.html#fourth"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.generated_library.fourth" title="Permalink to this definition">¶</a></dt>
-<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="n">a0</span> <span class="n">a1</span> <span class="n">a2</span> <span class="n">a3</span> <span class="o">...</span><span class="mi">0</span><span class="p">]</span> <span class="o">--</span> <span class="n">a3</span><span class="p">)</span>
+<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="n">a1</span> <span class="n">a2</span> <span class="n">a3</span> <span class="n">a4</span> <span class="o">...</span><span class="mi">1</span><span class="p">]</span> <span class="o">--</span> <span class="n">a4</span><span class="p">)</span>
 </pre></div>
 </div>
 </dd></dl>
@@ -852,7 +846,7 @@ from each list.  The smallest list sets the length of the result list.</p>
 <dl class="function">
 <dt id="joy.utils.generated_library.rrest">
 <code class="descclassname">joy.utils.generated_library.</code><code class="descname">rrest</code><span class="sig-paren">(</span><em>stack</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/generated_library.html#rrest"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.generated_library.rrest" title="Permalink to this definition">¶</a></dt>
-<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="n">a0</span> <span class="n">a1</span> <span class="o">...</span><span class="mi">0</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="o">...</span><span class="mi">0</span><span class="p">])</span>
+<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="n">a1</span> <span class="n">a2</span> <span class="o">...</span><span class="mi">1</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="o">...</span><span class="mi">1</span><span class="p">])</span>
 </pre></div>
 </div>
 </dd></dl>
@@ -860,7 +854,7 @@ from each list.  The smallest list sets the length of the result list.</p>
 <dl class="function">
 <dt id="joy.utils.generated_library.second">
 <code class="descclassname">joy.utils.generated_library.</code><code class="descname">second</code><span class="sig-paren">(</span><em>stack</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/generated_library.html#second"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.generated_library.second" title="Permalink to this definition">¶</a></dt>
-<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="n">a0</span> <span class="n">a1</span> <span class="o">...</span><span class="mi">0</span><span class="p">]</span> <span class="o">--</span> <span class="n">a1</span><span class="p">)</span>
+<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="n">a1</span> <span class="n">a2</span> <span class="o">...</span><span class="mi">1</span><span class="p">]</span> <span class="o">--</span> <span class="n">a2</span><span class="p">)</span>
 </pre></div>
 </div>
 </dd></dl>
@@ -876,7 +870,7 @@ from each list.  The smallest list sets the length of the result list.</p>
 <dl class="function">
 <dt id="joy.utils.generated_library.stuncons">
 <code class="descclassname">joy.utils.generated_library.</code><code class="descname">stuncons</code><span class="sig-paren">(</span><em>stack</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/generated_library.html#stuncons"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.generated_library.stuncons" title="Permalink to this definition">¶</a></dt>
-<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="o">...</span> <span class="n">a0</span> <span class="o">--</span> <span class="o">...</span> <span class="n">a0</span> <span class="n">a0</span> <span class="p">[</span><span class="o">...</span><span class="p">])</span>
+<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="o">...</span> <span class="n">a1</span> <span class="o">--</span> <span class="o">...</span> <span class="n">a1</span> <span class="n">a1</span> <span class="p">[</span><span class="o">...</span><span class="p">])</span>
 </pre></div>
 </div>
 </dd></dl>
@@ -884,7 +878,15 @@ from each list.  The smallest list sets the length of the result list.</p>
 <dl class="function">
 <dt id="joy.utils.generated_library.stununcons">
 <code class="descclassname">joy.utils.generated_library.</code><code class="descname">stununcons</code><span class="sig-paren">(</span><em>stack</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/generated_library.html#stununcons"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.generated_library.stununcons" title="Permalink to this definition">¶</a></dt>
-<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="o">...</span> <span class="n">a1</span> <span class="n">a0</span> <span class="o">--</span> <span class="o">...</span> <span class="n">a1</span> <span class="n">a0</span> <span class="n">a0</span> <span class="n">a1</span> <span class="p">[</span><span class="o">...</span><span class="p">])</span>
+<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="o">...</span> <span class="n">a2</span> <span class="n">a1</span> <span class="o">--</span> <span class="o">...</span> <span class="n">a2</span> <span class="n">a1</span> <span class="n">a1</span> <span class="n">a2</span> <span class="p">[</span><span class="o">...</span><span class="p">])</span>
+</pre></div>
+</div>
+</dd></dl>
+
+<dl class="function">
+<dt id="joy.utils.generated_library.swaack">
+<code class="descclassname">joy.utils.generated_library.</code><code class="descname">swaack</code><span class="sig-paren">(</span><em>stack</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/generated_library.html#swaack"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.generated_library.swaack" title="Permalink to this definition">¶</a></dt>
+<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="o">...</span><span class="mi">1</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="o">...</span><span class="mi">0</span><span class="p">])</span>
 </pre></div>
 </div>
 </dd></dl>
@@ -900,7 +902,7 @@ from each list.  The smallest list sets the length of the result list.</p>
 <dl class="function">
 <dt id="joy.utils.generated_library.swons">
 <code class="descclassname">joy.utils.generated_library.</code><code class="descname">swons</code><span class="sig-paren">(</span><em>stack</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/generated_library.html#swons"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.generated_library.swons" title="Permalink to this definition">¶</a></dt>
-<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="o">...</span><span class="mi">0</span><span class="p">]</span> <span class="n">a0</span> <span class="o">--</span> <span class="p">[</span><span class="n">a0</span> <span class="o">...</span><span class="mi">0</span><span class="p">])</span>
+<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="o">...</span><span class="mi">1</span><span class="p">]</span> <span class="n">a1</span> <span class="o">--</span> <span class="p">[</span><span class="n">a1</span> <span class="o">...</span><span class="mi">1</span><span class="p">])</span>
 </pre></div>
 </div>
 </dd></dl>
@@ -908,7 +910,7 @@ from each list.  The smallest list sets the length of the result list.</p>
 <dl class="function">
 <dt id="joy.utils.generated_library.third">
 <code class="descclassname">joy.utils.generated_library.</code><code class="descname">third</code><span class="sig-paren">(</span><em>stack</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/generated_library.html#third"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.generated_library.third" title="Permalink to this definition">¶</a></dt>
-<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="n">a0</span> <span class="n">a1</span> <span class="n">a2</span> <span class="o">...</span><span class="mi">0</span><span class="p">]</span> <span class="o">--</span> <span class="n">a2</span><span class="p">)</span>
+<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="n">a1</span> <span class="n">a2</span> <span class="n">a3</span> <span class="o">...</span><span class="mi">1</span><span class="p">]</span> <span class="o">--</span> <span class="n">a3</span><span class="p">)</span>
 </pre></div>
 </div>
 </dd></dl>
@@ -930,9 +932,17 @@ from each list.  The smallest list sets the length of the result list.</p>
 </dd></dl>
 
 <dl class="function">
+<dt id="joy.utils.generated_library.unit">
+<code class="descclassname">joy.utils.generated_library.</code><code class="descname">unit</code><span class="sig-paren">(</span><em>stack</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/generated_library.html#unit"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.generated_library.unit" title="Permalink to this definition">¶</a></dt>
+<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">a1</span> <span class="o">--</span> <span class="p">[</span><span class="n">a1</span> <span class="p">])</span>
+</pre></div>
+</div>
+</dd></dl>
+
+<dl class="function">
 <dt id="joy.utils.generated_library.unswons">
 <code class="descclassname">joy.utils.generated_library.</code><code class="descname">unswons</code><span class="sig-paren">(</span><em>stack</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/generated_library.html#unswons"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.generated_library.unswons" title="Permalink to this definition">¶</a></dt>
-<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="n">a0</span> <span class="o">...</span><span class="mi">0</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="o">...</span><span class="mi">0</span><span class="p">]</span> <span class="n">a0</span><span class="p">)</span>
+<dd><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="n">a1</span> <span class="o">...</span><span class="mi">1</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="o">...</span><span class="mi">1</span><span class="p">]</span> <span class="n">a1</span><span class="p">)</span>
 </pre></div>
 </div>
 </dd></dl>
index a6d4450..43070c7 100644 (file)
@@ -6,7 +6,7 @@
   <head>
     <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-    <title>Type Inference &#8212; Thun 0.2.0 documentation</title>
+    <title>The Blissful Elegance of Typing Joy &#8212; Thun 0.2.0 documentation</title>
     <link rel="stylesheet" href="../_static/alabaster.css" type="text/css" />
     <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
     <script type="text/javascript" src="../_static/documentation_options.js"></script>
@@ -32,8 +32,8 @@
         <div class="bodywrapper">
           <div class="body" role="main">
             
-  <div class="section" id="type-inference">
-<h1>Type Inference<a class="headerlink" href="#type-inference" title="Permalink to this headline">¶</a></h1>
+  <div class="section" id="the-blissful-elegance-of-typing-joy">
+<h1>The Blissful Elegance of Typing Joy<a class="headerlink" href="#the-blissful-elegance-of-typing-joy" title="Permalink to this headline">¶</a></h1>
 <p>This notebook presents a simple type inferencer for Joy code. It can
 infer the stack effect of most Joy expressions. It’s built largely by
 means of existing ideas and research. (A great overview of the existing
@@ -410,6 +410,8 @@ integers or tuples of type descriptors:</p>
         <span class="n">s</span><span class="p">[</span><span class="n">u</span><span class="p">]</span> <span class="o">=</span> <span class="n">v</span>
     <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
         <span class="n">s</span><span class="p">[</span><span class="n">v</span><span class="p">]</span> <span class="o">=</span> <span class="n">u</span>
+    <span class="k">else</span><span class="p">:</span>
+        <span class="n">s</span> <span class="o">=</span> <span class="kc">False</span>
 
     <span class="k">return</span> <span class="n">s</span>
 </pre></div>
@@ -566,6 +568,9 @@ work:</p>
     <span class="nb">print</span> <span class="n">e</span>
 </pre></div>
 </div>
+<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Cannot</span> <span class="n">unify</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="ow">and</span> <span class="p">(</span><span class="mi">1001</span><span class="p">,</span> <span class="mi">1002</span><span class="p">)</span><span class="o">.</span>
+</pre></div>
+</div>
 <div class="section" id="unify-version-2">
 <h4><code class="docutils literal notranslate"><span class="pre">unify()</span></code> version 2<a class="headerlink" href="#unify-version-2" title="Permalink to this headline">¶</a></h4>
 <p>The problem is that the <code class="docutils literal notranslate"><span class="pre">unify()</span></code> function as written doesn’t handle
@@ -594,6 +599,8 @@ deal with this recursively:</p>
         <span class="n">s</span> <span class="o">=</span> <span class="n">unify</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">s</span><span class="p">)</span>
         <span class="k">if</span> <span class="n">s</span> <span class="o">!=</span> <span class="kc">False</span><span class="p">:</span>
             <span class="n">s</span> <span class="o">=</span> <span class="n">unify</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">s</span><span class="p">)</span>
+    <span class="k">else</span><span class="p">:</span>
+        <span class="n">s</span> <span class="o">=</span> <span class="kc">False</span>
 
     <span class="k">return</span> <span class="n">s</span>
 </pre></div>
@@ -1337,8 +1344,8 @@ such. Note that this is <em>not</em> a <code class="docutils literal notranslate
 </div>
 <p>(Eventually I should come back around to this becuase it’s not tooo
 difficult to exend this code to be able to compile e.g.
-<code class="docutils literal notranslate"><span class="pre">n3</span> <span class="pre">=</span> <span class="pre">mul(n1,</span> <span class="pre">n2)</span></code> for <code class="docutils literal notranslate"><span class="pre">mul</span></code> and insert it in the right place with
-the right variable names. It requires a little more support from the
+<code class="docutils literal notranslate"><span class="pre">n2</span> <span class="pre">=</span> <span class="pre">mul(n1,</span> <span class="pre">n1)</span></code> for <code class="docutils literal notranslate"><span class="pre">mul</span></code> with the right variable names and
+insert it in the right place. It requires a little more support from the
 library functions, in that we need to know to call <code class="docutils literal notranslate"><span class="pre">mul()</span></code> the Python
 function for <code class="docutils literal notranslate"><span class="pre">mul</span></code> the Joy function, but since <em>most</em> of the math
 functions (at least) are already wrappers it should be straightforward.)</p>
@@ -2065,7 +2072,7 @@ disappears:</p>
 <h2>Part VII: Typing Combinators<a class="headerlink" href="#part-vii-typing-combinators" title="Permalink to this headline">¶</a></h2>
 <p>In order to compute the stack effect of combinators you kinda have to
 have the quoted programs they expect available. In the most general
-case, the <code class="docutils literal notranslate"><span class="pre">i</span></code> combinator, you can’t say anything about its stack
+case, the <code class="docutils literal notranslate"><span class="pre">i</span></code> combinator, you can’t say anything about its stack
 effect other than it expects one quote:</p>
 <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">i</span> <span class="p">(</span><span class="o">...</span> <span class="p">[</span><span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="o">--</span> <span class="o">...</span> <span class="o">.</span><span class="mf">1.</span><span class="p">)</span>
 </pre></div>
@@ -2088,14 +2095,21 @@ effect other than it expects one quote:</p>
 </div>
 <p>Without any information about the contents of the quote we can’t say
 much about the result.</p>
-<p>I think there’s a way forward. If we convert our list of terms we are
-composing into a stack structure we can use it as a <em>Joy expression</em>,
+<div class="section" id="hybrid-inferencer-interpreter">
+<h3>Hybrid Inferencer/Interpreter<a class="headerlink" href="#hybrid-inferencer-interpreter" title="Permalink to this headline">¶</a></h3>
+<p>I think there’s a way forward. If we convert our list (of terms we are
+composing) into a stack structure we can use it as a <em>Joy expression</em>,
 then we can treat the <em>output half</em> of a function’s stack effect comment
 as a Joy interpreter stack, and just execute combinators directly. We
 can hybridize the compostition function with an interpreter to evaluate
 combinators, compose non-combinator functions, and put type variables on
 the stack. For combinators like <code class="docutils literal notranslate"><span class="pre">branch</span></code> that can have more than one
 stack effect we have to “split universes” again and return both.</p>
+<div class="section" id="joy-types-for-functions">
+<h4>Joy Types for Functions<a class="headerlink" href="#joy-types-for-functions" title="Permalink to this headline">¶</a></h4>
+<p>We need a type variable for Joy functions that can go in our expressions
+and be used by the hybrid inferencer/interpreter. They have to store a
+name and a list of stack effects.</p>
 <div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">FunctionJoyType</span><span class="p">(</span><span class="n">AnyJoyType</span><span class="p">):</span>
 
     <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">sec</span><span class="p">,</span> <span class="n">number</span><span class="p">):</span>
@@ -2109,159 +2123,198 @@ stack effect we have to “split universes” again and return both.</p>
 
     <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
         <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="specialized-for-simple-functions-and-combinators">
+<h4>Specialized for Simple Functions and Combinators<a class="headerlink" href="#specialized-for-simple-functions-and-combinators" title="Permalink to this headline">¶</a></h4>
+<p>For non-combinator functions the stack effects list contains stack
+effect comments (represented by pairs of cons-lists as described above.)</p>
+<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">SymbolJoyType</span><span class="p">(</span><span class="n">FunctionJoyType</span><span class="p">):</span>
+    <span class="n">prefix</span> <span class="o">=</span> <span class="s1">&#39;F&#39;</span>
+</pre></div>
+</div>
+<p>For combinators the list contains Python functions.</p>
+<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">CombinatorJoyType</span><span class="p">(</span><span class="n">FunctionJoyType</span><span class="p">):</span>
+
+    <span class="n">prefix</span> <span class="o">=</span> <span class="s1">&#39;C&#39;</span>
+
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">sec</span><span class="p">,</span> <span class="n">number</span><span class="p">,</span> <span class="n">expect</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
+        <span class="nb">super</span><span class="p">(</span><span class="n">CombinatorJoyType</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">sec</span><span class="p">,</span> <span class="n">number</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">expect</span> <span class="o">=</span> <span class="n">expect</span>
+
+    <span class="k">def</span> <span class="nf">enter_guard</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">f</span><span class="p">):</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">expect</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
+            <span class="k">return</span> <span class="n">f</span>
+        <span class="n">g</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">expect</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">expect</span>
+        <span class="n">new_f</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">compose</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">g</span><span class="p">,</span> <span class="p">()))</span>
+        <span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">new_f</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">new_f</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">new_f</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span>
+</pre></div>
+</div>
+<p>For simple combinators that have only one effect (like <code class="docutils literal notranslate"><span class="pre">dip</span></code>) you only
+need one function and it can be the combinator itself.</p>
+<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">joy.library</span>
 
+<span class="n">dip</span> <span class="o">=</span> <span class="n">CombinatorJoyType</span><span class="p">(</span><span class="s1">&#39;dip&#39;</span><span class="p">,</span> <span class="p">[</span><span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">dip</span><span class="p">],</span> <span class="mi">23</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>For combinators that can have more than one effect (like <code class="docutils literal notranslate"><span class="pre">branch</span></code>) you
+have to write functions that each implement the action of one of the
+effects.</p>
+<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">branch_true</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">):</span>
+    <span class="p">(</span><span class="n">then</span><span class="p">,</span> <span class="p">(</span><span class="n">else_</span><span class="p">,</span> <span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="n">stack</span><span class="p">)))</span> <span class="o">=</span> <span class="n">stack</span>
+    <span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">concat</span><span class="p">(</span><span class="n">then</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span>
 
-<span class="k">class</span> <span class="nc">SymbolJoyType</span><span class="p">(</span><span class="n">FunctionJoyType</span><span class="p">):</span> <span class="n">prefix</span> <span class="o">=</span> <span class="s1">&#39;F&#39;</span>
-<span class="k">class</span> <span class="nc">CombinatorJoyType</span><span class="p">(</span><span class="n">FunctionJoyType</span><span class="p">):</span> <span class="n">prefix</span> <span class="o">=</span> <span class="s1">&#39;C&#39;</span>
+<span class="k">def</span> <span class="nf">branch_false</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">):</span>
+    <span class="p">(</span><span class="n">then</span><span class="p">,</span> <span class="p">(</span><span class="n">else_</span><span class="p">,</span> <span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="n">stack</span><span class="p">)))</span> <span class="o">=</span> <span class="n">stack</span>
+    <span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">concat</span><span class="p">(</span><span class="n">else_</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span>
+
+<span class="n">branch</span> <span class="o">=</span> <span class="n">CombinatorJoyType</span><span class="p">(</span><span class="s1">&#39;branch&#39;</span><span class="p">,</span> <span class="p">[</span><span class="n">branch_true</span><span class="p">,</span> <span class="n">branch_false</span><span class="p">],</span> <span class="mi">100</span><span class="p">)</span>
 </pre></div>
 </div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">flatten</span><span class="p">(</span><span class="n">g</span><span class="p">):</span>
-    <span class="k">return</span> <span class="nb">list</span><span class="p">(</span><span class="n">chain</span><span class="o">.</span><span class="n">from_iterable</span><span class="p">(</span><span class="n">g</span><span class="p">))</span>
+<p>You can also provide an optional stack effect, input-side only, that
+will then be used as an identity function (that accepts and returns
+stacks that match the “guard” stack effect) which will be used to guard
+against type mismatches going into the evaluation of the combinator.</p>
+</div>
+<div class="section" id="infer">
+<h4><code class="docutils literal notranslate"><span class="pre">infer()</span></code><a class="headerlink" href="#infer" title="Permalink to this headline">¶</a></h4>
+<p>With those in place, we can define a function that accepts a sequence of
+Joy type variables, including ones representing functions (not just
+values), and attempts to grind out all the possible stack effects of
+that expression.</p>
+<p>One tricky thing is that type variables <em>in the expression</em> have to be
+updated along with the stack effects after doing unification or we risk
+losing useful information. This was a straightforward, if awkward,
+modification to the call structure of <code class="docutils literal notranslate"><span class="pre">meta_compose()</span></code> et. al.</p>
+<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ID</span> <span class="o">=</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>  <span class="c1"># Identity function.</span>
 
 
-<span class="n">ID</span> <span class="o">=</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>  <span class="c1"># Identity function.</span>
+<span class="k">def</span> <span class="nf">infer</span><span class="p">(</span><span class="o">*</span><span class="n">expression</span><span class="p">):</span>
+    <span class="k">return</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">_infer</span><span class="p">(</span><span class="n">list_to_stack</span><span class="p">(</span><span class="n">expression</span><span class="p">))))</span>
 
 
-<span class="k">def</span> <span class="nf">infer</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">F</span><span class="o">=</span><span class="n">ID</span><span class="p">):</span>
+<span class="k">def</span> <span class="nf">_infer</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">F</span><span class="o">=</span><span class="n">ID</span><span class="p">):</span>
+    <span class="n">_log_it</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">F</span><span class="p">)</span>
     <span class="k">if</span> <span class="ow">not</span> <span class="n">e</span><span class="p">:</span>
         <span class="k">return</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span>
 
     <span class="n">n</span><span class="p">,</span> <span class="n">e</span> <span class="o">=</span> <span class="n">e</span>
 
     <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">SymbolJoyType</span><span class="p">):</span>
-        <span class="n">res</span> <span class="o">=</span> <span class="n">flatten</span><span class="p">(</span><span class="n">infer</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">Fn</span><span class="p">)</span> <span class="k">for</span> <span class="n">Fn</span> <span class="ow">in</span> <span class="n">MC</span><span class="p">([</span><span class="n">F</span><span class="p">],</span> <span class="n">n</span><span class="o">.</span><span class="n">stack_effects</span><span class="p">))</span>
+        <span class="n">eFG</span> <span class="o">=</span> <span class="n">meta_compose</span><span class="p">([</span><span class="n">F</span><span class="p">],</span> <span class="n">n</span><span class="o">.</span><span class="n">stack_effects</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span>
+        <span class="n">res</span> <span class="o">=</span> <span class="n">flatten</span><span class="p">(</span><span class="n">_infer</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">Fn</span><span class="p">)</span> <span class="k">for</span> <span class="n">e</span><span class="p">,</span> <span class="n">Fn</span> <span class="ow">in</span> <span class="n">eFG</span><span class="p">)</span>
 
     <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">CombinatorJoyType</span><span class="p">):</span>
-        <span class="n">res</span> <span class="o">=</span> <span class="p">[]</span>
-        <span class="k">for</span> <span class="n">combinator</span> <span class="ow">in</span> <span class="n">n</span><span class="o">.</span><span class="n">stack_effects</span><span class="p">:</span>
-            <span class="n">fi</span><span class="p">,</span> <span class="n">fo</span> <span class="o">=</span> <span class="n">F</span>
-            <span class="n">new_fo</span><span class="p">,</span> <span class="n">ee</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">combinator</span><span class="p">(</span><span class="n">fo</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="p">{})</span>
-            <span class="n">ee</span> <span class="o">=</span> <span class="n">update</span><span class="p">(</span><span class="n">FUNCTIONS</span><span class="p">,</span> <span class="n">ee</span><span class="p">)</span>  <span class="c1"># Fix Symbols.</span>
-            <span class="n">new_F</span> <span class="o">=</span> <span class="n">fi</span><span class="p">,</span> <span class="n">new_fo</span>
-            <span class="n">res</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">infer</span><span class="p">(</span><span class="n">ee</span><span class="p">,</span> <span class="n">new_F</span><span class="p">))</span>
+        <span class="n">fi</span><span class="p">,</span> <span class="n">fo</span> <span class="o">=</span> <span class="n">n</span><span class="o">.</span><span class="n">enter_guard</span><span class="p">(</span><span class="n">F</span><span class="p">)</span>
+        <span class="n">res</span> <span class="o">=</span> <span class="n">flatten</span><span class="p">(</span><span class="n">_interpret</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">fi</span><span class="p">,</span> <span class="n">fo</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">n</span><span class="o">.</span><span class="n">stack_effects</span><span class="p">)</span>
+
+    <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">Symbol</span><span class="p">):</span>
+        <span class="k">assert</span> <span class="n">n</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">FUNCTIONS</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
+        <span class="n">func</span> <span class="o">=</span> <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">_dictionary</span><span class="p">[</span><span class="n">n</span><span class="p">]</span>
+        <span class="n">res</span> <span class="o">=</span> <span class="n">_interpret</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">F</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">F</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">e</span><span class="p">)</span>
+
     <span class="k">else</span><span class="p">:</span>
-        <span class="n">lit</span> <span class="o">=</span> <span class="n">s9</span><span class="p">,</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">s9</span><span class="p">)</span>
-        <span class="n">res</span> <span class="o">=</span> <span class="n">flatten</span><span class="p">(</span><span class="n">infer</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">Fn</span><span class="p">)</span> <span class="k">for</span> <span class="n">Fn</span> <span class="ow">in</span> <span class="n">MC</span><span class="p">([</span><span class="n">F</span><span class="p">],</span> <span class="p">[</span><span class="n">lit</span><span class="p">]))</span>
+        <span class="n">fi</span><span class="p">,</span> <span class="n">fo</span> <span class="o">=</span> <span class="n">F</span>
+        <span class="n">res</span> <span class="o">=</span> <span class="n">_infer</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="p">(</span><span class="n">fi</span><span class="p">,</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">fo</span><span class="p">)))</span>
 
     <span class="k">return</span> <span class="n">res</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">f0</span><span class="p">,</span> <span class="n">f1</span><span class="p">,</span> <span class="n">f2</span><span class="p">,</span> <span class="n">f3</span><span class="p">,</span> <span class="n">f4</span><span class="p">,</span> <span class="n">f5</span><span class="p">,</span> <span class="n">f6</span><span class="p">,</span> <span class="n">f7</span><span class="p">,</span> <span class="n">f8</span><span class="p">,</span> <span class="n">f9</span> <span class="o">=</span> <span class="n">F</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="n">FloatJoyType</span><span class="p">,</span> <span class="n">_R</span><span class="p">)</span>
-<span class="n">i0</span><span class="p">,</span> <span class="n">i1</span><span class="p">,</span> <span class="n">i2</span><span class="p">,</span> <span class="n">i3</span><span class="p">,</span> <span class="n">i4</span><span class="p">,</span> <span class="n">i5</span><span class="p">,</span> <span class="n">i6</span><span class="p">,</span> <span class="n">i7</span><span class="p">,</span> <span class="n">i8</span><span class="p">,</span> <span class="n">i9</span> <span class="o">=</span> <span class="n">I</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="n">IntJoyType</span><span class="p">,</span> <span class="n">_R</span><span class="p">)</span>
-<span class="n">n0</span><span class="p">,</span> <span class="n">n1</span><span class="p">,</span> <span class="n">n2</span><span class="p">,</span> <span class="n">n3</span><span class="p">,</span> <span class="n">n4</span><span class="p">,</span> <span class="n">n5</span><span class="p">,</span> <span class="n">n6</span><span class="p">,</span> <span class="n">n7</span><span class="p">,</span> <span class="n">n8</span><span class="p">,</span> <span class="n">n9</span> <span class="o">=</span> <span class="n">N</span>
-<span class="n">s0</span><span class="p">,</span> <span class="n">s1</span><span class="p">,</span> <span class="n">s2</span><span class="p">,</span> <span class="n">s3</span><span class="p">,</span> <span class="n">s4</span><span class="p">,</span> <span class="n">s5</span><span class="p">,</span> <span class="n">s6</span><span class="p">,</span> <span class="n">s7</span><span class="p">,</span> <span class="n">s8</span><span class="p">,</span> <span class="n">s9</span> <span class="o">=</span> <span class="n">S</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">joy.library</span>
 
-<span class="n">FNs</span> <span class="o">=</span> <span class="s1">&#39;&#39;&#39;ccons cons divmod_ dup dupd first</span>
-<span class="s1">         over pm pop popd popdd popop pred</span>
-<span class="s1">         rest rolldown rollup rrest second</span>
-<span class="s1">         sqrt stack succ swaack swap swons</span>
-<span class="s1">         third tuck uncons&#39;&#39;&#39;</span>
 
-<span class="n">FUNCTIONS</span> <span class="o">=</span> <span class="p">{</span>
-    <span class="n">name</span><span class="p">:</span> <span class="n">SymbolJoyType</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="p">[</span><span class="n">NEW_DEFS</span><span class="p">[</span><span class="n">name</span><span class="p">]],</span> <span class="n">i</span><span class="p">)</span>
-    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">name</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">FNs</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">())</span>
-    <span class="p">}</span>
-<span class="n">FUNCTIONS</span><span class="p">[</span><span class="s1">&#39;sum&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">SymbolJoyType</span><span class="p">(</span><span class="s1">&#39;sum&#39;</span><span class="p">,</span> <span class="p">[(((</span><span class="n">Ns</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">s1</span><span class="p">),</span> <span class="n">s0</span><span class="p">),</span> <span class="p">(</span><span class="n">n0</span><span class="p">,</span> <span class="n">s0</span><span class="p">))],</span> <span class="mi">100</span><span class="p">)</span>
-<span class="n">FUNCTIONS</span><span class="p">[</span><span class="s1">&#39;mul&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">SymbolJoyType</span><span class="p">(</span><span class="s1">&#39;mul&#39;</span><span class="p">,</span> <span class="p">[</span>
-     <span class="p">((</span><span class="n">i2</span><span class="p">,</span> <span class="p">(</span><span class="n">i1</span><span class="p">,</span> <span class="n">s0</span><span class="p">)),</span> <span class="p">(</span><span class="n">i3</span><span class="p">,</span> <span class="n">s0</span><span class="p">)),</span>
-     <span class="p">((</span><span class="n">f2</span><span class="p">,</span> <span class="p">(</span><span class="n">i1</span><span class="p">,</span> <span class="n">s0</span><span class="p">)),</span> <span class="p">(</span><span class="n">f3</span><span class="p">,</span> <span class="n">s0</span><span class="p">)),</span>
-     <span class="p">((</span><span class="n">i2</span><span class="p">,</span> <span class="p">(</span><span class="n">f1</span><span class="p">,</span> <span class="n">s0</span><span class="p">)),</span> <span class="p">(</span><span class="n">f3</span><span class="p">,</span> <span class="n">s0</span><span class="p">)),</span>
-     <span class="p">((</span><span class="n">f2</span><span class="p">,</span> <span class="p">(</span><span class="n">f1</span><span class="p">,</span> <span class="n">s0</span><span class="p">)),</span> <span class="p">(</span><span class="n">f3</span><span class="p">,</span> <span class="n">s0</span><span class="p">)),</span>
-<span class="p">],</span> <span class="mi">101</span><span class="p">)</span>
-<span class="n">FUNCTIONS</span><span class="o">.</span><span class="n">update</span><span class="p">({</span>
-    <span class="n">combo</span><span class="o">.</span><span class="vm">__name__</span><span class="p">:</span> <span class="n">CombinatorJoyType</span><span class="p">(</span><span class="n">combo</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="p">[</span><span class="n">combo</span><span class="p">],</span> <span class="n">i</span><span class="p">)</span>
-    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">combo</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">((</span>
-        <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">i</span><span class="p">,</span>
-        <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">dip</span><span class="p">,</span>
-        <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">dipd</span><span class="p">,</span>
-        <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">dipdd</span><span class="p">,</span>
-        <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">dupdip</span><span class="p">,</span>
-        <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">b</span><span class="p">,</span>
-        <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">x</span><span class="p">,</span>
-        <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">infra</span><span class="p">,</span>
-        <span class="p">))</span>
-    <span class="p">})</span>
-
-<span class="k">def</span> <span class="nf">branch_true</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">):</span>
-    <span class="p">(</span><span class="n">then</span><span class="p">,</span> <span class="p">(</span><span class="n">else_</span><span class="p">,</span> <span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="n">stack</span><span class="p">)))</span> <span class="o">=</span> <span class="n">stack</span>
-    <span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">CONCAT</span><span class="p">(</span><span class="n">then</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span>
+<span class="k">def</span> <span class="nf">_interpret</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">fi</span><span class="p">,</span> <span class="n">fo</span><span class="p">,</span> <span class="n">e</span><span class="p">):</span>
+    <span class="n">new_fo</span><span class="p">,</span> <span class="n">ee</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">fo</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="p">{})</span>
+    <span class="n">ee</span> <span class="o">=</span> <span class="n">update</span><span class="p">(</span><span class="n">FUNCTIONS</span><span class="p">,</span> <span class="n">ee</span><span class="p">)</span>  <span class="c1"># Fix Symbols.</span>
+    <span class="n">new_F</span> <span class="o">=</span> <span class="n">fi</span><span class="p">,</span> <span class="n">new_fo</span>
+    <span class="k">return</span> <span class="n">_infer</span><span class="p">(</span><span class="n">ee</span><span class="p">,</span> <span class="n">new_F</span><span class="p">)</span>
 
-<span class="k">def</span> <span class="nf">branch_false</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">):</span>
-    <span class="p">(</span><span class="n">then</span><span class="p">,</span> <span class="p">(</span><span class="n">else_</span><span class="p">,</span> <span class="p">(</span><span class="n">flag</span><span class="p">,</span> <span class="n">stack</span><span class="p">)))</span> <span class="o">=</span> <span class="n">stack</span>
-    <span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">CONCAT</span><span class="p">(</span><span class="n">else_</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span>
 
-<span class="n">FUNCTIONS</span><span class="p">[</span><span class="s1">&#39;branch&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">CombinatorJoyType</span><span class="p">(</span><span class="s1">&#39;branch&#39;</span><span class="p">,</span> <span class="p">[</span><span class="n">branch_true</span><span class="p">,</span> <span class="n">branch_false</span><span class="p">],</span> <span class="mi">100</span><span class="p">)</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">globals</span><span class="p">()</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">FUNCTIONS</span><span class="p">)</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">itertools</span> <span class="k">import</span> <span class="n">chain</span>
-<span class="kn">from</span> <span class="nn">joy.utils.stack</span> <span class="k">import</span> <span class="n">list_to_stack</span> <span class="k">as</span> <span class="n">l2s</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">expression</span> <span class="o">=</span> <span class="n">l2s</span><span class="p">([</span><span class="n">n1</span><span class="p">,</span> <span class="n">n2</span><span class="p">,</span> <span class="p">(</span><span class="n">mul</span><span class="p">,</span> <span class="n">s2</span><span class="p">),</span> <span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">s3</span><span class="p">),</span> <span class="n">dip</span><span class="p">,</span> <span class="n">infra</span><span class="p">,</span> <span class="n">first</span><span class="p">])</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">expression</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">n1</span><span class="p">,</span> <span class="p">(</span><span class="n">n2</span><span class="p">,</span> <span class="p">((</span><span class="n">mul</span><span class="p">,</span> <span class="n">s2</span><span class="p">),</span> <span class="p">((</span><span class="n">stack</span><span class="p">,</span> <span class="n">s3</span><span class="p">),</span> <span class="p">(</span><span class="n">dip</span><span class="p">,</span> <span class="p">(</span><span class="n">infra</span><span class="p">,</span> <span class="p">(</span><span class="n">first</span><span class="p">,</span> <span class="p">())))))))</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">expression</span> <span class="o">=</span> <span class="n">l2s</span><span class="p">([</span><span class="n">n1</span><span class="p">,</span> <span class="n">n2</span><span class="p">,</span> <span class="n">mul</span><span class="p">])</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">expression</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">n1</span><span class="p">,</span> <span class="p">(</span><span class="n">n2</span><span class="p">,</span> <span class="p">(</span><span class="n">mul</span><span class="p">,</span> <span class="p">())))</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">infer</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[(</span><span class="n">s1</span><span class="p">,</span> <span class="p">(</span><span class="n">f1</span><span class="p">,</span> <span class="n">s1</span><span class="p">)),</span> <span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="p">(</span><span class="n">i1</span><span class="p">,</span> <span class="n">s1</span><span class="p">))]</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">infer</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[(</span><span class="n">s1</span><span class="p">,</span> <span class="p">(</span><span class="n">f1</span><span class="p">,</span> <span class="n">s1</span><span class="p">)),</span> <span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="p">(</span><span class="n">i1</span><span class="p">,</span> <span class="n">s1</span><span class="p">))]</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">stack_effect_comment</span> <span class="ow">in</span> <span class="n">infer</span><span class="p">(</span><span class="n">expression</span><span class="p">):</span>
-    <span class="nb">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">stack_effect_comment</span><span class="p">)</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="o">--</span> <span class="n">f1</span><span class="p">)</span>
-<span class="p">(</span><span class="o">--</span> <span class="n">i1</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">_log_it</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">F</span><span class="p">):</span>
+    <span class="n">_log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
+        <span class="sa">u</span><span class="s1">&#39;</span><span class="si">%3i</span><span class="s1"> </span><span class="si">%s</span><span class="s1"> ∘ </span><span class="si">%s</span><span class="s1">&#39;</span><span class="p">,</span>
+        <span class="nb">len</span><span class="p">(</span><span class="n">inspect_stack</span><span class="p">()),</span>
+        <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">F</span><span class="p">),</span>
+        <span class="n">expression_to_string</span><span class="p">(</span><span class="n">e</span><span class="p">),</span>
+        <span class="p">)</span>
 </pre></div>
 </div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">expression</span>
-</pre></div>
 </div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">n1</span><span class="p">,</span> <span class="p">(</span><span class="n">n2</span><span class="p">,</span> <span class="p">(</span><span class="n">mul</span><span class="p">,</span> <span class="p">())))</span>
+<div class="section" id="work-in-progress">
+<h4>Work in Progress<a class="headerlink" href="#work-in-progress" title="Permalink to this headline">¶</a></h4>
+<p>And that brings us to current Work-In-Progress. The mixed-mode
+inferencer/interpreter <code class="docutils literal notranslate"><span class="pre">infer()</span></code> function seems to work well. There
+are details I should document, and the rest of the code in the
+“polytypes” module (FIXME link to its docs here!) should be explained…
+There is cruft to convert the definitions in <code class="docutils literal notranslate"><span class="pre">DEFS</span></code> to the new
+<code class="docutils literal notranslate"><span class="pre">SymbolJoyType</span></code> objects, and some combinators. Here is an example of
+output from the current code :</p>
+<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">1</span><span class="o">/</span><span class="mi">0</span>  <span class="c1"># (Don&#39;t try to run this cell!  It&#39;s not going to work.  This is &quot;read only&quot; code heh..)</span>
+
+<span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="nb">format</span><span class="o">=</span><span class="s1">&#39;</span><span class="si">%(message)s</span><span class="s1">&#39;</span><span class="p">,</span> <span class="n">stream</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="p">,</span> <span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">INFO</span><span class="p">)</span>
+
+<span class="nb">globals</span><span class="p">()</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">FUNCTIONS</span><span class="p">)</span>
+
+<span class="n">h</span> <span class="o">=</span> <span class="n">infer</span><span class="p">((</span><span class="n">pred</span><span class="p">,</span> <span class="n">s2</span><span class="p">),</span> <span class="p">(</span><span class="n">mul</span><span class="p">,</span> <span class="n">s3</span><span class="p">),</span> <span class="p">(</span><span class="n">div</span><span class="p">,</span> <span class="n">s4</span><span class="p">),</span> <span class="p">(</span><span class="n">nullary</span><span class="p">,</span> <span class="p">(</span><span class="nb">bool</span><span class="p">,</span> <span class="n">s5</span><span class="p">)),</span> <span class="n">dipd</span><span class="p">,</span> <span class="n">branch</span><span class="p">)</span>
+
+<span class="nb">print</span> <span class="s1">&#39;-&#39;</span> <span class="o">*</span> <span class="mi">40</span>
+
+<span class="k">for</span> <span class="n">fi</span><span class="p">,</span> <span class="n">fo</span> <span class="ow">in</span> <span class="n">h</span><span class="p">:</span>
+    <span class="nb">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="n">fi</span><span class="p">,</span> <span class="n">fo</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>The numbers at the start of the lines are the current depth of the
+Python call stack. They’re followed by the current computed stack effect
+(initialized to <code class="docutils literal notranslate"><span class="pre">ID</span></code>) then the pending expression (the inference of
+the stack effect of which is the whole object of the current example.)</p>
+<p>In this example we are implementing (and inferring) <code class="docutils literal notranslate"><span class="pre">ifte</span></code> as
+<code class="docutils literal notranslate"><span class="pre">[nullary</span> <span class="pre">bool]</span> <span class="pre">dipd</span> <span class="pre">branch</span></code> which shows off a lot of the current
+implementation in action.</p>
+<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>  7 (--) ∘ [pred] [mul] [div] [nullary bool] dipd branch
+  8 (-- [pred ...2]) ∘ [mul] [div] [nullary bool] dipd branch
+  9 (-- [pred ...2] [mul ...3]) ∘ [div] [nullary bool] dipd branch
+ 10 (-- [pred ...2] [mul ...3] [div ...4]) ∘ [nullary bool] dipd branch
+ 11 (-- [pred ...2] [mul ...3] [div ...4] [nullary bool ...5]) ∘ dipd branch
+ 15 (-- [pred ...5]) ∘ nullary bool [mul] [div] branch
+ 19 (-- [pred ...2]) ∘ [stack] dinfrirst bool [mul] [div] branch
+ 20 (-- [pred ...2] [stack ]) ∘ dinfrirst bool [mul] [div] branch
+ 22 (-- [pred ...2] [stack ]) ∘ dip infra first bool [mul] [div] branch
+ 26 (--) ∘ stack [pred] infra first bool [mul] [div] branch
+ 29 (... -- ... [...]) ∘ [pred] infra first bool [mul] [div] branch
+ 30 (... -- ... [...] [pred ...1]) ∘ infra first bool [mul] [div] branch
+ 34 (--) ∘ pred s1 swaack first bool [mul] [div] branch
+ 37 (n1 -- n2) ∘ [n1] swaack first bool [mul] [div] branch
+ 38 (... n1 -- ... n2 [n1 ...]) ∘ swaack first bool [mul] [div] branch
+ 41 (... n1 -- ... n1 [n2 ...]) ∘ first bool [mul] [div] branch
+ 44 (n1 -- n1 n2) ∘ bool [mul] [div] branch
+ 47 (n1 -- n1 b1) ∘ [mul] [div] branch
+ 48 (n1 -- n1 b1 [mul ...1]) ∘ [div] branch
+ 49 (n1 -- n1 b1 [mul ...1] [div ...2]) ∘ branch
+ 53 (n1 -- n1) ∘ div
+ 56 (f2 f1 -- f3) ∘
+ 56 (i1 f1 -- f2) ∘
+ 56 (f1 i1 -- f2) ∘
+ 56 (i2 i1 -- f1) ∘
+ 53 (n1 -- n1) ∘ mul
+ 56 (f2 f1 -- f3) ∘
+ 56 (i1 f1 -- f2) ∘
+ 56 (f1 i1 -- f2) ∘
+ 56 (i2 i1 -- i3) ∘
+----------------------------------------
+(f2 f1 -- f3)
+(i1 f1 -- f2)
+(f1 i1 -- f2)
+(i2 i1 -- f1)
+(i2 i1 -- i3)
 </pre></div>
 </div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">infer</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
-</pre></div>
 </div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[(</span><span class="n">s1</span><span class="p">,</span> <span class="p">(</span><span class="n">f1</span><span class="p">,</span> <span class="n">s1</span><span class="p">)),</span> <span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="p">(</span><span class="n">i1</span><span class="p">,</span> <span class="n">s1</span><span class="p">))]</span>
-</pre></div>
 </div>
-<p>And that brings us to current Work-In-Progress. I’m pretty hopeful that
-the mixed-mode inferencer/interpreter <code class="docutils literal notranslate"><span class="pre">infer()</span></code> function along with
-the ability to specify multiple implementations for the combinators will
-permit modelling of the stack effects of e.g. <code class="docutils literal notranslate"><span class="pre">ifte</span></code>. If I can keep up
-the pace I should be able to verify that conjecture by the end of June.</p>
 </div>
 <div class="section" id="conclusion">
 <h2>Conclusion<a class="headerlink" href="#conclusion" title="Permalink to this headline">¶</a></h2>
-<p>(for now…)</p>
+<p>We built a simple type inferencer, and a kind of crude “compiler” for a
+subset of Joy functions. Then we built a more powerful inferencer that
+actually does some evaluation and explores branching code paths</p>
 <p>Work remains to be done:</p>
 <ul class="simple">
 <li>the rest of the library has to be covered</li>
@@ -2280,19 +2333,17 @@ the pace I should be able to verify that conjecture by the end of June.</p>
 went off and just started writing code to see if it would work. It
 does, but now I have to come back and describe here what I did.</li>
 </ul>
-<p>I’m starting to realize that, with the inferencer/checker/compiler
-coming along, and with the UI ready to be rewritten in Joy, I’m close to
-a time when my ephasis is going to have to shift from crunchy code stuff
-to squishy human stuff. I’m going to have to put normal people in front
-of this and see if, in fact, they <em>can</em> learn the basics of programming
-with it.</p>
-<p>The rest of this stuff is junk and/or unfinished material.</p>
 </div>
 <div class="section" id="appendix-joy-in-the-logical-paradigm">
 <h2>Appendix: Joy in the Logical Paradigm<a class="headerlink" href="#appendix-joy-in-the-logical-paradigm" title="Permalink to this headline">¶</a></h2>
-<p>For this to work the type label classes have to be modified to let
-<code class="docutils literal notranslate"><span class="pre">T</span> <span class="pre">&gt;=</span> <span class="pre">t</span></code> succeed, where e.g. <code class="docutils literal notranslate"><span class="pre">T</span></code> is <code class="docutils literal notranslate"><span class="pre">IntJoyType</span></code> and <code class="docutils literal notranslate"><span class="pre">t</span></code> is
-<code class="docutils literal notranslate"><span class="pre">int</span></code></p>
+<p>For <em>type checking</em> to work the type label classes have to be modified
+to let <code class="docutils literal notranslate"><span class="pre">T</span> <span class="pre">&gt;=</span> <span class="pre">t</span></code> succeed, where e.g. <code class="docutils literal notranslate"><span class="pre">T</span></code> is <code class="docutils literal notranslate"><span class="pre">IntJoyType</span></code> and <code class="docutils literal notranslate"><span class="pre">t</span></code>
+is <code class="docutils literal notranslate"><span class="pre">int</span></code>. If you do that you can take advantage of the <em>logical
+relational</em> nature of the stack effect comments to “compute in reverse”
+as it were. There’s a working demo of this at the end of the
+<code class="docutils literal notranslate"><span class="pre">polytypes</span></code> module. But if you’re interested in all that you should
+just use Prolog!</p>
+<p>Anyhow, type <em>checking</em> is a few easy steps away.</p>
 <div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">_ge</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
     <span class="k">return</span> <span class="p">(</span><span class="nb">issubclass</span><span class="p">(</span><span class="n">other</span><span class="o">.</span><span class="vm">__class__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">)</span>
             <span class="ow">or</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s1">&#39;accept&#39;</span><span class="p">)</span>
@@ -2303,271 +2354,6 @@ with it.</p>
 <span class="n">StackJoyType</span><span class="o">.</span><span class="n">accept</span> <span class="o">=</span> <span class="nb">tuple</span>
 </pre></div>
 </div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">F</span> <span class="o">=</span> <span class="n">infer</span><span class="p">(</span><span class="n">l2s</span><span class="p">((</span><span class="n">pop</span><span class="p">,</span> <span class="n">swap</span><span class="p">,</span> <span class="n">rolldown</span><span class="p">,</span> <span class="n">rest</span><span class="p">,</span> <span class="n">rest</span><span class="p">,</span> <span class="n">cons</span><span class="p">,</span> <span class="n">cons</span><span class="p">)))</span>
-
-<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">F</span><span class="p">:</span>
-    <span class="nb">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">f</span><span class="p">)</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="n">a4</span> <span class="n">a5</span> <span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="n">a3</span> <span class="n">a2</span> <span class="n">a1</span> <span class="o">--</span> <span class="p">[</span><span class="n">a2</span> <span class="n">a3</span> <span class="o">.</span><span class="mf">1.</span><span class="p">])</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">joy.parser</span> <span class="k">import</span> <span class="n">text_to_expression</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">F</span> <span class="o">=</span> <span class="n">infer</span><span class="p">(</span><span class="n">l2s</span><span class="p">((</span><span class="n">pop</span><span class="p">,</span> <span class="n">pop</span><span class="p">,</span> <span class="n">pop</span><span class="p">)))</span>
-
-<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">F</span><span class="p">:</span>
-    <span class="nb">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">f</span><span class="p">)</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">a3</span> <span class="n">a2</span> <span class="n">a1</span> <span class="o">--</span><span class="p">)</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">s</span> <span class="o">=</span> <span class="n">text_to_expression</span><span class="p">(</span><span class="s1">&#39;0 1 2&#39;</span><span class="p">)</span>
-<span class="n">s</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="p">())))</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">F</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="n">s1</span><span class="p">)))</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">L</span> <span class="o">=</span> <span class="n">unify</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">F</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span>
-<span class="n">L</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">()</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">s</span> <span class="o">=</span> <span class="n">text_to_expression</span><span class="p">(</span><span class="s1">&#39;0 1 2 [3 4]&#39;</span><span class="p">)</span>
-<span class="n">s</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="p">((</span><span class="mi">3</span><span class="p">,</span> <span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="p">())),</span> <span class="p">()))))</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">F</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="n">s1</span><span class="p">)))</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">L</span> <span class="o">=</span> <span class="n">unify</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">F</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span>
-<span class="n">L</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">()</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">L</span> <span class="o">=</span> <span class="n">unify</span><span class="p">(</span><span class="n">F</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span> <span class="n">s</span><span class="p">)</span>
-<span class="n">L</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">()</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">F</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">---------------------------------------------------------------------------</span>
-
-<span class="ne">IndexError</span>                                <span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">)</span>
-
-<span class="o">&lt;</span><span class="n">ipython</span><span class="o">-</span><span class="nb">input</span><span class="o">-</span><span class="mi">133</span><span class="o">-</span><span class="mi">58</span><span class="n">a8e44e9cba</span><span class="o">&gt;</span> <span class="ow">in</span> <span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span><span class="p">()</span>
-<span class="o">----&gt;</span> <span class="mi">1</span> <span class="n">F</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
-
-
-<span class="ne">IndexError</span><span class="p">:</span> <span class="nb">list</span> <span class="n">index</span> <span class="n">out</span> <span class="n">of</span> <span class="nb">range</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">s</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">A</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">23</span>
-</pre></div>
-</div>
-</div>
-<div class="section" id="abstract-interpretation">
-<h2><a class="reference external" href="https://en.wikipedia.org/wiki/Abstract_interpretation">Abstract Interpretation</a><a class="headerlink" href="#abstract-interpretation" title="Permalink to this headline">¶</a></h2>
-<p>I <em>think</em> this might be sorta what I’m doing above with the <code class="docutils literal notranslate"><span class="pre">kav()</span></code>
-function… In any event “mixed-mode” interpreters that include values
-and type variables and can track constraints, etc. will be, uh,
-super-useful. And Abstract Interpretation should be a rich source of
-ideas.</p>
-</div>
-<div class="section" id="junk">
-<h2>Junk<a class="headerlink" href="#junk" title="Permalink to this headline">¶</a></h2>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">SymbolJoyType</span><span class="p">(</span><span class="n">AnyJoyType</span><span class="p">):</span> <span class="n">prefix</span> <span class="o">=</span> <span class="s1">&#39;F&#39;</span>
-
-<span class="n">W</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="n">SymbolJoyType</span><span class="p">,</span> <span class="n">_R</span><span class="p">)</span>
-
-<span class="n">k</span> <span class="o">=</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="p">((</span><span class="n">W</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">2</span><span class="p">]),</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
-<span class="n">Symbol</span><span class="p">(</span><span class="s1">&#39;cons&#39;</span><span class="p">)</span>
-<span class="nb">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">k</span><span class="p">)</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">dip_a</span> <span class="o">=</span> <span class="p">((</span><span class="n">W</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">2</span><span class="p">]),</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">d</span> <span class="o">=</span> <span class="n">relabel</span><span class="p">(</span><span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">dip_a</span><span class="p">)</span>
-<span class="nb">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">d</span><span class="p">)</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">s</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">unify</span><span class="p">(</span><span class="n">d</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">k</span><span class="p">[</span><span class="mi">1</span><span class="p">]))[</span><span class="mi">0</span><span class="p">]</span>
-<span class="n">s</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">j</span> <span class="o">=</span> <span class="n">update</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">k</span><span class="p">)</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">j</span><span class="p">)</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">j</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">cons</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">MC</span><span class="p">([</span><span class="n">k</span><span class="p">],</span> <span class="p">[</span><span class="n">dup</span><span class="p">]):</span>
-    <span class="nb">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">f</span><span class="p">)</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">l</span> <span class="o">=</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="p">((</span><span class="n">cons</span><span class="p">,</span> <span class="n">S</span><span class="p">[</span><span class="mi">2</span><span class="p">]),</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">l</span><span class="p">)</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">dip_t</span><span class="p">(</span><span class="n">F</span><span class="p">):</span>
-    <span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">sec</span><span class="p">))</span> <span class="o">=</span> <span class="n">F</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
-    <span class="n">G</span> <span class="o">=</span> <span class="n">F</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">sec</span>
-    <span class="n">P</span> <span class="o">=</span> <span class="n">S</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">S</span><span class="p">[</span><span class="mi">3</span><span class="p">])</span>
-    <span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span>
-    <span class="k">while</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
-        <span class="n">term</span><span class="p">,</span> <span class="n">quote</span> <span class="o">=</span> <span class="n">quote</span>
-        <span class="n">a</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">term</span><span class="p">)</span>
-    <span class="n">a</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">G</span><span class="p">)</span>
-    <span class="k">return</span> <span class="n">a</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">joy.utils.stack</span> <span class="k">import</span> <span class="n">iter_stack</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span> <span class="o">=</span> <span class="n">dip_t</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">c</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">MC</span><span class="p">([</span><span class="n">a</span><span class="p">],</span> <span class="p">[</span><span class="n">b</span><span class="p">])</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">kjs</span> <span class="o">=</span> <span class="n">MC</span><span class="p">(</span><span class="n">MC</span><span class="p">([</span><span class="n">a</span><span class="p">],</span> <span class="p">[</span><span class="n">b</span><span class="p">]),</span> <span class="p">[</span><span class="n">c</span><span class="p">])</span>
-<span class="n">kjs</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="n">doc_from_stack_effect</span><span class="p">(</span><span class="o">*</span><span class="n">kjs</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">a0</span> <span class="p">[</span><span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="n">a0</span> <span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="n">a1</span><span class="p">)</span>
-
-   <span class="n">a0</span> <span class="p">[</span><span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="n">a1</span> <span class="p">[</span><span class="n">cons</span><span class="p">]</span> <span class="n">dip</span>
-<span class="o">----------------------------</span>
-   <span class="p">[</span><span class="n">a0</span> <span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="n">a1</span>
-</pre></div>
-</div>
-<div class="section" id="concat">
-<h3><code class="docutils literal notranslate"><span class="pre">concat</span></code><a class="headerlink" href="#concat" title="Permalink to this headline">¶</a></h3>
-<p>How to deal with <code class="docutils literal notranslate"><span class="pre">concat</span></code>?</p>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">concat</span> <span class="p">([</span><span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="o">.</span><span class="mf">0.</span> <span class="o">.</span><span class="mf">1.</span><span class="p">])</span>
-</pre></div>
-</div>
-<p>We would like to represent this in Python somehow…</p>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">concat</span> <span class="o">=</span> <span class="p">(</span><span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span> <span class="p">((</span><span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">]),)</span>
-</pre></div>
-</div>
-<p>But this is actually <code class="docutils literal notranslate"><span class="pre">cons</span></code> with the first argument restricted to be a
-stack:</p>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="o">--</span> <span class="p">[[</span><span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="o">.</span><span class="mf">1.</span><span class="p">])</span>
-</pre></div>
-</div>
-<p>What we have implemented so far would actually only permit:</p>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="o">.</span><span class="mf">2.</span><span class="p">])</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">concat</span> <span class="o">=</span> <span class="p">(</span><span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span> <span class="p">(</span><span class="n">S</span><span class="p">[</span><span class="mi">2</span><span class="p">],)</span>
-</pre></div>
-</div>
-<p>Which works but can lose information. Consider <code class="docutils literal notranslate"><span class="pre">cons</span> <span class="pre">concat</span></code>, this is
-how much information we <em>could</em> retain:</p>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mi">1</span> <span class="p">[</span><span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="mi">1</span> <span class="o">.</span><span class="mf">0.</span> <span class="o">.</span><span class="mf">1.</span><span class="p">])</span>
-</pre></div>
-</div>
-<p>As opposed to just:</p>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mi">1</span> <span class="p">[</span><span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="o">.</span><span class="mf">2.</span><span class="p">])</span>
-</pre></div>
-</div>
-</div>
-<div class="section" id="represent-concat">
-<h3>represent <code class="docutils literal notranslate"><span class="pre">concat</span></code><a class="headerlink" href="#represent-concat" title="Permalink to this headline">¶</a></h3>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="n">A</span><span class="o">*</span><span class="p">(</span><span class="o">.</span><span class="mf">0.</span><span class="p">)</span> <span class="o">.</span><span class="mf">1.</span><span class="p">])</span>
-</pre></div>
-</div>
-<p>Meaning that <code class="docutils literal notranslate"><span class="pre">A*</span></code> on the right-hand side should all the crap from
-<code class="docutils literal notranslate"><span class="pre">.0.</span></code>.</p>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span>      <span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span>      <span class="n">A</span><span class="o">*</span> <span class="o">.</span><span class="mf">1.</span><span class="p">])</span>
-<span class="p">([</span><span class="n">a</span>     <span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="n">a</span>     <span class="n">A</span><span class="o">*</span> <span class="o">.</span><span class="mf">1.</span><span class="p">])</span>
-<span class="p">([</span><span class="n">a</span> <span class="n">b</span>   <span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="n">a</span> <span class="n">b</span>   <span class="n">A</span><span class="o">*</span> <span class="o">.</span><span class="mf">1.</span><span class="p">])</span>
-<span class="p">([</span><span class="n">a</span> <span class="n">b</span> <span class="n">c</span> <span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="n">a</span> <span class="n">b</span> <span class="n">c</span> <span class="n">A</span><span class="o">*</span> <span class="o">.</span><span class="mf">1.</span><span class="p">])</span>
-</pre></div>
-</div>
-<p>or…</p>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span>       <span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span>       <span class="o">.</span><span class="mf">1.</span><span class="p">])</span>
-<span class="p">([</span><span class="n">a</span>      <span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="n">a</span>      <span class="o">.</span><span class="mf">1.</span><span class="p">])</span>
-<span class="p">([</span><span class="n">a</span> <span class="n">b</span>    <span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="n">a</span> <span class="n">b</span>    <span class="o">.</span><span class="mf">1.</span><span class="p">])</span>
-<span class="p">([</span><span class="n">a</span> <span class="n">b</span>  <span class="n">c</span> <span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="n">a</span> <span class="n">b</span>  <span class="n">c</span> <span class="o">.</span><span class="mf">1.</span><span class="p">])</span>
-<span class="p">([</span><span class="n">a</span> <span class="n">A</span><span class="o">*</span> <span class="n">c</span> <span class="o">.</span><span class="mf">0.</span><span class="p">]</span> <span class="p">[</span><span class="o">.</span><span class="mf">1.</span><span class="p">]</span> <span class="o">--</span> <span class="p">[</span><span class="n">a</span> <span class="n">A</span><span class="o">*</span> <span class="n">c</span> <span class="o">.</span><span class="mf">1.</span><span class="p">])</span>
-</pre></div>
-</div>
-<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">S0</span><span class="p">))</span> <span class="o">.</span> <span class="n">S1</span> <span class="o">=</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="p">(</span><span class="n">A</span><span class="o">*</span><span class="p">,</span> <span class="n">S1</span><span class="p">)))</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Astar</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
-    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
-        <span class="k">return</span> <span class="s1">&#39;A*&#39;</span>
-
-
-<span class="k">def</span> <span class="nf">concat</span><span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="n">s1</span><span class="p">):</span>
-    <span class="n">a</span> <span class="o">=</span> <span class="p">[]</span>
-    <span class="k">while</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
-        <span class="n">term</span><span class="p">,</span> <span class="n">s0</span> <span class="o">=</span> <span class="n">s0</span>
-        <span class="n">a</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">term</span><span class="p">)</span>
-    <span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="n">StackJoyType</span><span class="p">),</span> <span class="nb">repr</span><span class="p">(</span><span class="n">s0</span><span class="p">)</span>
-    <span class="n">s1</span> <span class="o">=</span> <span class="n">Astar</span><span class="p">(),</span> <span class="n">s1</span>
-    <span class="k">for</span> <span class="n">term</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">a</span><span class="p">):</span>
-        <span class="n">s1</span> <span class="o">=</span> <span class="n">term</span><span class="p">,</span> <span class="n">s1</span>
-    <span class="k">return</span> <span class="n">s1</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="p">(</span><span class="n">A</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">S</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
-</pre></div>
-</div>
-<div class="code ipython2 highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">concat</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>
-</pre></div>
-</div>
-</div>
 </div>
 </div>
 
@@ -2579,7 +2365,7 @@ how much information we <em>could</em> retain:</p>
         <div class="sphinxsidebarwrapper">
   <h3><a href="../index.html">Table Of Contents</a></h3>
   <ul>
-<li><a class="reference internal" href="#">Type Inference</a><ul>
+<li><a class="reference internal" href="#">The Blissful Elegance of Typing Joy</a><ul>
 <li><a class="reference internal" href="#part-i-poial-s-rules">Part I: Pöial’s Rules</a><ul>
 <li><a class="reference internal" href="#first-rule">First Rule</a></li>
 <li><a class="reference internal" href="#second-rule">Second Rule</a></li>
@@ -2652,15 +2438,18 @@ how much information we <em>could</em> retain:</p>
 </li>
 </ul>
 </li>
-<li><a class="reference internal" href="#part-vii-typing-combinators">Part VII: Typing Combinators</a></li>
-<li><a class="reference internal" href="#conclusion">Conclusion</a></li>
-<li><a class="reference internal" href="#appendix-joy-in-the-logical-paradigm">Appendix: Joy in the Logical Paradigm</a></li>
-<li><a class="reference internal" href="#abstract-interpretation">Abstract Interpretation</a></li>
-<li><a class="reference internal" href="#junk">Junk</a><ul>
-<li><a class="reference internal" href="#concat"><code class="docutils literal notranslate"><span class="pre">concat</span></code></a></li>
-<li><a class="reference internal" href="#represent-concat">represent <code class="docutils literal notranslate"><span class="pre">concat</span></code></a></li>
+<li><a class="reference internal" href="#part-vii-typing-combinators">Part VII: Typing Combinators</a><ul>
+<li><a class="reference internal" href="#hybrid-inferencer-interpreter">Hybrid Inferencer/Interpreter</a><ul>
+<li><a class="reference internal" href="#joy-types-for-functions">Joy Types for Functions</a></li>
+<li><a class="reference internal" href="#specialized-for-simple-functions-and-combinators">Specialized for Simple Functions and Combinators</a></li>
+<li><a class="reference internal" href="#infer"><code class="docutils literal notranslate"><span class="pre">infer()</span></code></a></li>
+<li><a class="reference internal" href="#work-in-progress">Work in Progress</a></li>
+</ul>
+</li>
 </ul>
 </li>
+<li><a class="reference internal" href="#conclusion">Conclusion</a></li>
+<li><a class="reference internal" href="#appendix-joy-in-the-logical-paradigm">Appendix: Joy in the Logical Paradigm</a></li>
 </ul>
 </li>
 </ul>
index 22d2d17..a6682b5 100644 (file)
@@ -16,7 +16,7 @@
     <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
     <link rel="index" title="Index" href="../genindex.html" />
     <link rel="search" title="Search" href="../search.html" />
-    <link rel="next" title="Type Inference" href="Types.html" />
+    <link rel="next" title="The Blissful Elegance of Typing Joy" href="Types.html" />
     <link rel="prev" title="Newton’s method" href="Newton-Raphson.html" />
    
   <link rel="stylesheet" href="../_static/custom.css" type="text/css" />
@@ -327,7 +327,7 @@ i d i d i d d Bingo!
   <li><a href="../index.html">Documentation overview</a><ul>
   <li><a href="index.html">Essays about Programming in Joy</a><ul>
       <li>Previous: <a href="Newton-Raphson.html" title="previous chapter">Newton’s method</a></li>
-      <li>Next: <a href="Types.html" title="next chapter">Type Inference</a></li>
+      <li>Next: <a href="Types.html" title="next chapter">The Blissful Elegance of Typing Joy</a></li>
   </ul></li>
   </ul></li>
 </ul>
index 937acd7..63e09f4 100644 (file)
@@ -17,7 +17,7 @@
     <link rel="index" title="Index" href="../genindex.html" />
     <link rel="search" title="Search" href="../search.html" />
     <link rel="next" title="Developing a Program in Joy" href="Developing.html" />
-    <link rel="prev" title="Functions Grouped by, er, Function with Examples" href="../lib.html" />
+    <link rel="prev" title="Type Inference of Joy Expressions" href="../types.html" />
    
   <link rel="stylesheet" href="../_static/custom.css" type="text/css" />
   
 <li class="toctree-l2"><a class="reference internal" href="Zipper.html#determining-the-right-path-for-an-item-in-a-tree">Determining the right “path” for an item in a tree.</a></li>
 </ul>
 </li>
-<li class="toctree-l1"><a class="reference internal" href="Types.html">Type Inference</a><ul>
+<li class="toctree-l1"><a class="reference internal" href="Types.html">The Blissful Elegance of Typing Joy</a><ul>
 <li class="toctree-l2"><a class="reference internal" href="Types.html#part-i-poial-s-rules">Part I: Pöial’s Rules</a></li>
 <li class="toctree-l2"><a class="reference internal" href="Types.html#part-ii-implementation">Part II: Implementation</a></li>
 <li class="toctree-l2"><a class="reference internal" href="Types.html#part-iii-compiling-yin-functions">Part III: Compiling Yin Functions</a></li>
 <li class="toctree-l2"><a class="reference internal" href="Types.html#part-vii-typing-combinators">Part VII: Typing Combinators</a></li>
 <li class="toctree-l2"><a class="reference internal" href="Types.html#conclusion">Conclusion</a></li>
 <li class="toctree-l2"><a class="reference internal" href="Types.html#appendix-joy-in-the-logical-paradigm">Appendix: Joy in the Logical Paradigm</a></li>
-<li class="toctree-l2"><a class="reference internal" href="Types.html#abstract-interpretation">Abstract Interpretation</a></li>
-<li class="toctree-l2"><a class="reference internal" href="Types.html#junk">Junk</a></li>
 </ul>
 </li>
 <li class="toctree-l1"><a class="reference internal" href="NoUpdates.html">No Updates</a></li>
 <h3>Related Topics</h3>
 <ul>
   <li><a href="../index.html">Documentation overview</a><ul>
-      <li>Previous: <a href="../lib.html" title="previous chapter">Functions Grouped by, er, Function with Examples</a></li>
+      <li>Previous: <a href="../types.html" title="previous chapter">Type Inference of Joy Expressions</a></li>
       <li>Next: <a href="Developing.html" title="next chapter">Developing a Program in Joy</a></li>
   </ul></li>
 </ul>
index 1fc25dd..0fda5b0 100644 (file)
Binary files a/docs/sphinx_docs/_build/html/objects.inv and b/docs/sphinx_docs/_build/html/objects.inv differ
index 6bbdba7..31994b5 100644 (file)
      <tr class="cg-1">
        <td></td>
        <td>&#160;&#160;&#160;
+       <a href="types.html#module-joy.utils.polytypes"><code class="xref">joy.utils.polytypes</code></a></td><td>
+       <em></em></td></tr>
+     <tr class="cg-1">
+       <td></td>
+       <td>&#160;&#160;&#160;
        <a href="pretty.html#module-joy.utils.pretty_print"><code class="xref">joy.utils.pretty_print</code></a></td><td>
        <em></em></td></tr>
      <tr class="cg-1">
        <td>&#160;&#160;&#160;
        <a href="stack.html#module-joy.utils.stack"><code class="xref">joy.utils.stack</code></a></td><td>
        <em></em></td></tr>
+     <tr class="cg-1">
+       <td></td>
+       <td>&#160;&#160;&#160;
+       <a href="types.html#module-joy.utils.types"><code class="xref">joy.utils.types</code></a></td><td>
+       <em></em></td></tr>
    </table>
 
 
index 4cb8576..ea99867 100644 (file)
@@ -1 +1 @@
-Search.setIndex({docnames:["index","joy","lib","library","notebooks/Categorical","notebooks/Developing","notebooks/Generator_Programs","notebooks/Intro","notebooks/Newton-Raphson","notebooks/NoUpdates","notebooks/Ordered_Binary_Trees","notebooks/Quadratic","notebooks/Recursion_Combinators","notebooks/Replacing","notebooks/Treestep","notebooks/Types","notebooks/Zipper","notebooks/index","parser","pretty","stack"],envversion:52,filenames:["index.rst","joy.rst","lib.rst","library.rst","notebooks/Categorical.rst","notebooks/Developing.rst","notebooks/Generator_Programs.rst","notebooks/Intro.rst","notebooks/Newton-Raphson.rst","notebooks/NoUpdates.rst","notebooks/Ordered_Binary_Trees.rst","notebooks/Quadratic.rst","notebooks/Recursion_Combinators.rst","notebooks/Replacing.rst","notebooks/Treestep.rst","notebooks/Types.rst","notebooks/Zipper.rst","notebooks/index.rst","parser.rst","pretty.rst","stack.rst"],objects:{"joy.joy":{joy:[1,1,1,""],repl:[1,1,1,""],run:[1,1,1,""]},"joy.library":{"void":[3,1,1,""],BinaryBuiltinWrapper:[3,1,1,""],DefinitionWrapper:[3,2,1,""],FunctionWrapper:[3,1,1,""],SimpleFunctionWrapper:[3,1,1,""],UnaryBuiltinWrapper:[3,1,1,""],add_aliases:[3,1,1,""],app1:[3,1,1,""],app2:[3,1,1,""],app3:[3,1,1,""],b:[3,1,1,""],branch:[3,1,1,""],choice:[3,1,1,""],clear:[3,1,1,""],cmp_:[3,1,1,""],concat_:[3,1,1,""],cond:[3,1,1,""],dip:[3,1,1,""],dipd:[3,1,1,""],dipdd:[3,1,1,""],divmod_:[3,1,1,""],drop:[3,1,1,""],dupdip:[3,1,1,""],floor:[3,1,1,""],genrec:[3,1,1,""],getitem:[3,1,1,""],help_:[3,1,1,""],i:[3,1,1,""],id_:[3,1,1,""],ifte:[3,1,1,""],infra:[3,1,1,""],initialize:[3,1,1,""],inscribe:[3,1,1,""],loop:[3,1,1,""],map_:[3,1,1,""],max_:[3,1,1,""],min_:[3,1,1,""],parse:[3,1,1,""],pm:[3,1,1,""],pred:[3,1,1,""],remove:[3,1,1,""],reverse:[3,1,1,""],select:[3,1,1,""],sharing:[3,1,1,""],shunt:[3,1,1,""],sort_:[3,1,1,""],sqrt:[3,1,1,""],step:[3,1,1,""],succ:[3,1,1,""],sum_:[3,1,1,""],swaack:[3,1,1,""],take:[3,1,1,""],times:[3,1,1,""],unique:[3,1,1,""],unstack:[3,1,1,""],warranty:[3,1,1,""],words:[3,1,1,""],x:[3,1,1,""],zip_:[3,1,1,""]},"joy.library.DefinitionWrapper":{add_def:[3,3,1,""],add_definitions:[3,3,1,""],parse_definition:[3,3,1,""]},"joy.parser":{ParseError:[18,4,1,""],Symbol:[18,2,1,""],text_to_expression:[18,1,1,""]},"joy.utils":{generated_library:[3,0,0,"-"],pretty_print:[19,0,0,"-"],stack:[20,0,0,"-"]},"joy.utils.generated_library":{ccons:[3,1,1,""],cons:[3,1,1,""],dup:[3,1,1,""],dupd:[3,1,1,""],dupdd:[3,1,1,""],first:[3,1,1,""],first_two:[3,1,1,""],fourth:[3,1,1,""],over:[3,1,1,""],pop:[3,1,1,""],popd:[3,1,1,""],popdd:[3,1,1,""],popop:[3,1,1,""],popopd:[3,1,1,""],popopdd:[3,1,1,""],rest:[3,1,1,""],rolldown:[3,1,1,""],rollup:[3,1,1,""],rrest:[3,1,1,""],second:[3,1,1,""],stack:[3,1,1,""],stuncons:[3,1,1,""],stununcons:[3,1,1,""],swap:[3,1,1,""],swons:[3,1,1,""],third:[3,1,1,""],tuck:[3,1,1,""],uncons:[3,1,1,""],unswons:[3,1,1,""]},"joy.utils.pretty_print":{TracePrinter:[19,2,1,""]},"joy.utils.pretty_print.TracePrinter":{go:[19,5,1,""],viewer:[19,5,1,""]},"joy.utils.stack":{concat:[20,1,1,""],expression_to_string:[20,1,1,""],iter_stack:[20,1,1,""],list_to_stack:[20,1,1,""],pick:[20,1,1,""],stack_to_string:[20,1,1,""]},joy:{joy:[1,0,0,"-"],library:[3,0,0,"-"],parser:[18,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","function","Python function"],"2":["py","class","Python class"],"3":["py","classmethod","Python class method"],"4":["py","exception","Python exception"],"5":["py","method","Python method"]},objtypes:{"0":"py:module","1":"py:function","2":"py:class","3":"py:classmethod","4":"py:exception","5":"py:method"},terms:{"0b11100111011011":5,"23rd":15,"4b4cb6ff86e5":[],"58a8e44e9cba":15,"5bkei":10,"5eb7ac5ad2c2":[],"7fde90b4e88f":[],"\u03b5":8,"abstract":[7,10,17],"boolean":[2,3,7,10],"break":[7,15],"byte":5,"case":[2,3,12,14,15,20],"class":[3,7,15,18,19,20],"default":[3,6,10,20],"export":[3,18],"final":[2,10,12],"float":[3,7,15,16,18],"function":[0,1,4,5,6,9,11,16,17,18,19,20],"g\u00e9rard":16,"import":[2,5,6,8,10,11,12,13,14,15,16],"int":[6,7,12,15,16,18,20],"long":[10,15,17],"new":[2,3,6,7,9,12,13,15],"p\u00f6ial":17,"p\u00f6ial06typingtool":15,"public":9,"return":[1,3,5,7,10,12,13,14,15,18,19,20],"static":[2,9],"super":15,"switch":[2,15],"throw":10,"true":[2,3,5,12,15],"try":[6,8,11,12,14,15],"void":[0,3],"while":[3,7,10,15,18,20],AND:15,Adding:[7,13,17],And:[5,6,8,10,12,15,16,20],But:[0,4,5,6,7,10,13,15],CPS:7,FNs:15,For:[2,3,10,12,13,15,17,20],Has:3,Its:3,Not:15,One:[2,7,15,17],TOS:[2,3],That:[5,10],The:[0,1,2,3,4,6,8,9,11,15,16,17,18,20],Then:[2,3,10,11,12,15],There:[11,12,14,15,20],These:[15,17,20],Use:[3,8,12],Using:[0,8,10,17],With:[8,12,15,17],_1000:15,__add__:15,__class__:15,__eq__:15,__ge__:15,__hash__:15,__init__:15,__main__:15,__name__:15,__radd__:15,__repr__:15,__str__:19,_ge:15,_names_for:15,_to_str:15,_tree_add_:10,_tree_add_e:10,_tree_add_p:10,_tree_add_r:10,_tree_add_t:10,_tree_delete_:10,_tree_delete_clear_stuff:10,_tree_delete_del:10,_tree_delete_r0:10,_tree_delete_r1:10,_tree_delete_rightmost:10,_tree_delete_w:10,_tree_get_:10,_tree_get_p:10,_tree_get_r:10,_tree_get_t:10,_tree_iter_order_curr:10,_tree_iter_order_left:10,_tree_iter_order_r:10,_tree_iter_order_right:10,_tree_t:10,_treestep_0:14,_treestep_1:14,_uniqu:15,_within_b:8,_within_p:8,_within_r:8,a10001:15,a10002:15,a10003:15,a10004:15,a1001:[],abbrevi:14,abil:15,abl:15,about:[0,7,10,15,16,20],abov:[0,5,8,10,12,15],abs:8,absolut:7,accept:[1,2,3,5,6,7,10,11,13,14,15,16],accordingli:10,accumul:5,action:[7,13,15,16],actual:[2,5,7,10,15],adapt:17,add:[3,5,6,7,13,15,19],add_alias:3,add_def:3,add_definit:[3,10,14],added:[4,10],adding:[9,15],addit:[0,2,3,5,7,12,13,14],address:17,adjust:10,after:[5,6,7,12],afterward:7,again:[2,3,5,7,10,12,15],aggreg:16,ahead:15,aka:[7,16],albrecht:0,algorithm:[7,15],alia:3,alias:[3,7],align:[7,19],all:[3,5,6,7,10,12,13,14,15,19],alloc:15,allow:[9,10],almost:10,along:[7,12,15],alphabet:3,alreadi:[8,13,15,16],also:[0,5,7,10,15,20],alter:15,altern:[4,15],although:[4,10],altogeth:6,alwai:[5,9,12],amaz:[],among:15,amort:10,analysi:[4,17],anamorph:[7,17],ani:[4,5,7,9,10,15,16,18],annual:7,anonym:10,anoth:[10,15,20],anyhow:[],anyjoytyp:15,anymor:15,anystarjoytyp:15,anyth:[2,3,7,15],apart:15,api:9,app1:3,app2:[3,7,11,12,13],app3:3,app:7,appear:[2,4,5,10],append:15,appendix:17,appli:[2,3,5,6,10,12,15],applic:6,approach:5,approxim:17,archiv:0,aren:16,arg:[2,3],argument:[2,3,7,8,11,12,17,19,20],arithmet:2,ariti:2,around:[5,15,20],arrang:14,arriv:[6,14],articl:[0,4,6,12],ask:[4,6,15],aspect:0,assert:15,assign:20,associ:10,assum:8,astar:15,asterisk:14,asterix:15,attack:7,attempt:[0,1],attribut:3,attributeerror:15,author:15,auto:[0,15],automat:[4,15],auxiliari:14,avail:[0,15],averag:[7,13],avoid:10,awai:10,awar:2,awkward:[10,12],azur:17,back:[10,15],backward:[9,10,11,14],bad:15,bag:7,banana:12,barb:12,base:[0,2,3,9,12,14,15],basic:[1,2,3,7,10,15],becaus:[2,3,7,10,14,15,16,20],becom:[10,14,20],becuas:15,been:[8,9,10,15,16],befor:[6,7,10],begin:[10,14],behavior:[9,14],behaviour:[0,1,15],being:0,below:[2,3,5,6,10,15,16],bespok:7,best:0,better:[5,10,12,15],between:[0,5],beyond:6,biannual:7,binari:[0,6,7,17],binary_search_tre:10,binarybuiltinwrapp:3,bind:7,bingo:16,bit:[5,6,10,15],block:5,bodi:[2,7,10],body_text:3,booktitl:15,bool:[12,15],borrow:[7,15],both:[2,5,7,11,12,13,15,20],bottom:6,bracket:[7,15,18],branch:[3,5,6,12,15],branch_fals:15,branch_tru:15,breakpoint:7,bring:[5,7,15],bruijn:15,brzozowski:15,btree:[10,14],buck:10,bug:[0,7],build:[6,7,11,12,16,20],built:[11,15],bundl:[2,3,12],burgeon:7,calculu:4,call:[2,7,9,10,12,15,19,20],caller:[10,15],can:[0,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,20],cannot:15,captur:7,card:7,care:[5,20],carefulli:16,carri:[6,10],cartesian:4,catamorph:17,categor:[0,17],categori:4,ccc:4,ccon:[3,10,15],cell:[12,15],certain:[7,20],certainli:10,chain:[3,15],chang:[2,9,10,15,16],charact:16,chat:7,chatter:[0,15],check:[6,8,15],checker:15,child:14,choic:[3,12],choos:9,chop:11,cinf:10,circuit:4,cite_not:10,classmethod:3,claus:[3,15],clean:15,clear:[3,5,7],clear_stuff:10,cleav:[7,11,13],close:[0,1,4,15],clunki:[5,15],cmp:[3,14,17],cmp_:3,code:[0,1,4,11,12,15,17],codireco:[6,8],collaps:12,collect:[4,6,7,15],combin:[0,3,5,6,7,8,11,14,16,17],combinatorjoytyp:15,combo:15,come:[7,10,15],command:[7,10,15],common:[2,5],compar:[3,4,15],comparison:[0,10],compel:4,compil:[2,4,7,10,13,17],complet:4,complex:[3,15,16],complic:15,composit:15,compostit:15,compound:10,comput:[2,4,5,7,11,15],con:[3,5,6,7,8,10,11,12,14,16,20],conal:4,concat:[3,6,7,14,20],concat_:3,concaten:0,concatin:[0,3,20],conclus:17,concurr:2,cond:[3,10],condit:[3,7],confer:15,conflict:[10,15],conjectur:15,consecut:17,consid:[5,6,10,12,14,15,16],consist:[2,6,7,14],constant:10,constitu:12,constraint:15,construct:15,consum:15,contain:[0,2,3,6,7,12],content:15,context:2,conting:10,continu:[0,12,15,16],control:7,conveni:[4,15],convers:15,convert:[12,13,14,15,18,20],cool:10,copi:[2,3,5,10,12,14,17],copyright:7,correct:[],correspond:4,could:[2,4,5,7,9,10,15,16],count:[3,15],counter:[5,15],coupl:14,cours:[5,10,15],cover:15,crack:10,crap:15,crash:10,creat:[0,2,3,5,8,10,15],creativ:15,crude:[10,15,18],crunchi:15,currect:[],current:[2,3,7,12,14,15,16,19],custom:9,cycl:[5,6],cython:7,dai:7,data:[2,3,12],datastructur:[0,2,12,15,17,18,20],datatyp:20,ddee30dbb1a6:[],ddididi:16,deal:[0,10],dealt:15,debugg:15,decid:10,declar:15,decor:3,decoupl:12,decrement:3,deduc:[5,15],deeper:0,deepli:4,def:[3,7,12,13,15,20],defaultdict:15,defi:3,defin:[2,3,4,5,6,7,8,9,11,12,13,15,16,17],definit:[2,3,5,6,7,9,10,12,14,15,17],definitionwrapp:[3,10,12,14],deleg:7,delet:17,deliber:15,demonstr:4,depend:[3,10,12],deposit:14,depth:[],dequot:12,der:10,deriv:[2,3,5,7,8,10,15,17],describ:[3,4,10,12,14,15,18],descript:[5,7],descriptor:15,design:[2,3,10,17],desir:[7,14],destruct:10,detail:[7,10,15],detect:[6,10,12,15],determin:17,develop:[0,6,7,15,17],diagram:5,dialect:1,dict:[1,3,15],dictionari:[0,1,3,7,15,17],did:15,differ:[0,4,5,8,10,11,12,20],differenti:4,difficult:15,dig:[10,16],digit:5,dinfrirst:7,dip:[3,5,6,7,8,10,11,12,13,14,15,17],dip_a:15,dip_t:15,dipd:[3,6,7,10,11,12,15,16],dipdd:[3,10,15],direco:17,direct:7,directli:[5,14,15,20],disappear:[2,15],discard:[3,6,8,10,12],disciplin:10,disenstacken:7,disk:7,displac:2,displai:15,distiguish:15,ditch:10,div:[3,7],dive:14,divis:10,divmod:3,divmod_:[3,15],doc:[2,3,7,15],docstr:15,document:[17,18,20],doe:[0,1,4,6,7,13,15,17,19],doesn:[5,9,10,14,15,20],doing:[4,5,7,15,16],domain:[4,15],don:[5,7,10,15],done:[2,5,7,9,15],dooooc:15,door:7,dot:19,doubl:[5,7,15],down:[2,8,12,16],down_to_zero:7,dozen:7,draft:[4,9],dream:7,drive:[6,8],driven:5,driver:6,drop:[3,10],dudipd:7,due:15,dup:[3,5,6,7,8,10,11,12,16,20],dupd:[3,15],dupdd:3,dupdip:[3,5,10,11,12,15],duplic:[3,10,12],durat:2,dure:[2,12],each:[2,3,4,5,7,12,13,14,15,19],easi:[0,10,14,15,16],easier:[3,10],easili:4,edit:17,effect:[2,3,7,16,17],effici:[6,13,16],either:[1,2,3,10,12,15],elabor:15,eleg:[7,10,15],element:2,elif:15,elimin:15,elliott:4,els:[2,3,12,15],else_:15,embed:[4,10,16],emit:15,empti:[3,7,14,15,20],encapsul:7,enclos:7,encod:6,encount:15,end:[5,10,12,14,15,20],endless:6,enforc:[2,7],engend:7,enorm:[],enough:[7,12,19],enstacken:[6,7,15],enter:7,entir:20,entri:[3,16,19],enumer:15,ephasi:15,epsilon:8,equal:[5,14,20],equat:[7,8],ergo:10,err:10,error:[7,15,18],essai:0,establish:15,etc:[3,14,15,16,18],euler:17,euro:15,eval:[0,15],evalu:[1,2,3,7,8,10,11,12,13,14,15],event:15,eventu:15,ever:15,everi:6,everyth:[3,10,11,15],evolv:9,examin:12,exampl:[0,3,5,15,17,18,20],exce:6,except:[7,10,15,18],execut:[0,1,2,3,7,12,13,14,15,16,20],exend:15,exercis:10,exist:[4,10,15],expand:10,expect:[2,3,14,15,20],experi:[7,14],explain:15,explan:7,explor:7,express:[0,1,2,3,4,10,12,13,15,16,19,20],expression_to_str:20,extend:15,extra:[5,6],extract:[10,11,17],extrem:7,extrememli:7,f1001:[],f_g:15,f_in:15,f_out:15,f_python:15,facet:0,facil:7,fact:[15,18],factor:[2,5,7,10,15],factori:17,fail:[2,3,10,18],fairli:15,fale:[],fall:15,fals:[2,3,5,12,15],falsei:15,far:[8,10,12,15],fascin:0,fear:[10,15],few:[5,7,8,11],fewer:[3,7],fg_in:15,fg_out:15,fib:6,fib_gen:6,fibonacci:17,figur:[2,3,10,12,15],filter:10,fin:5,find:[2,3,5,6,14,15,17],finder:8,fine:[0,5,10,15],first:[3,6,7,8,10,11,12,13,14,16,17],first_two:[3,10],fit:[5,7],five:[5,7,17],fix:[2,3,12,15],fixm:15,flag:15,flatten:[7,14,15],flexibl:17,floatjoytyp:15,floatstarjoytyp:15,floor:3,floordiv:5,flow:7,follow:[0,2,3,7,9,12,14,15,16],foo:[7,9,10,15],foo_ii:9,form:[2,3,4,5,6,12,14,15,20],forman:7,format:[15,17,19],formula:[0,5,17],forth:[7,15],forum:0,forward:15,found:7,foundat:[],four:[2,3,5,6,7,10,17],fourteen:5,fourth:[2,3,10,12],fractal:7,fraction0:7,fraction:[2,7],frame:12,framework:7,free:[4,7,10],freeli:2,from:[0,1,2,3,5,6,7,8,10,11,12,13,14,15,16,17,20],from_iter:15,front:[2,3,12,15],full:5,fulli:[],fun:17,func:15,functionjoytyp:15,functionwrapp:3,funtion:10,further:[8,15,17],g_in:15,g_out:15,garbag:7,gari:10,gcd:7,gener:[0,2,4,12,15,17,20],generated_librari:3,genrec:[3,7,10,12,14,15],geometr:5,get:[2,4,5,6,7,11,12,15,17],getitem:3,getrecursionlimit:20,getsourc:7,ghc:4,give:[4,5,10,12,14,15,20],given:[2,3,5,6,8,10,12,15,16,17],global:15,glue:7,going:[10,11,14,15,16],good:[5,10,15],grab:[3,15],grammar:18,grand:7,great:[0,7,15,17],greater:20,grok:[],group:0,gsra:8,guard:10,had:[5,16],haiku:7,half:[5,15,16],hand:[7,13,15,17],handi:[8,15],handl:[10,15,20],happen:[7,15],hard:[15,16],hardwar:4,has:[0,2,6,7,8,9,10,12,15,16,20],hasattr:15,hash:15,haskel:4,have:[2,3,5,6,7,8,9,12,13,15,16,17,20],haven:[],head:20,help:[7,10,12,15],help_:3,helper:3,herd:7,here:[5,6,10,14,15,16],hide:10,hierarchi:15,higher:[7,10,15],highli:7,histori:[15,19],hmm:10,hoist:3,hold:[5,15],hood:10,hope:[0,5,7,15,17],hopefulli:12,host:17,how:[0,4,8,10,12,15,16,17],howev:[12,13,15],html:[2,3,6,11,12,17],http:10,huet:16,huge:10,hugh:[8,14],human:[7,15],hybrid:15,hylomorph:17,hypothet:2,id_:3,idea:[4,5,7,15],ident:[3,12,15],if_not_empti:10,ift:[3,10,12,14,15],ignor:[3,10,15],iii:17,illustr:12,imagin:16,imap:15,imit:14,immedi:12,immut:[7,10],imper:12,implement:[0,1,2,3,4,7,9,10,12,13,17],impli:[],implicit:7,improv:15,includ:[4,10,14,15],inclus:5,incom:20,incompat:9,incorpor:11,increas:5,increment:[3,4,5,9],index:[0,7,15,20],indexerror:[15,20],indic:[14,15],ineffici:15,infer:[0,17],inform:[3,15],infra:[3,6,7,10,11,13,14,15,17],infrastructur:3,initi:[2,3,7,8,10],inlin:10,inner:15,inproceed:15,input:[1,8,15],inscrib:3,insert:15,insight:12,inspect:7,instal:0,instanc:15,instanti:[4,19],instead:[5,6,10,12,15,16,20],integ:[2,3,7,12,14,15],integr:3,intend:[0,7],interact:[7,17],interest:[0,5,10,15,17],interlud:17,intermedi:12,intern:[0,15,19,20],interpret:[0,4,9,13,17,18,19],interrupt:7,interv:[4,5],intjoytyp:15,introduc:9,introduct:0,intstarjoytyp:15,intuit:15,invari:3,invent:15,involv:15,ipf:7,ipython:15,isinst:15,isn:[10,16],issubclass:15,item:[2,3,7,10,12,14,15,17,20],iter:[1,3,7,12,14,15,17,20],iter_stack:[13,15,20],iteritem:15,itertool:15,its:[0,2,3,4,5,7,10,12,14,15,20],itself:[0,2,7,10,15],j05cmp:[2,3,12],jaanu:15,job:17,john:[8,14],joi:[2,4,9,10,11,13],join:15,joypi:[7,16],june:15,junk:17,jupyt:17,just:[0,2,3,6,7,9,10,12,14,15,16],kav:15,keep:[10,11,15,16],kei:[14,17],kevin:0,key_n:10,keyerror:[10,15],kind:[2,4,7,10,12,14,15],kinda:15,kjs:15,kleen:[14,15],kleenestar:15,kleffner:15,know:[5,10,15],knowledg:15,known:4,l2s:15,l_kei:10,l_left:10,l_right:10,l_valu:10,label:15,lambda:[4,15],languag:[4,7,9,10,13,15],larg:15,larger:20,largest:3,last:[5,10,12,15],lastli:6,later:[7,14,15],law:2,lazi:15,lazili:8,lcm:5,lead:[7,15],leaf:10,lean:7,learn:[0,15],least:[2,5,12,15,20],least_fract:7,leav:5,left:[7,11,12,14,15,16,19,20],leftov:12,len:15,length:[3,5,20],lens:12,less:[5,6,7,12,15,20],let:[6,8,10,11,12,14,15,16],letter:15,level:[4,10],librari:[0,13],like:[2,3,5,7,14,15,17,18],limit:15,line:[3,7,10,11,19],linear:20,link:0,linux:0,list:[0,3,5,7,8,10,12,14,15,16,19],list_to_stack:[15,20],lit:15,liter:[1,10,14,15,16,18],literatur:15,littl:[6,10,15,17],live:17,lkei:14,load:[5,7],local:15,locat:2,locu:19,lof:[],log_2:10,logic:[0,5,17],longer:[10,15],look:[6,7,8,10,11,15],lookup:7,loop:[0,1,3,5,15],lose:15,lot:[7,10,15,16],love:5,low:4,lower:5,lowercas:15,lowest:10,machin:0,machineri:[10,15],macro:7,made:[0,7,15,16],magic:15,mai:[2,12],mail:0,main:[0,3,7,11,15,16],mainloop:9,maintain:16,major:9,make:[2,3,4,5,7,10,12,13,14,15,16,17],make_gener:8,manfr:[0,2,3,4,12],mani:[0,7,15],manipul:15,manner:11,map:[1,3,5,7,9,12,14,15],map_:3,marker:7,mask:[5,6],match:[0,1],materi:[0,15],math:[0,7,8,10,11,15],mathemat:7,matter:[5,8,10,14],max_:3,maximum:3,mayb:[10,15],mean:[4,5,7,8,10,12,14,15,20],meant:[7,10,12,14],member:[2,3,12],mental:7,mention:2,mercuri:0,mess:15,messag:15,meta:[7,10,13],meta_compos:15,metal:[],method:[0,3,7,15,17,19],midpoint:5,might:[4,6,10,15],mike:10,million:6,min_:3,mind:15,minimum:3,minor:10,minu:3,mirror:0,miscellan:0,mix:[7,15],mod:3,mode:15,model:[4,7,15],modern:0,modif:6,modifi:[7,10,16],modul:[0,1,3,7,15,18],modulu:7,moment:15,month:7,more:[0,3,4,5,6,7,8,12,13,14,15,18,20],most:15,mostli:0,motiv:[],move:10,movement:2,much:[5,6,10,12,15],muck:10,mul:[7,11,16,19],multi:3,multipl:17,must:[2,3,5,9,12,14,15],myself:15,n10001:15,n10002:15,n10003:15,n1001:15,n1002:15,n1003:15,name:[1,3,7,9,10,12,15,16,17,18,20],narr:15,natur:[5,6,10],navig:16,nearli:15,neat:10,neato:15,necessarili:15,need:[2,3,5,6,8,9,10,12,15],neg:[3,11],neither:15,nest:[3,7,10,16],network:7,never:[9,12],new_def:15,new_f:15,new_fo:15,new_kei:10,new_valu:10,newton:[0,17],next:[5,14,15],nice:[0,12,20],niether:2,node:[14,17],node_kei:10,node_valu:10,non:[14,15],none:[1,3,15],nope:14,normal:15,notat:[7,10],note:[2,5,8,10,12,15,20],notebook:[5,6,7,15,16,17],notebook_preambl:[2,5,6,8,10,11,12,13,14,15,16],noth:[2,10],notic:5,now:[5,6,7,12,13,14,15,17],nth:[3,20],nullari:[7,10],number:[1,2,3,5,6,8,20],numberjoytyp:15,numberstarjoytyp:15,numer:15,object:[15,18],observ:5,obviou:6,obvious:15,occur:10,odd:[5,6],off:[2,3,5,6,11,15,16],okai:[],old:[2,13],old_k:10,old_kei:10,old_valu:10,omit:[12,15],onc:[3,9,10],one:[2,3,5,6,10,12,14,15,19,20],ones:[6,15],onli:[2,3,5,10,12,15,16,20],onto:[1,2,3,7,12,20],open:[7,15],oper:[3,7,10,12,20],oppos:15,optim:10,option:[1,7,10,20],order:[0,2,3,7,12,15,17,20],org:[0,10],origin:[0,1,2,3,10,16],other:[0,2,3,4,7,10,12,14,15,20],otherwis:[3,5,6,10,14,15],our:[5,6,7,8,12,14,15],out:[2,3,4,5,6,7,8,10,11,12,15,16],outcom:14,output:[8,12,15],outsid:4,over:[3,4,5,6,7,8,10,11,14,15,17],overhaul:15,overview:15,own:[10,15],pace:15,pack:20,packag:[0,7],page:[0,10,15,20],pair:[2,3,5,6,10,15],palidrom:5,palindrom:5,pam:7,paper:[4,7,12,16],paradigm:17,parallel:2,paramet:[1,2,3,12,13,18,19,20],parameter:17,paramorph:12,parenthes:[10,20],pariti:6,pars:[0,3,7],parse_definit:3,parseerror:18,parser:[0,15],part:[2,3,8,12,14,17],partial:15,particular:16,pass:[0,10,15,19],path:17,pattern:[5,14,17],pe1:[5,6],pe2:6,pearl:16,pend:[3,7,12,16,19],peopl:[15,17],per:[7,14],perform:15,perhap:6,period:7,permit:[15,20],permut:15,persist:10,phase:2,pick:[5,6,20],pickl:7,pictur:10,piec:12,pip:0,place:[3,5,7,15],plai:0,plu:3,plug:[6,12,14],point:[4,7,10,12],pointless:2,pop:[3,5,6,7,10,12,13,14,20],popd:[3,7,8,10,13,15],popdd:[3,6,11,15],popop:[3,5,6,7,8,10,14,15],popopd:3,popopdd:3,posit:[3,5,7,12],possibilit:10,possibl:[10,14,15,17],post:7,poswrd:15,power:7,pragmat:5,preambl:8,precis:[0,1],pred:[3,15],predic:[2,3,6,12],prefix:[15,19],present:15,preserv:[4,14],pretti:[8,10,11,14,15,19,20],pretty_print:0,previou:7,primari:[],prime:8,primit:[2,3,15,17],primrec:[3,6,7,8,12],principl:[],print:[0,1,2,3,15,19,20],probabl:[6,7,10,15],problem:[7,15,17],proc_curr:10,proc_left:10,proc_right:10,proce:5,process:[7,14,15,19],produc:[5,10,12,14,15],product:[6,7,15],program:[0,2,3,6,7,8,10,12,15,16],programm:15,progress:15,project:17,prolog:15,prompt:7,proper:[2,3,12],properti:0,provabl:[],proven:[],provid:[0,3,4,7],pun:[0,7],punctuat:15,pure:0,puriti:7,purpos:7,push:[2,3,7,12,16,20],pushback:7,put:[1,2,6,7,15,17,20],pypi:0,python:[0,2,3,10,12,16,17,18,20],quadrat:[0,17],queri:[10,14],query_kei:14,queu:12,quit:[0,1,14],quot:[0,3,6,7,10,11,12,14,15,16,19],quotat:[2,3,12],quotient:3,r_kei:10,r_left:10,r_right:10,r_valu:10,rais:[10,15,18,20],rang:[7,15],range_revers:12,range_to_zero:7,ranger:12,ranger_revers:12,raphson:8,rather:[5,7,12,14],ratio:7,reach:[5,6,12],read:[0,1,5,6,10,15,16],readabl:13,reader:10,readi:15,real:10,realiz:[4,10,15],rearrang:[2,10,15],reason:[5,7,15],rebuild:[14,16],rec1:[2,3,12],rec2:[2,3,12],recent:15,recogn:18,record:[7,19],recur:[12,15],recurs:[0,2,3,6,7,8,15,17,20],recus:7,recycl:[],redefin:17,redistribut:[3,7],reduc:[2,15],redund:20,refactor:[7,9],refer:[0,2],regist:2,regular:[15,18],reimplement:17,relat:15,releas:9,remain:[2,7,9,15],remaind:[3,8],remind:15,remov:[3,10,15,20],render:17,repeat:5,repeatedli:5,repl:[0,1],replac:[0,2,3,6,11,12,14,15,16,17,20],repositori:0,repr:15,repres:[2,7,10,18,19],represent:20,reprod:6,repurpos:15,requir:[15,20],res:15,research:15,resembl:7,respect:5,rest:[3,5,6,7,10,12,16,17,20],rest_two:10,restat:[],restor:2,restrict:15,result:[1,2,3,5,10,11,12,14,15,16],resum:7,retain:15,retir:2,retri:7,reus:[10,15],revers:[3,5,6,12,15,16,20],revisit:15,rewrit:[3,7,15],rewritten:[7,15],rich:15,rid:10,right:[6,7,11,14,15,17,19,20],rightest:10,rightmost:5,rkei:14,rob:15,robot:[],roll:[3,8,10,14],roll_dn:15,roll_down:[],roll_up:[],rolldown:[3,15],rollup:[3,15],root:[3,8,11],round:15,rrest:[3,15],rule:17,run:[0,1,3,5,7,8,10,11,12,14,16],runtimeerror:20,s1000:[],s1002:[],s23:[],sai:[6,10,11,14,15],same:[2,4,5,10,15,20],sandwich:[2,3,12],save:[2,5,7],scan:3,scanner:[7,18],scenario:16,scope:[6,10],search:[0,10],sec:15,second:[3,7,10,12,14,20],section:12,see:[0,6,7,8,9,11,12,13,15,16,19],seem:[0,5,7,14,15],seen:[15,16],select:3,self:15,semant:[2,3,7,9,10,15],semi:7,send:7,sens:[0,2,5,15,16],separ:[7,15],seq:15,sequenc:[0,1,2,3,5,7,10,12,13,16,17,18],sequence_to_stack:15,seri:[5,6,10,16],ses:15,set:[2,3,12,15,17],seven:[5,6],sever:[0,4,7,12],share:[3,7],shelf:2,shift:[5,6,15],shorter:17,shorthand:10,should:[2,3,5,10,12,15],shouldn:7,show:[4,16],shunt:[3,16],side:[10,15],signifi:[7,10],similar:[10,14,15],simon:7,simpl:[7,12,15,20],simplefunctionwrapp:[3,13,15],simpler:14,simplest:[15,17],simpli:4,simplifi:[5,10,16],sinc:[2,5,10,15],singl:[3,6,7,13,15,18],situ:10,situat:10,six:[5,6,7],sixti:[5,6],size:[7,17],skeptic:7,skip:15,slight:8,slightli:[10,12,15],smallest:3,smart:10,softwar:7,solei:2,solut:[5,6],solvabl:7,some:[2,3,6,7,10,12,14,15,17,20],somehow:[10,15],someth:[2,9,10,15],sometim:10,somewher:[10,17],sort:[3,10,15],sort_:3,sorta:15,sourc:[0,1,3,15,17,18,19,20],space:[5,19],span:5,spawn:15,special:[6,10,15,17],specif:[0,4],specifi:[10,15],speed:13,spell:14,sphinx:[17,20],spirit:[0,1,14],split:15,sqr:[7,8,11,16],sqrt:[3,8,15],squar:[3,8,15,18],squishi:15,stack:[0,1,3,5,6,8,10,11,12,13,14,16,17,18,19],stack_concat:[],stack_effect:15,stack_effect_com:15,stack_to_str:20,stacki:15,stackjoytyp:15,stackstarjoytyp:15,stage:14,stai:[0,1],stand:4,standard:[7,10],star:[14,15],stare:10,start:[5,6,7,8,10,12,14,15],state:7,statement:3,step:[3,5,7,10,13,15,16,17],still:[10,15],stop:10,storag:[5,10],store:[5,12],stori:12,str:[1,15,18,19,20],straightforward:[1,6,8,15,17],stream:5,stretch:10,string:[1,2,3,7,15,16,18,19,20],strip:15,structur:[7,14,15,16,17,20],stuff:[10,15],stuncon:3,stununcon:3,style:[0,4,15],sub:9,subclass:7,subject:16,subset:15,substitut:[10,15],subtract:5,subtyp:17,succ:[3,15],succe:15,success:8,suck:15,suffic:15,suffici:10,suffix:15,suggest:[4,10],suitabl:[3,4,5],sum:[3,6,7,11,12,13,14,15],sum_:[3,15],summand:5,sumtre:14,suppli:[10,18],support:[7,15,19,20],suspect:2,swaack:[3,11,13,15,16],swap:[3,5,6,7,8,10,12,13,14,16],swarm:[],swon:[3,6,7,12,14,15,16],swoncat:[6,7,8,12,14],swuncon:12,symbol:[2,3,15,16,17,18],symboljoytyp:15,symmetr:[5,10],syntact:7,syntax:[7,20],sys:20,system:[7,10],tabl:15,tag:15,tail:[10,15,17,20],take:[3,5,7,8,10,12,15,20],talk:[7,10,15,20],target:16,tast:4,tbd:7,tear:12,technic:2,techniqu:[4,16],technolog:2,temporari:16,ten:5,term:[1,2,7,8,12,15,17,18,20],termin:[2,3,12],ternari:7,test:[2,3,12],text:[0,1,3,15],text_to_express:[7,15,18],textual:7,than:[0,3,5,6,7,8,12,14,15,20],thei:[2,5,6,7,10,12,15,16,18,20],them:[2,3,5,6,10,12,15,16,17],themselv:15,theori:[2,3,12],therefor:6,thi:[0,1,2,3,4,5,6,7,8,11,12,14,15,16,17,18,19,20],thing:[2,6,10,12,15,16,18,20],think:[2,5,7,10,12,14,15],third:[3,6,7,10],thirti:5,those:[2,3,10,12,15,17],though:5,thought:7,thousand:5,thread:2,three:[2,3,5,7,10,11,14,15,17],through:[1,5,7,14,15,16,20],thun:[2,3,4,9,12],thunder:7,time:[3,5,7,8,10,12,15,16],titl:15,to_set:10,todai:7,todo:[7,18],togeth:[6,7,15,17],token:18,toler:17,too:[12,15],tool:[7,15],tooo:15,top:[2,3,7,12,15,19,20],total:5,tower:15,trace:[0,7,11,12,16,17,20],traceback:15,traceprint:19,track:[11,15,16],tracker:0,transform:4,translat:[4,11,15],trash:[],travers:[0,17],treasur:0,treat:[0,2,3,12,15,17],treatment:6,tree:[0,7,17],treegrind:17,treestep:[0,17],tri:5,triangular_numb:12,trick:[5,15],tricki:15,trobe:0,trove:0,truli:[],trust:[],truthi:[3,7,15],tuck:[3,7,15],tupl:[3,7,15,20],ture:[],turn:[2,3,15],twice:[10,12],two:[2,3,5,7,8,10,11,12,14,15,16,17,20],type:[0,1,4,7,10,12,17,18,19,20],typeerror:15,typeless:15,typic:[2,3,11,12],unari:7,unarybuiltinwrapp:3,unbalanc:[10,18],unchang:10,uncompil:15,uncon:[3,6,7,10,12,14,16],under:[2,3,7,10],underli:15,underscor:15,understand:[0,10],undistinguish:10,undocu:7,unend:[],unfinish:15,unfortun:20,unicod:15,unif:15,uniqu:[3,10,15],unit:[7,12],univers:[0,7,15],unnecessari:17,unnecesssari:15,unpack:[2,3,10,20],unpair:5,unquot:[7,14],unstack:[3,15],unswon:3,untangl:12,until:6,unus:5,unusu:10,updat:[0,17],usag:7,use:[0,2,3,4,5,6,7,8,9,10,11,12,13,14,16,17,20],used:[3,4,7,10,12,16,18,20],useful:[0,15],user:14,uses:[2,5,12],using:[3,6,10,11,12,14,16],usual:[0,2,12],util:[0,3,13,15],valid:15,valu:[0,2,3,5,7,8,11,12,13,14,15,17,20],value_n:10,valueerror:[15,20],variabl:[15,17],variant:10,variat:[12,17],varieti:[4,7],variou:0,vener:20,verbos:4,veri:[0,1,4,7,10,20],verifi:15,versa:[2,15],version:[0,1,2,6,9,14,16,17],via:7,vice:[2,15],view:[10,17],viewer:[1,7,9,19],vii:17,visibl:15,von:[0,2,3,4,12],wai:[0,2,3,4,5,7,12,13,15],wait:[],want:[2,5,6,8,10,12,15],warranti:[3,7],wash:7,wast:7,web:20,websit:[0,5],welcom:7,well:[0,4,7,8,10,15,18],went:15,were:[7,15,16],what:[2,3,4,7,10,12,14,15,19],whatev:[2,3,12,14,20],when:[5,6,7,10,12,15,16,18,20],where:[2,3,7,10,12,15,17,20],whether:12,which:[0,1,3,5,7,8,10,12,14,15,16,20],whole:[2,3,5,12,14,15],whose:6,why:[8,14],wiki:10,wikipedia:[0,10,16],wildli:7,wind:7,wire:12,within:[7,10,13,17],without:[2,7,10,11,15],won:[10,15,20],word:[0,3,5,7,12,16],work:[0,3,5,6,7,8,10,11,12,14,15,16,20],worth:5,would:[2,5,6,7,8,10,12,15,16,20],wrap:[3,7],wrapper:15,write:[4,8,10,12,14,15,16,17,20],written:[0,1,8,10,13,15,20],wrong:2,wrote:15,xrang:15,yang:15,year:[7,15],yet:[10,15,16],yield:[2,3,12,15,20],yin:17,you:[0,2,3,5,6,7,9,10,11,12,13,14,15,16,19,20],your:[2,3,7,12,15],yourself:[7,10],zero:[3,10,12,14,15,18,20],zip:[5,15],zip_:3,zipper:[0,17],zstr:16},titles:["Thun 0.2.0 Documentation","Joy Interpreter","Functions Grouped by, er, Function with Examples","Function Reference","Categorical Programming","Developing a Program in Joy","Using <code class=\"docutils literal notranslate\"><span class=\"pre\">x</span></code> to Generate Values","Thun: Joy in Python","Newton\u2019s method","No Updates","Treating Trees I: Ordered Binary Trees","Quadratic formula","Recursive Combinators","Replacing Functions in the Dictionary","Treating Trees II: <code class=\"docutils literal notranslate\"><span class=\"pre\">treestep</span></code>","Type Inference","Traversing Datastructures with Zippers","Essays about Programming in Joy","Parsing Text into Joy Expressions","Tracing Joy Execution","Stack or Quote or Sequence or List\u2026"],titleterms:{"abstract":15,"case":[8,10],"function":[2,3,7,8,10,12,13,14,15],"long":13,"new":10,"p\u00f6ial":15,"void":2,"while":2,Adding:10,One:[6,10],The:[5,7,10,12,14],There:7,Using:6,With:14,about:17,add:[2,10],adding:10,address:16,altern:14,ana:12,analysi:5,anamorph:[2,12],app1:2,app2:2,app3:2,appendix:[10,12,15],approxim:8,argument:15,auto:3,averag:2,base:[8,10],binari:[2,10,14],both:10,branch:[2,10],can:10,cata:12,catamorph:12,categor:4,chatter:2,child:10,choic:2,clear:2,cleav:2,cmp:10,code:[7,10],combin:[2,10,12,15],comment:15,compar:10,comparison:2,compil:[6,15],compile_:15,compos:15,comput:8,con:[2,15],concat:[2,15],conclus:[12,15],consecut:8,continu:7,current:10,datastructur:[7,10,16],deal:15,defin:[10,14],definit:11,delabel:15,delet:10,deriv:[11,12,14],design:12,determin:16,develop:5,dialect:0,dictionari:13,dip:[2,16],dipd:2,dipdd:2,direco:6,disenstacken:2,distinguish:15,div:2,doc_from_stack_effect:15,document:0,doe:10,down_to_zero:2,drop:2,dup:[2,15],dupd:2,dupdip:2,effect:15,els:10,empti:10,enstacken:2,equal:10,essai:17,euler:[5,6],eval:7,even:6,exampl:[2,7,10,12,14],execut:19,express:[7,18],extract:14,factori:12,fibonacci:6,filter:5,find:[8,10,12],first:[2,5,15],five:6,flatten:2,flexibl:14,floordiv:2,formula:11,found:10,four:12,fun:12,further:5,gcd:2,gener:[3,5,6,8],genrec:2,get:[10,14],getitem:2,given:14,greater:10,group:2,have:[10,14],help:2,highest:10,host:0,how:[5,6],hylo:12,hylomorph:12,identifi:15,ift:2,iii:15,implement:15,indic:0,infer:15,inferenc:15,inform:0,infra:[2,16],integ:5,interest:6,interlud:10,intern:18,interpret:[1,7,15],item:16,iter:[5,10],joi:[0,1,3,5,7,12,15,16,17,18,19,20],junk:15,just:5,kei:10,languag:0,least_fract:2,left:10,less:10,let:5,librari:[3,7,15],like:10,list:[2,20],literari:7,littl:5,logic:[2,15],loop:[2,7],lower:10,lshift:2,make:[6,8],mani:5,map:2,math:2,method:8,min:2,miscellan:2,mod:2,modifi:15,modulu:2,more:10,most:10,mul:[2,15],multipl:[5,6,15],must:10,name:11,neg:2,newton:8,next:8,node:10,non:10,now:10,nullari:2,number:[12,15],one:7,onli:7,order:[10,14],osdn:0,our:10,over:2,pack:5,pam:2,para:12,paradigm:15,parameter:[10,14],pars:[2,18],parser:[7,18],part:15,pass:7,path:16,pattern:12,per:10,pop:[2,15],popd:2,popop:2,pow:2,power:6,pred:2,predic:[5,8,10,14],pretty_print:19,primit:12,primrec:2,print:7,problem:[5,6],process:10,product:2,program:[4,5,11,14,17],project:[0,5,6],pure:7,put:[10,11,14],python:[7,13,15],quadrat:11,quick:0,quot:[2,20],rang:[2,5,12],range_to_zero:2,read:7,recur:[8,10],recurs:[10,12,14],redefin:[10,14],refactor:[5,10],refer:3,regular:7,reimplement:14,relabel:15,rem:2,remaind:2,remov:2,render:5,repl:7,replac:[10,13],repres:15,reset:6,rest:[2,15],revers:2,right:[10,16],rightmost:10,roll:[2,15],rolldown:2,rollup:2,rshift:2,rule:15,run:[2,6],second:[2,15],select:2,sequenc:[6,15,20],set:[8,10],shorter:13,should:7,shunt:2,simplest:5,size:[2,13],someth:[],sourc:10,special:12,sqr:[2,15],sqrt:[2,11],stack:[2,7,15,20],start:0,step:[2,12,14],straightforward:11,structur:10,style:7,sub:[2,10],subtyp:15,succ:2,sum:[2,5],swaack:2,swap:[2,15],swon:2,swoncat:2,symbol:[7,12],tabl:0,tail:12,take:2,term:[5,6,14],ternari:2,text:18,than:10,them:11,thi:10,third:[2,15],three:6,thun:[0,7],time:[2,6],togeth:[10,11,14],token:7,toler:8,trace:[13,19],traceprint:7,travers:[10,14,16],treat:[10,14],tree:[10,14,16],treegrind:14,treestep:14,triangular:12,truediv:2,truthi:2,tuck:2,two:6,type:15,unari:2,unbound:15,uncon:[2,15],unifi:15,unit:2,unnecessari:5,unquot:2,unstack:2,updat:[9,15],use:15,util:[19,20],valu:[6,10],variabl:11,variat:6,version:[5,10,13,15],view:7,vii:15,within:8,word:2,write:11,xor:2,yin:15,zero:6,zip:2,zipper:16}})
\ No newline at end of file
+Search.setIndex({docnames:["index","joy","lib","library","notebooks/Categorical","notebooks/Developing","notebooks/Generator_Programs","notebooks/Intro","notebooks/Newton-Raphson","notebooks/NoUpdates","notebooks/Ordered_Binary_Trees","notebooks/Quadratic","notebooks/Recursion_Combinators","notebooks/Replacing","notebooks/Treestep","notebooks/Types","notebooks/Zipper","notebooks/index","parser","pretty","stack","types"],envversion:52,filenames:["index.rst","joy.rst","lib.rst","library.rst","notebooks/Categorical.rst","notebooks/Developing.rst","notebooks/Generator_Programs.rst","notebooks/Intro.rst","notebooks/Newton-Raphson.rst","notebooks/NoUpdates.rst","notebooks/Ordered_Binary_Trees.rst","notebooks/Quadratic.rst","notebooks/Recursion_Combinators.rst","notebooks/Replacing.rst","notebooks/Treestep.rst","notebooks/Types.rst","notebooks/Zipper.rst","notebooks/index.rst","parser.rst","pretty.rst","stack.rst","types.rst"],objects:{"joy.joy":{joy:[1,1,1,""],repl:[1,1,1,""],run:[1,1,1,""]},"joy.library":{"void":[3,1,1,""],BinaryBuiltinWrapper:[3,1,1,""],DefinitionWrapper:[3,2,1,""],FunctionWrapper:[3,1,1,""],SimpleFunctionWrapper:[3,1,1,""],UnaryBuiltinWrapper:[3,1,1,""],add_aliases:[3,1,1,""],app1:[3,1,1,""],app2:[3,1,1,""],app3:[3,1,1,""],b:[3,1,1,""],branch:[3,1,1,""],choice:[3,1,1,""],clear:[3,1,1,""],cmp_:[3,1,1,""],concat_:[3,1,1,""],cond:[3,1,1,""],dip:[3,1,1,""],dipd:[3,1,1,""],dipdd:[3,1,1,""],divmod_:[3,1,1,""],drop:[3,1,1,""],dupdip:[3,1,1,""],floor:[3,1,1,""],genrec:[3,1,1,""],getitem:[3,1,1,""],help_:[3,1,1,""],i:[3,1,1,""],id_:[3,1,1,""],ifte:[3,1,1,""],infra:[3,1,1,""],initialize:[3,1,1,""],inscribe:[3,1,1,""],loop:[3,1,1,""],map_:[3,1,1,""],max_:[3,1,1,""],min_:[3,1,1,""],parse:[3,1,1,""],pm:[3,1,1,""],pred:[3,1,1,""],remove:[3,1,1,""],reverse:[3,1,1,""],select:[3,1,1,""],sharing:[3,1,1,""],shunt:[3,1,1,""],sort_:[3,1,1,""],sqrt:[3,1,1,""],step:[3,1,1,""],succ:[3,1,1,""],sum_:[3,1,1,""],take:[3,1,1,""],times:[3,1,1,""],unique:[3,1,1,""],unstack:[3,1,1,""],warranty:[3,1,1,""],words:[3,1,1,""],x:[3,1,1,""],zip_:[3,1,1,""]},"joy.library.DefinitionWrapper":{add_def:[3,3,1,""],add_definitions:[3,3,1,""],parse_definition:[3,3,1,""]},"joy.parser":{ParseError:[18,4,1,""],Symbol:[18,2,1,""],text_to_expression:[18,1,1,""]},"joy.utils":{generated_library:[3,0,0,"-"],polytypes:[21,0,0,"-"],pretty_print:[19,0,0,"-"],stack:[20,0,0,"-"],types:[21,0,0,"-"]},"joy.utils.generated_library":{ccons:[3,1,1,""],cons:[3,1,1,""],dup:[3,1,1,""],dupd:[3,1,1,""],dupdd:[3,1,1,""],first:[3,1,1,""],first_two:[3,1,1,""],fourth:[3,1,1,""],over:[3,1,1,""],pop:[3,1,1,""],popd:[3,1,1,""],popdd:[3,1,1,""],popop:[3,1,1,""],popopd:[3,1,1,""],popopdd:[3,1,1,""],rest:[3,1,1,""],rolldown:[3,1,1,""],rollup:[3,1,1,""],rrest:[3,1,1,""],second:[3,1,1,""],stack:[3,1,1,""],stuncons:[3,1,1,""],stununcons:[3,1,1,""],swaack:[3,1,1,""],swap:[3,1,1,""],swons:[3,1,1,""],third:[3,1,1,""],tuck:[3,1,1,""],uncons:[3,1,1,""],unit:[3,1,1,""],unswons:[3,1,1,""]},"joy.utils.polytypes":{AnyStarJoyType:[21,2,1,""],CombinatorJoyType:[21,2,1,""],FunctionJoyType:[21,2,1,""],IntJoyType:[21,2,1,""],KleeneStar:[21,2,1,""],NumberStarJoyType:[21,2,1,""],Ss:[21,6,1,""],StackStarJoyType:[21,2,1,""],SymbolJoyType:[21,2,1,""],compose:[21,1,1,""],defs:[21,1,1,""],infer:[21,1,1,""],meta_compose:[21,1,1,""],unify:[21,1,1,""]},"joy.utils.polytypes.AnyStarJoyType":{kind:[21,5,1,""]},"joy.utils.polytypes.KleeneStar":{kind:[21,5,1,""]},"joy.utils.polytypes.NumberStarJoyType":{kind:[21,5,1,""]},"joy.utils.polytypes.StackStarJoyType":{kind:[21,5,1,""]},"joy.utils.pretty_print":{TracePrinter:[19,2,1,""]},"joy.utils.pretty_print.TracePrinter":{go:[19,7,1,""],viewer:[19,7,1,""]},"joy.utils.stack":{concat:[20,1,1,""],expression_to_string:[20,1,1,""],iter_stack:[20,1,1,""],list_to_stack:[20,1,1,""],pick:[20,1,1,""],stack_to_string:[20,1,1,""]},"joy.utils.types":{AnyJoyType:[21,2,1,""],BooleanJoyType:[21,2,1,""],FloatJoyType:[21,2,1,""],IntJoyType:[21,2,1,""],JoyTypeError:[21,4,1,""],NumberJoyType:[21,2,1,""],StackJoyType:[21,2,1,""],compilable:[21,1,1,""],compile_:[21,1,1,""],compose:[21,1,1,""],defs:[21,1,1,""],delabel:[21,1,1,""],doc_from_stack_effect:[21,1,1,""],relabel:[21,1,1,""],unify:[21,1,1,""],update:[21,1,1,""]},joy:{joy:[1,0,0,"-"],library:[3,0,0,"-"],parser:[18,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","function","Python function"],"2":["py","class","Python class"],"3":["py","classmethod","Python class method"],"4":["py","exception","Python exception"],"5":["py","attribute","Python attribute"],"6":["py","data","Python data"],"7":["py","method","Python method"]},objtypes:{"0":"py:module","1":"py:function","2":"py:class","3":"py:classmethod","4":"py:exception","5":"py:attribute","6":"py:data","7":"py:method"},terms:{"0b11100111011011":5,"23rd":15,"4b4cb6ff86e5":[],"58a8e44e9cba":[],"5bkei":10,"5eb7ac5ad2c2":[],"7fde90b4e88f":[],"\u03b5":8,"abstract":[7,10],"boolean":[2,3,7,10],"break":[7,15],"byte":5,"case":[2,3,12,14,15,20],"class":[3,7,15,18,19,20,21],"default":[3,6,10,20],"export":[3,18],"final":[2,10,12],"float":[3,7,15,16,18],"function":[0,1,4,5,6,9,11,16,17,18,19,20,21],"g\u00e9rard":16,"import":[2,5,6,8,10,11,12,13,14,15,16],"int":[6,7,12,15,16,18,20],"long":[10,15,17],"new":[2,3,6,7,9,12,13,15,21],"p\u00f6ial":17,"p\u00f6ial06typingtool":15,"public":9,"return":[1,3,5,7,10,12,13,14,15,18,19,20,21],"static":[2,9],"super":15,"switch":[2,15],"throw":[10,21],"true":[2,3,5,12,15,21],"try":[6,8,11,12,14,15],"void":[0,3],"while":[3,7,10,15,18,20],AND:15,Adding:[7,13,17],And:[5,6,8,10,12,15,16,20],But:[0,4,5,6,7,10,13,15],CPS:7,FNs:[],For:[2,3,10,12,13,15,17,20,21],Has:3,Its:3,Not:15,One:[2,7,15,17],TOS:[2,3],That:[5,10],The:[0,1,2,3,4,6,8,9,11,16,17,18,20,21],Then:[2,3,10,11,12,15],There:[11,12,14,15,20],These:[15,17,20,21],Use:[3,8,12],Using:[0,8,10,17],With:[8,12,15,17,21],_1000:15,__add__:15,__class__:15,__eq__:15,__ge__:15,__hash__:15,__init__:15,__main__:15,__name__:[],__radd__:15,__repr__:15,__str__:19,_dictionari:15,_ge:15,_infer:15,_interpret:15,_log:15,_log_it:15,_names_for:15,_to_str:15,_tree_add_:10,_tree_add_e:[10,21],_tree_add_p:10,_tree_add_r:10,_tree_add_t:10,_tree_delete_:10,_tree_delete_clear_stuff:[10,21],_tree_delete_del:10,_tree_delete_r0:[10,21],_tree_delete_r1:10,_tree_delete_rightmost:10,_tree_delete_w:10,_tree_get_:[10,21],_tree_get_p:10,_tree_get_r:10,_tree_get_t:10,_tree_iter_order_curr:10,_tree_iter_order_left:10,_tree_iter_order_r:10,_tree_iter_order_right:10,_tree_t:10,_treestep_0:14,_treestep_1:14,_uniqu:15,_within_b:8,_within_p:8,_within_r:8,a10001:15,a10002:15,a10003:15,a10004:15,a1001:[],abbrevi:14,abil:[],abl:[15,21],about:[0,7,10,15,16,20,21],abov:[0,5,8,10,12,15],abs:8,absolut:7,accept:[1,2,3,5,6,7,10,11,13,14,15,16],accordingli:10,accumul:5,act:21,action:[7,13,15,16],actual:[2,5,7,10,15],adapt:17,add:[3,5,6,7,13,15,19,21],add_alias:3,add_def:3,add_definit:[3,10,14],added:[4,10],adding:[9,15],addit:[0,2,3,5,7,12,13,14],address:17,adjust:[10,21],advantag:15,after:[5,6,7,12,15,21],afterward:7,again:[2,3,5,7,10,12,15,21],against:[15,21],aggreg:16,ahead:15,aka:[7,16,21],albrecht:0,algorithm:[7,15],alia:[3,21],alias:[3,7],align:[7,19],all:[3,5,6,7,10,12,13,14,15,19,21],alloc:15,allow:[9,10],almost:10,along:[7,12,15,21],alphabet:3,alreadi:[8,13,15,16],also:[0,5,7,10,15,20,21],alter:15,altern:[4,15,21],although:[4,10],altogeth:6,alwai:[5,9,12],amaz:[],among:15,amort:10,analysi:[4,17],anamorph:[7,17],ani:[4,5,7,9,10,15,16,18,21],annual:7,anonym:10,anoth:[10,15,20,21],anyhow:15,anyjoytyp:[15,21],anymor:15,anystarjoytyp:[15,21],anyth:[2,3,7,15,21],apart:15,api:9,app1:3,app2:[3,7,11,12,13],app3:3,app:7,appear:[2,4,5,10,21],append:15,appendix:17,appli:[2,3,5,6,10,12,15,21],applic:6,approach:5,approxim:17,archiv:0,aren:16,arg:[2,3],argument:[2,3,7,8,11,12,17,19,20],arithmet:2,ariti:2,around:[5,15,20],arrang:14,arriv:[6,14],articl:[0,4,6,12],ask:[4,6,15],aspect:0,assert:15,assign:20,associ:10,assum:8,astar:[],asterisk:14,asterix:[15,21],attack:7,attempt:[0,1,15],attribut:3,attributeerror:15,author:15,auto:[0,15,21],automat:[4,15,21],auxiliari:14,avail:[0,15,21],averag:[7,13],avoid:[10,21],awai:[10,15],awar:2,awkward:[10,12,15],azur:17,back:[10,15],backport:[],backtrack:21,backward:[9,10,11,14],bad:15,bag:7,banana:12,barb:12,base:[0,2,3,9,12,14,15],basic:[1,2,3,7,10],basicconfig:15,becaus:[2,3,7,10,14,15,16,20],becom:[10,14,20],becuas:15,been:[8,9,10,15,16],befor:[6,7,10],begin:[10,14],behavior:[9,14,21],behaviour:[0,1,15,21],being:[0,21],below:[2,3,5,6,10,15,16],bespok:7,best:0,better:[5,10,12,15],between:[0,5,21],beyond:6,biannual:7,binari:[0,6,7,17],binary_search_tre:10,binarybuiltinwrapp:3,bind:7,bingo:16,bit:[5,6,10,15],bliss:[0,17],block:5,bodi:[2,7,10],body_text:3,booktitl:15,bool:[12,15,21],booleanjoytyp:21,borrow:[7,15],both:[2,5,7,11,12,13,15,20],bottom:6,bracket:[7,15,18],branch:[3,5,6,12,15,21],branch_fals:15,branch_tru:15,breakpoint:7,bring:[5,7,15],broken:[],bruijn:15,brzozowski:15,btree:[10,14],buck:10,bug:[0,7],build:[6,7,11,12,16,20],built:[11,15],bundl:[2,3,12],burgeon:7,calculu:4,call:[2,7,9,10,12,15,19,20],caller:[10,15],can:[0,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,20,21],cannot:15,captur:[7,21],card:7,care:[5,20],carefulli:16,carri:[6,10,21],cartesian:4,catamorph:17,categor:[0,17],categori:4,ccc:4,ccon:[3,10,15,21],cell:[12,15],certain:[7,20],certainli:10,chain:3,chang:[2,9,10,15,16],charact:16,chat:7,chatter:[0,15],check:[6,8,15],checker:[],child:14,choic:[3,12],choos:9,chop:11,cinf:10,circuit:4,cite_not:10,classmethod:3,claus:[3,15],clean:15,clear:[3,5,7],clear_stuff:10,cleav:[7,11,13],close:[0,1,4],clunki:[5,15],cmp:[3,14,17],cmp_:3,code:[0,1,4,11,12,15,17,21],codireco:[6,8],collaps:12,collect:[4,6,7,15],collis:21,combin:[0,3,5,6,7,8,11,14,16,17,21],combinatorjoytyp:[15,21],combo:[],come:[7,10,15],command:[7,10,15],comment:21,common:[2,5],compar:[3,4,15],comparison:[0,10],compel:4,compil:[2,4,7,10,13,17,21],compile_:21,complet:4,complex:[3,15,16,21],complic:15,compos:21,composit:[15,21],compostit:15,compound:10,comput:[2,4,5,7,11,15,21],con:[3,5,6,7,8,10,11,12,14,16,20,21],conal:4,concat:[3,6,7,14,15,20],concat_:3,concaten:0,concatin:[0,3,20],conclus:17,concurr:2,cond:[3,10],condit:[3,7],confer:15,conflict:[10,15,21],conjectur:[],consecut:17,consid:[5,6,10,12,14,15,16],consist:[2,6,7,14],constant:10,constitu:12,constraint:[],construct:15,consum:15,contain:[0,2,3,6,7,12,15],content:15,context:2,conting:10,continu:[0,12,15,16],control:7,conveni:[4,15],convers:15,convert:[12,13,14,15,18,20],cool:10,copi:[2,3,5,10,12,14,17],copyright:7,correct:[],correspond:4,could:[2,4,5,7,9,10,15,16],count:[3,15],counter:[5,15],coupl:14,cours:[5,10,15],cover:15,crack:10,crap:[],crash:10,creat:[0,2,3,5,8,10,15],creativ:15,crude:[10,15,18,21],cruft:15,crunchi:[],curent:21,currect:[],current:[2,3,7,12,14,15,16,19,21],custom:9,cycl:[5,6],cython:7,dai:7,data:[2,3,12],datastructur:[0,2,12,15,17,18,20],datatyp:20,ddee30dbb1a6:[],ddididi:16,deal:[0,10],dealt:15,debugg:15,decid:10,declar:15,decor:3,decoupl:12,decrement:3,deduc:[5,15],deeper:0,deepli:4,def:[3,7,12,13,15,20,21],defaultdict:15,defi:3,defin:[2,3,4,5,6,7,8,9,11,12,13,15,16,17],definit:[2,3,5,6,7,9,10,12,14,15,17,21],definitionwrapp:[3,10,12,14],delabel:21,deleg:7,delet:17,deliber:15,demo:15,demonstr:4,depend:[3,10,12],deposit:14,depth:[15,21],dequot:12,der:10,deriv:[2,3,5,7,8,10,15,17],describ:[3,4,10,12,14,15,18,21],descript:[5,7],descriptor:15,design:[2,3,10,17],desir:[7,14],destruct:10,detail:[7,10,15],detect:[6,10,12,15],determin:17,develop:[0,6,7,15,17],diagram:5,dialect:1,dict:[1,3,15,21],dictionari:[0,1,3,7,15,17],did:15,differ:[0,4,5,8,10,11,12,20],differenti:4,difficult:15,dig:[10,16],digit:5,dinfrirst:[7,15,21],dip:[3,5,6,7,8,10,11,12,13,14,15,17,21],dip_a:[],dip_t:[],dipd:[3,6,7,10,11,12,15,16,21],dipdd:[3,10],direco:17,direct:7,directli:[5,14,15,20],disappear:[2,15,21],discard:[3,6,8,10,12],disciplin:10,disenstacken:7,disk:7,displac:2,displai:15,distiguish:15,ditch:10,div:[3,7,15,21],dive:14,divis:10,divmod:[3,21],divmod_:[3,15],doc:[2,3,7,15,21],doc_from_stack_effect:21,docstr:[15,21],document:[15,17,18,20],doe:[0,1,4,6,7,13,15,17,19,21],doesn:[5,9,10,14,15,20],doing:[4,5,7,15,16],domain:[4,15],don:[5,7,10,15,21],done:[2,5,7,9,15],dooooc:15,door:7,dot:19,doubl:[5,7,15],down:[2,8,12,16,21],down_to_zero:7,dozen:7,draft:[4,9],dream:7,drive:[6,8],driven:5,driver:6,drop:[3,10],dudipd:7,due:15,dup:[3,5,6,7,8,10,11,12,16,20,21],dupd:[3,15,21],dupdd:[3,21],dupdip:[3,5,10,11,12],duplic:[3,10,12],durat:2,dure:[2,12],each:[2,3,4,5,7,12,13,14,15,19,21],easi:[0,10,14,15,16],easier:[3,10],easili:4,edit:17,effect:[2,3,7,16,17,21],effici:[6,13,16],efg:15,either:[1,2,3,10,12,15],elabor:15,eleg:[0,7,10,17],element:2,elif:15,elimin:15,elliott:4,els:[2,3,12,15],else_:15,embed:[4,10,16],emit:15,empti:[3,7,14,15,20,21],encapsul:7,enclos:7,encod:6,encount:15,end:[5,10,12,14,15,20],endless:6,enforc:[2,7],engend:7,enorm:[],enough:[7,12,19,21],enstacken:[6,7,15],enter:7,enter_guard:15,entir:20,entri:[3,16,19],enumer:15,ephasi:[],epsilon:8,equal:[5,14,20],equat:[7,8],ergo:10,err:10,error:[7,15,18],essai:0,establish:15,etc:[3,14,15,16,18],euler:17,euro:15,eval:[0,15],evalu:[1,2,3,7,8,10,11,12,13,14,15],event:[],eventu:15,ever:15,everi:6,everyth:[3,10,11,15],evolv:9,examin:12,exampl:[0,3,5,15,17,18,20,21],exce:6,except:[7,10,15,18,21],execut:[0,1,2,3,7,12,13,14,15,16,20,21],exend:15,exercis:10,exist:[4,10,15],expand:10,expect:[2,3,14,15,20,21],experi:[7,14],explain:15,explan:7,explor:[7,15],express:[0,1,2,3,4,10,12,13,15,16,19,20],expression_to_str:[15,20],extend:15,extra:[5,6],extract:[10,11,17],extrem:7,extrememli:7,f1001:[],f_g:15,f_in:15,f_out:15,f_python:15,facet:0,facil:7,fact:18,factor:[2,5,7,10,15],factori:17,fail:[2,3,10,18],fairli:15,fale:[],fall:15,fals:[2,3,5,12,15,21],falsei:15,far:[8,10,12,15,21],fascin:0,fear:[10,15],few:[5,7,8,11,15],fewer:[3,7],fg_in:15,fg_out:15,fib:6,fib_gen:6,fibonacci:17,figur:[2,3,10,12,15],filter:10,fin:5,find:[2,3,5,6,14,15,17],finder:8,fine:[0,5,10,15,21],first:[3,6,7,8,10,11,12,13,14,16,17,21],first_two:[3,10,21],fit:[5,7],five:[5,7,17],fix:[2,3,12,15,21],fixm:15,flag:15,flatten:[7,14,15],flexibl:17,floatjoytyp:[15,21],floatstarjoytyp:15,floor:3,floordiv:[5,21],flow:7,follow:[0,2,3,7,9,12,14,15,16,21],foo:[7,9,10,15],foo_ii:9,form:[2,3,4,5,6,12,14,15,20],forman:7,format:[15,17,19],formula:[0,5,17],forth:[7,15],forum:0,forward:15,found:7,foundat:[],four:[2,3,5,6,7,10,17],fourteen:5,fourth:[2,3,10,12,21],fractal:7,fraction0:7,fraction:[2,7],frame:12,framework:7,free:[4,7,10],freeli:2,from:[0,1,2,3,5,6,7,8,10,11,12,13,14,15,16,17,20],from_iter:[],front:[2,3,12],full:5,fulli:[],fun:17,func:15,functionjoytyp:[15,21],functionwrapp:3,funtion:10,further:[8,15,17],g_in:15,g_out:15,garbag:7,gari:10,gcd:7,gener:[0,2,4,12,15,17,20,21],generated_librari:3,genrec:[3,7,10,12,14,15],geometr:5,get:[2,4,5,6,7,11,12,15,17],getitem:3,getrecursionlimit:20,getsourc:7,ghc:4,give:[4,5,10,12,14,15,20],given:[2,3,5,6,8,10,12,15,16,17],global:15,glue:7,goe:21,going:[10,11,14,15,16],good:[5,10,15],grab:[3,15],grammar:18,grand:7,great:[0,7,15,17],greater:20,grind:15,grok:[],group:0,gsra:8,guard:[10,15,21],had:[5,16],haiku:7,half:[5,15,16],hand:[7,13,15,17],handi:[8,15],handl:[10,15,20,21],happen:[7,15],hard:[15,16],hardwar:4,has:[0,2,6,7,8,9,10,12,15,16,20],hasattr:15,hash:15,haskel:4,have:[2,3,5,6,7,8,9,12,13,15,16,17,20,21],haven:[],head:20,heh:15,help:[7,10,12,15],help_:3,helper:3,herd:7,here:[5,6,10,14,15,16,21],hide:10,hierarchi:15,higher:[7,10,15],highli:7,histori:[15,19,21],hmm:10,hoist:3,hold:[5,15],hood:10,hope:[0,5,7,17],hopefulli:12,host:17,how:[0,4,8,10,12,15,16,17],howev:[12,13,15],html:[2,3,6,11,12,17],http:10,huet:16,huge:10,hugh:[8,14],human:7,hybrid:21,hylomorph:17,hypothet:2,id_:3,idea:[4,5,7,15],ident:[3,12,15,21],if_not_empti:10,ift:[3,10,12,14,15,21],ignor:[3,10,15],iii:17,illustr:12,imagin:16,imap:15,imit:14,immedi:12,immut:[7,10],imper:12,implement:[0,1,2,3,4,7,9,10,12,13,17,21],impli:[],implicit:7,improv:15,includ:[4,10,14,15,21],inclus:5,incom:20,incompat:9,incorpor:11,increas:5,increment:[3,4,5,9],index:[0,7,15,20],indexerror:20,indic:[14,15,21],ineffici:15,infer:0,inferenc:21,info:15,inform:[3,15,21],infra:[3,6,7,10,11,13,14,15,17,21],infrastructur:3,initi:[2,3,7,8,10,15],inlin:10,inner:15,inproceed:15,input:[1,8,15,21],inscrib:3,insert:15,insight:12,inspect:7,inspect_stack:15,instal:0,instanc:[15,21],instanti:[4,19],instead:[5,6,10,12,15,16,20,21],integ:[2,3,7,12,14,15],integr:3,intend:[0,7],interact:[7,17],interest:[0,5,10,15,17],interlud:17,intermedi:12,intern:[0,15,19,20],interpret:[0,4,9,13,18,19,21],interrupt:7,interv:[4,5],intjoytyp:[15,21],introduc:[9,21],introduct:0,intstarjoytyp:15,intuit:15,invalid:21,invari:3,invent:15,involv:15,ipf:7,ipython:[],isinst:15,isn:[10,16],issubclass:15,item:[2,3,7,10,12,14,15,17,20],iter:[1,3,7,12,14,15,17,20],iter_stack:[13,20],iteritem:15,itertool:15,its:[0,2,3,4,5,7,10,12,14,15,20],itself:[0,2,7,10,15,21],j05cmp:[2,3,12],jaanu:15,job:17,john:[8,14],joi:[2,4,9,10,11,13],join:15,joypi:[7,16],joytypeerror:21,june:[],junk:15,jupyt:17,just:[0,2,3,6,7,9,10,12,14,15,16],kav:[],keep:[10,11,15,16],kei:[14,17],kevin:0,key_n:10,keyerror:[10,15],kind:[2,4,7,10,12,14,15,21],kinda:15,kjs:[],kleen:[14,15,21],kleenestar:[15,21],kleffner:15,know:[5,10,15],knowledg:15,known:4,l2s:[],l_kei:10,l_left:10,l_right:10,l_valu:10,label:15,lambda:[4,15],languag:[4,7,9,10,13,15],larg:15,larger:20,largest:3,last:[5,10,12,15],lastli:6,later:[7,14,15],law:2,lazi:15,lazili:8,lcm:5,lead:[7,15,21],leaf:10,lean:7,learn:0,least:[2,5,12,15,20],least_fract:7,leav:5,left:[7,11,12,14,15,16,19,20,21],leftov:12,len:15,length:[3,5,20],lens:12,less:[5,6,7,12,15,20],let:[6,8,10,11,12,14,15,16],letter:15,level:[4,10,15],librari:[0,13],like:[2,3,5,7,14,15,17,18,21],limit:[15,21],line:[3,7,10,11,15,19,21],linear:20,link:[0,15],linux:0,list:[0,3,5,7,8,10,12,14,15,16,19,21],list_to_stack:[15,20],lit:[],liter:[1,10,14,15,16,18],literatur:15,littl:[6,10,15,17],live:17,lkei:14,load:[5,7],local:15,locat:2,locu:19,lof:[],log:15,log_2:10,logic:[0,5,17],longer:[10,15],look:[6,7,8,10,11,15],lookup:7,loop:[0,1,3,5,15,21],lose:15,lot:[7,10,15,16],love:5,low:4,lower:5,lowercas:15,lowest:10,lshift:21,machin:0,machineri:[10,15,21],macro:7,made:[0,7,15,16],magic:15,mai:[2,12],mail:0,main:[0,3,7,11,15,16],mainloop:9,maintain:16,major:9,make:[2,3,4,5,7,10,12,13,14,15,16,17],make_gener:8,manfr:[0,2,3,4,12],mani:[0,7,15],manipul:15,manner:11,map:[1,3,5,7,9,12,14,15],map_:3,marker:7,mask:[5,6],match:[0,1,15],materi:0,math:[0,7,8,10,11,15],mathemat:7,matter:[5,8,10,14],max_:3,maximum:3,mayb:[10,15],mean:[4,5,7,8,10,12,14,15,20],meant:[7,10,12,14],member:[2,3,12],mental:7,mention:2,mercuri:0,mess:15,messag:15,meta:[7,10,13],meta_compos:[15,21],metal:[],method:[0,3,7,15,17,19],midpoint:5,might:[4,6,10,15],mike:10,million:6,min_:3,mind:15,minimum:3,minor:10,minu:3,mirror:0,miscellan:0,mismatch:15,mix:[7,15],mod:3,mode:15,model:[4,7],modern:0,modif:[6,15],modifi:[7,10,16],modul:[0,1,3,7,15,18],modulu:[7,21],moment:15,month:7,more:[0,3,4,5,6,7,8,12,13,14,15,18,20,21],most:[15,21],mostli:0,motiv:[],move:10,movement:2,much:[5,6,10,12,15],muck:10,mul:[7,11,16,19,21],multi:3,multipl:[17,21],must:[2,3,5,9,12,14,15],myself:15,n10001:15,n10002:15,n10003:15,n1001:15,n1002:15,n1003:15,name:[1,3,7,9,10,12,15,16,17,18,20,21],narr:15,natur:[5,6,10,15],navig:16,nearli:15,neat:10,neato:15,necessarili:15,need:[2,3,5,6,8,9,10,12,15],neg:[3,11,21],neither:15,nest:[3,7,10,16],network:7,never:[9,12],new_def:15,new_f:15,new_fo:15,new_kei:10,new_valu:10,newton:[0,17],next:[5,14,15,21],nice:[0,12,20],niether:2,node:[14,17],node_kei:10,node_valu:10,non:[14,15,21],none:[1,3,15,21],nope:14,normal:[],notat:[7,10],note:[2,5,8,10,12,15,20],notebook:[5,6,7,15,16,17],notebook_preambl:[2,5,6,8,10,11,12,13,14,15,16],noth:[2,10],notic:5,now:[5,6,7,12,13,14,15,17],nth:[3,20],nullari:[7,10,15,21],number:[1,2,3,5,6,8,20,21],numberjoytyp:[15,21],numberstarjoytyp:[15,21],numer:15,object:[15,18],observ:5,obviou:6,obvious:15,occur:10,odd:[5,6],off:[2,3,5,6,11,15,16],okai:[],old:[2,13],old_k:10,old_kei:10,old_valu:10,omit:[12,15],onc:[3,9,10],one:[2,3,5,6,10,12,14,15,19,20,21],ones:[6,15],onli:[2,3,5,10,12,15,16,20,21],onto:[1,2,3,7,12,20],open:[7,15],oper:[3,7,10,12,20],oppos:15,optim:10,option:[1,7,10,15,20],order:[0,2,3,7,12,15,17,20],org:[0,10],origin:[0,1,2,3,10,16],other:[0,2,3,4,7,10,12,14,15,20,21],otherwis:[3,5,6,10,14,15,21],our:[5,6,7,8,12,14,15],out:[2,3,4,5,6,7,8,10,11,12,15,16],outcom:14,output:[8,12,15,21],outsid:4,over:[3,4,5,6,7,8,10,11,14,15,17,21],overhaul:15,overview:15,own:[10,15],pace:[],pack:20,packag:[0,7],page:[0,10,15,20],pair:[2,3,5,6,10,15],palidrom:5,palindrom:5,pam:7,paper:[4,7,12,16],paradigm:17,parallel:2,paramet:[1,2,3,12,13,18,19,20],parameter:17,paramorph:12,parenthes:[10,20],pariti:6,pars:[0,3,7],parse_definit:3,parseerror:18,parser:[0,15],part:[2,3,8,12,14,17],partial:15,particular:16,pass:[0,10,15,19,21],path:[15,17],pattern:[5,14,17],pe1:[5,6],pe2:6,pearl:16,pend:[3,7,12,15,16,19],peopl:17,per:[7,14],perform:15,perhap:6,period:7,permit:[15,20],permut:15,persist:10,phase:2,pick:[5,6,20],pickl:7,pictur:10,piec:12,pip:0,place:[3,5,7,15],plai:0,plu:3,plug:[6,12,14],point:[4,7,10,12],pointless:2,poly_typ:[],polytyp:[0,15],pop:[3,5,6,7,10,12,13,14,20,21],popd:[3,7,8,10,13,15,21],popdd:[3,6,11,15,21],popop:[3,5,6,7,8,10,14,15,21],popopd:[3,21],popopdd:[3,21],posit:[3,5,7,12],possibilit:10,possibl:[10,14,15,17],post:7,poswrd:15,pow:21,power:[7,15],pragmat:5,preambl:8,precis:[0,1],pred:[3,15,21],predic:[2,3,6,12],prefix:[15,19],present:15,preserv:[4,14],pretti:[8,10,11,14,15,19,20],pretty_print:0,previou:7,primari:[],prime:8,primit:[2,3,15,17],primrec:[3,6,7,8,12],principl:[],print:[0,1,2,3,15,19,20,21],probabl:[6,7,10,15],problem:[7,15,17],proc_curr:10,proc_left:10,proc_right:10,proce:[5,21],process:[7,14,15,19],produc:[5,10,12,14,15],product:[6,7,15],program:[0,2,3,6,7,8,10,12,15,16,21],programm:15,progress:[],project:17,prolog:15,prompt:7,proper:[2,3,12,21],properti:0,provabl:[],proven:[],provid:[0,3,4,7,15,21],pun:[0,7],punctuat:15,pure:0,puriti:7,purpos:7,push:[2,3,7,12,16,20],pushback:7,put:[1,2,6,7,15,17,20],pypi:0,python:[0,2,3,10,12,16,17,18,20,21],quadrat:[0,17],queri:[10,14],query_kei:14,queu:12,quit:[0,1,14],quot:[0,3,6,7,10,11,12,14,15,16,19,21],quotat:[2,3,12],quotient:3,r_kei:10,r_left:10,r_right:10,r_valu:10,rais:[10,15,18,20],rang:[7,15],range_revers:12,range_to_zero:7,ranger:12,ranger_revers:12,raphson:8,rather:[5,7,12,14],ratio:7,reach:[5,6,12],read:[0,1,5,6,10,15,16],readabl:13,reader:10,readi:15,real:10,realiz:[4,10],rearrang:[2,10,15],reason:[5,7,15],rebuild:[14,16],rec1:[2,3,12],rec2:[2,3,12],recent:[],recogn:18,record:[7,19],recur:[12,15],recurs:[0,2,3,6,7,8,15,17,20],recus:7,recycl:[],redefin:17,redistribut:[3,7],reduc:[2,15],redund:20,refactor:[7,9],refer:[0,2],regist:2,regular:[15,18],reimplement:17,relabel:21,relat:15,releas:9,remain:[2,7,9,15],remaind:[3,8],remind:15,remov:[3,10,15,20],render:17,repeat:5,repeatedli:5,repl:[0,1],replac:[0,2,3,6,11,12,14,15,16,17,20],repositori:0,repr:15,repres:[2,7,10,18,19,21],represent:[20,21],reprod:6,repurpos:15,requir:[15,20],res:15,research:15,resembl:7,respect:5,rest:[3,5,6,7,10,12,16,17,20,21],rest_two:10,restat:[],restor:2,restrict:[],result:[1,2,3,5,10,11,12,14,15,16],resum:7,retain:[],retir:2,retri:7,reus:[10,15],revers:[3,5,6,12,15,16,20],revisit:15,rewrit:[3,7,15],rewritten:7,rich:[],rid:10,right:[6,7,11,14,15,17,19,20,21],rightest:10,rightmost:5,risk:15,rkei:14,rob:15,robot:[],roll:[3,8,10,14],roll_dn:15,roll_down:[],roll_up:[],rolldown:[3,15,21],rollup:[3,15,21],root:[3,8,11],round:15,rrest:[3,15,21],rshift:21,rule:17,run:[0,1,3,5,7,8,10,11,12,14,15,16],runtimeerror:20,s1000:[],s1002:[],s10:21,s23:[],sai:[6,10,11,14,15],same:[2,4,5,10,15,20],sandwich:[2,3,12],save:[2,5,7],scan:3,scanner:[7,18],scenario:16,scope:[6,10],search:[0,10],sec:[15,21],second:[3,7,10,12,14,20,21],section:12,see:[0,6,7,8,9,11,12,13,15,16,19],seem:[0,5,7,14,15,21],seen:[15,16,21],select:3,self:15,semant:[2,3,7,9,10,15],semi:7,send:7,sens:[0,2,5,15,16],separ:[7,15],seq:15,sequenc:[0,1,2,3,5,7,10,12,13,16,17,18,21],sequence_to_stack:15,seri:[5,6,10,16],ses:15,set:[2,3,12,15,17],seven:[5,6],sever:[0,4,7,12],share:[3,7],shelf:2,shift:[5,6],shorter:17,shorthand:10,should:[2,3,5,10,12,15],shouldn:7,show:[4,15,16],shunt:[3,16],side:[10,15,21],signatur:21,signifi:[7,10],similar:[10,14,15],simon:7,simpl:[7,12,20,21],simplefunctionwrapp:[3,13,15],simpler:14,simplest:[15,17],simpli:4,simplifi:[5,10,16],sinc:[2,5,10,15],singl:[3,6,7,13,15,18,21],situ:10,situat:10,six:[5,6,7],sixti:[5,6],size:[7,17],skeptic:7,skip:15,slight:8,slightli:[10,12,15],smallest:3,smart:10,softwar:7,solei:2,solut:[5,6],solvabl:7,some:[2,3,6,7,10,12,14,15,17,20,21],somehow:[10,15],someth:[2,9,10,15],sometim:10,somewher:[10,17],sort:[3,10,15],sort_:3,sorta:[],sourc:[0,1,3,15,17,18,19,20,21],space:[5,19],span:5,spawn:15,special:[6,10,17],specif:[0,4],specifi:[10,21],speed:13,spell:14,sphinx:[17,20,21],spirit:[0,1,14],split:[15,21],sqr:[7,8,11,16],sqrt:[3,8,15,21],squar:[3,8,15,18],squishi:[],stack:[0,1,3,5,6,8,10,11,12,13,14,16,17,18,19,21],stack_concat:[],stack_effect:15,stack_effect_com:15,stack_to_str:20,stacki:15,stackjoytyp:[15,21],stackstarjoytyp:[15,21],stage:14,stai:[0,1],stand:[4,21],standard:[7,10],star:[14,15,21],stare:10,start:[5,6,7,8,10,12,14,15,21],state:7,statement:3,stdout:15,step:[3,5,7,10,13,15,16,17],still:[10,15],stop:10,storag:[5,10],store:[5,12,15],stori:12,str:[1,15,18,19,20],straightforward:[1,6,8,15,17],stream:[5,15],stretch:10,string:[1,2,3,7,15,16,18,19,20,21],strip:[],structur:[7,14,15,16,17,20],stuff:[10,15],stuncon:[3,21],stununcon:[3,21],style:[0,4,15],sub:[9,21],subclass:7,subject:16,subset:[15,21],substitut:[10,15,21],subtract:5,subtyp:17,succ:[3,15,21],succe:15,success:8,suck:15,suffic:15,suffici:10,suffix:15,suggest:[4,10],suitabl:[3,4,5],sum:[3,6,7,11,12,13,14],sum_:[3,15],summand:5,sumtre:14,suppli:[10,18],support:[7,15,19,20],suspect:2,swaack:[3,11,13,15,16,21],swap:[3,5,6,7,8,10,12,13,14,16,21],swarm:[],swon:[3,6,7,12,14,15,16,21],swoncat:[6,7,8,12,14],swuncon:12,symbol:[2,3,15,16,17,18],symboljoytyp:[15,21],symmetr:[5,10],syntact:7,syntax:[7,20],sys:[15,20],system:[7,10],tabl:15,tag:15,tail:[10,15,17,20],take:[3,5,7,8,10,12,15,20],talk:[7,10,15,20],target:16,tast:4,tbd:7,tear:12,technic:2,techniqu:[4,16],technolog:2,temporari:16,ten:5,term:[1,2,7,8,12,15,17,18,20,21],termin:[2,3,12],ternari:7,test:[2,3,12],text:[0,1,3,15],text_to_express:[7,18],textual:7,than:[0,3,5,6,7,8,12,14,15,20,21],thei:[2,5,6,7,10,12,15,16,18,20,21],them:[2,3,5,6,10,12,15,16,17,21],themselv:[15,21],theori:[2,3,12],therefor:6,thi:[0,1,2,3,4,5,6,7,8,11,12,14,15,16,17,18,19,20,21],thing:[2,6,10,12,15,16,18,20,21],think:[2,5,7,10,12,14,15],third:[3,6,7,10,21],thirti:5,those:[2,3,10,12,15,17,21],though:5,thought:7,thousand:5,thread:2,three:[2,3,5,7,10,11,14,15,17],through:[1,5,7,14,15,16,20,21],thun:[2,3,4,9,12],thunder:7,time:[3,5,7,8,10,12,15,16],titl:15,to_set:10,todai:7,todo:[7,18],togeth:[6,7,15,17],token:18,toler:17,too:[12,15],tool:[7,15],tooo:15,top:[2,3,7,12,15,19,20],total:5,tower:15,trace:[0,7,11,12,16,17,20],traceback:[],traceprint:19,track:[11,15,16],tracker:0,transform:4,translat:[4,11,15],trash:[],travers:[0,17],treasur:0,treat:[0,2,3,12,15,17],treatment:6,tree:[0,7,17],treegrind:17,treestep:[0,17],tri:5,triangular_numb:12,trick:[5,15],tricki:15,trobe:0,trove:0,truediv:21,truli:[],trust:[],truthi:[3,7,15],tuck:[3,7,15,21],tupl:[3,7,15,20,21],ture:[],turn:[2,3,15,21],twice:[10,12],two:[2,3,5,7,8,10,11,12,14,15,16,17,20,21],type:[0,1,4,7,10,12,17,18,19,20],typeerror:15,typeless:15,typic:[2,3,11,12],unari:7,unarybuiltinwrapp:3,unbalanc:[10,18],unbound:21,unchang:10,uncompil:15,uncon:[3,6,7,10,12,14,16,21],under:[2,3,7,10],underli:15,underscor:15,understand:[0,10],undistinguish:10,undocu:7,unend:[],unfinish:[],unfortun:20,unicod:15,unif:15,unifi:21,uniqu:[3,10,15],unit:[3,7,12,21],univers:[0,7,15,21],unnecessari:17,unnecesssari:15,unpack:[2,3,10,20],unpair:5,unquot:[7,14],unstack:[3,15],unswon:[3,21],untangl:12,until:6,unus:5,unusu:10,updat:[0,17,21],usag:7,use:[0,2,3,4,5,6,7,8,9,10,11,12,13,14,16,17,20],used:[3,4,7,10,12,15,16,18,20,21],useful:[0,15],user:14,uses:[2,5,12],using:[3,6,10,11,12,14,16,21],usual:[0,2,12],util:[0,3,13,15],valid:15,valu:[0,2,3,5,7,8,11,12,13,14,15,17,20,21],value_n:10,valueerror:[15,20],variabl:[15,17,21],variant:10,variat:[12,17],varieti:[4,7],variou:0,vener:20,verbos:4,veri:[0,1,4,7,10,20],verifi:[],versa:[2,15],version:[0,1,2,6,9,14,16,17],via:7,vice:[2,15],view:[10,17],viewer:[1,7,9,19],vii:17,visibl:15,von:[0,2,3,4,12],wai:[0,2,3,4,5,7,12,13,15],wait:[],want:[2,5,6,8,10,12,15],warranti:[3,7],wash:7,wast:7,web:20,websit:[0,5],welcom:7,well:[0,4,7,8,10,15,18],went:15,were:[7,15,16],what:[2,3,4,7,10,12,14,15,19],whatev:[2,3,12,14,20],when:[5,6,7,10,12,15,16,18,20,21],where:[2,3,7,10,12,15,17,20],whether:12,which:[0,1,3,5,7,8,10,12,14,15,16,20,21],whole:[2,3,5,12,14,15],whose:6,why:[8,14],wiki:10,wikipedia:[0,10,16],wildli:7,wind:7,wire:12,within:[7,10,13,17],without:[2,7,10,11,15],won:[10,15,20],word:[0,3,5,7,12,16],work:[0,3,5,6,7,8,10,11,12,14,16,20,21],worth:5,would:[2,5,6,7,8,10,12,15,16,20,21],wrap:[3,7],wrapper:15,write:[4,8,10,12,14,15,16,17,20],written:[0,1,8,10,13,15,20],wrong:2,wrote:15,xrang:15,yang:15,year:[7,15],yet:[10,15,16],yield:[2,3,12,15,20,21],yin:17,you:[0,2,3,5,6,7,9,10,11,12,13,14,15,16,19,20],your:[2,3,7,12,15],yourself:[7,10],zero:[3,10,12,14,15,18,20,21],zip:[5,15],zip_:3,zipper:[0,17],zstr:16},titles:["Thun 0.2.0 Documentation","Joy Interpreter","Functions Grouped by, er, Function with Examples","Function Reference","Categorical Programming","Developing a Program in Joy","Using <code class=\"docutils literal notranslate\"><span class=\"pre\">x</span></code> to Generate Values","Thun: Joy in Python","Newton\u2019s method","No Updates","Treating Trees I: Ordered Binary Trees","Quadratic formula","Recursive Combinators","Replacing Functions in the Dictionary","Treating Trees II: <code class=\"docutils literal notranslate\"><span class=\"pre\">treestep</span></code>","The Blissful Elegance of Typing Joy","Traversing Datastructures with Zippers","Essays about Programming in Joy","Parsing Text into Joy Expressions","Tracing Joy Execution","Stack or Quote or Sequence or List\u2026","Type Inference of Joy Expressions"],titleterms:{"abstract":[],"case":[8,10],"function":[2,3,7,8,10,12,13,14,15],"long":13,"new":10,"p\u00f6ial":15,"void":2,"while":2,Adding:10,One:[6,10],The:[5,7,10,12,14,15],There:7,Using:6,With:14,about:17,add:[2,10],adding:10,address:16,altern:14,ana:12,analysi:5,anamorph:[2,12],app1:2,app2:2,app3:2,appendix:[10,12,15],approxim:8,argument:15,auto:3,averag:2,base:[8,10],binari:[2,10,14],bliss:15,both:10,branch:[2,10],can:10,cata:12,catamorph:12,categor:4,chatter:2,child:10,choic:2,clear:2,cleav:2,cmp:10,code:[7,10],combin:[2,10,12,15],comment:15,compar:10,comparison:2,compil:[6,15],compile_:15,compos:15,comput:8,con:[2,15],concat:2,conclus:[12,15],consecut:8,continu:7,current:10,datastructur:[7,10,16],deal:15,defin:[10,14],definit:11,delabel:15,delet:10,deriv:[11,12,14],design:12,determin:16,develop:5,dialect:0,dictionari:13,dip:[2,16],dipd:2,dipdd:2,direco:6,disenstacken:2,distinguish:15,div:2,doc_from_stack_effect:15,document:0,doe:10,down_to_zero:2,drop:2,dup:[2,15],dupd:2,dupdip:2,effect:15,eleg:15,els:10,empti:10,enstacken:2,equal:10,essai:17,euler:[5,6],eval:7,even:6,exampl:[2,7,10,12,14],execut:19,express:[7,18,21],extract:14,factori:12,fibonacci:6,filter:5,find:[8,10,12],first:[2,5,15],five:6,flatten:2,flexibl:14,floordiv:2,formula:11,found:10,four:12,fun:12,further:5,gcd:2,gener:[3,5,6,8],genrec:2,get:[10,14],getitem:2,given:14,greater:10,group:2,have:[10,14],help:2,highest:10,host:0,how:[5,6],hybrid:15,hylo:12,hylomorph:12,identifi:15,ift:2,iii:15,implement:15,indic:0,infer:[15,21],inferenc:15,inform:0,infra:[2,16],integ:5,interest:6,interlud:10,intern:18,interpret:[1,7,15],item:16,iter:[5,10],joi:[0,1,3,5,7,12,15,16,17,18,19,20,21],junk:[],just:5,kei:10,languag:0,least_fract:2,left:10,less:10,let:5,librari:[3,7,15],like:10,list:[2,20],literari:7,littl:5,logic:[2,15],loop:[2,7],lower:10,lshift:2,make:[6,8],mani:5,map:2,math:2,method:8,min:2,miscellan:2,mod:2,modifi:15,modulu:2,more:10,most:10,mul:[2,15],multipl:[5,6,15],must:10,name:11,neg:2,newton:8,next:8,node:10,non:10,now:10,nullari:2,number:[12,15],one:7,onli:7,order:[10,14],osdn:0,our:10,over:2,pack:5,pam:2,para:12,paradigm:15,parameter:[10,14],pars:[2,18],parser:[7,18],part:15,pass:7,path:16,pattern:12,per:10,poly_typ:[],polytyp:21,pop:[2,15],popd:2,popop:2,pow:2,power:6,pred:2,predic:[5,8,10,14],pretty_print:19,primit:12,primrec:2,print:7,problem:[5,6],process:10,product:2,program:[4,5,11,14,17],progress:15,project:[0,5,6],pure:7,put:[10,11,14],python:[7,13,15],quadrat:11,quick:0,quot:[2,20],rang:[2,5,12],range_to_zero:2,read:7,recur:[8,10],recurs:[10,12,14],redefin:[10,14],refactor:[5,10],refer:3,regular:7,reimplement:14,relabel:15,rem:2,remaind:2,remov:2,render:5,repl:7,replac:[10,13],repres:15,reset:6,rest:[2,15],revers:2,right:[10,16],rightmost:10,roll:[2,15],rolldown:2,rollup:2,rshift:2,rule:15,run:[2,6],second:[2,15],select:2,sequenc:[6,15,20],set:[8,10],shorter:13,should:7,shunt:2,simpl:15,simplest:5,size:[2,13],someth:[],sourc:10,special:[12,15],sqr:[2,15],sqrt:[2,11],stack:[2,7,15,20],start:0,step:[2,12,14],straightforward:11,structur:10,style:7,sub:[2,10],subtyp:15,succ:2,sum:[2,5],swaack:2,swap:[2,15],swon:2,swoncat:2,symbol:[7,12],tabl:0,tail:12,take:2,term:[5,6,14],ternari:2,text:18,than:10,them:11,thi:10,third:[2,15],three:6,thun:[0,7],time:[2,6],togeth:[10,11,14],token:7,toler:8,trace:[13,19],traceprint:7,travers:[10,14,16],treat:[10,14],tree:[10,14,16],treegrind:14,treestep:14,triangular:12,truediv:2,truthi:2,tuck:2,two:6,type:[15,21],unari:2,unbound:15,uncon:[2,15],unifi:15,unit:2,unnecessari:5,unquot:2,unstack:2,updat:[9,15],use:15,util:[19,20,21],valu:[6,10],variabl:11,variat:6,version:[5,10,13,15],view:7,vii:15,within:8,word:2,work:15,write:11,xor:2,yin:15,zero:6,zip:2,zipper:16}})
\ No newline at end of file
index ab0c360..781c7ad 100644 (file)
@@ -98,6 +98,7 @@ The following is specific information for this dialect of Joy.
    pretty
    library
    lib
+   types
    notebooks/index
 
 
index a8084de..dc209b5 100644 (file)
@@ -1,6 +1,6 @@
 
-Type Inference
-==============
+The Blissful Elegance of Typing Joy
+===================================
 
 This notebook presents a simple type inferencer for Joy code. It can
 infer the stack effect of most Joy expressions. It's built largely by
@@ -476,6 +476,8 @@ integers or tuples of type descriptors:
             s[u] = v
         elif isinstance(v, int):
             s[v] = u
+        else:
+            s = False
     
         return s
 
@@ -709,6 +711,12 @@ work:
     except Exception, e:
         print e
 
+
+.. parsed-literal::
+
+    Cannot unify (1, 2) and (1001, 1002).
+
+
 ``unify()`` version 2
 ^^^^^^^^^^^^^^^^^^^^^
 
@@ -741,6 +749,8 @@ deal with this recursively:
             s = unify(a, c, s)
             if s != False:
                 s = unify(b, d, s)
+        else:
+            s = False
     
         return s
 
@@ -1674,8 +1684,8 @@ such. Note that this is *not* a ``sqr`` function implementation:
 
 (Eventually I should come back around to this becuase it's not tooo
 difficult to exend this code to be able to compile e.g.
-``n3 = mul(n1, n2)`` for ``mul`` and insert it in the right place with
-the right variable names. It requires a little more support from the
+``n2 = mul(n1, n1)`` for ``mul`` with the right variable names and
+insert it in the right place. It requires a little more support from the
 library functions, in that we need to know to call ``mul()`` the Python
 function for ``mul`` the Joy function, but since *most* of the math
 functions (at least) are already wrappers it should be straightforward.)
@@ -2612,7 +2622,7 @@ Part VII: Typing Combinators
 
 In order to compute the stack effect of combinators you kinda have to
 have the quoted programs they expect available. In the most general
-case, the ``i`` combinator, you can't say anything about it's stack
+case, the ``i`` combinator, you can't say anything about its stack
 effect other than it expects one quote:
 
 ::
@@ -2646,8 +2656,11 @@ Obviously it would be:
 Without any information about the contents of the quote we can't say
 much about the result.
 
-I think there's a way forward. If we convert our list of terms we are
-composing into a stack structure we can use it as a *Joy expression*,
+Hybrid Inferencer/Interpreter
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+I think there's a way forward. If we convert our list (of terms we are
+composing) into a stack structure we can use it as a *Joy expression*,
 then we can treat the *output half* of a function's stack effect comment
 as a Joy interpreter stack, and just execute combinators directly. We
 can hybridize the compostition function with an interpreter to evaluate
@@ -2655,6 +2668,13 @@ combinators, compose non-combinator functions, and put type variables on
 the stack. For combinators like ``branch`` that can have more than one
 stack effect we have to "split universes" again and return both.
 
+Joy Types for Functions
+^^^^^^^^^^^^^^^^^^^^^^^
+
+We need a type variable for Joy functions that can go in our expressions
+and be used by the hybrid inferencer/interpreter. They have to store a
+name and a list of stack effects.
+
 .. code:: ipython2
 
     class FunctionJoyType(AnyJoyType):
@@ -2670,217 +2690,212 @@ stack effect we have to "split universes" again and return both.
     
         def __repr__(self):
             return self.name
+
+Specialized for Simple Functions and Combinators
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+For non-combinator functions the stack effects list contains stack
+effect comments (represented by pairs of cons-lists as described above.)
+
+.. code:: ipython2
+
+    class SymbolJoyType(FunctionJoyType):
+        prefix = 'F'
+
+For combinators the list contains Python functions.
+
+.. code:: ipython2
+
+    class CombinatorJoyType(FunctionJoyType):
     
+        prefix = 'C'
     
-    class SymbolJoyType(FunctionJoyType): prefix = 'F'
-    class CombinatorJoyType(FunctionJoyType): prefix = 'C'
+        def __init__(self, name, sec, number, expect=None):
+            super(CombinatorJoyType, self).__init__(name, sec, number)
+            self.expect = expect
     
+        def enter_guard(self, f):
+            if self.expect is None:
+                return f
+            g = self.expect, self.expect
+            new_f = list(compose(f, g, ()))
+            assert len(new_f) == 1, repr(new_f)
+            return new_f[0][1]
+
+For simple combinators that have only one effect (like ``dip``) you only
+need one function and it can be the combinator itself.
+
+.. code:: ipython2
+
+    import joy.library
     
+    dip = CombinatorJoyType('dip', [joy.library.dip], 23)
 
+For combinators that can have more than one effect (like ``branch``) you
+have to write functions that each implement the action of one of the
+effects.
 
 .. code:: ipython2
 
-    def flatten(g):
-        return list(chain.from_iterable(g))
+    def branch_true(stack, expression, dictionary):
+        (then, (else_, (flag, stack))) = stack
+        return stack, concat(then, expression), dictionary
     
+    def branch_false(stack, expression, dictionary):
+        (then, (else_, (flag, stack))) = stack
+        return stack, concat(else_, expression), dictionary
     
+    branch = CombinatorJoyType('branch', [branch_true, branch_false], 100)
+
+You can also provide an optional stack effect, input-side only, that
+will then be used as an identity function (that accepts and returns
+stacks that match the "guard" stack effect) which will be used to guard
+against type mismatches going into the evaluation of the combinator.
+
+``infer()``
+^^^^^^^^^^^
+
+With those in place, we can define a function that accepts a sequence of
+Joy type variables, including ones representing functions (not just
+values), and attempts to grind out all the possible stack effects of
+that expression.
+
+One tricky thing is that type variables *in the expression* have to be
+updated along with the stack effects after doing unification or we risk
+losing useful information. This was a straightforward, if awkward,
+modification to the call structure of ``meta_compose()`` et. al.
+
+.. code:: ipython2
+
     ID = S[0], S[0]  # Identity function.
     
     
-    def infer(e, F=ID):
+    def infer(*expression):
+        return sorted(set(_infer(list_to_stack(expression))))
+    
+    
+    def _infer(e, F=ID):
+        _log_it(e, F)
         if not e:
             return [F]
     
         n, e = e
     
         if isinstance(n, SymbolJoyType):
-            res = flatten(infer(e, Fn) for Fn in MC([F], n.stack_effects))
+            eFG = meta_compose([F], n.stack_effects, e)
+            res = flatten(_infer(e, Fn) for e, Fn in eFG)
     
         elif isinstance(n, CombinatorJoyType):
-            res = []
-            for combinator in n.stack_effects:
-                fi, fo = F
-                new_fo, ee, _ = combinator(fo, e, {})
-                ee = update(FUNCTIONS, ee)  # Fix Symbols.
-                new_F = fi, new_fo
-                res.extend(infer(ee, new_F))
+            fi, fo = n.enter_guard(F)
+            res = flatten(_interpret(f, fi, fo, e) for f in n.stack_effects)
+    
+        elif isinstance(n, Symbol):
+            assert n not in FUNCTIONS, repr(n)
+            func = joy.library._dictionary[n]
+            res = _interpret(func, F[0], F[1], e)
+    
         else:
-            lit = s9, (n, s9)
-            res = flatten(infer(e, Fn) for Fn in MC([F], [lit]))
+            fi, fo = F
+            res = _infer(e, (fi, (n, fo)))
     
         return res
     
-
-
-.. code:: ipython2
-
-    f0, f1, f2, f3, f4, f5, f6, f7, f8, f9 = F = map(FloatJoyType, _R)
-    i0, i1, i2, i3, i4, i5, i6, i7, i8, i9 = I = map(IntJoyType, _R)
-    n0, n1, n2, n3, n4, n5, n6, n7, n8, n9 = N
-    s0, s1, s2, s3, s4, s5, s6, s7, s8, s9 = S
-
-.. code:: ipython2
-
-    import joy.library
     
-    FNs = '''ccons cons divmod_ dup dupd first
-             over pm pop popd popdd popop pred
-             rest rolldown rollup rrest second
-             sqrt stack succ swaack swap swons
-             third tuck uncons'''
+    def _interpret(f, fi, fo, e):
+        new_fo, ee, _ = f(fo, e, {})
+        ee = update(FUNCTIONS, ee)  # Fix Symbols.
+        new_F = fi, new_fo
+        return _infer(ee, new_F)
     
-    FUNCTIONS = {
-        name: SymbolJoyType(name, [NEW_DEFS[name]], i)
-        for i, name in enumerate(FNs.strip().split())
-        }
-    FUNCTIONS['sum'] = SymbolJoyType('sum', [(((Ns[1], s1), s0), (n0, s0))], 100)
-    FUNCTIONS['mul'] = SymbolJoyType('mul', [
-         ((i2, (i1, s0)), (i3, s0)),
-         ((f2, (i1, s0)), (f3, s0)),
-         ((i2, (f1, s0)), (f3, s0)),
-         ((f2, (f1, s0)), (f3, s0)),
-    ], 101)
-    FUNCTIONS.update({
-        combo.__name__: CombinatorJoyType(combo.__name__, [combo], i)
-        for i, combo in enumerate((
-            joy.library.i,
-            joy.library.dip,
-            joy.library.dipd,
-            joy.library.dipdd,
-            joy.library.dupdip,
-            joy.library.b,
-            joy.library.x,
-            joy.library.infra,
-            ))
-        })
     
-    def branch_true(stack, expression, dictionary):
-        (then, (else_, (flag, stack))) = stack
-        return stack, CONCAT(then, expression), dictionary
-    
-    def branch_false(stack, expression, dictionary):
-        (then, (else_, (flag, stack))) = stack
-        return stack, CONCAT(else_, expression), dictionary
-    
-    FUNCTIONS['branch'] = CombinatorJoyType('branch', [branch_true, branch_false], 100)
-
-.. code:: ipython2
-
-    globals().update(FUNCTIONS)
-
-.. code:: ipython2
-
-    from itertools import chain
-    from joy.utils.stack import list_to_stack as l2s
-
-.. code:: ipython2
-
-    expression = l2s([n1, n2, (mul, s2), (stack, s3), dip, infra, first])
-
-.. code:: ipython2
-
-    expression
-
-
-
-
-.. parsed-literal::
-
-    (n1, (n2, ((mul, s2), ((stack, s3), (dip, (infra, (first, ())))))))
-
-
-
-.. code:: ipython2
-
-    expression = l2s([n1, n2, mul])
-
-.. code:: ipython2
-
-    expression
-
-
-
-
-.. parsed-literal::
-
-    (n1, (n2, (mul, ())))
-
-
-
-.. code:: ipython2
-
-    infer(expression)
-
-
-
-
-.. parsed-literal::
-
-    [(s1, (f1, s1)), (s1, (i1, s1))]
-
-
-
-.. code:: ipython2
-
-    infer(expression)
-
-
-
-
-.. parsed-literal::
-
-    [(s1, (f1, s1)), (s1, (i1, s1))]
-
-
-
-.. code:: ipython2
-
-    for stack_effect_comment in infer(expression):
-        print doc_from_stack_effect(*stack_effect_comment)
-
-
-.. parsed-literal::
-
-    (-- f1)
-    (-- i1)
-
-
-.. code:: ipython2
-
-    expression
-
-
-
-
-.. parsed-literal::
-
-    (n1, (n2, (mul, ())))
+    def _log_it(e, F):
+        _log.info(
+            u'%3i %s ∘ %s',
+            len(inspect_stack()),
+            doc_from_stack_effect(*F),
+            expression_to_string(e),
+            )
 
+Work in Progress
+^^^^^^^^^^^^^^^^
 
+And that brings us to current Work-In-Progress. The mixed-mode
+inferencer/interpreter ``infer()`` function seems to work well. There
+are details I should document, and the rest of the code in the
+"polytypes" module (FIXME link to its docs here!) should be explained...
+There is cruft to convert the definitions in ``DEFS`` to the new
+``SymbolJoyType`` objects, and some combinators. Here is an example of
+output from the current code :
 
 .. code:: ipython2
 
-    infer(expression)
-
-
-
-
-.. parsed-literal::
-
-    [(s1, (f1, s1)), (s1, (i1, s1))]
-
-
-
-And that brings us to current Work-In-Progress. I'm pretty hopeful that
-the mixed-mode inferencer/interpreter ``infer()`` function along with
-the ability to specify multiple implementations for the combinators will
-permit modelling of the stack effects of e.g. ``ifte``. If I can keep up
-the pace I should be able to verify that conjecture by the end of June.
+    1/0  # (Don't try to run this cell!  It's not going to work.  This is "read only" code heh..)
+    
+    logging.basicConfig(format='%(message)s', stream=sys.stdout, level=logging.INFO)
+    
+    globals().update(FUNCTIONS)
+    
+    h = infer((pred, s2), (mul, s3), (div, s4), (nullary, (bool, s5)), dipd, branch)
+    
+    print '-' * 40
+    
+    for fi, fo in h:
+        print doc_from_stack_effect(fi, fo)
+
+The numbers at the start of the lines are the current depth of the
+Python call stack. They're followed by the current computed stack effect
+(initialized to ``ID``) then the pending expression (the inference of
+the stack effect of which is the whole object of the current example.)
+
+In this example we are implementing (and inferring) ``ifte`` as
+``[nullary bool] dipd branch`` which shows off a lot of the current
+implementation in action.
+
+::
+
+      7 (--) ∘ [pred] [mul] [div] [nullary bool] dipd branch
+      8 (-- [pred ...2]) ∘ [mul] [div] [nullary bool] dipd branch
+      9 (-- [pred ...2] [mul ...3]) ∘ [div] [nullary bool] dipd branch
+     10 (-- [pred ...2] [mul ...3] [div ...4]) ∘ [nullary bool] dipd branch
+     11 (-- [pred ...2] [mul ...3] [div ...4] [nullary bool ...5]) ∘ dipd branch
+     15 (-- [pred ...5]) ∘ nullary bool [mul] [div] branch
+     19 (-- [pred ...2]) ∘ [stack] dinfrirst bool [mul] [div] branch
+     20 (-- [pred ...2] [stack ]) ∘ dinfrirst bool [mul] [div] branch
+     22 (-- [pred ...2] [stack ]) ∘ dip infra first bool [mul] [div] branch
+     26 (--) ∘ stack [pred] infra first bool [mul] [div] branch
+     29 (... -- ... [...]) ∘ [pred] infra first bool [mul] [div] branch
+     30 (... -- ... [...] [pred ...1]) ∘ infra first bool [mul] [div] branch
+     34 (--) ∘ pred s1 swaack first bool [mul] [div] branch
+     37 (n1 -- n2) ∘ [n1] swaack first bool [mul] [div] branch
+     38 (... n1 -- ... n2 [n1 ...]) ∘ swaack first bool [mul] [div] branch
+     41 (... n1 -- ... n1 [n2 ...]) ∘ first bool [mul] [div] branch
+     44 (n1 -- n1 n2) ∘ bool [mul] [div] branch
+     47 (n1 -- n1 b1) ∘ [mul] [div] branch
+     48 (n1 -- n1 b1 [mul ...1]) ∘ [div] branch
+     49 (n1 -- n1 b1 [mul ...1] [div ...2]) ∘ branch
+     53 (n1 -- n1) ∘ div
+     56 (f2 f1 -- f3) ∘ 
+     56 (i1 f1 -- f2) ∘ 
+     56 (f1 i1 -- f2) ∘ 
+     56 (i2 i1 -- f1) ∘ 
+     53 (n1 -- n1) ∘ mul
+     56 (f2 f1 -- f3) ∘ 
+     56 (i1 f1 -- f2) ∘ 
+     56 (f1 i1 -- f2) ∘ 
+     56 (i2 i1 -- i3) ∘ 
+    ----------------------------------------
+    (f2 f1 -- f3)
+    (i1 f1 -- f2)
+    (f1 i1 -- f2)
+    (i2 i1 -- f1)
+    (i2 i1 -- i3)
 
 Conclusion
 ----------
 
-(for now...)
+We built a simple type inferencer, and a kind of crude "compiler" for a
+subset of Joy functions. Then we built a more powerful inferencer that
+actually does some evaluation and explores branching code paths
 
 Work remains to be done:
 
@@ -2900,21 +2915,18 @@ Work remains to be done:
    went off and just started writing code to see if it would work. It
    does, but now I have to come back and describe here what I did.
 
-I'm starting to realize that, with the inferencer/checker/compiler
-coming along, and with the UI ready to be rewritten in Joy, I'm close to
-a time when my ephasis is going to have to shift from crunchy code stuff
-to squishy human stuff. I'm going to have to put normal people in front
-of this and see if, in fact, they *can* learn the basics of programming
-with it.
-
-The rest of this stuff is junk and/or unfinished material.
-
 Appendix: Joy in the Logical Paradigm
 -------------------------------------
 
-For this to work the type label classes have to be modified to let
-``T >= t`` succeed, where e.g. ``T`` is ``IntJoyType`` and ``t`` is
-``int``
+For *type checking* to work the type label classes have to be modified
+to let ``T >= t`` succeed, where e.g. ``T`` is ``IntJoyType`` and ``t``
+is ``int``. If you do that you can take advantage of the *logical
+relational* nature of the stack effect comments to "compute in reverse"
+as it were. There's a working demo of this at the end of the
+``polytypes`` module. But if you're interested in all that you should
+just use Prolog!
+
+Anyhow, type *checking* is a few easy steps away.
 
 .. code:: ipython2
 
@@ -2926,383 +2938,3 @@ For this to work the type label classes have to be modified to let
     AnyJoyType.__ge__ = _ge
     AnyJoyType.accept = tuple, int, float, long, str, unicode, bool, Symbol
     StackJoyType.accept = tuple
-
-.. code:: ipython2
-
-    F = infer(l2s((pop, swap, rolldown, rest, rest, cons, cons)))
-    
-    for f in F:
-        print doc_from_stack_effect(*f)
-
-
-.. parsed-literal::
-
-    ([a4 a5 .1.] a3 a2 a1 -- [a2 a3 .1.])
-
-
-.. code:: ipython2
-
-    from joy.parser import text_to_expression
-
-.. code:: ipython2
-
-    F = infer(l2s((pop, pop, pop)))
-    
-    for f in F:
-        print doc_from_stack_effect(*f)
-
-
-.. parsed-literal::
-
-    (a3 a2 a1 --)
-
-
-.. code:: ipython2
-
-    s = text_to_expression('0 1 2')
-    s
-
-
-
-
-.. parsed-literal::
-
-    (0, (1, (2, ())))
-
-
-
-.. code:: ipython2
-
-    F[0][0]
-
-
-
-
-.. parsed-literal::
-
-    (a1, (a2, (a3, s1)))
-
-
-
-.. code:: ipython2
-
-    L = unify(s, F[0][0])
-    L
-
-
-
-
-.. parsed-literal::
-
-    ()
-
-
-
-.. code:: ipython2
-
-    s = text_to_expression('0 1 2 [3 4]')
-    s
-
-
-
-
-.. parsed-literal::
-
-    (0, (1, (2, ((3, (4, ())), ()))))
-
-
-
-.. code:: ipython2
-
-    F[0][0]
-
-
-
-
-.. parsed-literal::
-
-    (a1, (a2, (a3, s1)))
-
-
-
-.. code:: ipython2
-
-    L = unify(s, F[0][0])
-    L
-
-
-
-
-.. parsed-literal::
-
-    ()
-
-
-
-.. code:: ipython2
-
-    L = unify(F[0][0], s)
-    L
-
-
-
-
-.. parsed-literal::
-
-    ()
-
-
-
-.. code:: ipython2
-
-    F[1][0]
-
-
-::
-
-
-    ---------------------------------------------------------------------------
-
-    IndexError                                Traceback (most recent call last)
-
-    <ipython-input-133-58a8e44e9cba> in <module>()
-    ----> 1 F[1][0]
-    
-
-    IndexError: list index out of range
-
-
-.. code:: ipython2
-
-    s[0]
-
-.. code:: ipython2
-
-    A[1] >= 23
-
-`Abstract Interpretation <https://en.wikipedia.org/wiki/Abstract_interpretation>`__
------------------------------------------------------------------------------------
-
-I *think* this might be sorta what I'm doing above with the ``kav()``
-function... In any event "mixed-mode" interpreters that include values
-and type variables and can track constraints, etc. will be, uh,
-super-useful. And Abstract Interpretation should be a rich source of
-ideas.
-
-Junk
-----
-
-.. code:: ipython2
-
-    class SymbolJoyType(AnyJoyType): prefix = 'F'
-    
-    W = map(SymbolJoyType, _R)
-    
-    k = S[0], ((W[1], S[2]), S[0])
-    Symbol('cons')
-    print doc_from_stack_effect(*k)
-
-
-.. code:: ipython2
-
-    dip_a = ((W[1], S[2]), (A[1], S[0]))
-
-.. code:: ipython2
-
-    d = relabel(S[0], dip_a)
-    print doc_from_stack_effect(*d)
-
-.. code:: ipython2
-
-    s = list(unify(d[1], k[1]))[0]
-    s
-
-.. code:: ipython2
-
-    j = update(s, k)
-
-.. code:: ipython2
-
-    print doc_from_stack_effect(*j)
-
-.. code:: ipython2
-
-    j
-
-.. code:: ipython2
-
-    cons
-
-.. code:: ipython2
-
-    for f in MC([k], [dup]):
-        print doc_from_stack_effect(*f)
-
-.. code:: ipython2
-
-    l = S[0], ((cons, S[2]), (A[1], S[0]))
-
-.. code:: ipython2
-
-    print doc_from_stack_effect(*l)
-
-.. code:: ipython2
-
-    
-    def dip_t(F):
-        (quote, (a1, sec)) = F[1]
-        G = F[0], sec
-        P = S[3], (a1, S[3])
-        a = [P]
-        while isinstance(quote, tuple):
-            term, quote = quote
-            a.append(term)
-        a.append(G)
-        return a[::-1]
-    
-    
-    
-
-
-.. code:: ipython2
-
-    from joy.utils.stack import iter_stack
-
-.. code:: ipython2
-
-    a, b, c = dip_t(l)
-
-.. code:: ipython2
-
-    a
-
-.. code:: ipython2
-
-    b
-
-.. code:: ipython2
-
-    c
-
-.. code:: ipython2
-
-    MC([a], [b])
-
-.. code:: ipython2
-
-    kjs = MC(MC([a], [b]), [c])
-    kjs
-
-.. code:: ipython2
-
-    print doc_from_stack_effect(*kjs[0])
-
-::
-
-    (a0 [.0.] -- [a0 .0.] a1)
-
-       a0 [.0.] a1 [cons] dip
-    ----------------------------
-       [a0 .0.] a1
-
-``concat``
-~~~~~~~~~~
-
-How to deal with ``concat``?
-
-::
-
-    concat ([.0.] [.1.] -- [.0. .1.])
-
-We would like to represent this in Python somehow...
-
-.. code:: ipython2
-
-    concat = (S[0], S[1]), ((S[0], S[1]),)
-
-But this is actually ``cons`` with the first argument restricted to be a
-stack:
-
-::
-
-    ([.0.] [.1.] -- [[.0.] .1.])
-
-What we have implemented so far would actually only permit:
-
-::
-
-    ([.0.] [.1.] -- [.2.])
-
-.. code:: ipython2
-
-    concat = (S[0], S[1]), (S[2],)
-
-Which works but can lose information. Consider ``cons concat``, this is
-how much information we *could* retain:
-
-::
-
-    (1 [.0.] [.1.] -- [1 .0. .1.])
-
-As opposed to just:
-
-::
-
-    (1 [.0.] [.1.] -- [.2.])
-
-represent ``concat``
-~~~~~~~~~~~~~~~~~~~~
-
-::
-
-    ([.0.] [.1.] -- [A*(.0.) .1.])
-
-Meaning that ``A*`` on the right-hand side should all the crap from
-``.0.``.
-
-::
-
-    ([      .0.] [.1.] -- [      A* .1.])
-    ([a     .0.] [.1.] -- [a     A* .1.])
-    ([a b   .0.] [.1.] -- [a b   A* .1.])
-    ([a b c .0.] [.1.] -- [a b c A* .1.])
-
-or...
-
-::
-
-    ([       .0.] [.1.] -- [       .1.])
-    ([a      .0.] [.1.] -- [a      .1.])
-    ([a b    .0.] [.1.] -- [a b    .1.])
-    ([a b  c .0.] [.1.] -- [a b  c .1.])
-    ([a A* c .0.] [.1.] -- [a A* c .1.])
-
-::
-
-    (a, (b, S0)) . S1 = (a, (b, (A*, S1)))
-
-.. code:: ipython2
-
-    class Astar(object):
-        def __repr__(self):
-            return 'A*'
-    
-    
-    def concat(s0, s1):
-        a = []
-        while isinstance(s0, tuple):
-            term, s0 = s0
-            a.append(term)
-        assert isinstance(s0, StackJoyType), repr(s0)
-        s1 = Astar(), s1
-        for term in reversed(a):
-            s1 = term, s1
-        return s1
-
-.. code:: ipython2
-
-    a, b = (A[1], S[0]), (A[2], S[1])
-
-.. code:: ipython2
-
-    concat(a, b)
diff --git a/docs/sphinx_docs/types.rst b/docs/sphinx_docs/types.rst
new file mode 100644 (file)
index 0000000..4b8240b
--- /dev/null
@@ -0,0 +1,141 @@
+
+Type Inference of Joy Expressions
+=================================
+
+Two kinds of type inference are provided, a simple inferencer that can handle functions that have a single stack effect (aka "type signature") and that can generate Python code for a limited subset of those functions, and a more complex inferencer/interpreter hybrid that can infer the stack effects of most Joy expressions, including multiple stack effects, unbounded sequences of values, and combinators (if enough information is available.)
+
+
+``joy.utils.types``
+-------------------
+
+
+Curently (asterix after name indicates a function that can be auto-compiled to Python)::
+
+    _Tree_add_Ee = ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) *
+    _Tree_delete_R0 = ([a2 ...1] a1 -- [a2 ...1] a2 a1 a1) *
+    _Tree_delete_clear_stuff = (a3 a2 [a1 ...1] -- [...1]) *
+    _Tree_get_E = ([a3 a4 ...1] a2 a1 -- a4) *
+    add = (n1 n2 -- n3)  
+    and = (b1 b2 -- b3)  
+    bool = (a1 -- b1)  
+    ccons = (a2 a1 [...1] -- [a2 a1 ...1]) *
+    cons = (a1 [...0] -- [a1 ...0]) *
+    div = (n1 n2 -- n3)  
+    divmod = (n2 n1 -- n4 n3)  
+    dup = (a1 -- a1 a1) *
+    dupd = (a2 a1 -- a2 a2 a1) *
+    dupdd = (a3 a2 a1 -- a3 a3 a2 a1) *
+    eq = (n1 n2 -- b1)  
+    first = ([a1 ...1] -- a1) *
+    first_two = ([a1 a2 ...1] -- a1 a2) *
+    floordiv = (n1 n2 -- n3)  
+    fourth = ([a1 a2 a3 a4 ...1] -- a4) *
+    ge = (n1 n2 -- b1)  
+    gt = (n1 n2 -- b1)  
+    le = (n1 n2 -- b1)  
+    lshift = (n1 n2 -- n3)  
+    lt = (n1 n2 -- b1)  
+    modulus = (n1 n2 -- n3)  
+    mul = (n1 n2 -- n3)  
+    ne = (n1 n2 -- b1)  
+    neg = (n1 -- n2)  
+    not = (a1 -- b1)  
+    over = (a2 a1 -- a2 a1 a2) *
+    pm = (n2 n1 -- n4 n3)  
+    pop = (a1 --) *
+    popd = (a2 a1 -- a1) *
+    popdd = (a3 a2 a1 -- a2 a1) *
+    popop = (a2 a1 --) *
+    popopd = (a3 a2 a1 -- a1) *
+    popopdd = (a4 a3 a2 a1 -- a2 a1) *
+    pow = (n1 n2 -- n3)  
+    pred = (n1 -- n2)  
+    rest = ([a1 ...0] -- [...0]) *
+    rolldown = (a1 a2 a3 -- a2 a3 a1) *
+    rollup = (a1 a2 a3 -- a3 a1 a2) *
+    rrest = ([a1 a2 ...1] -- [...1]) *
+    rshift = (n1 n2 -- n3)  
+    second = ([a1 a2 ...1] -- a2) *
+    sqrt = (n1 -- n2)  
+    stack = (... -- ... [...]) *
+    stuncons = (... a1 -- ... a1 a1 [...]) *
+    stununcons = (... a2 a1 -- ... a2 a1 a1 a2 [...]) *
+    sub = (n1 n2 -- n3)  
+    succ = (n1 -- n2)  
+    swaack = ([...1] -- [...0]) *
+    swap = (a1 a2 -- a2 a1) *
+    swons = ([...1] a1 -- [a1 ...1]) *
+    third = ([a1 a2 a3 ...1] -- a3) *
+    truediv = (n1 n2 -- n3)  
+    tuck = (a2 a1 -- a1 a2 a1) *
+    uncons = ([a1 ...0] -- a1 [...0]) *
+    unit = (a1 -- [a1 ]) *
+    unswons = ([a1 ...1] -- [...1] a1) *
+
+
+.. automodule:: joy.utils.types
+   :members:
+
+
+``joy.utils.polytypes``
+-------------------------
+
+Example output of the ``infer()`` function.  The first number on each line is the depth of the Python stack.  It goes down when the function backtracks.  The next thing on each line is the currently-computed stack effect so far.  It starts with the empty "identity function" and proceeds through the expression, which is the rest of each line.  The function acts like an interpreter but instead of executing the terms of the expression it composes them, but for combinators it *does* execute them, using the output side of the stack effect as the stack.  This seems to work fine.  With proper definitions for the behavior of the combinators that can have more than one effect (like ``branch`` or ``loop``) the ``infer()`` function seems to be able to handle anything I throw at it so far.
+
+::
+
+      7 (--) ∘ pop swap rolldown rest rest cons cons
+     10 (a1 --) ∘ swap rolldown rest rest cons cons
+     13 (a3 a2 a1 -- a2 a3) ∘ rolldown rest rest cons cons
+     16 (a4 a3 a2 a1 -- a2 a3 a4) ∘ rest rest cons cons
+     19 ([a4 ...1] a3 a2 a1 -- a2 a3 [...1]) ∘ rest cons cons
+     22 ([a4 a5 ...1] a3 a2 a1 -- a2 a3 [...1]) ∘ cons cons
+     25 ([a4 a5 ...1] a3 a2 a1 -- a2 [a3 ...1]) ∘ cons
+     28 ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) ∘ 
+    ----------------------------------------
+    ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1])
+
+
+Here's another example (implementing ``ifte``) using some combinators::
+
+      7 (--) ∘ [pred] [mul] [div] [nullary bool] dipd branch
+      8 (-- [pred ...2]) ∘ [mul] [div] [nullary bool] dipd branch
+      9 (-- [pred ...2] [mul ...3]) ∘ [div] [nullary bool] dipd branch
+     10 (-- [pred ...2] [mul ...3] [div ...4]) ∘ [nullary bool] dipd branch
+     11 (-- [pred ...2] [mul ...3] [div ...4] [nullary bool ...5]) ∘ dipd branch
+     15 (-- [pred ...5]) ∘ nullary bool [mul] [div] branch
+     19 (-- [pred ...2]) ∘ [stack] dinfrirst bool [mul] [div] branch
+     20 (-- [pred ...2] [stack ]) ∘ dinfrirst bool [mul] [div] branch
+     22 (-- [pred ...2] [stack ]) ∘ dip infra first bool [mul] [div] branch
+     26 (--) ∘ stack [pred] infra first bool [mul] [div] branch
+     29 (... -- ... [...]) ∘ [pred] infra first bool [mul] [div] branch
+     30 (... -- ... [...] [pred ...1]) ∘ infra first bool [mul] [div] branch
+     34 (--) ∘ pred s1 swaack first bool [mul] [div] branch
+     37 (n1 -- n2) ∘ [n1] swaack first bool [mul] [div] branch
+     38 (... n1 -- ... n2 [n1 ...]) ∘ swaack first bool [mul] [div] branch
+     41 (... n1 -- ... n1 [n2 ...]) ∘ first bool [mul] [div] branch
+     44 (n1 -- n1 n2) ∘ bool [mul] [div] branch
+     47 (n1 -- n1 b1) ∘ [mul] [div] branch
+     48 (n1 -- n1 b1 [mul ...1]) ∘ [div] branch
+     49 (n1 -- n1 b1 [mul ...1] [div ...2]) ∘ branch
+     53 (n1 -- n1) ∘ div
+     56 (f2 f1 -- f3) ∘ 
+     56 (i1 f1 -- f2) ∘ 
+     56 (f1 i1 -- f2) ∘ 
+     56 (i2 i1 -- f1) ∘ 
+     53 (n1 -- n1) ∘ mul
+     56 (f2 f1 -- f3) ∘ 
+     56 (i1 f1 -- f2) ∘ 
+     56 (f1 i1 -- f2) ∘ 
+     56 (i2 i1 -- i3) ∘ 
+    ----------------------------------------
+    (f2 f1 -- f3)
+    (i1 f1 -- f2)
+    (f1 i1 -- f2)
+    (i2 i1 -- f1)
+    (i2 i1 -- i3)
+
+.. automodule:: joy.utils.polytypes
+   :members:
+
+
index 13176c5..683c5e1 100644 (file)
@@ -125,6 +125,9 @@ step_zero == 0 roll> step
 codireco == cons dip rest cons
 make_generator == [codireco] ccons
 '''
+# ifte == [nullary not] dipd branch
+# ifte == [nullary] dipd swap branch
+              
 ##ccons == cons cons
 ##unit == [] cons
 ##second == rest first
index c467cc3..55ea077 100644 (file)
@@ -1,3 +1,4 @@
+# -*- coding: utf_8
 '''
 
 Multiple Stack Effects
@@ -8,22 +9,29 @@ and we can introduce a kind of Kleene Star or sequence type that can stand for
 an unbounded sequence of other types.
 
 '''
+from inspect import stack as inspect_stack
 from itertools import chain, product
+from logging import getLogger
+
+_log = getLogger(__name__)
 
 import joy.library
 from joy.parser import Symbol
-from joy.utils.stack import concat as CONCAT
+from joy.utils.stack import (
+    concat as CONCAT,
+    expression_to_string,
+    list_to_stack,
+    )
 from joy.utils.types import (
   AnyJoyType, A,
   BooleanJoyType, B,
-  C,
   DEFS,
   doc_from_stack_effect,
   FloatJoyType, F,
   JoyTypeError,
   NumberJoyType, N,
   StackJoyType, S,
-  stacky,
+  _stacky,
   _R,
   relabel, delabel,
   update,
@@ -107,10 +115,28 @@ class FunctionJoyType(AnyJoyType):
         return self.name
 
 
-class SymbolJoyType(FunctionJoyType): prefix = 'F'
+class SymbolJoyType(FunctionJoyType):
+    '''
+    Represent non-combinator functions.
+
+    These type variables carry the stack effect comments and can
+    appear in expressions (as in quoted programs.)
+    '''
+    prefix = 'F'
 
 
 class CombinatorJoyType(FunctionJoyType):
+    '''
+    Represent combinators.
+    
+    These type variables carry Joy functions that implement the
+    behaviour of Joy combinators and they can appear in expressions.
+    For simple combinators the implementation functions can be the
+    combinators themselves.
+
+    These types can also specify a stack effect (input side only) to
+    guard against being used on invalid types.
+    '''
 
     prefix = 'C'
 
@@ -122,13 +148,15 @@ class CombinatorJoyType(FunctionJoyType):
         if self.expect is None:
             return f
         g = self.expect, self.expect
-        new_f = list(C(f, g, ()))
+        new_f = list(compose(f, g, ()))
         assert len(new_f) == 1, repr(new_f)
         return new_f[0][1]
 
 
-
 def unify(u, v, s=None):
+    '''
+    Return a tuple of substitution dicts representing unifiers for u and v.
+    '''
     if s is None:
         s = {}
     elif s:
@@ -136,12 +164,9 @@ def unify(u, v, s=None):
         v = update(s, v)
 
     if u == v:
-        return s,
+        res = s,
 
-    if isinstance(u, AnyJoyType) and isinstance(v, AnyJoyType):
-        return _lil_uni(u, v, s)
-
-    if isinstance(u, tuple) and isinstance(v, tuple):
+    elif isinstance(u, tuple) and isinstance(v, tuple):
         if len(u) != 2 or len(v) != 2:
             raise JoyTypeError('Cannot unify %r and %r.' % (u, v))
 
@@ -149,41 +174,44 @@ def unify(u, v, s=None):
         if isinstance(a, KleeneStar):
             if isinstance(c, KleeneStar):
                 s = _lil_uni(a, c, s)  # Attempt to unify the two K-stars.
-                return unify(d, b, s[0])
-
-            # Two universes, in one the Kleene star disappears and unification
-            # continues without it...
-            s0 = unify(u, b)
-            
-            # In the other it spawns a new variable.
-            s1 = unify(u, (a.another(), v))
-            
-            t = s0 + s1
-            for sn in t:
-                sn.update(s)
-            return t
-
-        if isinstance(c, KleeneStar):
-            t = unify(v, d) + unify(v, (c.another(), u))
-            for sn in t:
+                res = unify(d, b, s[0])
+
+            else:
+                # Two universes, in one the Kleene star disappears and
+                # unification continues without it...
+                s0 = unify(u, b)
+                
+                # In the other it spawns a new variable.
+                s1 = unify(u, (a.another(), v))
+                
+                res = s0 + s1
+                for sn in res:
+                    sn.update(s)
+
+        elif isinstance(c, KleeneStar):
+            res = unify(v, d) + unify(v, (c.another(), u))
+            for sn in res:
               sn.update(s)
-            return t
 
-        return tuple(flatten(unify(d, b, sn) for sn in unify(c, a, s)))
+        else:
+            res = tuple(flatten(unify(d, b, sn) for sn in unify(c, a, s)))
  
-    if isinstance(v, tuple):
-        if not stacky(u):
+    elif isinstance(v, tuple):
+        if not _stacky(u):
             raise JoyTypeError('Cannot unify %r and %r.' % (u, v))
         s[u] = v
-        return s,
+        res = s,
 
-    if isinstance(u, tuple):
-        if not stacky(v):
+    elif isinstance(u, tuple):
+        if not _stacky(v):
             raise JoyTypeError('Cannot unify %r and %r.' % (v, u))
         s[v] = u
-        return s,
+        res = s,
+
+    else:
+        res = _lil_uni(u, v, s)
 
-    return _lil_uni(u, v, s)
+    return res
 
 
 def _lil_uni(u, v, s):
@@ -196,28 +224,36 @@ def _lil_uni(u, v, s):
     raise JoyTypeError('Cannot unify %r and %r.' % (u, v))
 
 
-def compose(f, g, e):
+def _compose(f, g, e):
     (f_in, f_out), (g_in, g_out) = f, g
     for s in unify(g_in, f_out):
         yield update(s, (e, (f_in, g_out)))
 
 
-def C(f, g, e):
+def compose(f, g, e):
+    '''
+    Yield the stack effects of the composition of two stack effects.  An
+    expression is carried along and updated and yielded.
+    '''
     f, g = relabel(f, g)
-    for fg in compose(f, g, e):
+    for fg in _compose(f, g, e):
         yield delabel(fg)
 
 
-def meta_compose(F, G, e):
+def _meta_compose(F, G, e):
     for f, g in product(F, G):
         try:
-            for result in C(f, g, e): yield result
+            for result in compose(f, g, e): yield result
         except JoyTypeError:
             pass
 
 
-def MC(F, G, e):
-    res = sorted(set(meta_compose(F, G, e)))
+def meta_compose(F, G, e):
+    '''
+    Yield the stack effects of the composition of two lists of stack
+    effects.  An expression is carried along and updated and yielded.
+    '''
+    res = sorted(set(_meta_compose(F, G, e)))
     if not res:
         raise JoyTypeError('Cannot unify %r and %r.' % (F, G))
     return res
@@ -230,14 +266,16 @@ def flatten(g):
 ID = S[0], S[0]  # Identity function.
 
 
-def infer(e, F=ID):
+def _infer(e, F=ID):
+    _log_it(e, F)
     if not e:
         return [F]
 
     n, e = e
 
     if isinstance(n, SymbolJoyType):
-        res = flatten(infer(e, Fn) for e, Fn in MC([F], n.stack_effects, e))
+        eFG = meta_compose([F], n.stack_effects, e)
+        res = flatten(_infer(e, Fn) for e, Fn in eFG)
 
     elif isinstance(n, CombinatorJoyType):
         fi, fo = n.enter_guard(F)
@@ -250,7 +288,7 @@ def infer(e, F=ID):
 
     else:
         fi, fo = F
-        res = infer(e, (fi, (n, fo)))
+        res = _infer(e, (fi, (n, fo)))
 
     return res
 
@@ -259,7 +297,34 @@ def _interpret(f, fi, fo, e):
   new_fo, ee, _ = f(fo, e, {})
   ee = update(FUNCTIONS, ee)  # Fix Symbols.
   new_F = fi, new_fo
-  return infer(ee, new_F)
+  return _infer(ee, new_F)
+
+
+def _log_it(e, F):
+    _log.info(
+        u'%3i %s ∘ %s',
+        len(inspect_stack()),
+        doc_from_stack_effect(*F),
+        expression_to_string(e),
+        )
+
+
+def infer(*expression):
+    '''
+    Return a list of stack effects for a Joy expression.
+
+    For example::
+
+        h = infer(pop, swap, rolldown, rest, rest, cons, cons)
+        for fi, fo in h:
+            print doc_from_stack_effect(fi, fo)
+
+    Prints::
+
+        ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1])
+
+    '''
+    return sorted(set(_infer(list_to_stack(expression))))
 
 
 a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 = A
@@ -275,34 +340,76 @@ Ns = map(NumberStarJoyType, _R)
 Ss = map(StackStarJoyType, _R)
 
 
+'''Docstring for functions in Sphinx?'''
 FUNCTIONS = {
     name: SymbolJoyType(name, [DEFS[name]], i)
     for i, name in enumerate('''
-        ccons cons divmod_ dup dupd dupdd first first_two fourth over pop
+        ccons cons divmod dup dupd dupdd first first_two fourth over pop
         popd popdd popop popopd popopdd rest rrest rolldown rollup second
         stack swaack swap swons third tuck uncons unswons stuncons
-        stununcons unit eq ge gt le lt ne and_ bool_ not_
+        stununcons unit eq ge gt le lt ne and bool not
+        _Tree_add_Ee _Tree_delete_R0 _Tree_delete_clear_stuff _Tree_get_E
         '''.strip().split())
     }
-# sqrt succ pred pm
-FUNCTIONS['sum'] = SymbolJoyType('sum', [(((Ns[1], s1), s0), (n0, s0))], 100)
-FUNCTIONS['mul'] = SymbolJoyType('mul', [
-     ((i2, (i1, s0)), (i3, s0)),
-     ((f2, (i1, s0)), (f3, s0)),
-     ((i2, (f1, s0)), (f3, s0)),
-     ((f2, (f1, s0)), (f3, s0)),
-], 101)
+
+
+def defs():
+    '''
+    Return a dict of FunctionJoyType instances to be used with ``infer()``.
+    '''
+
+    sum_ = product = [(((Ns[1], s1), s0), (n0, s0))]
+
+    add = mul = sub = floordiv = modulus = [
+        ((i2, (i1, s0)), (i3, s0)),
+        ((f2, (i1, s0)), (f3, s0)),
+        ((i2, (f1, s0)), (f3, s0)),
+        ((f2, (f1, s0)), (f3, s0)),
+        ]
+
+    div = truediv = pow_ = [
+        ((i2, (i1, s0)), (f3, s0)),
+        ((f2, (i1, s0)), (f3, s0)),
+        ((i2, (f1, s0)), (f3, s0)),
+        ((f2, (f1, s0)), (f3, s0)),
+        ]
+
+    lshift = rshift = [((i2, (i1, s0)), (i3, s0))]
+
+    neg = pred = succ = [((n1, s0), (n2, s0))]
+
+    sqrt = [((n1, s0), (f2, s0))]
+
+    pm = divmod_ = [
+        ((i2, (i1, s0)), (i3, (i4, s0))),
+        ((f2, (i1, s0)), (f3, (f4, s0))),
+        ((i2, (f1, s0)), (f3, (f4, s0))),
+        ((f2, (f1, s0)), (f3, (f4, s0))),
+        ]
+
+    return {
+        name.rstrip('_'): stack_effect
+        for name, stack_effect in locals().iteritems()
+        }
+
+
+FUNCTIONS.update({
+    name: SymbolJoyType(name, stack_effect, i)
+    for i, (name, stack_effect) in enumerate(defs().iteritems())
+    })
 FUNCTIONS.update({
     combo.__name__: CombinatorJoyType(combo.__name__, [combo], i)
     for i, combo in enumerate((
-        joy.library.i,
+        joy.library.b,
+        joy.library.concat_,
         joy.library.dip,
         joy.library.dipd,
         joy.library.dipdd,
         joy.library.dupdip,
-        joy.library.b,
-        joy.library.x,
+        joy.library.i,
         joy.library.infra,
+        joy.library._dictionary['nullary'],
+        joy.library.x,
         ))
     })
 
@@ -315,25 +422,39 @@ def branch_false(stack, expression, dictionary):
   return stack, CONCAT(else_, expression), dictionary
 
 FUNCTIONS['branch'] = CombinatorJoyType('branch', [branch_true, branch_false], 100)
+pop = FUNCTIONS['pop']
 
+def loop_true(stack, expression, dictionary):
+    quote, (flag, stack) = stack
+    return stack, CONCAT(quote, (pop, expression)), dictionary
 
-globals().update(FUNCTIONS)
+def loop_two_true(stack, expression, dictionary):
+    quote, (flag, stack) = stack
+    return stack, CONCAT(quote, (pop, CONCAT(quote, (pop, expression)))), dictionary
 
-branch.expect = s7, (s6, (b1, s5))
-i.expect = x.expect = s7, s6
-dip.expect = s8, (a8, s7)
-dipd.expect = s8, (a8, (a7, s7))
-infra.expect = s8, (s7, s6)
+def loop_false(stack, expression, dictionary):
+    quote, (flag, stack) = stack
+    return stack, expression, dictionary
 
-NULLARY = infer(((stack, s3), (dip, (infra, (first, ())))))
-##print NULLARY
+FUNCTIONS['loop'] = CombinatorJoyType('loop', [loop_two_true, loop_true, loop_false], 101)
 
-nullary = FUNCTIONS['nullary'] = CombinatorJoyType(
-    'nullary',
-    [joy.library._dictionary['nullary']],
-    101,
-    )
-nullary.expect = s7, s6
+
+def set_expectations():
+    branch.expect = s7, (s6, (b1, s5))
+    loop.expect = s6, (b1, s5)
+    i.expect = x.expect = s7, s6
+    dip.expect = dupdip.expect = s8, (a8, s7)
+    dipd.expect = s8, (a8, (a7, s7))
+    dipdd.expect = s8, (a8, (a7, (a6, s7)))
+    b.expect = concat_.expect = infra.expect = s8, (s7, s6)
+    nullary.expect = s7, s6
+scope = globals().copy()
+scope.update(FUNCTIONS)
+eval(set_expectations.func_code, scope)
+
+
+#NULLARY = infer(((stack, s3), (dip, (infra, (first, ())))))
+##print NULLARY
 
 
 # Type Checking...
index 0a0506f..590135d 100644 (file)
@@ -156,7 +156,7 @@ def concat(quote, expression):
   # RuntimeError: maximum recursion depth exceeded
   # on quotes longer than sys.getrecursionlimit().
 
-##  return (quote[0], concat(quote[1], expression)) if quote else expression
+  return (quote[0], concat(quote[1], expression)) if quote else expression
 
   # Original implementation.
 
@@ -165,13 +165,13 @@ def concat(quote, expression):
   # In-lining is slightly faster (and won't break the
   # recursion limit on long quotes.)
 
-  temp = []
-  while quote:
-    item, quote = quote
-    temp.append(item)
-  for item in reversed(temp):
-    expression = item, expression
-  return expression
+##  temp = []
+##  while quote:
+##    item, quote = quote
+##    temp.append(item)
+##  for item in reversed(temp):
+##    expression = item, expression
+##  return expression
 
 
 
index 01bf690..47ea63d 100644 (file)
@@ -1,8 +1,12 @@
 from collections import Counter
 from itertools import imap
+from joy.utils.stack import concat
 
 
 class AnyJoyType(object):
+    '''
+    Joy type variable.  Represents any Joy value.
+    '''
 
     prefix = 'a'
 
@@ -46,12 +50,18 @@ class JoyTypeError(Exception): pass
 
 
 def update(s, term):
+    '''
+    Apply substitution dict to term, returning new term.
+    '''
     if not isinstance(term, tuple):
         return s.get(term, term)
     return tuple(update(s, inner) for inner in term)
 
 
 def relabel(left, right):
+    '''
+    Re-number type variables to avoid collisions between stack effects.
+    '''
     return left, _1000(right)
 
 
@@ -62,6 +72,9 @@ def _1000(right):
 
 
 def delabel(f, seen=None, c=None):
+    '''
+    Fix up type variable numbers after relabel().
+    '''
     if seen is None:
         assert c is None
         seen, c = {}, Counter()
@@ -83,88 +96,79 @@ def delabel(f, seen=None, c=None):
     return tuple(delabel(inner, seen, c) for inner in f)
 
 
-def stack_concat(q, e):
-  return (q[0], stack_concat(q[1], e)) if q else e
-
-
 def unify(u, v, s=None):
+    '''
+    Return a substitution dict representing a unifier for u and v.
+    '''
     if s is None:
         s = {}
     elif s:
         u = update(s, u)
         v = update(s, v)
 
-    if u == v:
-        return s
-
     if isinstance(u, AnyJoyType) and isinstance(v, AnyJoyType):
         if u >= v:
             s[u] = v
-            return s
-        if v >= u:
+        elif v >= u:
             s[v] = u
-            return s
-        raise JoyTypeError('Cannot unify %r and %r.' % (u, v))
+        else:
+            raise JoyTypeError('Cannot unify %r and %r.' % (u, v))
 
-    if isinstance(u, tuple) and isinstance(v, tuple):
+    elif isinstance(u, tuple) and isinstance(v, tuple):
         if len(u) != len(v) != 2:
-            raise ValueError(repr((u, v)))
-        for uu, vv in zip(u, v):
-            s = unify(uu, vv, s)
-            if s == False: # (instead of a substitution dict.)
-                break
-        return s
-
-    if isinstance(v, tuple):
-        if not stacky(u):
+            raise ValueError(repr((u, v)))  # Bad input.
+        (a, b), (c, d) = u, v
+        s = unify(b, d, unify(a, c, s))
+
+    elif isinstance(v, tuple):
+        if not _stacky(u):
             raise JoyTypeError('Cannot unify %r and %r.' % (u, v))
         s[u] = v
-        return s
 
-    if isinstance(u, tuple):
-        if not stacky(v):
+    elif isinstance(u, tuple):
+        if not _stacky(v):
             raise JoyTypeError('Cannot unify %r and %r.' % (v, u))
         s[v] = u
-        return s
-
-    return False
-
-
-def stacky(thing):
-    return thing.__class__ in {AnyJoyType, StackJoyType}
 
+    else:
+        raise JoyTypeError('Cannot unify %r and %r.' % (u, v))
 
-def compose(f, g):
-    (f_in, f_out), (g_in, g_out) = f, g
+    return s
 
-    if not g_in:
-        fg_in, fg_out = f_in, stack_concat(g_out, f_out)
-    elif not f_out:
-        fg_in, fg_out = stack_concat(f_in, g_in), g_out
-    else:
-        s = unify(g_in, f_out)
-        if s == False:  # s can also be the empty dict, which is ok.
-            raise JoyTypeError('Cannot unify %r and %r.' % (fo, gi))
-        fg_in, fg_out = update(s, (f_in, g_out))
 
-    return fg_in, fg_out
+def _stacky(thing):
+    return thing.__class__ in {AnyJoyType, StackJoyType}
 
 
-def _C(f, g):
-    f, g = relabel(f, g)
-    fg = compose(f, g)
+def _compose(f, g):
+    '''
+    Return the stack effect of the composition of two stack effects.
+    '''
+    # Relabel, unify, update, delabel.
+    (f_in, f_out), (g_in, g_out) = relabel(f, g)
+    fg = update(unify(g_in, f_out), (f_in, g_out))
     return delabel(fg)
 
 
-def C(*functions):
-    return reduce(_C, functions)
+def compose(*functions):
+    '''
+    Return the stack effect of the composition of some of stack effects.
+    '''
+    return reduce(_compose, functions)
 
 
 def compilable(f):
-    return isinstance(f, tuple) and all(imap(compilable, f)) or stacky(f)
+    '''
+    Return True if a stack effect represents a function that can be
+    automatically compiled (to Python), False otherwise.
+    '''
+    return isinstance(f, tuple) and all(imap(compilable, f)) or _stacky(f)
 
 
 def doc_from_stack_effect(inputs, outputs):
+    '''
+    Return a crude string representation of a stack effect.
+    '''
     switch = [False]  # Do we need to display the '...' for the rest of the main stack?
     i, o = _f(inputs, switch), _f(outputs, switch)
     if switch[0]:
@@ -213,6 +217,11 @@ def _to_str(term, stack, switch):
 
 
 def compile_(name, f, doc=None):
+    '''
+    Return a string of Python code implementing the function described
+    by the stack effect.  If no doc string is passed doc_from_stack_effect()
+    is used to generate one.
+    '''
     i, o = f
     if doc is None:
         doc = doc_from_stack_effect(i, o)
@@ -243,8 +252,11 @@ I = i0, i1, i2, i3, i4, i5, i6, i7, i8, i9 = map(IntJoyType, _R)
 
 
 def defs():
+    '''
+    Return a dict of named stack effects.
+    '''
     cons = __(a1, s0), __((a1, s0),)
-    ccons = C(cons, cons)
+    ccons = compose(cons, cons)
     dup = __(a1,), __(a1, a1)
     dupd = __(a2, a1), __(a2, a2, a1)
     dupdd = __(a3, a2, a1), __(a3, a3, a2, a1)
@@ -259,18 +271,18 @@ def defs():
     rest = __((a1, s0),), __(s0,)
     rolldown = __(a1, a2, a3), __(a2, a3, a1)
     rollup = __(a1, a2, a3), __(a3, a1, a2)
-    rrest = C(rest, rest)
-    second = C(rest, first)
+    rrest = compose(rest, rest)
+    second = compose(rest, first)
     stack = s0, (s0, s0)
     swaack = (s1, s0), (s0, s1)
     swap = __(a1, a2), __(a2, a1)
-    swons = C(swap, cons)
-    third = C(rest, second)
+    swons = compose(swap, cons)
+    third = compose(rest, second)
     tuck = __(a2, a1), __(a1, a2, a1)
     uncons = __((a1, s0),), __(a1, s0)
-    unswons = C(uncons, swap)
-    stuncons = C(stack, uncons)
-    stununcons = C(stack, uncons, uncons)
+    unswons = compose(uncons, swap)
+    stuncons = compose(stack, uncons)
+    stununcons = compose(stack, uncons, uncons)
     unit = __(a1), __((a1, ()))
 
     eq = ge = gt = le = lt = ne = __(n1, n2), __(b1)
@@ -280,25 +292,26 @@ def defs():
 
     add = div = floordiv = modulus = mul = pow_ = sub = truediv = \
           lshift = rshift = __(n1, n2), __(n3,)
-    sqrt = C(dup, mul)
+    sqrt = compose(dup, mul)
     succ = pred = neg = __(n1,), __(n2,)
     divmod_ = pm = __(n2, n1), __(n4, n3)
 
-    first_two = C(uncons, uncons, pop)
-    fourth = C(rest, third)
+    first_two = compose(uncons, uncons, pop)
+    fourth = compose(rest, third)
 
-    _Tree_add_Ee = C(pop, swap, rolldown, rrest, ccons)
-    _Tree_get_E = C(popop, second)
-    _Tree_delete_clear_stuff = C(rollup, popop, rest)
-    _Tree_delete_R0 = C(over, first, swap, dup)
+    _Tree_add_Ee = compose(pop, swap, rolldown, rrest, ccons)
+    _Tree_get_E = compose(popop, second)
+    _Tree_delete_clear_stuff = compose(rollup, popop, rest)
+    _Tree_delete_R0 = compose(over, first, swap, dup)
 
-    return locals()
+    return {
+        name.rstrip('_'): stack_effect
+        for name, stack_effect in locals().iteritems()
+        }
 
 
 DEFS = defs()
 
-#globals().update(DEFS)
-
 
 def show():
     for name, stack_effect_comment in sorted(DEFS.iteritems()):
index 1d59407..2460ede 100644 (file)
@@ -5,9 +5,6 @@ from joy.utils.polytypes import *
 from joy.utils.stack import list_to_stack as __
 
 
-infr = lambda e: infer(__(e))
-
-
 globals().update(FUNCTIONS)
 
 
@@ -51,29 +48,34 @@ class TestCombinators(TestMixin, unittest.TestCase):
       ((s0, (a0, s1)), ((a0, s0), s1)),  # (a0 [...0] -- [a0 ...0])
       ((a0, s0),        (a0, (a0, s0))), #        (a0 -- a0 a0)
       ]
-    self.assertEqualTypeStructure(infr(expression), f)
+    self.assertEqualTypeStructure(infer(*expression), f)
+
+  def test_concat(self):
+    expression = (swons, s3), (a4, s0), concat_
+    f = (s1, ((swons, (a1, s1)), s1))  # (... -- ... [swons a1 ...])
+    self.assertEqualTypeStructure(infer(*expression), [f])
 
   def test_dip(self):
     expression = dip,
     f = ((s1, (a1, s2)), (a2, s2))  # (a1 [...1] -- a2)
-    self.assertEqualTypeStructure(infr(expression), [f])
+    self.assertEqualTypeStructure(infer(*expression), [f])
 
   def test_cons_dip(self):
     expression = (cons, s0), dip  # [cons] dip
     # (a2 [...1] a1 -- [a2 ...1] a1)
     f =  (a1, (s1, (a2, s2))), (a1, ((a2, s1), s2))
-    self.assertEqualTypeStructure(infr(expression), [f])
+    self.assertEqualTypeStructure(infer(*expression), [f])
 
   def test_cons_dipd(self):
     expression = a1, a3, (cons, s0), dipd
     f = ((s0, (a0, s1)), (a1, (a2, ((a0, s0), s1))))
     # (a0 [...0] -- [a0 ...0] a2 a1)
-    self.assertEqualTypeStructure(infr(expression), [f])
+    self.assertEqualTypeStructure(infer(*expression), [f])
 
   def test_i(self):
     # [cons] i == cons
     expression = (cons, s0), i
-    self.assertEqualTypeStructure(infr(expression), infr([cons]))
+    self.assertEqualTypeStructure(infer(*expression), infer(cons))
 
   def test_infra(self):
     expression = [
@@ -85,7 +87,7 @@ class TestCombinators(TestMixin, unittest.TestCase):
       (s1, ((f1, (n1, s2)), s3)),  # (-- [f1 n1 ...2])
       (s1, ((i1, (n1, s2)), s3)),  # (-- [i1 n1 ...2])
       ]
-    self.assertEqualTypeStructure(infr(expression), f)
+    self.assertEqualTypeStructure(infer(*expression), f)
 
   def test_nullary(self):
     expression = n1, n2, (mul, s2), (stack, s3), dip, infra, first
@@ -95,27 +97,27 @@ class TestCombinators(TestMixin, unittest.TestCase):
       (s1, (f1, (i1, (f2, s1)))),  # (-- f2 i1 f1)
       (s1, (i1, (i2, (i3, s1)))),  # (-- i3 i2 i1)
       ]
-    self.assertEqualTypeStructure(infr(expression), f)
+    self.assertEqualTypeStructure(infer(*expression), f)
 
     expression = n1, n2, (mul, s2), nullary
-    self.assertEqualTypeStructure(infr(expression), f)
+    self.assertEqualTypeStructure(infer(*expression), f)
 
   def test_nullary_too(self):
     expression = (stack, s3), dip, infra, first
     f = ((s1, (a1, s2)), (a1, (a1, s2)))  # (a1 [...1] -- a1 a1)
-    self.assertEqualTypeStructure(infr(expression), [f])
+    self.assertEqualTypeStructure(infer(*expression), [f])
 
     expression = nullary,
     f = ((s1, (a1, s2)), (a1, (a1, s2)))  # (a1 [...1] -- a1 a1)
     # Something's not quite right here...
-    e = infr(expression)
-    self.assertEqualTypeStructure(infr(expression), [f])
+    # e = infer(*expression)
+    self.assertEqualTypeStructure(infer(*expression), [f])
 
   def test_x(self):
-    expression = (a1, (swap, ((dup, s2), (dip, s0)))), x
+    expression = (a1, (swap, ((dup, s2), (dip, s1)))), x
     f = (s0, ((a0, (swap, ((dup, s1), (dip, s2)))), (a1, (a1, s0))))
     # (-- a1 a1 [a0 swap [dup ...1] dip ...2])
-    self.assertEqualTypeStructure(infr(expression), [f])
+    self.assertEqualTypeStructure(infer(*expression), [f])
 
 
 class TestKleeneStar(TestMixin, unittest.TestCase):
@@ -126,7 +128,7 @@ class TestKleeneStar(TestMixin, unittest.TestCase):
       (s1, ((a1, s2), s1)),  # (-- [a1 ...2])
       (s1, ((a1, s2), (As[1], (a2, s1)))),  # (-- a2 a1* [a1 ...2])
       ]
-    self.assertEqualTypeStructure(infr(expression), f)
+    self.assertEqualTypeStructure(infer(*expression), f)
 
   def test_sum(self):
     expression = [
@@ -135,7 +137,7 @@ class TestKleeneStar(TestMixin, unittest.TestCase):
       ]
     # A function that puts a single number on the stack.
     f = s0, (n0, s0)
-    self.assertEqualTypeStructure(infr(expression), [f])
+    self.assertEqualTypeStructure(infer(*expression), [f])
 
   def test_no_infinite_loop(self):
     expression = [
@@ -144,7 +146,7 @@ class TestKleeneStar(TestMixin, unittest.TestCase):
       ]
     # A function that puts a single number on the stack.
     f = s0, (n0, s0)
-    self.assertEqualTypeStructure(infr(expression), [f])
+    self.assertEqualTypeStructure(infer(*expression), [f])
 
 
 class TestYin(TestMixin, unittest.TestCase):
@@ -153,31 +155,31 @@ class TestYin(TestMixin, unittest.TestCase):
     expression = pop, swap, rolldown, rest, rest, cons, cons
     # ([a3 a4 ...0] a2 a1 a0 -- [a1 a2 ...0])
     f = (a0, (a1, (a2, ((a3, (a4, s0)), s1)))), ((a1, (a2, s0)), s1)
-    self.assertEqualTypeStructure(infr(expression), [f])
+    self.assertEqualTypeStructure(infer(*expression), [f])
 
   def test_swaack(self):
     expression = a0, (a1, s0), swaack
     f = (s0, ((a0, s0), (a1, s1)))  # (-- a1 [a0 ...0])
-    self.assertEqualTypeStructure(infr(expression), [f])
+    self.assertEqualTypeStructure(infer(*expression), [f])
   
   def test_z_down(self):
     expression = s2, swap, uncons, swap
     f = (((a1, s1), s2), (a1, (s1, (s3, s2))))
     # ([a1 ...1] -- [...3] [...1] a1)
-    self.assertEqualTypeStructure(infr(expression), [f])
+    self.assertEqualTypeStructure(infer(*expression), [f])
 
   def test_z_right(self):
     expression = a1, a2, (swons, s3), cons, dip, uncons, swap
     f = ((s1, s2), (a1, (s3, ((a2, s1), s2))))
     # ([...1] -- [a2 ...1] [...3] a1)
-    self.assertEqualTypeStructure(infr(expression), [f])
+    self.assertEqualTypeStructure(infer(*expression), [f])
 
 ##  def test_(self):
 ##    expression = pop, swap, rolldown, rest, rest, cons, cons
 ##    f = 
-##    for sec in infr(expression):
+##    for sec in infer(*expression):
 ##      print sec, doc_from_stack_effect(*sec)
-##    self.assertEqualTypeStructure(infr(expression), [f])
+##    self.assertEqualTypeStructure(infer(*expression), [f])
 
 ##      for g in MC(dup, mul):
 ##        print doc_from_stack_effect(*g)