package iskra const ( TritEnd = 0 // Level 1: declaration kind BranchType = 1 BranchFunc = 2 BranchData = 3 // Level 2 under BranchType SubField = 1 SubMethod = 2 SubEmbed = 3 // Level 2 under BranchFunc SubStatement = 1 SubExpression = 2 SubControl = 3 // Level 2 under BranchData SubConst = 1 SubVar = 2 SubImport = 3 ) type TritPath uint32 func (p TritPath) Trit(i int) uint8 { return uint8((p >> (uint(i) * 2)) & 0x3) } func (p TritPath) Depth() int { for i := 0; i < 8; i++ { if p.Trit(i) == TritEnd { return i } } return 8 } func (p TritPath) Branch() uint8 { return p.Trit(0) } func MakeTritPath(trits ...uint8) TritPath { var p TritPath for i, t := range trits { if i >= 8 { break } p |= TritPath(t&0x3) << (uint(i) * 2) } return p } // KindToTritPath maps a NodeKind to its trit-path in the code lattice. func KindToTritPath(kind NodeKind) TritPath { switch { // Type branch case kind.Has(KindField): return MakeTritPath(BranchType, SubField) case kind.Has(KindMethod): return MakeTritPath(BranchType, SubMethod) case kind.Has(KindType): return MakeTritPath(BranchType) // Func branch case kind.Has(KindControl): return MakeTritPath(BranchFunc, SubControl) case kind.Has(KindExpr): return MakeTritPath(BranchFunc, SubExpression) case kind.Has(KindStmt): return MakeTritPath(BranchFunc, SubStatement) case kind.Has(KindFunc): return MakeTritPath(BranchFunc) // Data branch case kind.Has(KindConst): return MakeTritPath(BranchData, SubConst) case kind.Has(KindVar): return MakeTritPath(BranchData, SubVar) case kind.Has(KindImport), kind.Has(KindPkg): return MakeTritPath(BranchData, SubImport) default: return MakeTritPath() } } func (m *MetaEntry) SetTritPath(p TritPath) { m.Extra[0] = byte(p) m.Extra[1] = byte(p >> 8) m.Extra[2] = byte(p >> 16) m.Extra[3] = byte(p >> 24) } func (m *MetaEntry) GetTritPath() TritPath { return TritPath(m.Extra[0]) | TritPath(m.Extra[1])<<8 | TritPath(m.Extra[2])<<16 | TritPath(m.Extra[3])<<24 } // TritPathDistance measures distance between two trit-paths on the lattice. // Returns -1 if either path is unassigned. func TritPathDistance(a, b TritPath) int { da := a.Depth() db := b.Depth() if da == 0 || db == 0 { return -1 } shared := 0 limit := da if db < limit { limit = db } for i := 0; i < limit; i++ { if a.Trit(i) != b.Trit(i) { break } shared++ } return (da - shared) + (db - shared) }