1 package iskra
2 3 import "git.smesh.lol/iskradb/lattice"
4 5 // SubLattice is a domain-scoped view of an iskradb tree.
6 // All keys in a sub-lattice share the same domain byte, ensuring
7 // non-collision with other domains in the same physical tree.
8 type SubLattice struct {
9 Tree *lattice.Tree
10 Pool []byte
11 Domain uint8
12 }
13 14 // NewSubLattice creates a SubLattice view over an existing tree.
15 func NewSubLattice(tree *lattice.Tree, pool []byte, domain uint8) SubLattice {
16 return SubLattice{Tree: tree, Pool: pool, Domain: domain}
17 }
18 19 // MakeKey returns the key for (word, coord) in this sub-lattice's domain.
20 // The word is normalized via the registered KeyNormalizer for the domain.
21 func (sl SubLattice) MakeKey(coord uint64, word string) lattice.Key {
22 return MakeKey(sl.Domain, coord, NormalizeKey(sl.Domain, word))
23 }
24 25 // Translate finds the best match for word in dstDomain by:
26 // 1. Looking up word in src sub-lattice at coord
27 // 2. Following Record.Link[0] to the primary cross-domain translation
28 // 3. Reading the target form from the dst sub-lattice record
29 //
30 // coord should encode the semantic/morph context of word in the source domain.
31 // RelaxCoord is applied if the exact coord is not found.
32 func Translate(src, dst SubLattice, word string, coord uint64) string {
33 norm := NormalizeKey(src.Domain, word)
34 branches := [3]lattice.Branch{lattice.Bnoun, lattice.Bverb, lattice.Bmodifier}
35 36 for _, c := range RelaxCoord(coord) {
37 key := MakeKey(src.Domain, c, norm)
38 for _, b := range branches {
39 ri := src.Tree.LookupRecIdx(b, key)
40 if ri == lattice.NullRec {
41 continue
42 }
43 rec := src.Tree.GetRecord(ri)
44 if rec == nil || rec.Link[0] == lattice.NullRec {
45 continue
46 }
47 dst_rec := dst.Tree.GetRecord(rec.Link[0])
48 if dst_rec == nil {
49 continue
50 }
51 n := int(dst_rec.Inline[23])
52 if n > 0 && n <= 23 {
53 return string(dst_rec.Inline[:n])
54 }
55 if dst_rec.DataFile == 1 && dst_rec.DataLen > 0 {
56 end := dst_rec.DataOff + dst_rec.DataLen
57 if int(end) <= len(dst.Pool) {
58 return string(dst.Pool[dst_rec.DataOff:end])
59 }
60 }
61 }
62 }
63 return ""
64 }
65 66 // Compose registers src as a sub-lattice within dst's tree by sharing the
67 // physical tree. Since domain bytes differ, keys cannot collide.
68 // Both sub-lattices must use the same physical *lattice.Tree.
69 // This is a conceptual operation - the tree is already shared if both
70 // SubLattices were created from the same tree pointer.
71 func Compose(a, b SubLattice) bool {
72 return a.Tree == b.Tree
73 }
74