157 lines
4.6 KiB
Forth
157 lines
4.6 KiB
Forth
ALSO UTILITY
|
|
|
|
STRUCT
|
|
AA-NODE% FIELD SIMPLE>NODE
|
|
CELL% FIELD SIMPLE>VALUE
|
|
ENDSTRUCT SIMPLE%
|
|
|
|
: NODE>SIMPLE ( aa-node -- simple-node ) CONTAINEROF SIMPLE>NODE ;
|
|
|
|
: MAKE-SIMPLE ( x -- simple-addr )
|
|
SIMPLE% %ALLOCATE TUCK SIMPLE>VALUE ! ;
|
|
|
|
: SHOW-RIGHT-NODE LOCALS| rpre' cpre' lpre' rxt |
|
|
rpre' cpre' lpre' rxt EXECUTE
|
|
lpre' EXECUTE EOL
|
|
rpre' FREE-CLOSURE ▪ cpre' FREE-CLOSURE ▪ lpre' FREE-CLOSURE ;
|
|
|
|
: SHOW-LEFT-NODE LOCALS| rpre' cpre' lpre' lxt |
|
|
rpre' EXECUTE EOL
|
|
rpre' cpre' lpre' lxt EXECUTE
|
|
rpre' FREE-CLOSURE ▪ cpre' FREE-CLOSURE ▪ lpre' FREE-CLOSURE ;
|
|
|
|
: SHOW-NODE LOCALS| rpre cpre lpre rxt node lxt |
|
|
node AA>RIGHT @ IF
|
|
rpre { " " TYPE } COMPOSE
|
|
rpre { " R-" TYPE } COMPOSE
|
|
rpre { " | " TYPE } COMPOSE
|
|
rxt ▪ SHOW-RIGHT-NODE
|
|
THEN
|
|
|
|
cpre EXECUTE "(" TYPE node AA>LEVEL @ . ") " TYPE
|
|
node NODE>SIMPLE SIMPLE>VALUE @ . EOL
|
|
|
|
node AA>LEFT @ IF
|
|
lpre { " | " TYPE } COMPOSE
|
|
lpre { " L-" TYPE } COMPOSE
|
|
lpre { " " TYPE } COMPOSE
|
|
lxt ▪ SHOW-LEFT-NODE
|
|
THEN ;
|
|
|
|
: SHOW-NULL ( rpre cpre lpre -- ) DROP NIP EXECUTE "<empty>\n" TYPE ;
|
|
|
|
: SHOW-TREE ( aa-tree -- )
|
|
>R { " " TYPE } DUP DUP [[ ' SHOW-NODE ]] [[ ' SHOW-NULL ]] R>
|
|
EOL AA-TRAVERSE EOL ;
|
|
|
|
: ?NODE-INVARIANTS ( parentn ... parent1 n aa-node -- ) RECURSIVE
|
|
?DUP IF
|
|
DUP AA>LEFT @ NULL= OVER AA>RIGHT @ NULL= AND IF
|
|
DUP AA>LEVEL @ 1 <>
|
|
"FAIL: 1. The level of every leaf node is one." ?FAIL
|
|
THEN
|
|
OVER 0> IF
|
|
2 PICK
|
|
2DUP AA>LEFT @ = IF
|
|
2DUP AA>LEVEL @ 1- SWAP AA>LEVEL @ <>
|
|
"FAIL: 2. The level of every left child is exactly one less than that of its parent." ?FAIL
|
|
THEN
|
|
2DUP AA>RIGHT @ = IF
|
|
2DUP SWAP AA>LEVEL @ SWAP AA>LEVEL @ DUP 1- SWAP 1+ WITHIN 0=
|
|
"FAIL: 3. The level of every right child is equal to or one less than that of its parent." ?FAIL
|
|
THEN
|
|
DROP
|
|
THEN
|
|
OVER 1 > IF
|
|
2 PICK AA>RIGHT @ OVER = IF
|
|
3 PICK AA>RIGHT @ 3 PICK = IF
|
|
DUP AA>LEVEL @ 4 PICK AA>LEVEL @ U>=
|
|
"FAIL: 4. The level of every right grandchild is strictly less than that of its grandparent." ?FAIL
|
|
THEN
|
|
THEN
|
|
THEN
|
|
DUP AA>LEVEL @ 1 > IF
|
|
DUP AA>LEFT @ NULL= ▪ OVER AA>RIGHT @ NULL= ▪ OR
|
|
"FAIL: 5. Every node of level greater than one has two children." ?FAIL
|
|
THEN
|
|
|
|
SWAP 1+
|
|
OVER AA>LEFT @ ?NODE-INVARIANTS
|
|
OVER AA>RIGHT @ ?NODE-INVARIANTS
|
|
1- NIP
|
|
THEN ;
|
|
|
|
: ?INVARIANTS ( aa-tree -- )
|
|
AA>ROOT @ 0 SWAP ?NODE-INVARIANTS DROP ;
|
|
|
|
VARIABLE TREE
|
|
|
|
"creating tree…\n" TYPE
|
|
{ NODE>SIMPLE SIMPLE>VALUE @ } ' <=> NEW-AA-TREE VALUE TREE
|
|
TREE SHOW-TREE
|
|
|
|
0xc43d7de6 CONSTANT SEED
|
|
|
|
{
|
|
20 0 ?DO
|
|
I SEED + HASHCELL 31 AND
|
|
DUP "inserting " TYPE . "…\n" TYPE
|
|
MAKE-SIMPLE TREE AA-INSERT
|
|
TREE SHOW-TREE
|
|
TREE ?INVARIANTS
|
|
LOOP
|
|
} EXECUTE
|
|
|
|
"breaking invariant 1…\n" TYPE
|
|
{ TREE SHOW-TREE ▪ { TREE ?INVARIANTS } CATCH DUP IF REPORT EOL THEN }
|
|
7 ▪ TREE AA>ROOT @ AA>LEFT @ AA>LEFT @ AA>LEFT @ AA>RIGHT @ AA>LEVEL ▪ !LOCALLY
|
|
|
|
"breaking invariant 2…\n" TYPE
|
|
{ TREE SHOW-TREE ▪ { TREE ?INVARIANTS } CATCH DUP IF REPORT EOL THEN }
|
|
4 ▪ TREE AA>ROOT @ AA>LEFT @ AA>LEVEL ▪ !LOCALLY
|
|
|
|
"breaking invariant 3…\n" TYPE
|
|
{ TREE SHOW-TREE ▪ { TREE ?INVARIANTS } CATCH DUP IF REPORT EOL THEN }
|
|
2 ▪ TREE AA>ROOT @ AA>RIGHT @ AA>LEVEL ▪ !LOCALLY
|
|
|
|
"breaking invariant 4…\n" TYPE
|
|
DEFER BREAK-INV-4 ( aa-node -- )
|
|
{
|
|
DUP AA>LEVEL @ 1 = IF
|
|
DROP ▪ TREE SHOW-TREE ▪ { TREE ?INVARIANTS } CATCH ?DUP IF REPORT EOL THEN
|
|
ELSE
|
|
{ { AA>RIGHT @ BREAK-INV-4 } OVER AA>LEVEL 1 SWAP !LOCALLY }
|
|
OVER AA>LEFT NULL SWAP !LOCALLY
|
|
THEN
|
|
} IS BREAK-INV-4
|
|
|
|
TREE AA>ROOT @ BREAK-INV-4
|
|
|
|
"breaking invariant 5…\n" TYPE
|
|
{ TREE SHOW-TREE ▪ { TREE ?INVARIANTS } CATCH DUP IF REPORT EOL THEN }
|
|
NULL ▪ TREE AA>ROOT @ AA>LEFT ▪ !LOCALLY
|
|
|
|
"finding node with value 16…\n" TYPE
|
|
16 TREE AA-LOOKUP
|
|
DUP 0= [IF] "not found\n" TYPE [ELSE]
|
|
"found\nvalue: " TYPE NODE>SIMPLE SIMPLE>VALUE @ . EOL
|
|
[THEN]
|
|
|
|
TREE SHOW-TREE
|
|
{
|
|
10 0 ?DO
|
|
"count before: " TYPE TREE AA-#NODES DUP . EOL
|
|
I SEED + HASHCELL HASHCELL 31 AND
|
|
DUP "deleting " TYPE . "…\n" TYPE
|
|
TREE AA-DELETE DUP FREE NULL<>
|
|
IF 1- "removed\n" ELSE "not found\n" THEN TYPE
|
|
"count after: " TYPE TREE AA-#NODES DUP . EOL
|
|
<> "wrong count" ?FAIL
|
|
TREE SHOW-TREE
|
|
TREE ?INVARIANTS
|
|
LOOP
|
|
} EXECUTE
|
|
|
|
"iterating tree…\n" TYPE
|
|
{ NODE>SIMPLE SIMPLE>VALUE @ . SPACE } TREE AA-ITERATE EOL
|