package iskra import "git.smesh.lol/iskradb/lattice" // MorphState is a 5-bit field in Record.DataFile bits 1-5. // // Bit layout (wu xing mapping): // bit 4 (earth, 16): tense 0=present 1=past // bit 3 (wood, 8): aspect 0=simple 1=progressive // bit 2 (metal, 4): polarity 0=affirm 1=negative // bit 1 (water, 2): formality 0=plain 1=polite // bit 0 (fire, 1): evidential 0=direct 1=reported // // State 0 = present simple affirmative plain direct (dictionary/base form). const ( MorphPresAffPlain uint8 = 0 // 00000 MorphPresAffPolite uint8 = 2 // 00010 MorphPresNegPlain uint8 = 4 // 00100 MorphPresNegPolite uint8 = 6 // 00110 MorphPresProgPlain uint8 = 8 // 01000 MorphPresProgPolite uint8 = 10 // 01010 MorphPresProgNeg uint8 = 12 // 01100 MorphPastAffPlain uint8 = 16 // 10000 MorphPastAffPolite uint8 = 18 // 10010 MorphPastNegPlain uint8 = 20 // 10100 MorphPastNegPolite uint8 = 22 // 10110 MorphPastProgPlain uint8 = 24 // 11000 MorphPastProgPolite uint8 = 26 // 11010 MorphPastProgNeg uint8 = 28 // 11100 MorphPresReported uint8 = 1 // 00001 MorphPastReported uint8 = 17 // 10001 // Language activation masks. MaskJA uint8 = 0b11111 // all 5 bits MaskEN uint8 = 0b11100 // tense + aspect + polarity only MaskBG uint8 = 0b11111 // all 5 bits ) // Register values (Record.Branch bits 3-4). const ( RegNeutral uint8 = 0 RegFormal uint8 = 1 RegInformal uint8 = 2 RegVulgar uint8 = 3 ) // Domain values (Record.Branch bits 5-6). const ( DomGeneral uint8 = 0 DomTechnical uint8 = 1 DomMedical uint8 = 2 DomLegal uint8 = 3 ) // Special values (Record.Branch bit 7). const ( SpecNormal uint8 = 0 SpecHonorific uint8 = 1 SpecArchaic = SpecNormal SpecHumble = RegFormal ) // Filter constants for register-based translation filtering. const ( FilterNone uint8 = 0 FilterFormal uint8 = 1 FilterNeutral uint8 = 2 FilterCasual uint8 = 3 ) // SetMorphState packs a 5-bit morph state into Record.DataFile bits 1-5. func SetMorphState(rec *lattice.Record, state uint8) { rec.DataFile = (rec.DataFile & 0xFFFFFFC1) | (uint32(state&0x1F) << 1) } // GetMorphState extracts the 5-bit morph state from Record.DataFile bits 1-5. func GetMorphState(rec *lattice.Record) uint8 { return uint8((rec.DataFile >> 1) & 0x1F) } const semanticDataFileShift = 6 // SetSemanticInDataFile packs 16-bit semantic flags into Record.DataFile bits 6-21. func SetSemanticInDataFile(rec *lattice.Record, flags uint64) { rec.DataFile = (rec.DataFile &^ (0xFFFF << semanticDataFileShift)) | (uint32(flags&0xFFFF) << semanticDataFileShift) } // GetSemanticFromDataFile extracts the 16-bit semantic flags from Record.DataFile bits 6-21. func GetSemanticFromDataFile(rec *lattice.Record) uint64 { return uint64((rec.DataFile >> semanticDataFileShift) & 0xFFFF) } // PackBranch encodes POS (3 bits), register, domain, and honorific into a Branch byte. func PackBranch(pos uint8, reg, dom, spec uint8) uint8 { return (pos & 0x07) | ((reg & 0x03) << 3) | ((dom & 0x03) << 5) | ((spec & 0x01) << 7) } // POSFromBranch extracts the 3-bit POS (branch index 0-7) from a packed Branch byte. func POSFromBranch(b uint8) uint8 { return b & 0x07 } // RegFromBranch extracts the register bits (3-4). func RegFromBranch(b uint8) uint8 { return (b >> 3) & 0x03 } // DomFromBranch extracts the domain bits (5-6). func DomFromBranch(b uint8) uint8 { return (b >> 5) & 0x03 } // SpecFromBranch extracts the honorific bit (7). func SpecFromBranch(b uint8) uint8 { return (b >> 7) & 0x01 } // BranchWeirdness returns a tiebreaker score for register ranking. Lower = more preferred. func BranchWeirdness(b uint8) uint32 { reg := uint32(RegFromBranch(b)) spec := uint32(SpecFromBranch(b)) return reg*10 + spec*5 } // MatchesFilter returns true if a packed Branch byte is acceptable under the filter. func MatchesFilter(b uint8, filter uint8) bool { reg := RegFromBranch(b) switch filter { case FilterNone: return true case FilterFormal: return reg != RegVulgar case FilterNeutral: return reg == RegNeutral case FilterCasual: return reg != RegFormal && SpecFromBranch(b) != SpecHonorific } return true }