Skip to content

Commit 94a233e

Browse files
table lookup works now
Table function still eats too many items from the stack which is weird.
1 parent 1ecc9cc commit 94a233e

File tree

2 files changed

+93
-27
lines changed

2 files changed

+93
-27
lines changed

cogni.c

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -434,73 +434,81 @@ static cog_object* _wraptab(cog_object* tree) {
434434
return tab;
435435
}
436436

437+
// TODO: use binary search tree instead of binary path tree which is super weird
438+
437439
static cog_object* _iou_helper(cog_object* tree, cog_object* key, cog_object* val, int64_t hash) {
438440
if (!tree) {
439441
// we got to the end without finding a existing node, so add a new one
440-
cog_printf("DEBUG: New node with %O: %O\n", key, val);
442+
// cog_printf("DEBUG: New node with %O: %O\n", key, val);
441443
return _treenode(key, val, NULL, NULL);
442444
}
443-
bool is_left = hash & 1;
444-
int64_t rest_hash = hash >> 1;
445445
if (cog_equal(tree->TKEY, key)) {
446446
// update this node
447-
cog_printf("DEBUG: Update node with %O: %O\n", key, val);
447+
// cog_printf("DEBUG: Update node with %O: %O\n", key, val);
448448
return _treenode(tree->TKEY, val, tree->TRIGHT, tree->TLEFT);
449449
}
450450
// need to recurse
451-
printf("->%s", is_left ? "left" : "right");
452-
fflush(stdout);
453-
cog_object* newnode = _treenode(tree->TKEY, tree->TVAL, tree->TRIGHT, tree->TLEFT);
454-
if (is_left) newnode->TLEFT = _iou_helper(newnode->TLEFT, key, val, rest_hash);
455-
else newnode->TRIGHT = _iou_helper(newnode->TRIGHT, key, val, rest_hash);
456-
return newnode;
451+
bool is_left = hash < (cog_hash(tree->TKEY)->as_int);
452+
// printf("->%s", is_left ? "left" : "right");
453+
// fflush(stdout);
454+
if (is_left) return _treenode(tree->TKEY, tree->TVAL, _iou_helper(tree->TLEFT, key, val, hash), tree->TRIGHT);
455+
else return _treenode(tree->TKEY, tree->TVAL, tree->TLEFT, _iou_helper(tree->TRIGHT, key, val, hash));
456+
}
457+
458+
static cog_object* _succ(cog_object* tree) {
459+
tree = tree->TRIGHT;
460+
while (tree != NULL && tree->TLEFT != NULL)
461+
tree = tree->TLEFT;
462+
return tree;
457463
}
458464

459465
static cog_object* _rem_helper(cog_object* tree, cog_object* key, int64_t hash) {
460466
if (!tree) return NULL;
461-
bool is_left = hash & 1;
462-
int64_t rest_hash = hash >> 1;
463-
cog_object* newtree;
464467

465468
if (cog_equal(key, tree->TKEY)) {
466469
// this node is what needs to be deleted
467-
if (!tree->TLEFT && !tree->TRIGHT) newtree = NULL; // leaf node gets deleted
468-
// else just pick which side to delete. I chose right first else left
469-
else if (tree->TRIGHT) newtree = _treenode(tree->TRIGHT->TKEY, tree->TRIGHT->TVAL, tree->TLEFT, tree->TRIGHT->TRIGHT);
470-
else newtree = _treenode(tree->TLEFT->TKEY, tree->TLEFT->TVAL, tree->TLEFT->TLEFT, tree->TRIGHT);
470+
// No children
471+
if (!tree->TLEFT && !tree->TRIGHT) return NULL;
472+
// if only one child, then just become that one
473+
else if (tree->TRIGHT && !tree->TLEFT) return tree->TRIGHT;
474+
else if (tree->TLEFT && !tree->TRIGHT) return tree->TLEFT;
475+
else {
476+
// two children
477+
cog_object* next = _succ(tree);
478+
return _treenode(next->TKEY, next->TVAL, tree->TLEFT, _rem_helper(tree->TRIGHT, next->TKEY, cog_hash(next->TKEY)->as_int));
479+
}
471480
} else {
472481
// it's another node that needs to be deleted
473-
if (is_left) newtree = _treenode(tree->TKEY, tree->TVAL, _rem_helper(tree->TLEFT, key, rest_hash), tree->TRIGHT);
474-
else newtree = _treenode(tree->TKEY, tree->TVAL, tree->TLEFT, _rem_helper(tree->TRIGHT, key, rest_hash));
482+
bool is_left = hash < (cog_hash(tree->TKEY)->as_int);
483+
if (is_left) return _treenode(tree->TKEY, tree->TVAL, _rem_helper(tree->TLEFT, key, hash), tree->TRIGHT);
484+
else return _treenode(tree->TKEY, tree->TVAL, tree->TLEFT, _rem_helper(tree->TRIGHT, key, hash));
475485
}
476-
return newtree;
477486
}
478487

479488
cog_object* cog_table_get(cog_object* tab, cog_object* key, bool* found) {
480489
assert(tab && tab->type == &cog_ot_table);
481490
cog_object* tree = tab->next; // get the internal tree
482491
int64_t hash = cog_hash(key)->as_int;
483-
cog_printf("DEBUG: getting with hash %llX, tree is: %O\n", hash, tree);
492+
// cog_printf("DEBUG: getting with hash %llX, tree is: %O\n", hash, tree);
484493
while (tree) {
485-
cog_printf("DEBUG: looking at key %O\n", tree->TKEY);
494+
// cog_printf("DEBUG: looking at key %O\n", tree->TKEY);
486495
if (cog_equal(tree->TKEY, key)) {
487496
*found = true;
488497
return tree->TVAL;
489498
}
490-
bool is_left = hash & 1;
491-
hash = hash >> 1;
499+
bool is_left = hash < (cog_hash(tree->TKEY)->as_int);
492500
if (is_left) tree = tree->TLEFT;
493501
else tree = tree->TRIGHT;
494-
printf("%s->", is_left ? "left" : "right");
495-
fflush(stdout);
502+
// printf("%s->", is_left ? "left" : "right");
503+
// fflush(stdout);
496504
}
497505
*found = false;
498506
return NULL;
499507
}
500508

501509
cog_object* cog_table_insert_or_update(cog_object* tab, cog_object* key, cog_object* val) {
502510
assert(tab && tab->type == &cog_ot_table);
503-
cog_printf("DEBUG: adding key %O to table\n", key);
511+
// cog_printf("DEBUG: adding key %O to table\n", key);
504512
return _wraptab(_iou_helper(tab->next, key, val, cog_hash(key)->as_int));
505513
}
506514

tree.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from __future__ import annotations
2+
3+
from dataclasses import dataclass
4+
from pprint import pprint
5+
import random
6+
from typing import Any, Hashable
7+
8+
type Tree = Node | None
9+
10+
11+
@dataclass
12+
class Node:
13+
key: Any
14+
value: Any
15+
left: Tree
16+
right: Tree
17+
18+
19+
def _iou_helper(tree: Tree, key: Hashable, value: Any, hval: int) -> Node:
20+
if tree is None:
21+
return Node(key, value, None, None)
22+
if tree.key == key:
23+
return Node(key, value, tree.left, tree.right)
24+
is_left = hval < hash(tree.key)
25+
newnode = Node(tree.key, tree.value, tree.left, tree.right)
26+
if is_left:
27+
newnode.left = _iou_helper(newnode.left, key, value, hval)
28+
else:
29+
newnode.right = _iou_helper(newnode.right, key, value, hval)
30+
return newnode
31+
32+
33+
def with_inserted(tree: Tree, key: Hashable, value: Any) -> Node:
34+
return _iou_helper(tree, key, value, hash(key))
35+
36+
37+
def dict2tree(d: dict) -> Tree:
38+
tree = None
39+
for k, v in d.items():
40+
tree = with_inserted(tree, k, v)
41+
return tree
42+
43+
44+
def treeget(t: Tree, k: Hashable) -> Any:
45+
hval = hash(k)
46+
while t:
47+
if t.key == k:
48+
return t.value
49+
t = t.left if hval < hash(t.key) else t.right
50+
raise KeyError(k)
51+
52+
53+
testdict = {random.randrange(100): random.randrange(100) for _ in range(20)}
54+
test_tree = dict2tree(testdict)
55+
56+
pprint(test_tree)
57+
assert all(treeget(test_tree, k) == v for k, v in testdict.items())
58+
print("get is ok")

0 commit comments

Comments
 (0)