Bring in the Prolog impl.
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
The `source/gen-*.pl` files are created by `partial_reduce_thun/0`. I'm
|
||||
just messing around with it at the moment. In theory the reduced forms
|
||||
would be more efficient, but there's no pressure to improve performance
|
||||
yet, and I'm not e.g. feeding the output to GNU Prolog to compile to
|
||||
machine code, eh?
|
||||
|
||||
It's just neat to see what the reducer makes of it.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
@@ -0,0 +1,310 @@
|
||||
% With abs as a definition: abs ::= dup 0 < [] [neg] branch
|
||||
|
||||
?- joy(`[abs] ii <=`, [int(A), int(C)], [bool(B)]).
|
||||
|
||||
% Eight solutions:
|
||||
|
||||
B = false,
|
||||
A in 0..sup,
|
||||
A#=<C+ -1,
|
||||
A+1#=_67378,
|
||||
C in 1..sup,
|
||||
C+1#=_67426,
|
||||
_67426 in 1..sup,
|
||||
_67378 in 1..sup ;
|
||||
|
||||
|
||||
B = true,
|
||||
A in 0..sup,
|
||||
A#>=C,
|
||||
A+1#=_67204,
|
||||
C in 0..sup,
|
||||
C+1#=_67252,
|
||||
_67252 in 1..sup,
|
||||
_67204 in 1..sup ;
|
||||
|
||||
|
||||
B = false,
|
||||
A in inf.. -1,
|
||||
_67892+A#=0,
|
||||
A+1#=_67912,
|
||||
_67892 in 1..sup,
|
||||
_67892#=<C+ -1,
|
||||
C in 2..sup,
|
||||
C+1#=_68008,
|
||||
_68008 in 1..sup,
|
||||
_67912 in inf..0 ;
|
||||
|
||||
|
||||
B = true,
|
||||
A in inf.. -1,
|
||||
_67724+A#=0,
|
||||
A+1#=_67744,
|
||||
_67724 in 1..sup,
|
||||
_67724#>=C,
|
||||
C in 0..sup,
|
||||
C+1#=_67834,
|
||||
_67834 in 1..sup,
|
||||
_67744 in inf..0 ;
|
||||
|
||||
|
||||
B = false,
|
||||
A in 0..sup,
|
||||
A#=<_67850+ -1,
|
||||
A+1#=_67870,
|
||||
_67850 in 1..sup,
|
||||
_67850+C#=0,
|
||||
C in inf.. -1,
|
||||
C+1#=_67966,
|
||||
_67966 in inf..0,
|
||||
_67870 in 1..sup ;
|
||||
|
||||
|
||||
B = true,
|
||||
A in 1..sup,
|
||||
A#>=_67762,
|
||||
A+1#=_67780,
|
||||
_67762 in 1..sup,
|
||||
_67762+C#=0,
|
||||
C in inf.. -1,
|
||||
C+1#=_67876,
|
||||
_67876 in inf..0,
|
||||
_67780 in 1..sup ;
|
||||
|
||||
|
||||
B = false,
|
||||
A in inf.. -1,
|
||||
_68746+A#=0,
|
||||
A+1#=_68766,
|
||||
_68746 in 1..sup,
|
||||
_68746#=<_68818+ -1,
|
||||
_68818 in 2..sup,
|
||||
_68818+C#=0,
|
||||
C in inf.. -2,
|
||||
C+1#=_68910,
|
||||
_68910 in inf..0,
|
||||
_68766 in inf..0 ;
|
||||
|
||||
|
||||
B = true,
|
||||
A in inf.. -1,
|
||||
_68258+A#=0,
|
||||
A+1#=_68278,
|
||||
_68258 in 1..sup,
|
||||
_68258#>=_68326,
|
||||
_68326 in 1..sup,
|
||||
_68326+C#=0,
|
||||
C in inf.. -1,
|
||||
C+1#=_68416,
|
||||
_68416 in inf..0,
|
||||
_68278 in inf..0 ;
|
||||
|
||||
|
||||
false.
|
||||
|
||||
|
||||
% If we add a function rule for it using CLP(FD)...:
|
||||
|
||||
func(abs, [int(A)|S], [int(B)|S]) :- B #= abs(A).
|
||||
|
||||
?- joy(`[abs] ii <=`, [int(A), int(C)], [bool(B)]).
|
||||
|
||||
% We get eighteen solutions! Egad.
|
||||
|
||||
B = false,
|
||||
_7784#=abs(A),
|
||||
_7784 in 0..sup,
|
||||
_7784#=<_7836+ -1,
|
||||
_7836 in 1..sup,
|
||||
_7836#=abs(C),
|
||||
C in inf.. -1\/1..sup ;
|
||||
|
||||
|
||||
B = true,
|
||||
_6512#=abs(A),
|
||||
_6512 in 0..sup,
|
||||
_6512#>=_6560,
|
||||
_6560 in 0..sup,
|
||||
_6560#=abs(C) ;
|
||||
|
||||
|
||||
B = false,
|
||||
A in 0..sup,
|
||||
A#=<_8820+ -1,
|
||||
A+1#=_8840,
|
||||
_8820 in 1..sup,
|
||||
_8820#=abs(C),
|
||||
C in inf.. -1\/1..sup,
|
||||
_8840 in 1..sup ;
|
||||
|
||||
|
||||
B = true,
|
||||
A in 0..sup,
|
||||
A#>=_7544,
|
||||
A+1#=_7562,
|
||||
_7544 in 0..sup,
|
||||
_7544#=abs(C),
|
||||
_7562 in 1..sup ;
|
||||
|
||||
|
||||
B = false,
|
||||
A in inf.. -1,
|
||||
_9354+A#=0,
|
||||
A+1#=_9374,
|
||||
_9354 in 1..sup,
|
||||
_9354#=<_9426+ -1,
|
||||
_9426 in 2..sup,
|
||||
_9426#=abs(C),
|
||||
C in inf.. -2\/2..sup,
|
||||
_9374 in inf..0 ;
|
||||
|
||||
|
||||
B = true,
|
||||
A in inf.. -1,
|
||||
_8082+A#=0,
|
||||
A+1#=_8102,
|
||||
_8082 in 1..sup,
|
||||
_8082#>=_8150,
|
||||
_8150 in 0..sup,
|
||||
_8150#=abs(C),
|
||||
_8102 in inf..0 ;
|
||||
|
||||
|
||||
B = false,
|
||||
_7686#=abs(A),
|
||||
_7686 in 0..sup,
|
||||
_7686#=<C+ -1,
|
||||
C in 1..sup,
|
||||
C+1#=_7782,
|
||||
_7782 in 1..sup ;
|
||||
|
||||
|
||||
B = true,
|
||||
_7518#=abs(A),
|
||||
_7518 in 0..sup,
|
||||
_7518#>=C,
|
||||
C in 0..sup,
|
||||
C+1#=_7608,
|
||||
_7608 in 1..sup ;
|
||||
|
||||
|
||||
B = false,
|
||||
A in 0..sup,
|
||||
A#=<C+ -1,
|
||||
A+1#=_8742,
|
||||
C in 1..sup,
|
||||
C+1#=_8790,
|
||||
_8790 in 1..sup,
|
||||
_8742 in 1..sup ;
|
||||
|
||||
|
||||
B = true,
|
||||
A in 0..sup,
|
||||
A#>=C,
|
||||
A+1#=_8568,
|
||||
C in 0..sup,
|
||||
C+1#=_8616,
|
||||
_8616 in 1..sup,
|
||||
_8568 in 1..sup ;
|
||||
|
||||
|
||||
B = false,
|
||||
A in inf.. -1,
|
||||
_9256+A#=0,
|
||||
A+1#=_9276,
|
||||
_9256 in 1..sup,
|
||||
_9256#=<C+ -1,
|
||||
C in 2..sup,
|
||||
C+1#=_9372,
|
||||
_9372 in 1..sup,
|
||||
_9276 in inf..0 ;
|
||||
|
||||
|
||||
B = true,
|
||||
A in inf.. -1,
|
||||
_9088+A#=0,
|
||||
A+1#=_9108,
|
||||
_9088 in 1..sup,
|
||||
_9088#>=C,
|
||||
C in 0..sup,
|
||||
C+1#=_9198,
|
||||
_9198 in 1..sup,
|
||||
_9108 in inf..0 ;
|
||||
|
||||
|
||||
B = false,
|
||||
_8178#=abs(A),
|
||||
_8178 in 0..sup,
|
||||
_8178#=<_8230+ -1,
|
||||
_8230 in 1..sup,
|
||||
_8230+C#=0,
|
||||
C in inf.. -1,
|
||||
C+1#=_8322,
|
||||
_8322 in inf..0 ;
|
||||
|
||||
|
||||
B = true,
|
||||
A in inf.. -1\/1..sup,
|
||||
_9272#=abs(A),
|
||||
_9272 in 1..sup,
|
||||
_9272#>=_9320,
|
||||
_9320 in 1..sup,
|
||||
_9320+C#=0,
|
||||
C in inf.. -1,
|
||||
C+1#=_9410,
|
||||
_9410 in inf..0 ;
|
||||
|
||||
|
||||
B = false,
|
||||
A in 0..sup,
|
||||
A#=<_9214+ -1,
|
||||
A+1#=_9234,
|
||||
_9214 in 1..sup,
|
||||
_9214+C#=0,
|
||||
C in inf.. -1,
|
||||
C+1#=_9330,
|
||||
_9330 in inf..0,
|
||||
_9234 in 1..sup ;
|
||||
|
||||
|
||||
B = true,
|
||||
A in 1..sup,
|
||||
A#>=_9126,
|
||||
A+1#=_9144,
|
||||
_9126 in 1..sup,
|
||||
_9126+C#=0,
|
||||
C in inf.. -1,
|
||||
C+1#=_9240,
|
||||
_9240 in inf..0,
|
||||
_9144 in 1..sup ;
|
||||
|
||||
|
||||
B = false,
|
||||
A in inf.. -1,
|
||||
_10110+A#=0,
|
||||
A+1#=_10130,
|
||||
_10110 in 1..sup,
|
||||
_10110#=<_10182+ -1,
|
||||
_10182 in 2..sup,
|
||||
_10182+C#=0,
|
||||
C in inf.. -2,
|
||||
C+1#=_10274,
|
||||
_10274 in inf..0,
|
||||
_10130 in inf..0 ;
|
||||
|
||||
|
||||
B = true,
|
||||
A in inf.. -1,
|
||||
_9622+A#=0,
|
||||
A+1#=_9642,
|
||||
_9622 in 1..sup,
|
||||
_9622#>=_9690,
|
||||
_9690 in 1..sup,
|
||||
_9690+C#=0,
|
||||
C in inf.. -1,
|
||||
C+1#=_9780,
|
||||
_9780 in inf..0,
|
||||
_9642 in inf..0 ;
|
||||
|
||||
|
||||
false.
|
||||
@@ -0,0 +1,4 @@
|
||||
Talk about minimal basis, Kirby (sp?) has found a basis involving a
|
||||
combinator he calls 'cake'...
|
||||
|
||||
Branch, Loop, Sequence, Parallel.
|
||||
@@ -0,0 +1,225 @@
|
||||
___ _ ___ _
|
||||
| __|_ ____ _ _ __ _ __| |___ / __|___ __| |___
|
||||
| _|\ \ / _` | ' \| '_ \ / -_) | (__/ _ \/ _` / -_)
|
||||
|___/_\_\__,_|_|_|_| .__/_\___| \___\___/\__,_\___|
|
||||
|_|
|
||||
# On the Square Spiral Example Code
|
||||
|
||||
Here is the example of Joy code from the `README` file:
|
||||
|
||||
[[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte
|
||||
|
||||
It might seem unreadable but with a little familiarity it becomes just as
|
||||
legible as any other notation. Some layout helps:
|
||||
|
||||
[ [[abs] ii <=]
|
||||
[
|
||||
[<>] [pop !-] ||
|
||||
] &&
|
||||
]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
ifte
|
||||
|
||||
This function accepts two integers on the stack and increments or
|
||||
decrements one of them such that the new pair of numbers is the next
|
||||
coordinate pair in a square spiral (like the kind used to construct an
|
||||
Ulam Spiral).
|
||||
|
||||
|
||||
## Original Form
|
||||
|
||||
It's adapted from the [original code on StackOverflow](https://stackoverflow.com/questions/398299/looping-in-a-spiral/31864777#31864777):
|
||||
|
||||
> If all you're trying to do is generate the first N points in the spiral
|
||||
> (without the original problem's constraint of masking to an N x M
|
||||
> region), the code becomes very simple:
|
||||
|
||||
void spiral(const int N)
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
for(int i = 0; i < N; ++i)
|
||||
{
|
||||
cout << x << '\t' << y << '\n';
|
||||
if(abs(x) <= abs(y) && (x != y || x >= 0))
|
||||
x += ((y >= 0) ? 1 : -1);
|
||||
else
|
||||
y += ((x >= 0) ? -1 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
> The trick is that you can compare x and y to determine what side of the
|
||||
> square you're on, and that tells you what direction to move in.
|
||||
|
||||
|
||||
## Translation to Joy
|
||||
|
||||
I'm going to make a function that take two ints (`x` and `y`) and
|
||||
generates the next pair, we'll turn it into a generator later using the
|
||||
`x` combinator.
|
||||
|
||||
### First Boolean Predicate
|
||||
|
||||
We need a function that computes `abs(x) <= abs(y)`, we can use `ii` to
|
||||
apply `abs` in parallel (eventually) to both values and then compare them
|
||||
with `<=`:
|
||||
|
||||
[abs] ii <=
|
||||
|
||||
I've defined two short-circuiting Boolean combinators `&&` and `||` that
|
||||
each accept two quoted predicate programs, run the first, and
|
||||
conditionally run the second only if required (to compute the final
|
||||
Boolean value). They run their predicate arguments `nullary`. Given
|
||||
those, we can define `x != y || x >= 0` as:
|
||||
|
||||
[<>] [pop 0 >=] ||
|
||||
|
||||
And `(abs(x) <= abs(y) && (x != y || x >= 0))` as:
|
||||
|
||||
[[abs] ii <=] [[<>] [pop 0 >=] ||] &&
|
||||
|
||||
It's a little rough, but, as I say, with a little familiarity it becomes
|
||||
legible.
|
||||
|
||||
### The Increment / Decrement Branches
|
||||
|
||||
Turning to the branches of the main `if` statement:
|
||||
|
||||
x += ((y >= 0) ? 1 : -1);
|
||||
|
||||
Rewrite as a hybrid (pseudo-code) `ifte` expression:
|
||||
|
||||
[y >= 0] [x += 1] [X -= 1] ifte
|
||||
|
||||
Change each C phrase to Joy code:
|
||||
|
||||
[0 >=] [[++] dip] [[--] dip] ifte
|
||||
|
||||
Factor out the dip from each branch:
|
||||
|
||||
[0 >=] [[++]] [[--]] ifte dip
|
||||
|
||||
Similar logic applies to the other branch:
|
||||
|
||||
y += ((x >= 0) ? -1 : 1);
|
||||
|
||||
[x >= 0] [y -= 1] [y += 1] ifte
|
||||
|
||||
[pop 0 >=] [--] [++] ifte
|
||||
|
||||
|
||||
## Putting the Pieces Together
|
||||
|
||||
We can assemble the three functions we just defined in quotes and give
|
||||
them them to the `ifte` combinator. With some arrangement to show off
|
||||
the symmetry of the two branches, we have:
|
||||
|
||||
[[[abs] ii <=] [[<>] [pop !-] ||] &&]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
ifte
|
||||
|
||||
As I was writing this up I realized that, since the `&&` combinator
|
||||
doesn't consume the stack (below its quoted args), I can unquote the
|
||||
predicate, swap the branches, and use the `branch` combinator instead of
|
||||
`ifte`:
|
||||
|
||||
[[abs] ii <=] [[<>] [pop !-] ||] &&
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
branch
|
||||
|
||||
|
||||
## Turning it into a Generator with `x`
|
||||
|
||||
It can be used with the x combinator to make a kind of generator for
|
||||
spiral square coordinates.
|
||||
|
||||
|
||||
We can use `codireco` to make a generator
|
||||
|
||||
codireco ::= cons dip rest cons
|
||||
|
||||
It will look like this:
|
||||
|
||||
[value [F] codireco]
|
||||
|
||||
Here's a trace of how it works:
|
||||
|
||||
[0 [dup ++] codireco] . x
|
||||
[0 [dup ++] codireco] . 0 [dup ++] codireco
|
||||
[0 [dup ++] codireco] 0 . [dup ++] codireco
|
||||
[0 [dup ++] codireco] 0 [dup ++] . codireco
|
||||
[0 [dup ++] codireco] 0 [dup ++] . cons dip rest cons
|
||||
[0 [dup ++] codireco] [0 dup ++] . dip rest cons
|
||||
. 0 dup ++ [0 [dup ++] codireco] rest cons
|
||||
0 . dup ++ [0 [dup ++] codireco] rest cons
|
||||
0 0 . ++ [0 [dup ++] codireco] rest cons
|
||||
0 1 . [0 [dup ++] codireco] rest cons
|
||||
0 1 [0 [dup ++] codireco] . rest cons
|
||||
0 1 [[dup ++] codireco] . cons
|
||||
0 [1 [dup ++] codireco] .
|
||||
|
||||
But first we have to change the `spiral_next` function to work on a
|
||||
quoted pair of integers, and leave a copy of the pair on the stack.
|
||||
From:
|
||||
|
||||
y x spiral_next
|
||||
---------------------
|
||||
y' x'
|
||||
|
||||
to:
|
||||
|
||||
[x y] [spiral_next] infra
|
||||
-------------------------------
|
||||
[x' y']
|
||||
|
||||
So our generator is:
|
||||
|
||||
[[x y] [dup [spiral_next] infra] codireco]
|
||||
|
||||
Or rather:
|
||||
|
||||
[[0 0] [dup [spiral_next] infra] codireco]
|
||||
|
||||
There is a function `make_generator` that will build the generator for us
|
||||
out of the value and stepper function:
|
||||
|
||||
[0 0] [dup [spiral_next] infra] make_generator
|
||||
----------------------------------------------------
|
||||
[[0 0] [dup [spiral_next] infra] codireco]
|
||||
|
||||
Here it is in action:
|
||||
|
||||
?- joy(`[[0 0] [dup [spiral_next] infra] codireco] x x x x pop`, [], _So),
|
||||
| joy_terms_to_string(_So, S).
|
||||
|
||||
_So = [list([int(-1), int(0)]), list([int(-1), int(1)]), list([int(0), int(1)]), list([int(0), int(0)])],
|
||||
|
||||
S = "[-1 0] [-1 1] [0 1] [0 0]" .
|
||||
|
||||
Four `x` combinators, four pairs of coordinates.
|
||||
|
||||
|
||||
## Conclusion
|
||||
|
||||
So that's an example of Joy code. It's a straightforward translation of
|
||||
the original. It's a little long for a single definition, you might
|
||||
break it up like so:
|
||||
|
||||
_spn_P ::= [[abs] ii <=] [[<>] [pop !-] ||] &&
|
||||
|
||||
_spn_T ::= [ !-] [[++]] [[--]] ifte dip
|
||||
_spn_E ::= [pop !-] [--] [++] ifte
|
||||
|
||||
spiral_next ::= _spn_P [_spn_E] [_spn_T] branch
|
||||
|
||||
This way it's easy to see that the function is a branch with two
|
||||
quasi-symmetrical paths.
|
||||
|
||||
We then used this function to make a simple generator of coordinate
|
||||
pairs, where the next pair in the series can be generated at any time by
|
||||
using the `x` combinator on the generator (which is just a quoted
|
||||
expression containing a copy of the current pair and the "stepper
|
||||
function" to generate the next pair from that.)
|
||||
@@ -0,0 +1,61 @@
|
||||
# list-structured memory
|
||||
|
||||
[In SICP, section 5.3, "Storage Allocation and Garbage Collection"](https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-33.html#%_sec_5.3):
|
||||
|
||||
> In order to simplify the discussion, we will assume that our register
|
||||
machines can be equipped with a list-structured memory, in which the
|
||||
basic operations for manipulating list-structured data are primitive.
|
||||
|
||||
So they bunt to an abstraction and then implement that abstraction as a
|
||||
separate problem. Makes sense. I see no reason not to adopt the design
|
||||
described here.
|
||||
|
||||
------------------
|
||||
|
||||
# Machine Ints vs BigNums
|
||||
|
||||
Already there is a problem in the semantics. SWI Prolog integers can be
|
||||
larger than machine words, which in the RISC CPU are thirty-two bits.
|
||||
(GNU Prolog uses machine words for its integers). THe main options are:
|
||||
|
||||
1. Implements "BigNums" for Wirth RISC.
|
||||
|
||||
2. Adjust the semantics of Thun to reflect the modular arithmetic of
|
||||
machine words and native machine integer math operations.
|
||||
|
||||
3. ... something else.
|
||||
|
||||
------------------
|
||||
|
||||
# specialized versions of `branch` and `ifte`
|
||||
|
||||
THere's another semantic wrinkle with branches and Boolean values.
|
||||
Namely, the CPU provides the condition and the offset in one instruction
|
||||
whereas Joy has them separated. I have been thinking about introducing
|
||||
specialized versions of `branch` as primitives:
|
||||
|
||||
=branch
|
||||
>branch
|
||||
<branch
|
||||
<=branch
|
||||
>=branch
|
||||
<>branch
|
||||
|
||||
Or maybe:
|
||||
|
||||
=?
|
||||
>?
|
||||
<?
|
||||
<=?
|
||||
>=?
|
||||
<>?
|
||||
|
||||
Anyway, it would be pretty easy to detect simple cases of the split
|
||||
pattern and convert them automatically, but the programmer could use them
|
||||
directly whenever it made sense.
|
||||
|
||||
> [F] [T] branch ==> [F] [T] >branch
|
||||
|
||||
Probably specialized versions of `ifte` would be useful as well.
|
||||
|
||||
------------------
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
--------------------
|
||||
|
||||
Get a list of currently defined functors with:
|
||||
|
||||
?- joy(`words`, [], [Words]), maplist(writeln, Words).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
FORMAT:
|
||||
|
||||
--------------------
|
||||
|
||||
## Name
|
||||
|
||||
[Basis] Function | Combinator
|
||||
|
||||
Summary
|
||||
|
||||
Gentzen diagram.
|
||||
|
||||
### Definition
|
||||
|
||||
if not basis.
|
||||
|
||||
### Derivation
|
||||
|
||||
if not basis.
|
||||
|
||||
### Source
|
||||
|
||||
if basis
|
||||
|
||||
### Discussion
|
||||
|
||||
|
||||
### Crosslinks
|
||||
@@ -0,0 +1,353 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="generator" content="pandoc" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<title>Functor-Reference</title>
|
||||
<style>
|
||||
html {
|
||||
line-height: 1.5;
|
||||
font-family: Georgia, serif;
|
||||
font-size: 20px;
|
||||
color: #1a1a1a;
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
body {
|
||||
margin: 0 auto;
|
||||
max-width: 36em;
|
||||
padding-left: 50px;
|
||||
padding-right: 50px;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
hyphens: auto;
|
||||
word-wrap: break-word;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-kerning: normal;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
body {
|
||||
font-size: 0.9em;
|
||||
padding: 1em;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
body {
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
font-size: 12pt;
|
||||
}
|
||||
p, h2, h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
h2, h3, h4 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
a {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
a:visited {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
h5, h6 {
|
||||
font-size: 1em;
|
||||
font-style: italic;
|
||||
}
|
||||
h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ol, ul {
|
||||
padding-left: 1.7em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
li > ol, li > ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
blockquote {
|
||||
margin: 1em 0 1em 1.7em;
|
||||
padding-left: 1em;
|
||||
border-left: 2px solid #e6e6e6;
|
||||
color: #606060;
|
||||
}
|
||||
code {
|
||||
font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
}
|
||||
pre {
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
hr {
|
||||
background-color: #1a1a1a;
|
||||
border: none;
|
||||
height: 1px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
table {
|
||||
margin: 1em 0;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
display: block;
|
||||
font-variant-numeric: lining-nums tabular-nums;
|
||||
}
|
||||
table caption {
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
tbody {
|
||||
margin-top: 0.5em;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
border-bottom: 1px solid #1a1a1a;
|
||||
}
|
||||
th {
|
||||
border-top: 1px solid #1a1a1a;
|
||||
padding: 0.25em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
td {
|
||||
padding: 0.125em 0.5em 0.25em 0.5em;
|
||||
}
|
||||
header {
|
||||
margin-bottom: 4em;
|
||||
text-align: center;
|
||||
}
|
||||
#TOC li {
|
||||
list-style: none;
|
||||
}
|
||||
#TOC a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
code{white-space: pre-wrap;}
|
||||
span.smallcaps{font-variant: small-caps;}
|
||||
span.underline{text-decoration: underline;}
|
||||
div.column{display: inline-block; vertical-align: top; width: 50%;}
|
||||
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
||||
ul.task-list{list-style: none;}
|
||||
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
|
||||
</style>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<nav id="TOC" role="doc-toc">
|
||||
<ul>
|
||||
<li><a href="#functor-reference">Functor Reference</a>
|
||||
<ul>
|
||||
<li><a href="#section">!-</a></li>
|
||||
<li><a href="#app1">app1</a></li>
|
||||
<li><a href="#b">b</a></li>
|
||||
<li><a href="#binary">binary</a></li>
|
||||
<li><a href="#ccons">ccons</a></li>
|
||||
<li><a href="#cons">cons</a></li>
|
||||
<li><a href="#i">i</a></li>
|
||||
<li><a href="#infra">infra</a></li>
|
||||
<li><a href="#nullary">nullary</a></li>
|
||||
<li><a href="#ternary">ternary</a></li>
|
||||
<li><a href="#unary">unary</a></li>
|
||||
<li><a href="#uncons">uncons</a></li>
|
||||
<li><a href="#x">x</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<h1 id="functor-reference">Functor Reference</h1>
|
||||
<p>Version -10.0.0</p>
|
||||
<p>Each function, combinator, or definition should be documented here.</p>
|
||||
<hr />
|
||||
<h2 id="section">!-</h2>
|
||||
<p>“not negative”</p>
|
||||
<p>(Function, Boolean Predicate)</p>
|
||||
<p>Integer on top of stack is replaced by Boolean value indicating whether it is non-negative.</p>
|
||||
<pre><code> N !-
|
||||
----------- N < 0
|
||||
false
|
||||
|
||||
N !-
|
||||
---------- N >= 0
|
||||
true</code></pre>
|
||||
<h3 id="definition">Definition</h3>
|
||||
<pre><code>0 >=</code></pre>
|
||||
<hr />
|
||||
<h2 id="app1">app1</h2>
|
||||
<p>“apply one”</p>
|
||||
<p>(Combinator)</p>
|
||||
<p>Given a quoted program on TOS and anything as the second stack item run the program without disturbing the stack and replace the two args with the first result of the program.</p>
|
||||
<pre><code> ... x [Q] app1
|
||||
---------------------------------
|
||||
... [x ...] [Q] infra first</code></pre>
|
||||
<h3 id="definition-1">Definition</h3>
|
||||
<pre><code>nullary popd</code></pre>
|
||||
<h3 id="discussion">Discussion</h3>
|
||||
<p>Just a specialization of <code>nullary</code> really. Its parallelizable cousins are more useful.</p>
|
||||
<hr />
|
||||
<h2 id="b">b</h2>
|
||||
<p>(Combinator)</p>
|
||||
<p>Run two quoted programs</p>
|
||||
<pre><code> [P] [Q] b
|
||||
---------------
|
||||
P Q</code></pre>
|
||||
<h3 id="definition-2">Definition</h3>
|
||||
<pre><code>[i] dip i</code></pre>
|
||||
<h3 id="derivation">Derivation</h3>
|
||||
<pre><code>[P] [Q] b
|
||||
[P] [Q] [i] dip i
|
||||
[P] i [Q] i
|
||||
P [Q] i
|
||||
P Q</code></pre>
|
||||
<h3 id="discussion-1">Discussion</h3>
|
||||
<p>This combinator comes in handy.</p>
|
||||
<h3 id="crosslinks">Crosslinks</h3>
|
||||
<p><a href="#dupdip">dupdip</a> <a href="#ii">ii</a></p>
|
||||
<hr />
|
||||
<h2 id="binary">binary</h2>
|
||||
<p>(Combinator)</p>
|
||||
<p>Run a quoted program using exactly two stack values and leave the first item of the result on the stack.</p>
|
||||
<pre><code> ... y x [P] binary
|
||||
-----------------------
|
||||
... A</code></pre>
|
||||
<h3 id="definition-3">Definition</h3>
|
||||
<pre><code>unary popd</code></pre>
|
||||
<h3 id="discussion-2">Discussion</h3>
|
||||
<p>Runs any other quoted function and returns its first result while consuming exactly two items from the stack.</p>
|
||||
<h3 id="crosslinks-1">Crosslinks</h3>
|
||||
<p><a href="#nullary">nullary</a> <a href="#ternary">ternary</a> <a href="#unary">unary</a></p>
|
||||
<hr />
|
||||
<h2 id="ccons">ccons</h2>
|
||||
<p>(Function)</p>
|
||||
<p>Given two items and a list, append the items to the list to make a new list.</p>
|
||||
<pre><code> B A [...] ccons
|
||||
---------------------
|
||||
[B A ...]</code></pre>
|
||||
<h3 id="definition-4">Definition</h3>
|
||||
<pre><code>cons cons</code></pre>
|
||||
<h3 id="discussion-3">Discussion</h3>
|
||||
<p>Does <code>cons</code> twice.</p>
|
||||
<h3 id="crosslinks-2">Crosslinks</h3>
|
||||
<p><a href="#cons">cons</a></p>
|
||||
<hr />
|
||||
<h2 id="cons">cons</h2>
|
||||
<p>(Basis Function)</p>
|
||||
<p>Given an item and a list, append the item to the list to make a new list.</p>
|
||||
<pre><code> A [...] cons
|
||||
------------------
|
||||
[A ...]</code></pre>
|
||||
<h3 id="source">Source</h3>
|
||||
<pre><code>func(cons, [list(A), B|S], [list([B|A])|S]).</code></pre>
|
||||
<h3 id="discussion-4">Discussion</h3>
|
||||
<p>Cons is a venerable old function from Lisp. It doesn’t inspect the item but it will not cons onto a non-list. It’s inverse operation is called <code>uncons</code>.</p>
|
||||
<h3 id="crosslinks-3">Crosslinks</h3>
|
||||
<p><a href="#ccons">ccons</a> <a href="#uncons">uncons</a></p>
|
||||
<hr />
|
||||
<h2 id="i">i</h2>
|
||||
<p>(Basis Combinator)</p>
|
||||
<p>Append a quoted expression onto the pending expression.</p>
|
||||
<pre><code> [Q] i
|
||||
-----------
|
||||
Q</code></pre>
|
||||
<h3 id="source-1">Source</h3>
|
||||
<pre><code>combo(i, [list(P)|S], S, Ei, Eo) :- append(P, Ei, Eo).</code></pre>
|
||||
<h3 id="discussion-5">Discussion</h3>
|
||||
<p>This is probably the fundamental combinator. You wind up using it in all kinds of places (for example, the <code>x</code> combinator can be defined as <code>dup i</code>.)</p>
|
||||
<hr />
|
||||
<h2 id="infra">infra</h2>
|
||||
<p>(Combinator)</p>
|
||||
<p>Accept a quoted program and a list on the stack and run the program with the list as its stack. Does not affect the stack (below the list.)</p>
|
||||
<pre><code> ... [a b c] [Q] infra
|
||||
---------------------------
|
||||
c b a Q [...] swaack</code></pre>
|
||||
<h3 id="definition-5">Definition</h3>
|
||||
<pre><code>swons swaack [i] dip swaack</code></pre>
|
||||
<h3 id="discussion-6">Discussion</h3>
|
||||
<p>This is one of the more useful combinators. It allows a quoted expression to serve as a stack for a program, effectively running it in a kind of “pocket universe”. If the list represents a datastructure then <code>infra</code> lets you work on its internal structure.</p>
|
||||
<h3 id="crosslinks-4">Crosslinks</h3>
|
||||
<p><a href="#swaack">swaack</a></p>
|
||||
<hr />
|
||||
<h2 id="nullary">nullary</h2>
|
||||
<p>(Combinator)</p>
|
||||
<p>Run a quoted program without using any stack values and leave the first item of the result on the stack.</p>
|
||||
<pre><code> ... [P] nullary
|
||||
---------------------
|
||||
... A</code></pre>
|
||||
<h3 id="definition-6">Definition</h3>
|
||||
<pre><code>[stack] dip infra first</code></pre>
|
||||
<h3 id="derivation-1">Derivation</h3>
|
||||
<pre><code>... [P] nullary
|
||||
... [P] [stack] dip infra first
|
||||
... stack [P] infra first
|
||||
... [...] [P] infra first
|
||||
... [A ...] first
|
||||
... A</code></pre>
|
||||
<h3 id="discussion-7">Discussion</h3>
|
||||
<p>A very useful function that runs any other quoted function and returns it’s first result without disturbing the stack (under the quoted program.)</p>
|
||||
<h3 id="crosslinks-5">Crosslinks</h3>
|
||||
<p><a href="#unary">unary</a> <a href="#binary">binary</a> <a href="#ternary">ternary</a></p>
|
||||
<hr />
|
||||
<h2 id="ternary">ternary</h2>
|
||||
<p>(Combinator)</p>
|
||||
<p>Run a quoted program using exactly three stack values and leave the first item of the result on the stack.</p>
|
||||
<pre><code> ... z y x [P] unary
|
||||
-------------------------
|
||||
... A</code></pre>
|
||||
<h3 id="definition-7">Definition</h3>
|
||||
<pre><code>binary popd</code></pre>
|
||||
<h3 id="discussion-8">Discussion</h3>
|
||||
<p>Runs any other quoted function and returns its first result while consuming exactly three items from the stack.</p>
|
||||
<h3 id="crosslinks-6">Crosslinks</h3>
|
||||
<p><a href="#binary">binary</a> <a href="#nullary">nullary</a> <a href="#unary">unary</a></p>
|
||||
<hr />
|
||||
<h2 id="unary">unary</h2>
|
||||
<p>(Combinator)</p>
|
||||
<p>Run a quoted program using exactly one stack value and leave the first item of the result on the stack.</p>
|
||||
<pre><code> ... x [P] unary
|
||||
---------------------
|
||||
... A</code></pre>
|
||||
<h3 id="definition-8">Definition</h3>
|
||||
<pre><code>nullary popd</code></pre>
|
||||
<h3 id="discussion-9">Discussion</h3>
|
||||
<p>Runs any other quoted function and returns its first result while consuming exactly one item from the stack.</p>
|
||||
<h3 id="crosslinks-7">Crosslinks</h3>
|
||||
<p><a href="#binary">binary</a> <a href="#nullary">nullary</a> <a href="#ternary">ternary</a></p>
|
||||
<hr />
|
||||
<h2 id="uncons">uncons</h2>
|
||||
<p>(Basis Function)</p>
|
||||
<p>Removes an item from a list and leaves it on the stack under the rest of the list. You cannot <code>uncons</code> an item from an empty list.</p>
|
||||
<pre><code> [A ...] uncons
|
||||
--------------------
|
||||
A [...]</code></pre>
|
||||
<h3 id="source-2">Source</h3>
|
||||
<pre><code>func(uncons, Si, So) :- func(cons, So, Si).</code></pre>
|
||||
<h3 id="discussion-10">Discussion</h3>
|
||||
<p>This is the inverse of <code>cons</code>.</p>
|
||||
<h3 id="crosslinks-8">Crosslinks</h3>
|
||||
<p><a href="#cons">cons</a></p>
|
||||
<hr />
|
||||
<h2 id="x">x</h2>
|
||||
<p>(Combinator)</p>
|
||||
<pre><code> [F] x
|
||||
-----------
|
||||
[F] F</code></pre>
|
||||
<h3 id="definition-9">Definition</h3>
|
||||
<pre><code>dup i</code></pre>
|
||||
<h3 id="discussion-11">Discussion</h3>
|
||||
<p>The <code>x</code> combinator …</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,355 @@
|
||||
# Functor Reference
|
||||
|
||||
Version -10.0.0
|
||||
|
||||
Each function, combinator, or definition should be documented here.
|
||||
|
||||
--------------------
|
||||
|
||||
## !-
|
||||
|
||||
"not negative"
|
||||
|
||||
(Function, Boolean Predicate)
|
||||
|
||||
Integer on top of stack is replaced by Boolean value indicating whether
|
||||
it is non-negative.
|
||||
|
||||
N !-
|
||||
----------- N < 0
|
||||
false
|
||||
|
||||
N !-
|
||||
---------- N >= 0
|
||||
true
|
||||
|
||||
|
||||
### Definition
|
||||
|
||||
0 >=
|
||||
|
||||
--------------------
|
||||
|
||||
## app1
|
||||
|
||||
"apply one"
|
||||
|
||||
(Combinator)
|
||||
|
||||
Given a quoted program on TOS and anything as the second stack item run
|
||||
the program without disturbing the stack and replace the two args with
|
||||
the first result of the program.
|
||||
|
||||
... x [Q] app1
|
||||
---------------------------------
|
||||
... [x ...] [Q] infra first
|
||||
|
||||
### Definition
|
||||
|
||||
nullary popd
|
||||
|
||||
### Discussion
|
||||
|
||||
Just a specialization of `nullary` really. Its parallelizable cousins
|
||||
are more useful.
|
||||
|
||||
|
||||
--------------------
|
||||
|
||||
## b
|
||||
|
||||
(Combinator)
|
||||
|
||||
Run two quoted programs
|
||||
|
||||
[P] [Q] b
|
||||
---------------
|
||||
P Q
|
||||
|
||||
### Definition
|
||||
|
||||
[i] dip i
|
||||
|
||||
### Derivation
|
||||
|
||||
[P] [Q] b
|
||||
[P] [Q] [i] dip i
|
||||
[P] i [Q] i
|
||||
P [Q] i
|
||||
P Q
|
||||
|
||||
### Discussion
|
||||
|
||||
This combinator comes in handy.
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[dupdip](#dupdip)
|
||||
[ii](#ii)
|
||||
|
||||
--------------------
|
||||
|
||||
## binary
|
||||
|
||||
(Combinator)
|
||||
|
||||
Run a quoted program using exactly two stack values and leave the first
|
||||
item of the result on the stack.
|
||||
|
||||
... y x [P] binary
|
||||
-----------------------
|
||||
... A
|
||||
|
||||
### Definition
|
||||
|
||||
unary popd
|
||||
|
||||
### Discussion
|
||||
|
||||
Runs any other quoted function and returns its first result while
|
||||
consuming exactly two items from the stack.
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[nullary](#nullary)
|
||||
[ternary](#ternary)
|
||||
[unary](#unary)
|
||||
|
||||
--------------------
|
||||
|
||||
## ccons
|
||||
|
||||
(Function)
|
||||
|
||||
Given two items and a list, append the items to the list to make a new list.
|
||||
|
||||
B A [...] ccons
|
||||
---------------------
|
||||
[B A ...]
|
||||
|
||||
### Definition
|
||||
|
||||
cons cons
|
||||
|
||||
### Discussion
|
||||
|
||||
Does `cons` twice.
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[cons](#cons)
|
||||
|
||||
--------------------
|
||||
|
||||
## cons
|
||||
|
||||
(Basis Function)
|
||||
|
||||
Given an item and a list, append the item to the list to make a new list.
|
||||
|
||||
A [...] cons
|
||||
------------------
|
||||
[A ...]
|
||||
|
||||
### Source
|
||||
|
||||
func(cons, [list(A), B|S], [list([B|A])|S]).
|
||||
|
||||
### Discussion
|
||||
|
||||
Cons is a venerable old function from Lisp. It doesn't inspect the item
|
||||
but it will not cons onto a non-list. It's inverse operation is called
|
||||
`uncons`.
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[ccons](#ccons)
|
||||
[uncons](#uncons)
|
||||
|
||||
--------------------
|
||||
|
||||
## i
|
||||
|
||||
(Basis Combinator)
|
||||
|
||||
Append a quoted expression onto the pending expression.
|
||||
|
||||
|
||||
[Q] i
|
||||
-----------
|
||||
Q
|
||||
|
||||
### Source
|
||||
|
||||
combo(i, [list(P)|S], S, Ei, Eo) :- append(P, Ei, Eo).
|
||||
|
||||
### Discussion
|
||||
|
||||
This is probably the fundamental combinator. You wind up using it in all
|
||||
kinds of places (for example, the `x` combinator can be defined as `dup i`.)
|
||||
|
||||
--------------------
|
||||
|
||||
## infra
|
||||
|
||||
(Combinator)
|
||||
|
||||
Accept a quoted program and a list on the stack and run the program with
|
||||
the list as its stack. Does not affect the stack (below the list.)
|
||||
|
||||
... [a b c] [Q] infra
|
||||
---------------------------
|
||||
c b a Q [...] swaack
|
||||
|
||||
### Definition
|
||||
|
||||
swons swaack [i] dip swaack
|
||||
|
||||
|
||||
### Discussion
|
||||
|
||||
This is one of the more useful combinators. It allows a quoted
|
||||
expression to serve as a stack for a program, effectively running it in a
|
||||
kind of "pocket universe". If the list represents a datastructure then
|
||||
`infra` lets you work on its internal structure.
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[swaack](#swaack)
|
||||
|
||||
--------------------
|
||||
|
||||
## nullary
|
||||
|
||||
(Combinator)
|
||||
|
||||
Run a quoted program without using any stack values and leave the first item of the result on the stack.
|
||||
|
||||
... [P] nullary
|
||||
---------------------
|
||||
... A
|
||||
|
||||
### Definition
|
||||
|
||||
[stack] dip infra first
|
||||
|
||||
### Derivation
|
||||
|
||||
... [P] nullary
|
||||
... [P] [stack] dip infra first
|
||||
... stack [P] infra first
|
||||
... [...] [P] infra first
|
||||
... [A ...] first
|
||||
... A
|
||||
|
||||
### Discussion
|
||||
|
||||
A very useful function that runs any other quoted function and returns
|
||||
it's first result without disturbing the stack (under the quoted
|
||||
program.)
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[unary](#unary)
|
||||
[binary](#binary)
|
||||
[ternary](#ternary)
|
||||
|
||||
--------------------
|
||||
|
||||
## ternary
|
||||
|
||||
(Combinator)
|
||||
|
||||
|
||||
Run a quoted program using exactly three stack values and leave the first
|
||||
item of the result on the stack.
|
||||
|
||||
... z y x [P] unary
|
||||
-------------------------
|
||||
... A
|
||||
|
||||
### Definition
|
||||
|
||||
binary popd
|
||||
|
||||
### Discussion
|
||||
|
||||
Runs any other quoted function and returns its first result while
|
||||
consuming exactly three items from the stack.
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[binary](#binary)
|
||||
[nullary](#nullary)
|
||||
[unary](#unary)
|
||||
|
||||
--------------------
|
||||
|
||||
## unary
|
||||
|
||||
(Combinator)
|
||||
|
||||
Run a quoted program using exactly one stack value and leave the first item of the result on the stack.
|
||||
|
||||
... x [P] unary
|
||||
---------------------
|
||||
... A
|
||||
|
||||
### Definition
|
||||
|
||||
nullary popd
|
||||
|
||||
### Discussion
|
||||
|
||||
Runs any other quoted function and returns its first result while
|
||||
consuming exactly one item from the stack.
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[binary](#binary)
|
||||
[nullary](#nullary)
|
||||
[ternary](#ternary)
|
||||
|
||||
--------------------
|
||||
|
||||
## uncons
|
||||
|
||||
(Basis Function)
|
||||
|
||||
Removes an item from a list and leaves it on the stack under the rest of
|
||||
the list. You cannot `uncons` an item from an empty list.
|
||||
|
||||
[A ...] uncons
|
||||
--------------------
|
||||
A [...]
|
||||
|
||||
### Source
|
||||
|
||||
func(uncons, Si, So) :- func(cons, So, Si).
|
||||
|
||||
### Discussion
|
||||
|
||||
This is the inverse of `cons`.
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[cons](#cons)
|
||||
|
||||
--------------------
|
||||
|
||||
## x
|
||||
|
||||
(Combinator)
|
||||
|
||||
[F] x
|
||||
-----------
|
||||
[F] F
|
||||
|
||||
### Definition
|
||||
|
||||
dup i
|
||||
|
||||
### Discussion
|
||||
|
||||
The `x` combinator ...
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
all:
|
||||
pandoc -s --toc --toc-depth=2 --ascii Functor-Reference.md -o FuncRef.html
|
||||
@@ -0,0 +1,26 @@
|
||||
--------------------
|
||||
|
||||
## app1
|
||||
|
||||
"apply one"
|
||||
|
||||
(Combinator)
|
||||
|
||||
Given a quoted program on TOS and anything as the second stack item run
|
||||
the program without disturbing the stack and replace the two args with
|
||||
the first result of the program.
|
||||
|
||||
... x [Q] app1
|
||||
---------------------------------
|
||||
... [x ...] [Q] infra first
|
||||
|
||||
### Definition
|
||||
|
||||
nullary popd
|
||||
|
||||
### Discussion
|
||||
|
||||
Just a specialization of `nullary` really. Its parallelizable cousins
|
||||
are more useful.
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
--------------------
|
||||
|
||||
## b
|
||||
|
||||
(Combinator)
|
||||
|
||||
Run two quoted programs
|
||||
|
||||
[P] [Q] b
|
||||
---------------
|
||||
P Q
|
||||
|
||||
### Definition
|
||||
|
||||
[i] dip i
|
||||
|
||||
### Derivation
|
||||
|
||||
[P] [Q] b
|
||||
[P] [Q] [i] dip i
|
||||
[P] i [Q] i
|
||||
P [Q] i
|
||||
P Q
|
||||
|
||||
### Discussion
|
||||
|
||||
This combinator comes in handy.
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[dupdip](#dupdip)
|
||||
[ii](#ii)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
--------------------
|
||||
|
||||
## binary
|
||||
|
||||
(Combinator)
|
||||
|
||||
Run a quoted program using exactly two stack values and leave the first
|
||||
item of the result on the stack.
|
||||
|
||||
... y x [P] binary
|
||||
-----------------------
|
||||
... A
|
||||
|
||||
### Definition
|
||||
|
||||
unary popd
|
||||
|
||||
### Discussion
|
||||
|
||||
Runs any other quoted function and returns its first result while
|
||||
consuming exactly two items from the stack.
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[nullary](#nullary)
|
||||
[ternary](#ternary)
|
||||
[unary](#unary)
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
The problem is twofold:
|
||||
|
||||
1.) Programming is very young, and has been in a growth phase since it's inception. I forget the exact numbers, but *half* of *all* programmers have been doing it for less than *five years*, and that has been true for many decades.
|
||||
|
||||
Because there has been no "shakedown" phase (a "correction" in financial jargon), and because the influx of newbies ("Eternal September") has washed out any attempts at *better* programming ("Mother of All Demos", Nelson's "Dream Machine", etc., on the one hand and e.g. Ada on the other, all of it pretty much ignored in the mainstream machines and software available today. How many people have heard of Jef Raskin, let alone read "Humane Interface"? etc...) because of these things we should not expect programming to be at the level of engineering. We are in the Alchemy phase, not Chemistry.
|
||||
|
||||
|
||||
2.) Choice of notation. Without going into a long rant, our fundamental mathematical tools for programming are grotesque. (It would be shocking if the first thing out of the primordial ooze was the perfect programming notation, eh? In point of fact we have Turing Machines, Lambda Calculus, and what was the other one? Anyway, they're clunky.)
|
||||
|
||||
For binary Boolean circuits the notation in "Laws of Form" by George Spencer-Brown is the most elegant and parsimonious:
|
||||
|
||||
AA == A
|
||||
((A)) == A
|
||||
A(AB) == A(B)
|
||||
|
||||
That is a complete system of binary Boolean logic that is more efficient than other notations. (For instance, de Morgan's law doesn't apply: you can convert a formula into it's dual, reduce, and recover the original formula. (Ergo, conventional notation has (non-useful) redundancy.))
|
||||
|
||||
For orchestrating binary Boolean logic circuits into what we call "programs" the best notation is something called "Joy". It was invented by a philosopher! It has the best aspects of Lisp and Forth. It handles concurrency in a very simple and tractable way. It delivers on the promise of Backus' FP to enable mathematical *algebraic* derivations of algorithms/programs. Etc...
|
||||
|
||||
Anyhow, I'm preparing a demo of Joy, with UI influenced by psycho-ergonomic considerations, that can be compiled down to the logic circuits (and e.g. burned onto an FPGA or whatever.) A new model of computer architecture is implied, using latching sort-nets to allow for dynamic reconfiguration of what amounts to dataflow on the level of the CPU. (No more Von Neumann bottleneck.)
|
||||
@@ -0,0 +1,24 @@
|
||||
--------------------
|
||||
|
||||
## ccons
|
||||
|
||||
(Function)
|
||||
|
||||
Given two items and a list, append the items to the list to make a new list.
|
||||
|
||||
B A [...] ccons
|
||||
---------------------
|
||||
[B A ...]
|
||||
|
||||
### Definition
|
||||
|
||||
cons cons
|
||||
|
||||
### Discussion
|
||||
|
||||
Does `cons` twice.
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[cons](#cons)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
--------------------
|
||||
|
||||
## cons
|
||||
|
||||
(Basis Function)
|
||||
|
||||
Given an item and a list, append the item to the list to make a new list.
|
||||
|
||||
A [...] cons
|
||||
------------------
|
||||
[A ...]
|
||||
|
||||
### Source
|
||||
|
||||
func(cons, [list(A), B|S], [list([B|A])|S]).
|
||||
|
||||
### Discussion
|
||||
|
||||
Cons is a venerable old function from Lisp. It doesn't inspect the item
|
||||
but it will not cons onto a non-list. It's inverse operation is called
|
||||
`uncons`.
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[ccons](#ccons)
|
||||
[uncons](#uncons)
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
Implement modular arithmetic semantics for Joy, or
|
||||
|
||||
Implement 'BigNums' for Oberon RISC, or
|
||||
|
||||
Implement mod arith in Joy and use that to implement BigNums in mod-Joy,
|
||||
then partial reduce/eval etc. to get BigNums for RISC?
|
||||
|
||||
|
||||
|
||||
OR, let division operator make rationals!?
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
I'm using DCG w/ the lists as machine code, and explicitly passing the
|
||||
environment around; If I put the machine code into the environment I can
|
||||
just pass that around and define an asm//n DCG for writing machine code.
|
||||
|
||||
|
||||
|
||||
Parsing and Compiling Using Prolog
|
||||
|
||||
1. Introduction
|
||||
2. Parsing
|
||||
2.1 Bottom-Up
|
||||
2.2 Top-Down
|
||||
2.3 Recursive Descent
|
||||
3. Syntax-Directed Translation
|
||||
4. M-Grammars and DCGs
|
||||
5. Grammar Properties
|
||||
6. Lexical Scanners And Parser Generation
|
||||
7. Code Generation
|
||||
7.1 Generating Code from Polish
|
||||
7.2 Generating Code from Trees
|
||||
7.3 A Machine-Independent Algorithm for Code Generation
|
||||
7.4 Code Generation from a Labelled Tree
|
||||
8. Optimizations
|
||||
8.1 Compile-Time Evaluation
|
||||
8.2 Peephole Optimization
|
||||
9. Using Proposed Extension
|
||||
10. Final Remarks
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
type Item
|
||||
= Integer Int
|
||||
| Symbol String
|
||||
| Boolean Bool
|
||||
|
||||
|
||||
|
||||
|
||||
The Web UI
|
||||
|
||||
- Docs for each function
|
||||
- Crosslinks to other funcs in PatLang style
|
||||
- "Forge" for creating new funcs
|
||||
- Type-checking
|
||||
- Examples
|
||||
- Docs
|
||||
- Domain/Applicability
|
||||
- Mathematical Aspects (Cat Theory)
|
||||
- Evaluation Contexts
|
||||
- Stage
|
||||
- Spreadsheet/Grid
|
||||
- Factory
|
||||
- Dataflow
|
||||
- Hall of Records
|
||||
- History
|
||||
- Learning from
|
||||
- Quoting from
|
||||
- Changing/Deleting (sometimes you gotta)
|
||||
- Publishing/Sharing
|
||||
- Registry of definition/functions
|
||||
- Money?
|
||||
|
||||
|
||||
https://thenewstack.io/rust-creator-graydon-hoare-recounts-the-history-of-compilers/
|
||||
|
||||
|
||||
I've been working (on and off, for years) on making a system inspired by that book and by Jef Raskin's "Humane Interface", et. el., and I'm convinced that software could be made bug-free and cheaply, however I have no hope of convincing other programmers. Instead, I'm going to take it directly to end users (and not tell them that they are learning to program until they already have, so as not to jinx it.)
|
||||
|
||||
Trying to market to other developers would be an uphill battle, but normal people can use it to develop bug-free software easily and with minimal training (it's fun, like playing a video game).
|
||||
|
||||
I should have a demo going in a week or two. I'm learning Elm lang right now to make a web UI for it. The original demo UI is in Python 2 and Tkinter, but I've transitioned to an implementation based on Prolog, where inter-op with TCL/Tk would be more trouble than simple putting a web server in front of it (not to go off on a tangent but search for "pengine" if you want to know more about Prolog-over-TCP.)
|
||||
|
||||
|
||||
- - - -
|
||||
|
||||
Graydon Hoare has a talk on the history of compilers but he doesn't mention Prolog once. I think it's possible he doesn't know about the research into logic programming and compilers.
|
||||
|
||||
|
||||
"Parsing and Compiling Using Prolog" Jacques Cohen and Tim Hickey
|
||||
ACM Transactions on Programming Languages and Systems 9(2):125-163 · April 1987
|
||||
DOI: 10.1145/22719.22946 · Source: DBLP
|
||||
@@ -0,0 +1,22 @@
|
||||
--------------------
|
||||
|
||||
## i
|
||||
|
||||
(Basis Combinator)
|
||||
|
||||
Append a quoted expression onto the pending expression.
|
||||
|
||||
|
||||
[Q] i
|
||||
-----------
|
||||
Q
|
||||
|
||||
### Source
|
||||
|
||||
combo(i, [list(P)|S], S, Ei, Eo) :- append(P, Ei, Eo).
|
||||
|
||||
### Discussion
|
||||
|
||||
This is probably the fundamental combinator. You wind up using it in all
|
||||
kinds of places (for example, the `x` combinator can be defined as `dup i`.)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
--------------------
|
||||
|
||||
## infra
|
||||
|
||||
(Combinator)
|
||||
|
||||
Accept a quoted program and a list on the stack and run the program with
|
||||
the list as its stack. Does not affect the stack (below the list.)
|
||||
|
||||
... [a b c] [Q] infra
|
||||
---------------------------
|
||||
c b a Q [...] swaack
|
||||
|
||||
### Definition
|
||||
|
||||
swons swaack [i] dip swaack
|
||||
|
||||
|
||||
### Discussion
|
||||
|
||||
This is one of the more useful combinators. It allows a quoted
|
||||
expression to serve as a stack for a program, effectively running it in a
|
||||
kind of "pocket universe". If the list represents a datastructure then
|
||||
`infra` lets you work on its internal structure.
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[swaack](#swaack)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
--------------------
|
||||
|
||||
## !-
|
||||
|
||||
"not negative"
|
||||
|
||||
(Function, Boolean Predicate)
|
||||
|
||||
Integer on top of stack is replaced by Boolean value indicating whether
|
||||
it is non-negative.
|
||||
|
||||
N !-
|
||||
----------- N < 0
|
||||
false
|
||||
|
||||
N !-
|
||||
---------- N >= 0
|
||||
true
|
||||
|
||||
|
||||
### Definition
|
||||
|
||||
0 >=
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
--------------------
|
||||
|
||||
## nullary
|
||||
|
||||
(Combinator)
|
||||
|
||||
Run a quoted program without using any stack values and leave the first item of the result on the stack.
|
||||
|
||||
... [P] nullary
|
||||
---------------------
|
||||
... A
|
||||
|
||||
### Definition
|
||||
|
||||
[stack] dip infra first
|
||||
|
||||
### Derivation
|
||||
|
||||
... [P] nullary
|
||||
... [P] [stack] dip infra first
|
||||
... stack [P] infra first
|
||||
... [...] [P] infra first
|
||||
... [A ...] first
|
||||
... A
|
||||
|
||||
### Discussion
|
||||
|
||||
A very useful function that runs any other quoted function and returns
|
||||
it's first result without disturbing the stack (under the quoted
|
||||
program.)
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[unary](#unary)
|
||||
[binary](#binary)
|
||||
[ternary](#ternary)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
--------------------
|
||||
|
||||
## ternary
|
||||
|
||||
(Combinator)
|
||||
|
||||
|
||||
Run a quoted program using exactly three stack values and leave the first
|
||||
item of the result on the stack.
|
||||
|
||||
... z y x [P] unary
|
||||
-------------------------
|
||||
... A
|
||||
|
||||
### Definition
|
||||
|
||||
binary popd
|
||||
|
||||
### Discussion
|
||||
|
||||
Runs any other quoted function and returns its first result while
|
||||
consuming exactly three items from the stack.
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[binary](#binary)
|
||||
[nullary](#nullary)
|
||||
[unary](#unary)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
--------------------
|
||||
|
||||
## unary
|
||||
|
||||
(Combinator)
|
||||
|
||||
Run a quoted program using exactly one stack value and leave the first item of the result on the stack.
|
||||
|
||||
... x [P] unary
|
||||
---------------------
|
||||
... A
|
||||
|
||||
### Definition
|
||||
|
||||
nullary popd
|
||||
|
||||
### Discussion
|
||||
|
||||
Runs any other quoted function and returns its first result while
|
||||
consuming exactly one item from the stack.
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[binary](#binary)
|
||||
[nullary](#nullary)
|
||||
[ternary](#ternary)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
--------------------
|
||||
|
||||
## uncons
|
||||
|
||||
(Basis Function)
|
||||
|
||||
Removes an item from a list and leaves it on the stack under the rest of
|
||||
the list. You cannot `uncons` an item from an empty list.
|
||||
|
||||
[A ...] uncons
|
||||
--------------------
|
||||
A [...]
|
||||
|
||||
### Source
|
||||
|
||||
func(uncons, Si, So) :- func(cons, So, Si).
|
||||
|
||||
### Discussion
|
||||
|
||||
This is the inverse of `cons`.
|
||||
|
||||
### Crosslinks
|
||||
|
||||
[cons](#cons)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
--------------------
|
||||
|
||||
## x
|
||||
|
||||
(Combinator)
|
||||
|
||||
[F] x
|
||||
-----------
|
||||
[F] F
|
||||
|
||||
### Definition
|
||||
|
||||
dup i
|
||||
|
||||
### Discussion
|
||||
|
||||
The `x` combinator ...
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
# User Guide
|
||||
|
||||
There is no use interface as such. At the moment you just load the
|
||||
`thun.pl` file into SWI Prolog and use some of these "top-level"
|
||||
predicates to interact with it.
|
||||
|
||||
------------------
|
||||
|
||||
## `joy/3`
|
||||
|
||||
joy(InputString, StackIn, StackOut)
|
||||
|
||||
### Evaluation
|
||||
|
||||
Accepts a joy expression as a list of codes (in SWI Prolog you can use
|
||||
backticks to quote a string literal and get codes):
|
||||
|
||||
?- joy(`+ *`, [int(2), int(3), int(10)], StackOut).
|
||||
StackOut = [int(50)] ;
|
||||
false.
|
||||
|
||||
?- joy(`2 3 + 10 *`, StackIn, StackOut).
|
||||
StackOut = [int(50)|StackIn] ;
|
||||
false.
|
||||
|
||||
### Type Checking
|
||||
|
||||
This predicate can also perform type checking:
|
||||
|
||||
?- joy(`2 [] +`, StackIn, StackOut).
|
||||
false.
|
||||
|
||||
### Type Inference
|
||||
|
||||
And type inference with CLP(FD) constraints on integer operations and
|
||||
comparisons:
|
||||
|
||||
?- joy(`+ *`, StackIn, StackOut).
|
||||
StackIn = [int(_37782), int(_37792), int(_37802)|_37798],
|
||||
StackOut = [int(_37824)|_37798],
|
||||
_37782+_37792#=_37842,
|
||||
_37842*_37802#=_37824 ;
|
||||
false.
|
||||
|
||||
------------------
|
||||
|
||||
## `joy_parse//1`
|
||||
|
||||
If you just want to parse a string into a Joy expression use joy_parse//1
|
||||
DCG, like so:
|
||||
|
||||
phrase(joy_parse(Expression), InputString)
|
||||
|
||||
Or directly:
|
||||
|
||||
joy_parse(Expression, InputString, [])
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
?- phrase(joy_parse(Expression), `1 [i]`).
|
||||
Expression = [int(1), list([symbol(i)])] ;
|
||||
false.
|
||||
|
||||
------------------
|
||||
|
||||
## `thun/3`
|
||||
|
||||
Once you have a (type-tagged) Joy exression as Prolog data-structure you
|
||||
can use the `thun/3` predicate to evaluate it:
|
||||
|
||||
thun(Expression, InputStack, OutputStack)
|
||||
|
||||
|
||||
------------------
|
||||
|
||||
## `sjc/2`
|
||||
|
||||
sjc(Name, InputString)
|
||||
|
||||
Helper function to see to what Prolog code a given Joy expression would
|
||||
compile. Give it a name (Prolog atom) and a list of code.
|
||||
|
||||
?- sjc(third, `third`).
|
||||
func(third, [list([_, _, A|_])|B], [A|B]).
|
||||
true ;
|
||||
false.
|
||||
|
||||
?- sjc(ccons, `ccons`).
|
||||
func(ccons, [list(C), B, A|D], [list([A, B|C])|D]).
|
||||
true ;
|
||||
false.
|
||||
|
||||
Compilation captures CLP(FD) constraints:
|
||||
|
||||
?- sjc(+*, `+ *`).
|
||||
func(+*, [int(D), int(E), int(B)|A], [int(C)|A]) :-
|
||||
maplist(call,
|
||||
[ clpfd:(F*B#=C),
|
||||
clpfd:(D+E#=F)
|
||||
]).
|
||||
true ;
|
||||
false.
|
||||
|
||||
------------------
|
||||
|
||||
## `show_joy_compile/2`
|
||||
|
||||
show_joy_compile(Name, Expression)
|
||||
|
||||
Same as `sjc/2` but you give it an already-parsed expression.
|
||||
|
||||
------------------
|
||||
|
||||
## `joy_compile/2`
|
||||
|
||||
joy_compile(Name, Expression)
|
||||
|
||||
This actually asserts the new function definition into the Prolog rule
|
||||
database. Use with care.
|
||||
|
||||
At some point I'll probably add a build phase that tries to pre-compile
|
||||
all definitions it can into Prolog rules but for now this is just
|
||||
experimental.
|
||||
|
||||
------------------
|
||||
|
||||
## `compiler/4`
|
||||
|
||||
compiler(InputString, MachineCode, StackIn, StackOut)
|
||||
|
||||
Experimental *and* unfinished, this predicate attempts to build a list of
|
||||
terms representing machine code for the RISC CPU that Prof. Wirth has
|
||||
specified for his Project Oberon.
|
||||
|
||||
------------------
|
||||
|
||||
## `grow//0` & `shrink//0`
|
||||
|
||||
These DCGs recursively unfold or fold definitions in a Joy expression:
|
||||
|
||||
?- phrase(grow, [symbol(third)], Out).
|
||||
Out = [symbol(rest), symbol(rest), symbol(first)] ;
|
||||
Out = [symbol(rest), symbol(rest), symbol(first)] ;
|
||||
Out = [symbol(rest), symbol(second)] ;
|
||||
Out = [symbol(third)].
|
||||
|
||||
?- phrase(shrink, [symbol(rest), symbol(rest), symbol(first)], Out).
|
||||
Out = [symbol(rrest), symbol(first)] ;
|
||||
Out = [symbol(third)] ;
|
||||
Out = [symbol(rest), symbol(second)] ;
|
||||
Out = [symbol(rest), symbol(rest), symbol(first)].
|
||||
|
||||
They are more a proof-of-concept than useful at the moment. I imagine
|
||||
that it might be possible to set up some kind of automated search through
|
||||
all the variations to see if a more efficient form (after compiling with
|
||||
whatever optimizations) can be found.
|
||||
|
||||
------------------
|
||||
|
||||
## `joy_terms_to_string/2`
|
||||
|
||||
joy_terms_to_string(Expr, String)
|
||||
|
||||
Converts a Joy expression into a string (an actual string, not a list of
|
||||
codes. See the [SWI Prolog manual for more information on strings](https://www.swi-prolog.org/pldoc/man?section=strings).)
|
||||
|
||||
Reference in New Issue
Block a user