A little more documentation.

This commit is contained in:
Simon Forman 2018-07-11 07:13:05 -07:00
parent fcf483af22
commit f8829e25fa
14 changed files with 25870 additions and 257 deletions

12081
docs/The_Four_Operations.html Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,337 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# The Four Fundamental Operations of Definite Action\n",
"\n",
"All definite actions (computer program) can be defined by four fundamental patterns of combination:\n",
"\n",
"1. Sequence\n",
"2. Branch\n",
"3. Loop\n",
"4. Parallel"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Sequence\n",
"\n",
"Do one thing after another. In joy this is represented by putting two symbols together, juxtaposition:\n",
"\n",
" foo bar\n",
"\n",
"Operations have inputs and outputs. The outputs of `foo` must be compatible in \"arity\", type, and shape with the inputs of `bar`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Branch\n",
"\n",
"Do one thing or another.\n",
"\n",
" boolean [F] [T] branch\n",
"\n",
"\n",
" t [F] [T] branch\n",
" ----------------------\n",
" T\n",
"\n",
"\n",
" f [F] [T] branch\n",
" ----------------------\n",
" F\n",
"\n",
"\n",
" branch == unit cons swap pick i\n",
"\n",
" boolean [F] [T] branch\n",
" boolean [F] [T] unit cons swap pick i\n",
" boolean [F] [[T]] cons swap pick i\n",
" boolean [[F] [T]] swap pick i\n",
" [[F] [T]] boolean pick i\n",
" [F-or-T] i"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Given some branch function `G`:\n",
"\n",
" G == [F] [T] branch\n",
"\n",
"Used in a sequence like so:\n",
"\n",
" foo G bar\n",
"\n",
"The inputs and outputs of `F` and `T` must be compatible with the outputs for `foo` and the inputs of `bar`, respectively.\n",
"\n",
" foo F bar\n",
"\n",
" foo T bar"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `ifte`\n",
"\n",
"Often it will be easier on the programmer to write branching code with the predicate specified in a quote. The `ifte` combinator provides this (`T` for \"then\" and `E` for \"else\"):\n",
"\n",
" [P] [T] [E] ifte\n",
"\n",
"Defined in terms of `branch`:\n",
"\n",
" ifte == [nullary not] dip branch\n",
"\n",
"\n",
"In this case, `P` must be compatible with the stack and return a Boolean value, and `T` and `E` both must be compatible with the preceeding and following functions, as described above for `F` and `T`. (Note that in the current implementation we are depending on Python for the underlying semantics, so the Boolean value doesn't *have* to be Boolean because Python's rules for \"truthiness\" will be used to evaluate it. I reflect this in the structure of the stack effect comment of `branch`, it will only accept Boolean values, and in the definition of `ifte` above by including `not` in the quote, which also has the effect that the subject quotes are in the proper order for `branch`.)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Loop\n",
"\n",
"Do one thing zero or more times.\n",
"\n",
" boolean [Q] loop\n",
"\n",
"\n",
" t [Q] loop\n",
" ----------------\n",
" Q [Q] loop\n",
"\n",
"\n",
" ... f [Q] loop\n",
" --------------------\n",
" ...\n",
"\n",
"The `loop` combinator generates a copy of itself in the true branch. This is the hallmark of recursive defintions. In Thun there is no equivalent to conventional loops. (There is, however, the `x` combinator, defined as `x == dup i`, which permits recursive constructs that do not need to be directly self-referential, unlike `loop` and `genrec`.)\n",
"\n",
" loop == [] swap [dup dip loop] cons branch\n",
"\n",
" boolean [Q] loop\n",
" boolean [Q] [] swap [dup dip loop] cons branch\n",
" boolean [] [Q] [dup dip loop] cons branch\n",
" boolean [] [[Q] dup dip loop] branch\n",
"\n",
"In action the false branch does nothing while the true branch does:\n",
"\n",
" t [] [[Q] dup dip loop] branch\n",
" [Q] dup dip loop\n",
" [Q] [Q] dip loop\n",
" Q [Q] loop"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Because `loop` expects and consumes a Boolean value, the `Q` function must be compatible with the previous stack *and itself* with a boolean flag for the next iteration:\n",
"\n",
" Q == G b\n",
"\n",
" Q [Q] loop\n",
" G b [Q] loop\n",
" G Q [Q] loop\n",
" G G b [Q] loop\n",
" G G Q [Q] loop\n",
" G G G b [Q] loop\n",
" G G G\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `while`\n",
"\n",
"Keep doing `B` _while_ some predicate `P` is true. This is convenient as the predicate function is made nullary automatically and the body function can be designed without regard to leaving a Boolean flag for the next iteration:\n",
"\n",
"\n",
"\n",
" [P] [B] while\n",
" --------------------------------------\n",
" [P] nullary [B [P] nullary] loop\n",
"\n",
"\n",
" while == swap [nullary] cons dup dipd concat loop\n",
"\n",
"\n",
" [P] [B] while\n",
" [P] [B] swap [nullary] cons dup dipd concat loop\n",
" [B] [P] [nullary] cons dup dipd concat loop\n",
" [B] [[P] nullary] dup dipd concat loop\n",
" [B] [[P] nullary] [[P] nullary] dipd concat loop\n",
" [P] nullary [B] [[P] nullary] concat loop\n",
" [P] nullary [B [P] nullary] loop\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Parallel\n",
"\n",
"The *parallel* operation indicates that two (or more) functions *do not interfere* with each other and so can run in parallel. The main difficulty in this sort of thing is orchestrating the recombining (\"join\" or \"wait\") of the results of the functions after they finish.\n",
"\n",
"The current implementaions and the following definitions *are not actually parallel* (yet), but there is no reason they couldn't be reimplemented in terms of e.g. Python threads. I am not concerned with performance of the system just yet, only the elegance of the code it allows us to write."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `cleave`\n",
"\n",
"Joy has a few parallel combinators, the main one being `cleave`:\n",
"\n",
" ... x [A] [B] cleave\n",
" ---------------------------------------------------------\n",
" ... [x ...] [A] infra first [x ...] [B] infra first\n",
" ---------------------------------------------------------\n",
" ... a b\n",
"\n",
"The `cleave` combinator expects a value and two quotes and it executes each quote in \"separate universes\" such that neither can affect the other, then it takes the first item from the stack in each universe and replaces the value and quotes with their respective results.\n",
"\n",
"(I think this corresponds to the \"fork\" operator, the little upward-pointed triangle, that takes two functions `A :: x -> a` and `B :: x -> b` and returns a function `F :: x -> (a, b)`, in Conal Elliott's \"Compiling to Categories\" paper, et. al.)\n",
"\n",
"Just a thought, if you `cleave` two jobs and one requires more time to finish than the other you'd like to be able to assign resources accordingly so that they both finish at the same time."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### \"Apply\" Functions\n",
"\n",
"There are also `app2` and `app3` which run a single quote on more than one value:\n",
"\n",
" ... y x [Q] app2\n",
" ---------------------------------------------------------\n",
" ... [y ...] [Q] infra first [x ...] [Q] infra first\n",
"\n",
"\n",
" ... z y x [Q] app3\n",
" ---------------------------------\n",
" ... [z ...] [Q] infra first\n",
" [y ...] [Q] infra first\n",
" [x ...] [Q] infra first\n",
"\n",
"Because the quoted program can be `i` we can define `cleave` in terms of `app2`:\n",
"\n",
" cleave == [i] app2 [popd] dip"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"(I'm not sure why `cleave` was specified to take that value, I may make a combinator that does the same thing but without expecting a value.)\n",
"\n",
" clv == [i] app2\n",
"\n",
" [A] [B] clv\n",
" ------------------\n",
" a b"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `map`\n",
"\n",
"The common `map` function in Joy should also be though of as a *parallel* operator:\n",
"\n",
" [a b c ...] [Q] map\n",
"\n",
"There is no reason why the implementation of `map` couldn't distribute the `Q` function over e.g. a pool of worker CPUs."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `pam`\n",
"\n",
"One of my favorite combinators, the `pam` combinator is just:\n",
"\n",
" pam == [i] map\n",
"\n",
"This can be used to run any number of programs separately on the current stack and combine their (first) outputs in a result list.\n",
"\n",
" [[A] [B] [C] ...] [i] map\n",
" -------------------------------\n",
" [ a b c ...]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Handling Other Kinds of Join\n",
"\n",
"The `cleave` operators and others all have pretty brutal join semantics: everything works and we always wait for every sub-computation. We can imagine a few different potentially useful patterns of \"joining\" results from parallel combinators."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### first-to-finish\n",
"\n",
"Thinking about variations of `pam` there could be one that only returns the first result of the first-to-finish sub-program, or the stack could be replaced by its output stack.\n",
"\n",
"The other sub-programs would be cancelled."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### \"Fulminators\"\n",
"\n",
"Also known as \"Futures\" or \"Promises\" (by *everybody* else. \"Fulinators\" is what I was going to call them when I was thinking about implementing them in Thun.)\n",
"\n",
"The runtime could be amended to permit \"thunks\" representing the results of in-progress computations to be left on the stack and picked up by subsequent functions. These would themselves be able to leave behind more \"thunks\", the values of which depend on the eventual resolution of the values of the previous thunks.\n",
"\n",
"In this way you can create \"chains\" (and more complex shapes) out of normal-looking code that consist of a kind of call-graph interspersed with \"asyncronous\" ... events?\n",
"\n",
"In any case, until I can find a rigorous theory that shows that this sort of thing works perfectly in Joy code I'm not going to worry about it. (And I think the Categories can deal with it anyhow? Incremental evaluation, yeah?)\n",
"\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.12"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

217
docs/The_Four_Operations.md Normal file
View File

@ -0,0 +1,217 @@
# The Four Fundamental Operations of Definite Action
All definite actions (computer program) can be defined by four fundamental patterns of combination:
1. Sequence
2. Branch
3. Loop
4. Parallel
## Sequence
Do one thing after another. In joy this is represented by putting two symbols together, juxtaposition:
foo bar
Operations have inputs and outputs. The outputs of `foo` must be compatible in "arity", type, and shape with the inputs of `bar`.
## Branch
Do one thing or another.
boolean [F] [T] branch
t [F] [T] branch
----------------------
T
f [F] [T] branch
----------------------
F
branch == unit cons swap pick i
boolean [F] [T] branch
boolean [F] [T] unit cons swap pick i
boolean [F] [[T]] cons swap pick i
boolean [[F] [T]] swap pick i
[[F] [T]] boolean pick i
[F-or-T] i
Given some branch function `G`:
G == [F] [T] branch
Used in a sequence like so:
foo G bar
The inputs and outputs of `F` and `T` must be compatible with the outputs for `foo` and the inputs of `bar`, respectively.
foo F bar
foo T bar
### `ifte`
Often it will be easier on the programmer to write branching code with the predicate specified in a quote. The `ifte` combinator provides this (`T` for "then" and `E` for "else"):
[P] [T] [E] ifte
Defined in terms of `branch`:
ifte == [nullary not] dip branch
In this case, `P` must be compatible with the stack and return a Boolean value, and `T` and `E` both must be compatible with the preceeding and following functions, as described above for `F` and `T`. (Note that in the current implementation we are depending on Python for the underlying semantics, so the Boolean value doesn't *have* to be Boolean because Python's rules for "truthiness" will be used to evaluate it. I reflect this in the structure of the stack effect comment of `branch`, it will only accept Boolean values, and in the definition of `ifte` above by including `not` in the quote, which also has the effect that the subject quotes are in the proper order for `branch`.)
## Loop
Do one thing zero or more times.
boolean [Q] loop
t [Q] loop
----------------
Q [Q] loop
... f [Q] loop
--------------------
...
The `loop` combinator generates a copy of itself in the true branch. This is the hallmark of recursive defintions. In Thun there is no equivalent to conventional loops. (There is, however, the `x` combinator, defined as `x == dup i`, which permits recursive constructs that do not need to be directly self-referential, unlike `loop` and `genrec`.)
loop == [] swap [dup dip loop] cons branch
boolean [Q] loop
boolean [Q] [] swap [dup dip loop] cons branch
boolean [] [Q] [dup dip loop] cons branch
boolean [] [[Q] dup dip loop] branch
In action the false branch does nothing while the true branch does:
t [] [[Q] dup dip loop] branch
[Q] dup dip loop
[Q] [Q] dip loop
Q [Q] loop
Because `loop` expects and consumes a Boolean value, the `Q` function must be compatible with the previous stack *and itself* with a boolean flag for the next iteration:
Q == G b
Q [Q] loop
G b [Q] loop
G Q [Q] loop
G G b [Q] loop
G G Q [Q] loop
G G G b [Q] loop
G G G
### `while`
Keep doing `B` _while_ some predicate `P` is true. This is convenient as the predicate function is made nullary automatically and the body function can be designed without regard to leaving a Boolean flag for the next iteration:
[P] [B] while
--------------------------------------
[P] nullary [B [P] nullary] loop
while == swap [nullary] cons dup dipd concat loop
[P] [B] while
[P] [B] swap [nullary] cons dup dipd concat loop
[B] [P] [nullary] cons dup dipd concat loop
[B] [[P] nullary] dup dipd concat loop
[B] [[P] nullary] [[P] nullary] dipd concat loop
[P] nullary [B] [[P] nullary] concat loop
[P] nullary [B [P] nullary] loop
## Parallel
The *parallel* operation indicates that two (or more) functions *do not interfere* with each other and so can run in parallel. The main difficulty in this sort of thing is orchestrating the recombining ("join" or "wait") of the results of the functions after they finish.
The current implementaions and the following definitions *are not actually parallel* (yet), but there is no reason they couldn't be reimplemented in terms of e.g. Python threads. I am not concerned with performance of the system just yet, only the elegance of the code it allows us to write.
### `cleave`
Joy has a few parallel combinators, the main one being `cleave`:
... x [A] [B] cleave
---------------------------------------------------------
... [x ...] [A] infra first [x ...] [B] infra first
---------------------------------------------------------
... a b
The `cleave` combinator expects a value and two quotes and it executes each quote in "separate universes" such that neither can affect the other, then it takes the first item from the stack in each universe and replaces the quotes with their respective results.
(I'm not sure why it was specified to take that value, I may make a combinator that does the same thing but without expecting a value.)
cleavish == unit cons pam uncons uncons pop
[A] [B] cleavish
[A] [B] unit cons pam uncons uncons pop
[A] [[B]] cons pam uncons uncons pop
[[A] [B]] pam uncons uncons pop
[a b] uncons uncons pop
a b
### "Apply" Functions
There are also `app2` and `app3` which run a single quote on more than one value:
... y x [Q] app2
---------------------------------------------------------
... [y ...] [Q] infra first [x ...] [Q] infra first
... z y x [Q] app3
---------------------------------
... [z ...] [Q] infra first
[y ...] [Q] infra first
[x ...] [Q] infra first
Because the quoted program can be `i` we can define `cleave` in terms of `app2`:
cleave == [i] app2 [popd] dip
### `map`
The common `map` function in Joy should also be though of as a *parallel* operator:
[a b c ...] [Q] map
There is no reason why the implementation of `map` couldn't distribute the `Q` function over e.g. a pool of worker CPUs.
### `pam`
One of my favorite combinators, the `pam` combinator is just:
pam == [i] map
This can be used to run any number of programs separately on the current stack and combine their (first) outputs in a result list.
[[A] [B] [C] ...] [i] map
-------------------------------
[ a b c ...]
### Handling Other Kinds of Join
We can imagine a few different potentially useful patterns of "joining" results from parallel combinators.
#### first-to-finish
Thinking about variations of `pam` there could be one that only returns the first result of the first-to-finish sub-program, or the stack could be replaced by its output stack.
The other sub-programs would be cancelled.

View File

@ -0,0 +1,306 @@
The Four Fundamental Operations of Definite Action
==================================================
All definite actions (computer program) can be defined by four
fundamental patterns of combination:
1. Sequence
2. Branch
3. Loop
4. Parallel
Sequence
--------
Do one thing after another. In joy this is represented by putting two
symbols together, juxtaposition:
::
foo bar
Operations have inputs and outputs. The outputs of ``foo`` must be
compatible in "arity", type, and shape with the inputs of ``bar``.
Branch
------
Do one thing or another.
::
boolean [F] [T] branch
t [F] [T] branch
----------------------
T
f [F] [T] branch
----------------------
F
branch == unit cons swap pick i
boolean [F] [T] branch
boolean [F] [T] unit cons swap pick i
boolean [F] [[T]] cons swap pick i
boolean [[F] [T]] swap pick i
[[F] [T]] boolean pick i
[F-or-T] i
Given some branch function ``G``:
::
G == [F] [T] branch
Used in a sequence like so:
::
foo G bar
The inputs and outputs of ``F`` and ``T`` must be compatible with the
outputs for ``foo`` and the inputs of ``bar``, respectively.
::
foo F bar
foo T bar
``ifte``
~~~~~~~~
Often it will be easier on the programmer to write branching code with
the predicate specified in a quote. The ``ifte`` combinator provides
this (``T`` for "then" and ``E`` for "else"):
::
[P] [T] [E] ifte
Defined in terms of ``branch``:
::
ifte == [nullary not] dip branch
In this case, ``P`` must be compatible with the stack and return a
Boolean value, and ``T`` and ``E`` both must be compatible with the
preceeding and following functions, as described above for ``F`` and
``T``. (Note that in the current implementation we are depending on
Python for the underlying semantics, so the Boolean value doesn't *have*
to be Boolean because Python's rules for "truthiness" will be used to
evaluate it. I reflect this in the structure of the stack effect comment
of ``branch``, it will only accept Boolean values, and in the definition
of ``ifte`` above by including ``not`` in the quote, which also has the
effect that the subject quotes are in the proper order for ``branch``.)
Loop
----
Do one thing zero or more times.
::
boolean [Q] loop
t [Q] loop
----------------
Q [Q] loop
... f [Q] loop
--------------------
...
The ``loop`` combinator generates a copy of itself in the true branch.
This is the hallmark of recursive defintions. In Thun there is no
equivalent to conventional loops. (There is, however, the ``x``
combinator, defined as ``x == dup i``, which permits recursive
constructs that do not need to be directly self-referential, unlike
``loop`` and ``genrec``.)
::
loop == [] swap [dup dip loop] cons branch
boolean [Q] loop
boolean [Q] [] swap [dup dip loop] cons branch
boolean [] [Q] [dup dip loop] cons branch
boolean [] [[Q] dup dip loop] branch
In action the false branch does nothing while the true branch does:
::
t [] [[Q] dup dip loop] branch
[Q] dup dip loop
[Q] [Q] dip loop
Q [Q] loop
Because ``loop`` expects and consumes a Boolean value, the ``Q``
function must be compatible with the previous stack *and itself* with a
boolean flag for the next iteration:
::
Q == G b
Q [Q] loop
G b [Q] loop
G Q [Q] loop
G G b [Q] loop
G G Q [Q] loop
G G G b [Q] loop
G G G
``while``
~~~~~~~~~
Keep doing ``B`` *while* some predicate ``P`` is true. This is
convenient as the predicate function is made nullary automatically and
the body function can be designed without regard to leaving a Boolean
flag for the next iteration:
::
[P] [B] while
--------------------------------------
[P] nullary [B [P] nullary] loop
while == swap [nullary] cons dup dipd concat loop
[P] [B] while
[P] [B] swap [nullary] cons dup dipd concat loop
[B] [P] [nullary] cons dup dipd concat loop
[B] [[P] nullary] dup dipd concat loop
[B] [[P] nullary] [[P] nullary] dipd concat loop
[P] nullary [B] [[P] nullary] concat loop
[P] nullary [B [P] nullary] loop
Parallel
--------
The *parallel* operation indicates that two (or more) functions *do not
interfere* with each other and so can run in parallel. The main
difficulty in this sort of thing is orchestrating the recombining
("join" or "wait") of the results of the functions after they finish.
The current implementaions and the following definitions *are not
actually parallel* (yet), but there is no reason they couldn't be
reimplemented in terms of e.g. Python threads. I am not concerned with
performance of the system just yet, only the elegance of the code it
allows us to write.
``cleave``
~~~~~~~~~~
Joy has a few parallel combinators, the main one being ``cleave``:
::
... x [A] [B] cleave
---------------------------------------------------------
... [x ...] [A] infra first [x ...] [B] infra first
---------------------------------------------------------
... a b
The ``cleave`` combinator expects a value and two quotes and it executes
each quote in "separate universes" such that neither can affect the
other, then it takes the first item from the stack in each universe and
replaces the quotes with their respective results.
(I'm not sure why it was specified to take that value, I may make a
combinator that does the same thing but without expecting a value.)
::
cleavish == unit cons pam uncons uncons pop
[A] [B] cleavish
[A] [B] unit cons pam uncons uncons pop
[A] [[B]] cons pam uncons uncons pop
[[A] [B]] pam uncons uncons pop
[a b] uncons uncons pop
a b
"Apply" Functions
~~~~~~~~~~~~~~~~~
There are also ``app2`` and ``app3`` which run a single quote on more
than one value:
::
... y x [Q] app2
---------------------------------------------------------
... [y ...] [Q] infra first [x ...] [Q] infra first
... z y x [Q] app3
---------------------------------
... [z ...] [Q] infra first
[y ...] [Q] infra first
[x ...] [Q] infra first
Because the quoted program can be ``i`` we can define ``cleave`` in
terms of ``app2``:
::
cleave == [i] app2 [popd] dip
``map``
~~~~~~~
The common ``map`` function in Joy should also be though of as a
*parallel* operator:
::
[a b c ...] [Q] map
There is no reason why the implementation of ``map`` couldn't distribute
the ``Q`` function over e.g. a pool of worker CPUs.
``pam``
~~~~~~~
One of my favorite combinators, the ``pam`` combinator is just:
::
pam == [i] map
This can be used to run any number of programs separately on the current
stack and combine their (first) outputs in a result list.
::
[[A] [B] [C] ...] [i] map
-------------------------------
[ a b c ...]
Handling Other Kinds of Join
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We can imagine a few different potentially useful patterns of "joining"
results from parallel combinators.
first-to-finish
^^^^^^^^^^^^^^^
Thinking about variations of ``pam`` there could be one that only
returns the first result of the first-to-finish sub-program, or the
stack could be replaced by its output stack.
The other sub-programs would be cancelled.

12225
docs/TypeChecking.html Normal file

File diff suppressed because it is too large Load Diff

307
docs/TypeChecking.ipynb Normal file
View File

@ -0,0 +1,307 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Type Checking"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import logging, sys\n",
"\n",
"logging.basicConfig(\n",
" format='%(message)s',\n",
" stream=sys.stdout,\n",
" level=logging.INFO,\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from joy.utils.polytypes import (\n",
" doc_from_stack_effect, \n",
" infer,\n",
" reify,\n",
" unify,\n",
" FUNCTIONS,\n",
" JoyTypeError,\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"D = FUNCTIONS.copy()\n",
"del D['product']\n",
"globals().update(D)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## An Example"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 25 (--) ∘ pop swap rolldown rrest ccons\n",
" 28 (a1 --) ∘ swap rolldown rrest ccons\n",
" 31 (a3 a2 a1 -- a2 a3) ∘ rolldown rrest ccons\n",
" 34 (a4 a3 a2 a1 -- a2 a3 a4) ∘ rrest ccons\n",
" 37 ([a4 a5 ...1] a3 a2 a1 -- a2 a3 [...1]) ∘ ccons\n",
" 40 ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) ∘ \n"
]
}
],
"source": [
"fi, fo = infer(pop, swap, rolldown, rrest, ccons)[0]"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1])\n"
]
}
],
"source": [
"print doc_from_stack_effect(fi, fo)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"from joy.parser import text_to_expression\n",
"from joy.utils.stack import stack_to_string\n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[3 4] 2 1 0\n"
]
}
],
"source": [
"e = text_to_expression('0 1 2 [3 4]') # reverse order\n",
"print stack_to_string(e)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{a1: 0, a2: 1, a3: 2, a4: 3, a5: 4, s2: (), s1: ()}"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"u = unify(e, fi)[0]\n",
"u"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(... [3 4 ] 2 1 0 -- ... [1 2 ])\n"
]
}
],
"source": [
"g = reify(u, (fi, fo))\n",
"print doc_from_stack_effect(*g)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Unification Works \"in Reverse\""
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"e = text_to_expression('[2 3]')"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{a2: 2, a3: 3, s2: (), s1: ()}"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"u = unify(e, fo)[0] # output side, not input side\n",
"u"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(... [a4 a5 ] 3 2 a1 -- ... [2 3 ])\n"
]
}
],
"source": [
"g = reify(u, (fi, fo))\n",
"print doc_from_stack_effect(*g)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Failing a Check"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 25 (--) ∘ dup mul\n",
" 28 (a1 -- a1 a1) ∘ mul\n",
" 31 (f1 -- f2) ∘ \n",
" 31 (i1 -- i2) ∘ \n"
]
}
],
"source": [
"fi, fo = infer(dup, mul)[0]"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"'two'\n"
]
}
],
"source": [
"e = text_to_expression('\"two\"')\n",
"print stack_to_string(e)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Cannot unify 'two' and f1.\n"
]
}
],
"source": [
"try:\n",
" unify(e, fi)\n",
"except JoyTypeError, err:\n",
" print err"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.12"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

155
docs/TypeChecking.md Normal file
View File

@ -0,0 +1,155 @@
# Type Checking
```python
import logging, sys
logging.basicConfig(
format='%(message)s',
stream=sys.stdout,
level=logging.INFO,
)
```
```python
from joy.utils.polytypes import (
doc_from_stack_effect,
infer,
reify,
unify,
FUNCTIONS,
JoyTypeError,
)
```
```python
D = FUNCTIONS.copy()
del D['product']
globals().update(D)
```
## An Example
```python
fi, fo = infer(pop, swap, rolldown, rrest, ccons)[0]
```
25 (--) ∘ pop swap rolldown rrest ccons
28 (a1 --) ∘ swap rolldown rrest ccons
31 (a3 a2 a1 -- a2 a3) ∘ rolldown rrest ccons
34 (a4 a3 a2 a1 -- a2 a3 a4) ∘ rrest ccons
37 ([a4 a5 ...1] a3 a2 a1 -- a2 a3 [...1]) ∘ ccons
40 ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) ∘
```python
print doc_from_stack_effect(fi, fo)
```
([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1])
```python
from joy.parser import text_to_expression
from joy.utils.stack import stack_to_string
```
```python
e = text_to_expression('0 1 2 [3 4]') # reverse order
print stack_to_string(e)
```
[3 4] 2 1 0
```python
u = unify(e, fi)[0]
u
```
{a1: 0, a2: 1, a3: 2, a4: 3, a5: 4, s2: (), s1: ()}
```python
g = reify(u, (fi, fo))
print doc_from_stack_effect(*g)
```
(... [3 4 ] 2 1 0 -- ... [1 2 ])
## Unification Works "in Reverse"
```python
e = text_to_expression('[2 3]')
```
```python
u = unify(e, fo)[0] # output side, not input side
u
```
{a2: 2, a3: 3, s2: (), s1: ()}
```python
g = reify(u, (fi, fo))
print doc_from_stack_effect(*g)
```
(... [a4 a5 ] 3 2 a1 -- ... [2 3 ])
## Failing a Check
```python
fi, fo = infer(dup, mul)[0]
```
25 (--) ∘ dup mul
28 (a1 -- a1 a1) ∘ mul
31 (f1 -- f2) ∘
31 (i1 -- i2) ∘
```python
e = text_to_expression('"two"')
print stack_to_string(e)
```
'two'
```python
try:
unify(e, fi)
except JoyTypeError, err:
print err
```
Cannot unify 'two' and f1.

172
docs/TypeChecking.rst Normal file
View File

@ -0,0 +1,172 @@
Type Checking
=============
.. code:: ipython2
import logging, sys
logging.basicConfig(
format='%(message)s',
stream=sys.stdout,
level=logging.INFO,
)
.. code:: ipython2
from joy.utils.polytypes import (
doc_from_stack_effect,
infer,
reify,
unify,
FUNCTIONS,
JoyTypeError,
)
.. code:: ipython2
D = FUNCTIONS.copy()
del D['product']
globals().update(D)
An Example
----------
.. code:: ipython2
fi, fo = infer(pop, swap, rolldown, rrest, ccons)[0]
.. parsed-literal::
25 (--) ∘ pop swap rolldown rrest ccons
28 (a1 --) ∘ swap rolldown rrest ccons
31 (a3 a2 a1 -- a2 a3) ∘ rolldown rrest ccons
34 (a4 a3 a2 a1 -- a2 a3 a4) ∘ rrest ccons
37 ([a4 a5 ...1] a3 a2 a1 -- a2 a3 [...1]) ∘ ccons
40 ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) ∘
.. code:: ipython2
print doc_from_stack_effect(fi, fo)
.. parsed-literal::
([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1])
.. code:: ipython2
from joy.parser import text_to_expression
from joy.utils.stack import stack_to_string
.. code:: ipython2
e = text_to_expression('0 1 2 [3 4]') # reverse order
print stack_to_string(e)
.. parsed-literal::
[3 4] 2 1 0
.. code:: ipython2
u = unify(e, fi)[0]
u
.. parsed-literal::
{a1: 0, a2: 1, a3: 2, a4: 3, a5: 4, s2: (), s1: ()}
.. code:: ipython2
g = reify(u, (fi, fo))
print doc_from_stack_effect(*g)
.. parsed-literal::
(... [3 4 ] 2 1 0 -- ... [1 2 ])
Unification Works "in Reverse"
------------------------------
.. code:: ipython2
e = text_to_expression('[2 3]')
.. code:: ipython2
u = unify(e, fo)[0] # output side, not input side
u
.. parsed-literal::
{a2: 2, a3: 3, s2: (), s1: ()}
.. code:: ipython2
g = reify(u, (fi, fo))
print doc_from_stack_effect(*g)
.. parsed-literal::
(... [a4 a5 ] 3 2 a1 -- ... [2 3 ])
Failing a Check
---------------
.. code:: ipython2
fi, fo = infer(dup, mul)[0]
.. parsed-literal::
25 (--) ∘ dup mul
28 (a1 -- a1 a1) ∘ mul
31 (f1 -- f2) ∘
31 (i1 -- i2) ∘
.. code:: ipython2
e = text_to_expression('"two"')
print stack_to_string(e)
.. parsed-literal::
'two'
.. code:: ipython2
try:
unify(e, fi)
except JoyTypeError, err:
print err
.. parsed-literal::
Cannot unify 'two' and f1.

View File

@ -31,7 +31,8 @@
<div class="body" role="main">
<h1>All modules for which code is available</h1>
<ul><li><a href="joy/joy.html">joy.joy</a></li>
<ul><li><a href="__builtin__.html">__builtin__</a></li>
<li><a href="joy/joy.html">joy.joy</a></li>
<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>

View File

@ -160,7 +160,11 @@
<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"># genrec == [[genrec] cons cons cons cons] nullary swons concat ifte</span>
<span class="c1"># Another definition for while. FWIW</span>
<span class="c1"># while == over [[i] dip nullary] ccons [nullary] dip loop</span>
<span class="c1">##ccons == cons cons</span>
<span class="c1">##unit == [] cons</span>
<span class="c1">##second == rest first</span>
@ -254,8 +258,11 @@
<span class="bp">self</span><span class="o">.</span><span class="n">body</span> <span class="o">=</span> <span class="n">text_to_expression</span><span class="p">(</span><span class="n">body_text</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_body</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">iter_stack</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">body</span><span class="p">))</span>
<span class="bp">self</span><span class="o">.</span><span class="vm">__doc__</span> <span class="o">=</span> <span class="n">doc</span> <span class="ow">or</span> <span class="n">body_text</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_compiled</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</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="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compiled</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compiled</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="n">expression</span> <span class="o">=</span> <span class="n">list_to_stack</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_body</span><span class="p">,</span> <span class="n">expression</span><span class="p">)</span>
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span>
@ -311,32 +318,6 @@
<span class="k">return</span> <span class="n">expression</span><span class="p">,</span> <span class="n">stack</span></div>
<span class="c1">##@inscribe</span>
<span class="c1">##@SimpleFunctionWrapper</span>
<span class="c1">##def first(stack):</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## ::</span>
<span class="c1">##</span>
<span class="c1">## first == uncons pop</span>
<span class="c1">##</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## ((head, tail), stack) = stack</span>
<span class="c1">## return head, stack</span>
<span class="c1">##@inscribe</span>
<span class="c1">##@SimpleFunctionWrapper</span>
<span class="c1">##def rest(stack):</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## ::</span>
<span class="c1">##</span>
<span class="c1">## rest == uncons popd</span>
<span class="c1">##</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## ((head, tail), stack) = stack</span>
<span class="c1">## return tail, stack</span>
<div class="viewcode-block" id="getitem"><a class="viewcode-back" href="../../library.html#joy.library.getitem">[docs]</a><span class="nd">@inscribe</span>
<span class="nd">@SimpleFunctionWrapper</span>
<span class="k">def</span> <span class="nf">getitem</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
@ -523,30 +504,6 @@
<span class="k">return</span> <span class="n">list_to_stack</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="n">iter_stack</span><span class="p">(</span><span class="n">tos</span><span class="p">))),</span> <span class="n">stack</span></div>
<span class="c1">##@inscribe</span>
<span class="c1">##@SimpleFunctionWrapper</span>
<span class="c1">##def cons(S):</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## The cons operator expects a list on top of the stack and the potential</span>
<span class="c1">## member below. The effect is to add the potential member into the</span>
<span class="c1">## aggregate.</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## (tos, (second, stack)) = S</span>
<span class="c1">## return (second, tos), stack</span>
<span class="c1">##@inscribe</span>
<span class="c1">##@SimpleFunctionWrapper</span>
<span class="c1">##def uncons(S):</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## Inverse of cons, removes an item from the top of the list on the stack</span>
<span class="c1">## and places it under the remaining list.</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## (tos, stack) = S</span>
<span class="c1">## item, tos = tos</span>
<span class="c1">## return tos, (item, stack)</span>
<div class="viewcode-block" id="clear"><a class="viewcode-back" href="../../library.html#joy.library.clear">[docs]</a><span class="nd">@inscribe</span>
<span class="nd">@SimpleFunctionWrapper</span>
<span class="k">def</span> <span class="nf">clear</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
@ -560,72 +517,6 @@
<span class="k">return</span> <span class="p">()</span></div>
<span class="c1">##@inscribe</span>
<span class="c1">##@SimpleFunctionWrapper</span>
<span class="c1">##def dup(S):</span>
<span class="c1">## &#39;&#39;&#39;Duplicate the top item on the stack.&#39;&#39;&#39;</span>
<span class="c1">## (tos, stack) = S</span>
<span class="c1">## return tos, (tos, stack)</span>
<span class="c1">##@inscribe</span>
<span class="c1">##@SimpleFunctionWrapper</span>
<span class="c1">##def over(S):</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## Copy the second item down on the stack to the top of the stack.</span>
<span class="c1">## ::</span>
<span class="c1">##</span>
<span class="c1">## a b over</span>
<span class="c1">## --------------</span>
<span class="c1">## a b a</span>
<span class="c1">##</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## second = S[1][0]</span>
<span class="c1">## return second, S</span>
<span class="c1">##@inscribe</span>
<span class="c1">##@SimpleFunctionWrapper</span>
<span class="c1">##def tuck(S):</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## Copy the item at TOS under the second item of the stack.</span>
<span class="c1">## ::</span>
<span class="c1">##</span>
<span class="c1">## a b tuck</span>
<span class="c1">## --------------</span>
<span class="c1">## b a b</span>
<span class="c1">##</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## (tos, (second, stack)) = S</span>
<span class="c1">## return tos, (second, (tos, stack))</span>
<span class="c1">##@inscribe</span>
<span class="c1">##@SimpleFunctionWrapper</span>
<span class="c1">##def swap(S):</span>
<span class="c1">## &#39;&#39;&#39;Swap the top two items on stack.&#39;&#39;&#39;</span>
<span class="c1">## (tos, (second, stack)) = S</span>
<span class="c1">## return second, (tos, stack)</span>
<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>
<span class="c1">##@SimpleFunctionWrapper</span>
<span class="c1">##def stack_(stack):</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## The stack operator pushes onto the stack a list containing all the</span>
<span class="c1">## elements of the stack.</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## return stack, stack</span>
<div class="viewcode-block" id="unstack"><a class="viewcode-back" href="../../library.html#joy.library.unstack">[docs]</a><span class="nd">@inscribe</span>
<span class="nd">@SimpleFunctionWrapper</span>
<span class="k">def</span> <span class="nf">unstack</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
@ -636,44 +527,6 @@
<span class="k">return</span> <span class="n">stack</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></div>
<span class="c1">##@inscribe</span>
<span class="c1">##@SimpleFunctionWrapper</span>
<span class="c1">##def pop(stack):</span>
<span class="c1">## &#39;&#39;&#39;Pop and discard the top item from the stack.&#39;&#39;&#39;</span>
<span class="c1">## return stack[1]</span>
<span class="c1">##@inscribe</span>
<span class="c1">##@SimpleFunctionWrapper</span>
<span class="c1">##def popd(stack):</span>
<span class="c1">## &#39;&#39;&#39;Pop and discard the second item from the stack.&#39;&#39;&#39;</span>
<span class="c1">## (tos, (_, stack)) = stack</span>
<span class="c1">## return tos, stack</span>
<span class="c1">##@inscribe</span>
<span class="c1">##@SimpleFunctionWrapper</span>
<span class="c1">##def popdd(stack):</span>
<span class="c1">## &#39;&#39;&#39;Pop and discard the third item from the stack.&#39;&#39;&#39;</span>
<span class="c1">## (tos, (second, (_, stack))) = stack</span>
<span class="c1">## return tos, (second, stack)</span>
<span class="c1">##@inscribe</span>
<span class="c1">##@SimpleFunctionWrapper</span>
<span class="c1">##def popop(stack):</span>
<span class="c1">## &#39;&#39;&#39;Pop and discard the first and second items from the stack.&#39;&#39;&#39;</span>
<span class="c1">## return stack[1][1]</span>
<span class="c1">##@inscribe</span>
<span class="c1">##@SimpleFunctionWrapper</span>
<span class="c1">##def dupd(S):</span>
<span class="c1">## &#39;&#39;&#39;Duplicate the second item on the stack.&#39;&#39;&#39;</span>
<span class="c1">## (tos, (second, stack)) = S</span>
<span class="c1">## return tos, (second, (second, stack))</span>
<div class="viewcode-block" id="reverse"><a class="viewcode-back" href="../../library.html#joy.library.reverse">[docs]</a><span class="nd">@inscribe</span>
<span class="nd">@SimpleFunctionWrapper</span>
<span class="k">def</span> <span class="nf">reverse</span><span class="p">(</span><span class="n">S</span><span class="p">):</span>
@ -804,36 +657,6 @@
<span class="k">return</span> <span class="n">r</span></div>
<span class="c1">##@inscribe</span>
<span class="c1">##@SimpleFunctionWrapper</span>
<span class="c1">##def rollup(S):</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## ::</span>
<span class="c1">##</span>
<span class="c1">## a b c</span>
<span class="c1">## -----------</span>
<span class="c1">## b c a</span>
<span class="c1">##</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## (a, (b, (c, stack))) = S</span>
<span class="c1">## return b, (c, (a, stack))</span>
<span class="c1">##@inscribe</span>
<span class="c1">##@SimpleFunctionWrapper</span>
<span class="c1">##def rolldown(S):</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## ::</span>
<span class="c1">##</span>
<span class="c1">## a b c</span>
<span class="c1">## -----------</span>
<span class="c1">## c a b</span>
<span class="c1">##</span>
<span class="c1">## &#39;&#39;&#39;</span>
<span class="c1">## (a, (b, (c, stack))) = S</span>
<span class="c1">## return c, (a, (b, stack))</span>
<span class="c1">#def execute(S):</span>
<span class="c1"># (text, stack) = S</span>
<span class="c1"># if isinstance(text, str):</span>
@ -1481,42 +1304,7 @@
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span></div>
<span class="c1">#def nullary(S, expression, dictionary):</span>
<span class="c1"># &#39;&#39;&#39;</span>
<span class="c1"># Run the program on TOS and return its first result without consuming</span>
<span class="c1"># any of the stack (except the program on TOS.)</span>
<span class="c1"># &#39;&#39;&#39;</span>
<span class="c1"># (quote, stack) = S</span>
<span class="c1"># result = joy(stack, quote, dictionary)</span>
<span class="c1"># return (result[0][0], stack), expression, dictionary</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="c1">#def unary(S, expression, dictionary):</span>
<span class="c1"># (quote, stack) = S</span>
<span class="c1"># _, return_stack = stack</span>
<span class="c1"># result = joy(stack, quote, dictionary)[0]</span>
<span class="c1"># return (result[0], return_stack), expression, dictionary</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="c1">#def binary(S, expression, dictionary):</span>
<span class="c1"># (quote, stack) = S</span>
<span class="c1"># _, (_, return_stack) = stack</span>
<span class="c1"># result = joy(stack, quote, dictionary)[0]</span>
<span class="c1"># return (result[0], return_stack), expression, dictionary</span>
<span class="c1">#</span>
<span class="c1">#</span>
<span class="c1">#def ternary(S, expression, dictionary):</span>
<span class="c1"># (quote, stack) = S</span>
<span class="c1"># _, (_, (_, return_stack)) = stack</span>
<span class="c1"># result = joy(stack, quote, dictionary)[0]</span>
<span class="c1"># return (result[0], return_stack), expression, dictionary</span>
<span class="c1"># FunctionWrapper(binary),</span>
<span class="c1"># FunctionWrapper(cleave),</span>
<span class="c1"># FunctionWrapper(nullary),</span>
<span class="c1"># FunctionWrapper(ternary),</span>
<span class="c1"># FunctionWrapper(unary),</span>
<span class="c1"># FunctionWrapper(while_),</span>

View File

@ -64,16 +64,26 @@
<h2 id="A">A</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.BooleanJoyType.accept">accept (joy.utils.types.BooleanJoyType attribute)</a>
<ul>
<li><a href="types.html#joy.utils.types.FloatJoyType.accept">(joy.utils.types.FloatJoyType attribute)</a>
</li>
<li><a href="types.html#joy.utils.types.IntJoyType.accept">(joy.utils.types.IntJoyType attribute)</a>
</li>
<li><a href="types.html#joy.utils.types.StackJoyType.accept">(joy.utils.types.StackJoyType attribute)</a>
</li>
</ul></li>
<li><a href="library.html#joy.library.add_aliases">add_aliases() (in module joy.library)</a>
</li>
<li><a href="library.html#joy.library.DefinitionWrapper.add_def">add_def() (joy.library.DefinitionWrapper class method)</a>
</li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<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>
@ -192,13 +202,15 @@
</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>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<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="types.html#joy.utils.polytypes.FUNCTIONS">FUNCTIONS (in module joy.utils.polytypes)</a>
</li>
<li><a href="library.html#joy.library.FunctionWrapper">FunctionWrapper() (in module joy.library)</a>
</li>
@ -388,6 +400,8 @@
<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.reify">reify() (in module joy.utils.types)</a>
</li>
<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>
@ -427,8 +441,6 @@
<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>
@ -490,12 +502,8 @@
</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><a href="types.html#joy.utils.types.unify">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>
@ -505,8 +513,6 @@
<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>

File diff suppressed because one or more lines are too long

View File

@ -109,17 +109,35 @@
<dl class="class">
<dt id="joy.utils.types.BooleanJoyType">
<em class="property">class </em><code class="descclassname">joy.utils.types.</code><code class="descname">BooleanJoyType</code><span class="sig-paren">(</span><em>number</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/types.html#BooleanJoyType"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.types.BooleanJoyType" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dd><dl class="attribute">
<dt id="joy.utils.types.BooleanJoyType.accept">
<code class="descname">accept</code><a class="headerlink" href="#joy.utils.types.BooleanJoyType.accept" title="Permalink to this definition"></a></dt>
<dd><p>alias of <code class="xref py py-class docutils literal notranslate"><span class="pre">__builtin__.bool</span></code></p>
</dd></dl>
</dd></dl>
<dl class="class">
<dt id="joy.utils.types.FloatJoyType">
<em class="property">class </em><code class="descclassname">joy.utils.types.</code><code class="descname">FloatJoyType</code><span class="sig-paren">(</span><em>number</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/types.html#FloatJoyType"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.types.FloatJoyType" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dd><dl class="attribute">
<dt id="joy.utils.types.FloatJoyType.accept">
<code class="descname">accept</code><a class="headerlink" href="#joy.utils.types.FloatJoyType.accept" title="Permalink to this definition"></a></dt>
<dd><p>alias of <code class="xref py py-class docutils literal notranslate"><span class="pre">__builtin__.float</span></code></p>
</dd></dl>
</dd></dl>
<dl class="class">
<dt id="joy.utils.types.IntJoyType">
<em class="property">class </em><code class="descclassname">joy.utils.types.</code><code class="descname">IntJoyType</code><span class="sig-paren">(</span><em>number</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/types.html#IntJoyType"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.types.IntJoyType" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dd><dl class="attribute">
<dt id="joy.utils.types.IntJoyType.accept">
<code class="descname">accept</code><a class="headerlink" href="#joy.utils.types.IntJoyType.accept" title="Permalink to this definition"></a></dt>
<dd><p>alias of <code class="xref py py-class docutils literal notranslate"><span class="pre">__builtin__.int</span></code></p>
</dd></dl>
</dd></dl>
<dl class="exception">
<dt id="joy.utils.types.JoyTypeError">
@ -134,7 +152,13 @@
<dl class="class">
<dt id="joy.utils.types.StackJoyType">
<em class="property">class </em><code class="descclassname">joy.utils.types.</code><code class="descname">StackJoyType</code><span class="sig-paren">(</span><em>number</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/types.html#StackJoyType"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.types.StackJoyType" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dd><dl class="attribute">
<dt id="joy.utils.types.StackJoyType.accept">
<code class="descname">accept</code><a class="headerlink" href="#joy.utils.types.StackJoyType.accept" title="Permalink to this definition"></a></dt>
<dd><p>alias of <code class="xref py py-class docutils literal notranslate"><span class="pre">__builtin__.tuple</span></code></p>
</dd></dl>
</dd></dl>
<dl class="function">
<dt id="joy.utils.types.compilable">
@ -175,6 +199,12 @@ is used to generate one.</p>
<dd><p>Return a crude string representation of a stack effect.</p>
</dd></dl>
<dl class="function">
<dt id="joy.utils.types.reify">
<code class="descclassname">joy.utils.types.</code><code class="descname">reify</code><span class="sig-paren">(</span><em>meaning</em>, <em>name</em>, <em>seen=None</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/types.html#reify"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.types.reify" title="Permalink to this definition"></a></dt>
<dd><p>Apply substitution dict to term, returning new term.</p>
</dd></dl>
<dl class="function">
<dt id="joy.utils.types.relabel">
<code class="descclassname">joy.utils.types.</code><code class="descname">relabel</code><span class="sig-paren">(</span><em>left</em>, <em>right</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/types.html#relabel"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.types.relabel" title="Permalink to this definition"></a></dt>
@ -187,12 +217,6 @@ is used to generate one.</p>
<dd><p>Return a substitution dict representing a unifier for u and v.</p>
</dd></dl>
<dl class="function">
<dt id="joy.utils.types.update">
<code class="descclassname">joy.utils.types.</code><code class="descname">update</code><span class="sig-paren">(</span><em>s</em>, <em>term</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/types.html#update"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.types.update" title="Permalink to this definition"></a></dt>
<dd><p>Apply substitution dict to term, returning new term.</p>
</dd></dl>
</div>
<div class="section" id="joy-utils-polytypes">
<h2><code class="docutils literal notranslate"><span class="pre">joy.utils.polytypes</span></code><a class="headerlink" href="#joy-utils-polytypes" title="Permalink to this headline"></a></h2>
@ -276,6 +300,12 @@ combinators themselves.</p>
guard against being used on invalid types.</p>
</dd></dl>
<dl class="data">
<dt id="joy.utils.polytypes.FUNCTIONS">
<code class="descclassname">joy.utils.polytypes.</code><code class="descname">FUNCTIONS</code><em class="property"> = {'_Tree_add_Ee': _Tree_add_Ee, '_Tree_delete_R0': _Tree_delete_R0, '_Tree_delete_clear_stuff': _Tree_delete_clear_stuff, '_Tree_get_E': _Tree_get_E, 'add': add, 'and': and, 'b': b, 'bool': bool, 'branch': branch, 'ccons': ccons, 'clear': clear, 'concat_': concat_, 'cons': cons, 'dip': dip, 'dipd': dipd, 'dipdd': dipdd, 'div': div, 'divmod': divmod, 'dup': dup, 'dupd': dupd, 'dupdd': dupdd, 'dupdip': dupdip, 'eq': eq, 'first': first, 'first_two': first_two, 'floordiv': floordiv, 'fourth': fourth, 'ge': ge, 'gt': gt, 'i': i, 'infra': infra, 'le': le, 'loop': loop, 'lshift': lshift, 'lt': lt, 'modulus': modulus, 'mul': mul, 'ne': ne, 'neg': neg, 'not': not, 'nullary': nullary, 'over': over, 'pm': pm, 'pop': pop, 'popd': popd, 'popdd': popdd, 'popop': popop, 'popopd': popopd, 'popopdd': popopdd, 'pow': pow, 'pred': pred, 'product': product, 'rest': rest, 'rolldown': rolldown, 'rollup': rollup, 'rrest': rrest, 'rshift': rshift, 'second': second, 'sqrt': sqrt, 'stack': stack, 'stuncons': stuncons, 'stununcons': stununcons, 'sub': sub, 'succ': succ, 'sum': sum, 'swaack': swaack, 'swap': swap, 'swons': swons, 'third': third, 'truediv': truediv, 'tuck': tuck, 'uncons': uncons, 'unit': unit, 'unswons': unswons, 'x': x}</em><a class="headerlink" href="#joy.utils.polytypes.FUNCTIONS" title="Permalink to this definition"></a></dt>
<dd><p>Docstring for functions in Sphinx?</p>
</dd></dl>
<dl class="class">
<dt id="joy.utils.polytypes.FunctionJoyType">
<em class="property">class </em><code class="descclassname">joy.utils.polytypes.</code><code class="descname">FunctionJoyType</code><span class="sig-paren">(</span><em>name</em>, <em>sec</em>, <em>number</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/polytypes.html#FunctionJoyType"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.polytypes.FunctionJoyType" title="Permalink to this definition"></a></dt>
@ -320,12 +350,6 @@ dicts, the “unifiers”) that dont lead to type conflicts.</p>
</dd></dl>
<dl class="data">
<dt id="joy.utils.polytypes.Ss">
<code class="descclassname">joy.utils.polytypes.</code><code class="descname">Ss</code><em class="property"> = [s1*, s2*, s3*, s4*, s5*, s6*, s7*, s8*, s9*, s10*]</em><a class="headerlink" href="#joy.utils.polytypes.Ss" title="Permalink to this definition"></a></dt>
<dd><p>Docstring for functions in Sphinx?</p>
</dd></dl>
<dl class="class">
<dt id="joy.utils.polytypes.StackStarJoyType">
<em class="property">class </em><code class="descclassname">joy.utils.polytypes.</code><code class="descname">StackStarJoyType</code><span class="sig-paren">(</span><em>number</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/polytypes.html#StackStarJoyType"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.polytypes.StackStarJoyType" title="Permalink to this definition"></a></dt>
@ -381,12 +405,6 @@ expression is carried along and updated and yielded.</p>
effects. An expression is carried along and updated and yielded.</p>
</dd></dl>
<dl class="function">
<dt id="joy.utils.polytypes.unify">
<code class="descclassname">joy.utils.polytypes.</code><code class="descname">unify</code><span class="sig-paren">(</span><em>u</em>, <em>v</em>, <em>s=None</em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/utils/polytypes.html#unify"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#joy.utils.polytypes.unify" title="Permalink to this definition"></a></dt>
<dd><p>Return a tuple of substitution dicts representing unifiers for u and v.</p>
</dd></dl>
</div>
</div>