Type inference of Joy expressions.

More remains to be done but it seems to work.
This commit is contained in:
Simon Forman
2018-06-29 13:19:12 -07:00
parent 6ca59847ab
commit 4406a6620b
25 changed files with 1867 additions and 4593 deletions
+241 -1221
View File
File diff suppressed because it is too large Load Diff
+205 -1028
View File
File diff suppressed because it is too large Load Diff
+161 -549
View 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'
```
#### 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
def flatten(g):
return list(chain.from_iterable(g))
class SymbolJoyType(FunctionJoyType):
prefix = 'F'
```
For combinators the list contains Python functions.
```python
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.
```python
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.
```python
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.
```python
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
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)
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 :
```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
```
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)
```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,
))
})
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)
```
```python
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.)
```python
from itertools import chain
from joy.utils.stack import list_to_stack as l2s
```
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.
```python
expression = l2s([n1, n2, (mul, s2), (stack, s3), dip, infra, first])
```
```python
expression
```
(n1, (n2, ((mul, s2), ((stack, s3), (dip, (infra, (first, ())))))))
```python
expression = l2s([n1, n2, mul])
```
```python
expression
```
(n1, (n2, (mul, ())))
```python
infer(expression)
```
[(s1, (f1, s1)), (s1, (i1, s1))]
```python
infer(expression)
```
[(s1, (f1, s1)), (s1, (i1, s1))]
```python
for stack_effect_comment in infer(expression):
print doc_from_stack_effect(*stack_effect_comment)
```
(-- f1)
(-- i1)
```python
expression
```
(n1, (n2, (mul, ())))
```python
infer(expression)
```
[(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.
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.
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.
```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)
```
+210 -578
View 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
class SymbolJoyType(FunctionJoyType): prefix = 'F'
class CombinatorJoyType(FunctionJoyType): prefix = 'C'
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
def flatten(g):
return list(chain.from_iterable(g))
class SymbolJoyType(FunctionJoyType):
prefix = 'F'
For combinators the list contains Python functions.
.. code:: ipython2
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 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
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)
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
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
1/0 # (Don't try to run this cell! It's not going to work. This is "read only" code heh..)
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'''
logging.basicConfig(format='%(message)s', stream=sys.stdout, level=logging.INFO)
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, ())))
.. 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.
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)
@@ -35,8 +35,10 @@
<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>
@@ -127,7 +127,6 @@
<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>
@@ -153,13 +152,17 @@
<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>
@@ -605,12 +608,12 @@
<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>
@@ -189,7 +189,7 @@
<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>
@@ -198,13 +198,13 @@
<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>
@@ -98,6 +98,7 @@ The following is specific information for this dialect of Joy.
pretty
library
lib
types
notebooks/index
+114 -12
View File
@@ -45,8 +45,10 @@
| <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>
@@ -67,9 +69,13 @@
<li><a href="library.html#joy.library.DefinitionWrapper.add_def">add_def() (joy.library.DefinitionWrapper class method)</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>
@@ -83,10 +89,12 @@
<table style="width: 100%" class="indextable genindextable"><tr>
<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>
@@ -103,9 +111,21 @@
<li><a href="library.html#joy.library.clear">clear() (in module joy.library)</a>
</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>
@@ -121,17 +141,27 @@
<table style="width: 100%" class="indextable genindextable"><tr>
<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>
@@ -159,12 +189,16 @@
<li><a href="library.html#joy.utils.generated_library.first">first() (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>
@@ -202,14 +236,22 @@
</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>
@@ -224,15 +266,41 @@
</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>
@@ -254,15 +322,29 @@
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="library.html#joy.library.map_">map_() (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>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<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>
@@ -306,16 +388,18 @@
<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>
@@ -343,13 +427,19 @@
<li><a href="library.html#joy.library.sort_">sort_() (in module joy.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>
@@ -360,13 +450,15 @@
</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><a href="library.html#joy.utils.generated_library.swons">swons() (in module joy.utils.generated_library)</a>
</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>
@@ -398,13 +490,23 @@
</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>
+6 -1
View File
@@ -131,6 +131,11 @@ interesting aspects. Its 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. Its 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">Newtons 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>
+26 -16
View File
@@ -612,12 +612,6 @@ on top of the stack.</p>
<p>sum == 0 swap [+] step</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>
@@ -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>
@@ -929,10 +931,18 @@ from each list. The smallest list sets the length of the result list.</p>
</div>
</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>
+202 -413
View 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. Its 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 doesnt 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 its 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 cant say anything about its stack
case, the <code class="docutils literal notranslate"><span class="pre">i</span></code> combinator, you cant 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 cant say
much about the result.</p>
<p>I think theres 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 theres 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 functions 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>
<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>
<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>
</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">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>
<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">_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_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="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 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">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>
<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>
<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>
<p>The numbers at the start of the lines are the current depth of the
Python call stack. Theyre 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="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>
</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>
<p>And that brings us to current Work-In-Progress. Im 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>Im starting to realize that, with the inferencer/checker/compiler
coming along, and with the UI ready to be rewritten in Joy, Im close to
a time when my ephasis is going to have to shift from crunchy code stuff
to squishy human stuff. Im 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. Theres a working demo of this at the end of the
<code class="docutils literal notranslate"><span class="pre">polytypes</span></code> module. But if youre 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 Im 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öials 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,17 +2438,20 @@ 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>
<div class="relations">
<h3>Related Topics</h3>
@@ -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="Newtons 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">Newtons 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>
@@ -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" />
@@ -118,7 +118,7 @@
<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öials 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>
@@ -128,8 +128,6 @@
<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>
@@ -147,7 +145,7 @@
<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>
Binary file not shown.
@@ -70,6 +70,11 @@
<td>&#160;&#160;&#160;
<a href="library.html#module-joy.utils.generated_library"><code class="xref">joy.utils.generated_library</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.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;
@@ -80,6 +85,11 @@
<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>
File diff suppressed because one or more lines are too long
+1
View File
@@ -98,6 +98,7 @@ The following is specific information for this dialect of Joy.
pretty
library
lib
types
notebooks/index
+210 -578
View 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
class SymbolJoyType(FunctionJoyType): prefix = 'F'
class CombinatorJoyType(FunctionJoyType): prefix = 'C'
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
def flatten(g):
return list(chain.from_iterable(g))
class SymbolJoyType(FunctionJoyType):
prefix = 'F'
For combinators the list contains Python functions.
.. code:: ipython2
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 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
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)
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
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
1/0 # (Don't try to run this cell! It's not going to work. This is "read only" code heh..)
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'''
logging.basicConfig(format='%(message)s', stream=sys.stdout, level=logging.INFO)
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, ())))
.. 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.
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)
+141
View File
@@ -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: