// ===== moonrdfs 全链自证 demo(验收役 2026-11-03;cmd/demo 家法形)=====
// MemoryDataset 门面七面:insert 集合律(重复装载折叠)/match_triples 全开/
// exec_bgp 变量连接/match_quads named-graph 分账/词典去重计/prefix 册往返/
// infer 物化闭包(四族六条;二跑 0)。
// 数据纪律:跨包 record 字面量一律拔带型 let(家法 #11/#22);插值内复杂
// 表达式一律上提 let(家法:插值内嵌引号咬串);insert/exec 的 raise 收敛
// 到 run 的 RdfStoreError 域,main 侧 catch 收 Bool。

///|
fn run() -> Bool raise {
  let ds = @store.MemoryDataset::new()
  ds.set_prefix("foaf", "http://xmlns.com/foaf/0.1/")
  // 装店:alice 与 bob 互知,各带名字(字面量无 lang 无型)
  let alice : @core.Term = @core.Term::Iri("http://example.org/alice")
  let bob : @core.Term = @core.Term::Iri("http://example.org/bob")
  let name_p : @core.Term = @core.Term::Iri("http://xmlns.com/foaf/0.1/name")
  let knows_p : @core.Term = @core.Term::Iri("http://xmlns.com/foaf/0.1/knows")
  let alice_name : @core.Term = @core.Term::Literal("Alice", None, None)
  let bob_name : @core.Term = @core.Term::Literal("Bob", None, None)
  let t1 : @core.Triple = { s: alice, p: name_p, o: alice_name, }
  let t2 : @core.Triple = { s: bob, p: name_p, o: bob_name, }
  let t3 : @core.Triple = { s: alice, p: knows_p, o: bob, }
  let t4 : @core.Triple = { s: bob, p: knows_p, o: alice, }
  println("--- 装店(insert 集合律)")
  let r1 = ds.insert(t1)
  let r2 = ds.insert(t2)
  let r3 = ds.insert(t3)
  let r4 = ds.insert(t4)
  let r5 = ds.insert(t1) // 重复装载 → 折叠(false)
  println("[解] 首装 4 条 = \{r1}\{r2}\{r3}\{r4};重复第 5 条 = \{r5}")
  let ok_insert = r1 && r2 && r3 && r4 && !r5
  println("--- match_triples 全开(s/p/o 缺省 = 无界)")
  let all = ds.match_triples()
  println("[解] 全开 \{all.length()} 条(重复折叠后)")
  let ok_match = all.length() == 4
  println(
    "--- exec_bgp 三模式连接(?a foaf:name ?n)(?a foaf:knows ?b)(?b foaf:name ?m)",
  )
  let pa : @core.TriplePattern = {
    s: @core.Var("a"),
    p: @core.Fixed(name_p),
    o: @core.Var("n"),
  }
  let pb : @core.TriplePattern = {
    s: @core.Var("a"),
    p: @core.Fixed(knows_p),
    o: @core.Var("b"),
  }
  let pc : @core.TriplePattern = {
    s: @core.Var("b"),
    p: @core.Fixed(name_p),
    o: @core.Var("m"),
  }
  let bgp : @core.Bgp = { patterns: [pa, pb, pc], }
  let solutions = ds.exec_bgp(bgp)
  println("[解] \{solutions.length()} 解")
  for sol in solutions {
    let ca : @core.Term = sol.get("a").unwrap()
    let cn : @core.Term = sol.get("n").unwrap()
    let cb : @core.Term = sol.get("b").unwrap()
    let cm : @core.Term = sol.get("m").unwrap()
    println(
      "    ?a=\{@core.canonical_of_term(ca)} ?n=\{@core.canonical_of_term(cn)} ?b=\{@core.canonical_of_term(cb)} ?m=\{@core.canonical_of_term(cm)}",
    )
  }
  let ok_bgp = solutions.length() == 2 && bgp_names_ok(solutions)
  println("--- 四元组面(named-graph 分账)")
  let gb : @core.GraphName? = Some(@core.Named(bob))
  let q : @core.Quad = { s: alice, p: knows_p, o: bob, g: @core.Named(bob), }
  let _ = ds.insert_quad(q)
  let quads = ds.match_quads(g=gb)
  println("[解] named graph 账 \{quads.length()} 条")
  let ok_quads = quads.length() == 1
  println("--- 词典与 prefix 册")
  let distinct = ds.distinct_term_count()
  // prefix_of(key) = 按 prefix 名查回 namespace(set_prefix 的键值往返)
  let prefix = ds.prefix_of("foaf")
  let prefix_text = prefix.unwrap_or("(无)")
  println("[解] 词典去重 \{distinct} 词;prefix 往返 = \{prefix_text}")
  let ok_dict = distinct == 6 && prefix is Some("http://xmlns.com/foaf/0.1/")
  println("--- infer 物化闭包(RDFS-lite 四族六条首现;二跑 0)")
  let bird_c : @core.Term = @core.Term::Iri("http://example.org/Bird")
  let animal_c : @core.Term = @core.Term::Iri("http://example.org/Animal")
  let wings_p : @core.Term = @core.Term::Iri("http://example.org/wings")
  let keet_x : @core.Term = @core.Term::Iri("http://example.org/keet")
  let sub_c : @core.Term = @core.Term::Iri(@infer.RDFS_SUBCLASS_OF)
  let dom_c : @core.Term = @core.Term::Iri(@infer.RDFS_DOMAIN)
  let type_c : @core.Term = @core.Term::Iri(@infer.RDF_TYPE)
  let blue_v : @core.Term = @core.Term::Literal("blue", None, None)
  let _ = ds.insert({ s: bird_c, p: sub_c, o: animal_c, })
  let _ = ds.insert({ s: wings_p, p: dom_c, o: bird_c, })
  let _ = ds.insert({ s: keet_x, p: wings_p, o: blue_v, })
  let n1 = ds.materialize()
  let n2 = ds.materialize()
  println(
    "[解] 首物化 +\{n1}(域律 keet type Bird → 子类链 keet type Animal);二跑 +\{n2}",
  )
  let derived = ds.match_triples(
    s=Some(keet_x),
    p=Some(type_c),
    o=Some(animal_c),
  )
  let ok_infer = n1 == 2 && n2 == 0 && derived.length() == 1
  report("insert 集合律(重复折叠)", ok_insert)
  report("全开匹配 4 条", ok_match)
  report("BGP 互知双向恰两解(n/m 各含 Alice+Bob)", ok_bgp)
  report("named-graph 恰一账", ok_quads)
  report("词典 6 词 + prefix 往返", ok_dict)
  report("infer 物化闭包(+2 / 二跑 0 / 派生可见)", ok_infer)
  ok_insert && ok_match && ok_bgp && ok_quads && ok_dict && ok_infer
}

///|
/// BGP 双向解账(解序不钉——显式集合判,不走 sort:String 内建全序 =
/// (长度,内容),Bob 会排在 Alice 前,坑账第一条)
fn bgp_names_ok(solutions : Array[Map[String, @core.Term]]) -> Bool {
  let ns : Array[String] = []
  let ms : Array[String] = []
  for sol in solutions {
    let n = name_of(sol, "n")
    let m = name_of(sol, "m")
    if n == "" || m == "" || n == m {
      return false
    }
    ns.push(n)
    ms.push(m)
  }
  solutions.length() == 2 &&
  string_in(ns, "Alice") &&
  string_in(ns, "Bob") &&
  string_in(ms, "Alice") &&
  string_in(ms, "Bob")
}

///|
fn string_in(arr : Array[String], want : String) -> Bool {
  for x in arr {
    if x == want {
      return true
    }
  }
  false
}

///|
/// 解集取字面量词面(变量缺绑/非字面 = 空串——判定位)
fn name_of(sol : Map[String, @core.Term], key : String) -> String {
  match sol.get(key) {
    Some(term) =>
      match term {
        @core.Literal(v, _, _) => v
        _ => ""
      }
    None => ""
  }
}

///|
fn report(label : String, ok : Bool) -> Unit {
  println("[判] \{label} ⇒ \{if ok { "✓" } else { "✗" }}")
}

///|
fn main {
  let ok = run() catch {
    _ => {
      println("[判] 存储异常(不该发生)")
      false
    }
  }
  if !ok {
    println("DEMO:FAIL")
    abort("demo 期望失配——看上方 [判] ✗ 行")
  }
  println("DEMO:PASS")
}