Motivation
- Inspired by Back and Forth - Hans Bezemer (thanks Martin Andronikos!)
- Locals don't fit Forth
- Shallow stacks are best
- But we should be able to reason about stacks better
- Are we missing an "algebra" of stack manipulation?
How to Build an Algebra
- Find a set of "atomic" objects
- Propose a set of rules describing how they can be manipulated while maintaining equivalence
- Rules might require arithmetic for non-trivial algebras
- Key Open Question: Can a small set of substitution rules connect all equivalent Forth expressions?
Which stack words are "atomic"?
I propose: DUP SWAP DROP >R R>
OVER ↔ >R DUP R> SWAP
NIP ↔ SWAP DROP
TUCK ↔ SWAP OVER
ROT ↔ >R SWAP R> SWAP
-ROT ↔ SWAP >R SWAP R>
RDROP ↔ R> DROP
R@ ↔ R> DUP >R
DUP DROP ↔ OVER DROP ↔ >R R> ↔ NOP
Notation for repetition
nDROP ↔ DROPn
: nDROP 0 ?DO DROP LOOP ; ( gets harder with other words! )
PICK and ROLL
0 PICK ↔ DUP
1 PICK ↔ OVER
n PICK ↔ >Rn DUP ( R> SWAP )n
0 ROLL ↔ NOP
1 ROLL ↔ SWAP
2 ROLL ↔ ROT
n ROLL ↔ >Rn ( R> SWAP )n
n-Operations
nDUP ↔ ( n-1 PICK )n
nSWAP ↔ ( 2n-1 ROLL )n
nDROP ↔ DROPn
n>R ↔ >Rn
nR> ↔ R>n
Doubling Operations
2DUP ↔ OVER OVER
2SWAP ↔ ROT >R ROT R>
↔ >R SWAP R> SWAP >R >R SWAP R> SWAP R>
a b c d -- a c d b -- c d a b
2DROP ↔ DROP DROP
2>R ↔ >R >R
2R> ↔ R> R>
Build up by 2x
2DUP ↔ OVER OVER
2nDUP ↔ nOVER nOVER
2OVER ↔ 2>R 2DUP 2R> 2SWAP
nOVER ↔ n>R nDUP nR> nSWAP
2SWAP ↔ >R SWAP R> SWAP >R >R SWAP R> SWAP R>
2nSWAP ↔ n>R nSWAP nR> nSWAP n>R n>R nSWAP nR> nSWAP nR>
2SWAP Equivalence?
nSWAP ↔ ( 2n-1 ROLL )n
2SWAP ↔ 3 ROLL 3 ROLL n ROLL ↔ >Rn ( R> SWAP )n
↔ >R >R >R R> SWAP R> SWAP R> SWAP
>R >R >R R> SWAP R> SWAP R> SWAP
↔ >R >R SWAP R> SWAP R> SWAP
>R >R SWAP R> SWAP R> SWAP
↔ >R ROT R> SWAP
>R ROT R> SWAP
?
↔ ROT >R ROT R>
2SWAP ↔ >R SWAP R> SWAP >R >R SWAP R> SWAP R>
What if we alway empty the rstack?
>R >R SWAP R> SWAP R> SWAP
>R >R SWAP R> SWAP R> SWAP
↔
>R >R SWAP R> R> >R SWAP R> SWAP
>R >R SWAP R> R> >R SWAP R> SWAP
↔
SWAP2 SWAP1 SWAP0
Layer Notation
SWAPn ↔ >Rn SWAP R>n
DUPn ↔ >Rn DUP R>n
DROPn ↔ >Rn DROP R>n
Rule S1: Swap Canceling
SWAPn SWAPn ↔ NOP
↔
Rule S2: Swap Passing
SWAPk SWAPn ↔ SWAPn SWAPk if |k-n| > 1
↔
Rule S3: Swap Flipping Doubles
SWAPk SWAPn ↔ SWAPn SWAPk SWAPn SWAPk if |k-n| = 1
↔
2SWAP Problem again
2SWAP ↔ 3 ROLL 3 ROLL n ROLL ↔ >Rn ( R> SWAP )n
↔ >R >R >R R> SWAP R> SWAP R> SWAP
>R >R >R R> SWAP R> SWAP R> SWAP
↔ >R >R SWAP R> SWAP R> SWAP
>R >R SWAP R> SWAP R> SWAP
↔ >R >R SWAP R> R> >R SWAP R> SWAP
>R >R SWAP R> R> >R SWAP R> SWAP
↔ SWAP2 SWAP1 SWAP0
SWAP2 SWAP1 SWAP0
...???...
↔ SWAP1 SWAP0 SWAP2 SWAP1
↔ >R SWAP R> SWAP >R >R SWAP R> R> >R SWAP R>
2SWAP ↔ >R SWAP R> SWAP >R >R SWAP R> SWAP R>
2SWAP ↔ ROT >R ROT R>
2SWAP ↔ 3 ROLL 3 ROLL ↔ ROT >R ROT R>
↔ SWAP2 SWAP1 SWAP0 SWAP2 SWAP1 SWAP0 ↔ SWAP1 SWAP0 SWAP2 SWAP1
↔
by Rule S3: Swap Flipping Doubles
↔
by Rule S2: Swap Passing
↔
by Rule S1: Swap Cancelling
↔
by Rule S3: Swap Flipping Doubles
↔
by Rule S2: Swap Passing
↔
3DUP Problem
3DUP ↔ 2 PICK 2 PICK 2 PICK nDUP ↔ ( n-1 PICK )n
↔ >R >R DUP R> SWAP R> SWAP
>R >R DUP R> SWAP R> SWAP
>R >R DUP R> SWAP R> SWAP
↔ DUP2 SWAP1 SWAP0
DUP2 SWAP1 SWAP0
DUP2 SWAP1 SWAP0
( But this is shorter! )
3DUP ↔ >R 2DUP R@ -ROT R>
↔ >R OVER OVER R> DUP >R SWAP >R SWAP R> R>
↔ >R OVER OVER R> DUP >R SWAP >R SWAP R> R>
↔ >R >R DUP R> SWAP
>R DUP R> SWAP
R> DUP >R SWAP >R SWAP R> R>
↔ DUP2 SWAP1 DUP2 SWAP1 DUP0 SWAP1 SWAP2
Rule D1: Dup Climbing
DUPk DUPn ↔ DUPn DUPk+1 if k≥n
↔
Rule D1: Dup Climbing (special case)
DUPn DUPn ↔ DUPn DUPn+1
↔
Rule M1: Overhead Passing
DUPk SWAPn ↔ SWAPn DUPk if k≥n+2
↔
Rule M2: Underneath Dipping
SWAPk DUPn ↔ DUPn SWAPk+1 if k>n
↔
Rule M3: Useless Duping
DUPn SWAPn ↔ DUPn
↔
Rule M4: Left Capping
DUPn SWAPn+1 ↔ SWAPn DUPn+1 SWAPn
↔
Rule M5: Right Capping (Derivable from M4)
SWAPn DUPn ↔ DUPn+1 SWAPn SWAPn+1
↔
3DUP ↔ 2 PICK 2 PICK 2 PICK
↔ DUP2 SWAP1 SWAP0 DUP2 SWAP1 SWAP0 DUP2 SWAP1 SWAP0
↔ DUP2 SWAP1 DUP2 SWAP1 DUP0 SWAP1 SWAP2 ↔ >R 2DUP R@ -ROT R>
by S3: Swap Flipping Doubles
by M1: Overhead Passing + S1: Swap Canceling
3DUP ↔ DUP2 SWAP1 DUP2 SWAP1 DUP0 SWAP1 SWAP2
↔ >R 2DUP R@ -ROT R> by M4: Left Capping
Layer Notation Rules
SWAPn ↔ >Rn SWAP R>n
DUPn ↔ >Rn DUP R>n
DROPn ↔ >Rn DROP R>n ( missing rules for DROPn & non-stack words! )
Rule S1: Swap Canceling -- SWAPn SWAPn ↔ NOP
Rule S2: Swap Passing -- SWAPk SWAPn ↔ SWAPn SWAPk if |k-n| > 1
Rule S3: Swap Flipping Doubles --
SWAPk SWAPn ↔ SWAPn SWAPk SWAPn SWAPk if |k-n| = 1
Rule D1: Dup Climbing -- DUPk DUPn ↔ DUPn DUPk+1 if k≥n
Rule M1: Overhead Passing -- DUPk SWAPn ↔ SWAPn DUPk if k≥n+2
Rule M2: Underneath Dipping -- SWAPk DUPn ↔ DUPn SWAPk+1 if k>n
Rule M3: Useless Duping -- DUPn SWAPn ↔ DUPn
Rule M4: Left Capping -- DUPn SWAPn+1 ↔ SWAPn DUPn+1 SWAPn
Thank you!
- Challenge #1: Can any of these rules be derived from the others?
- Challenge #2: Can you find equivalent expressions not resolvable from these rules?
- Challenge #3: What about DROPn, what are its rules?
- Challenge #4: What about non-stack words?