package lattice // WalkPattern encodes branch transitions as 2 bits per branch. // Values are absolute branch identifiers + 1: // 0 = stop // 1 = noun (Branch 0 + 1) // 2 = verb (Branch 1 + 1) // 3 = modifier (Branch 2 + 1) // // bits 0-1: after noun, go to ... // bits 2-3: after verb, go to ... // bits 4-5: after modifier, go to ... type WalkPattern uint8 const ( PatNounVerbMod WalkPattern = 0x02 | (0x03 << 2) // noun->verb->mod->stop PatNounMod WalkPattern = 0x03 // noun->mod->stop PatVerbNoun WalkPattern = 0x01 << 2 // verb->noun->stop PatFull WalkPattern = 0x02 | (0x03 << 2) | (0x01 << 4) // noun->verb->mod->noun (cycle) ) func (wp WalkPattern) Next(current Branch) uint8 { shift := uint(current) * 2 return uint8((wp >> shift) & 0x3) } // branchToLinkIndex maps a (current branch, target branch) pair to the Link index on a Record. // noun: Link[0]=verb, Link[1]=modifier // verb: Link[0]=noun, Link[1]=modifier // mod: Link[0]=noun, Link[1]=verb func branchToLinkIndex(current, target Branch) int { switch current { case Bnoun: if target == Bverb { return 0 } return 1 case Bverb: if target == Bnoun { return 0 } return 1 default: if target == Bnoun { return 0 } return 1 } } // CrossWalk follows Record.Link pointers across branches according to the pattern. // Records are stable across B-tree splits, so links never go stale. func (t *Tree) CrossWalk(startRecIdx uint32, pattern WalkPattern, visit func(uint32, *Record) bool) { ri := startRecIdx visited := uint8(0) for { if ri == NullRec { return } rec := t.getRecord(ri) if !visit(ri, rec) { return } visited++ if visited > 3 { return } current := Branch(rec.Branch) next := pattern.Next(current) if next == 0 { return } targetBranch := Branch(next - 1) linkIdx := branchToLinkIndex(current, targetBranch) ri = rec.Link[linkIdx] } } // TripleWalk looks up one key per branch and returns the three records. func (t *Tree) TripleWalk(nounKey, verbKey, modKey Key) (n, v, m *Record) { n = t.Lookup(Bnoun, nounKey) v = t.Lookup(Bverb, verbKey) m = t.Lookup(Bmodifier, modKey) return } // Linked returns the cross-branch partner record indices. func (t *Tree) Linked(recIdx uint32) (uint32, uint32) { r := t.getRecord(recIdx) return r.Link[0], r.Link[1] }