code wiki / (root) / nx_ontology.nx

nx_ontology.nx source

↩ module page · 239 lines · 7662 B

1// nx_ontology.nx -- substrate-native ontology over RDF-style triples. 2// 3// Per user directive 2026-05-14: "ontology needs to be recognized as a 4// part of what we are doing as we build this math layer" (Wikipedia: 5// Ontology (information science)). 6// 7// Reads nxc2/specs/nx_ontology.txt (TSV: subject, predicate, object, 8// optional notes) and exposes count + lookup queries. Predicates are 9// free-form strings; consumers compare directly. 10// 11// Composes with patent_check, provenance, emit_journal: substrate now 12// has a typed knowledge graph linking algorithm -> category -> source 13// -> license -> patent_status. 14// 15// genealogy_id: substrate_ontology_2026_05_14 16// lineage_id: substrate_self_description 17 18// nx_safety_envelope: 19// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 20// sil_target: SIL1 21// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 22// verdict: NOT_YET_EVALUATED 23 24import "nx_syscalls.nx" 25import "nx_runtime.nx" 26import "nx_tier.nx" 27import "nx_str.nx" 28 29const NX_ONT_MAX_TRIPLES: nx_int = 4096 30const NX_ONT_FIELD_CAP: nx_size = 96 31 32// ===== struct ======================================================= 33 34struct NxOntologyTriple { 35 subject: *u8, 36 predicate: *u8, 37 object: *u8, 38} 39 40const NX_ONT_TRIPLE_BYTES: nx_size = 24 41 42struct NxOntology { 43 triples: *NxOntologyTriple, 44 n: nx_int, 45 capacity: nx_int, 46} 47 48// ===== parse one TSV row ============================================ 49 50// Returns 1 on success, 0 on skip (blank/comment/malformed). 51func nx_ont_parse_line(buf: *u8, lo: nx_int, hi: nx_int, 52 s_buf: *u8, p_buf: *u8, o_buf: *u8, 53 out: *NxOntologyTriple) -> nx_int { 54 // Skip leading whitespace 55 var p: nx_int = lo 56 var ws_done: nx_int = 0 57 while ws_done == 0 { 58 if p >= hi { ws_done = 1 } 59 if ws_done == 0 { 60 let c: nx_int = buf[p] as nx_int 61 if c == 32 { p = p + 1 } 62 if c != 32 { 63 if c == 9 { p = p + 1 } 64 if c != 9 { ws_done = 1 } 65 } 66 } 67 } 68 if p >= hi { return 0 } 69 if buf[p] == 35 { return 0 } // '#' comment 70 if buf[p] == 10 { return 0 } // blank 71 72 // Field 1: subject 73 var e1: nx_int = p 74 var d1: nx_int = 0 75 while d1 == 0 { 76 if e1 >= hi { d1 = 1 } 77 if d1 == 0 { 78 let c: nx_int = buf[e1] as nx_int 79 if c == 9 { d1 = 1 } 80 if c == 10 { d1 = 1 } 81 if d1 == 0 { e1 = e1 + 1 } 82 } 83 } 84 if e1 >= hi { return 0 } 85 if buf[e1] == 10 { return 0 } 86 let s_len: nx_int = e1 - p 87 if s_len == 0 { return 0 } 88 if s_len >= (NX_ONT_FIELD_CAP as nx_int) { return 0 } 89 var i: nx_int = 0 90 while i < s_len { s_buf[i] = buf[p + i]; i = i + 1 } 91 s_buf[s_len] = 0 92 93 // Field 2: predicate 94 p = e1 + 1 95 var e2: nx_int = p 96 var d2: nx_int = 0 97 while d2 == 0 { 98 if e2 >= hi { d2 = 1 } 99 if d2 == 0 { 100 let c: nx_int = buf[e2] as nx_int 101 if c == 9 { d2 = 1 } 102 if c == 10 { d2 = 1 } 103 if d2 == 0 { e2 = e2 + 1 } 104 } 105 } 106 if e2 >= hi { return 0 } 107 if buf[e2] == 10 { return 0 } 108 let p_len: nx_int = e2 - p 109 if p_len == 0 { return 0 } 110 if p_len >= (NX_ONT_FIELD_CAP as nx_int) { return 0 } 111 i = 0 112 while i < p_len { p_buf[i] = buf[p + i]; i = i + 1 } 113 p_buf[p_len] = 0 114 115 // Field 3: object (up to TAB or NL -- TAB allowed for trailing notes) 116 p = e2 + 1 117 var e3: nx_int = p 118 var d3: nx_int = 0 119 while d3 == 0 { 120 if e3 >= hi { d3 = 1 } 121 if d3 == 0 { 122 let c: nx_int = buf[e3] as nx_int 123 if c == 9 { d3 = 1 } 124 if c == 10 { d3 = 1 } 125 if d3 == 0 { e3 = e3 + 1 } 126 } 127 } 128 let o_len: nx_int = e3 - p 129 if o_len == 0 { return 0 } 130 if o_len >= (NX_ONT_FIELD_CAP as nx_int) { return 0 } 131 i = 0 132 while i < o_len { o_buf[i] = buf[p + i]; i = i + 1 } 133 o_buf[o_len] = 0 134 135 // Own copies 136 let s_owned: *u8 = sys_mmap((s_len + 1) as nx_size) 137 nx_str_cpy(s_owned, s_buf) 138 let p_owned: *u8 = sys_mmap((p_len + 1) as nx_size) 139 nx_str_cpy(p_owned, p_buf) 140 let o_owned: *u8 = sys_mmap((o_len + 1) as nx_size) 141 nx_str_cpy(o_owned, o_buf) 142 out.subject = s_owned 143 out.predicate = p_owned 144 out.object = o_owned 145 return 1 146} 147 148// ===== load + queries =============================================== 149 150func nx_ontology_load(path: *u8) -> *NxOntology { 151 let raw: *u8 = sys_mmap(24) 152 let o: *NxOntology = raw as *NxOntology 153 o.triples = (sys_mmap((NX_ONT_MAX_TRIPLES as nx_size) * NX_ONT_TRIPLE_BYTES)) as *NxOntologyTriple 154 o.n = 0 155 o.capacity = NX_ONT_MAX_TRIPLES 156 157 let len_p: *nx_size = (sys_mmap(NX_SIZEOF_NX_SIZE)) as *nx_size 158 len_p[0] = 0 159 let buf: *u8 = sys_read_file(path, len_p) 160 if (buf as nx_size) == 0 { return o } 161 let n: nx_int = len_p[0] as nx_int 162 163 let s_buf: *u8 = sys_mmap(NX_ONT_FIELD_CAP) 164 let p_buf: *u8 = sys_mmap(NX_ONT_FIELD_CAP) 165 let o_buf: *u8 = sys_mmap(NX_ONT_FIELD_CAP) 166 167 var p: nx_int = 0 168 while p < n { 169 var eol: nx_int = p 170 var de: nx_int = 0 171 while de == 0 { 172 if eol >= n { de = 1 } 173 if de == 0 { 174 if buf[eol] == 10 { de = 1 } 175 if de == 0 { eol = eol + 1 } 176 } 177 } 178 if o.n < o.capacity { 179 let raw_t: *u8 = ((o.triples as nx_size) + (o.n as nx_size) * NX_ONT_TRIPLE_BYTES) as *u8 180 let t: *NxOntologyTriple = raw_t as *NxOntologyTriple 181 let parsed: nx_int = nx_ont_parse_line(buf, p, eol, s_buf, p_buf, o_buf, t) 182 if parsed == 1 { o.n = o.n + 1 } 183 } 184 p = eol + 1 185 } 186 return o 187} 188 189func nx_ontology_n_triples(o: *NxOntology) -> nx_int { return o.n } 190 191// Count triples with given predicate. 192func nx_ontology_count_by_predicate(o: *NxOntology, pred: *u8) -> nx_int { 193 var c: nx_int = 0 194 var i: nx_int = 0 195 while i < o.n { 196 let raw_t: *u8 = ((o.triples as nx_size) + (i as nx_size) * NX_ONT_TRIPLE_BYTES) as *u8 197 let t: *NxOntologyTriple = raw_t as *NxOntologyTriple 198 if nx_str_eq(t.predicate, pred) == 1 { c = c + 1 } 199 i = i + 1 200 } 201 return c 202} 203 204// Count triples with given (predicate, object) -- e.g. 205// nx_ontology_count_with_po(o, "in_domain", "competitive_programming") 206func nx_ontology_count_with_po(o: *NxOntology, pred: *u8, obj: *u8) -> nx_int { 207 var c: nx_int = 0 208 var i: nx_int = 0 209 while i < o.n { 210 let raw_t: *u8 = ((o.triples as nx_size) + (i as nx_size) * NX_ONT_TRIPLE_BYTES) as *u8 211 let t: *NxOntologyTriple = raw_t as *NxOntologyTriple 212 if nx_str_eq(t.predicate, pred) == 1 { 213 if nx_str_eq(t.object, obj) == 1 { c = c + 1 } 214 } 215 i = i + 1 216 } 217 return c 218} 219 220// Exact-match triple lookup. 221func nx_ontology_has_triple(o: *NxOntology, subj: *u8, pred: *u8, obj: *u8) -> nx_int { 222 var i: nx_int = 0 223 while i < o.n { 224 let raw_t: *u8 = ((o.triples as nx_size) + (i as nx_size) * NX_ONT_TRIPLE_BYTES) as *u8 225 let t: *NxOntologyTriple = raw_t as *NxOntologyTriple 226 if nx_str_eq(t.subject, subj) == 1 { 227 if nx_str_eq(t.predicate, pred) == 1 { 228 if nx_str_eq(t.object, obj) == 1 { return 1 } 229 } 230 } 231 i = i + 1 232 } 233 return 0 234} 235 236// "Is this subject in this domain?" -- shortcut for in_domain triple lookup. 237func nx_ontology_in_domain(o: *NxOntology, subj: *u8, domain: *u8) -> nx_int { 238 return nx_ontology_has_triple(o, subj, "in_domain" as *u8, domain) 239}