# -*- coding: utf-8 -*- """gen_elp_seed_full.py — emit a FULL-lexicon vocabulary-{lang}.el in the established ELP seed-fn format (same as vocabulary-non.el / the 18 classical languages), iterating the ENTIRE morphology_{lang}_full lexicon (every verb, noun, adjective lemma) — NOT a curated demo core. Schema per row: [lemma, pos, form0, form1, form2, en_translation, semantic_hint] Verbs: form0=pres-ind-3sg form1=preterite-3sg form2=past-participle Nouns: form0=singular form1=plural form2=REAL gender (lexicon) Adjs : form0=masc-sg form1=fem-sg form2=masc-pl Output structure (chunked to stay within the proven ~5k-append/function scale): fn vocab_{lang}_seed_pN(v) -> [[String]] { ... appends ... return v } fn vocab_{lang}_seed() -> [[String]] { chains all chunks; return v } fn vocab_{lang}_lookup(w) -> [String] { linear scan } Usage: python3 gen_elp_seed_full.py """ import sys, importlib CHUNK = 5000 def esc(s): return str(s).replace("\\", "\\\\").replace('"', '\\"') def row(fields): return " let v = native_list_append(v, [" + ", ".join(f'"{esc(f)}"' for f in fields) + "])" def build_rows(lang, M): rows = [] stats = {"verbs":0,"nouns":0,"adjs":0} has = lambda n: hasattr(M, n) # --- verbs --- if has("_VERBS") and has("conjugate"): verbs = sorted({k[0] for k in M._VERBS}) for lem in verbs: if not lem: continue try: f0, s0 = M.conjugate(lem, "ind", "present", "third", "singular") f1, _ = M.conjugate(lem, "ind", "preterite", "third", "singular") pp, _ = (M.participle(lem) if has("participle") else ("","")) except Exception: continue vclass = lem[-2:] if lem[-2:] in ("ar","er","ir","re") else lem[-2:] rows.append([lem, "verb", f0 or "", f1 or "", pp or "", "", "class:"+vclass+" src:"+str(s0)]) stats["verbs"] += 1 # --- nouns --- if has("_NOUNS") and has("inflect_noun"): for lem in sorted(M._NOUNS): if not lem: continue try: sg, _ = M.inflect_noun(lem, "singular") pl, _ = M.inflect_noun(lem, "plural") g = M.noun_gender(lem) if has("noun_gender") else "" except Exception: continue src = "lexicon" if (isinstance(M._NOUNS.get(lem), dict) and M._NOUNS[lem].get("g")) else "heuristic" rows.append([lem, "noun", sg or lem, pl or "", g or "", "", "gender:"+src]) stats["nouns"] += 1 # --- adjectives --- if has("_ADJS") and has("inflect_adj"): for lem in sorted(M._ADJS): if not lem: continue try: m_sg, _ = M.inflect_adj(lem, "m", "singular") f_sg, _ = M.inflect_adj(lem, "f", "singular") m_pl, _ = M.inflect_adj(lem, "m", "plural") except Exception: continue rows.append([lem, "adj", m_sg or lem, f_sg or "", m_pl or "", "", "src:lexicon"]) stats["adjs"] += 1 return rows, stats def write_seed(lang, rows, stats, out_path): """Write vocabulary-{lang}.el in the chunked seed-fn format from prebuilt rows. Each row is a 7-field list [lemma,pos,f0,f1,f2,gloss,hint].""" total = len(rows) chunks = [rows[i:i+CHUNK] for i in range(0, total, CHUNK)] or [[]] L = [] L.append(f"// vocabulary-{lang}.el — FULL {lang} lexicon for ELP surface realization.") L.append(f"// Generated by gen_elp_seed_full.py from morphology_{lang}_full") L.append(f"// (real UniMorph + kaikki.org Wiktionary forms; gender from lexicon, not heuristic).") L.append(f"// Entries: {total} (verbs={stats['verbs']} nouns={stats['nouns']} adjs={stats['adjs']})") L.append(f"// Schema: [lemma, pos, form0, form1, form2, en_translation, semantic_hint]") L.append(f"// verbs: form0=pres-3sg form1=pret-3sg form2=past-participle") L.append(f"// nouns: form0=sg form1=pl form2=REAL gender adjs: form0=m-sg form1=f-sg form2=m-pl") L.append("") for ci, ch in enumerate(chunks): L.append(f"fn vocab_{lang}_seed_p{ci}(v: [[String]]) -> [[String]] {{") for r in ch: L.append(row(r)) L.append(" return v") L.append("}") L.append("") L.append(f"fn vocab_{lang}_seed() -> [[String]] {{") L.append(" let v: [[String]] = native_list_empty()") for ci in range(len(chunks)): L.append(f" let v = vocab_{lang}_seed_p{ci}(v)") L.append(" return v") L.append("}") L.append("") L.append(f"fn vocab_{lang}_lookup(word: String) -> [String] {{") L.append(f" let vocab: [[String]] = vocab_{lang}_seed()") L.append(" let n: Int = native_list_len(vocab)") L.append(" let i: Int = 0") L.append(" while i < n {") L.append(" let entry: [String] = native_list_get(vocab, i)") L.append(' if str_eq(native_list_get(entry, 0), word) { return entry }') L.append(" let i = i + 1") L.append(" }") L.append(" return native_list_empty()") L.append("}") with open(out_path, "w", encoding="utf-8") as fh: fh.write("\n".join(L) + "\n") return total, stats def emit(lang, out_path): M = importlib.import_module(f"morphology_{lang}_full") rows, stats = build_rows(lang, M) return write_seed(lang, rows, stats, out_path) if __name__ == "__main__": lang, out = sys.argv[1], sys.argv[2] total, stats = emit(lang, out) print(f"{lang}: wrote {out} total={total} verbs={stats['verbs']} nouns={stats['nouns']} adjs={stats['adjs']}")