nx_mathml_lib.nx
buildroot/runtime/nx_mathml_lib.nx
about
nx_mathml_lib.nx -- LATEX SUBSET -> MATHML, THE SOVEREIGN MATH TYPESETTER.
WHY THIS EXISTS (measured 2026-09-03). The estate had already chosen MathML as its math rendering path
and already had the symbols, and NOTHING joined them: nx_paper_native's grammar takes ".MATH <id>
<mathml>" with the MathML subtree VERBATIM, so an author had to hand-write MathML; nx_unicode_math
carries ~50 UTF-8 math symbols but no layout. nx_capsearch over 7,266 sources (corpus_complete=1)
returns no LaTeX reader of any kind. The missing primitive was the CONVERTER, and it is the one every
math surface needs: a board note, a paper, a document in the unified portal, and the applied-math UI
all want to write a formula the way a mathematician writes it and have it render.
WHY MATHML AND NOT A JAVASCRIPT TYPESETTER. MathML is rendered NATIVELY by the browser, so a page that
emits it carries NO third-party runtime, no script, and no network fetch -- which is the estate's
standing rule that the oracle stays outside and nothing foreign enters the build or run path. A page
using MathJax or KaTeX would import the oracle instead of building the twin. This organ therefore emits
markup the browser already understands, and the same bytes render in the Nishi browser.
SCOPE, DECLARED RATHER THAN IMPLIED. This is a SUBSET of LaTeX math: numbers, identifiers, operators,
superscripts, subscripts, fractions, roots, grouping, the Greek letters and the operator/relation
symbols nx_unicode_math already carries, and upright function names. It does NOT do matrices,
alignment environments, macros, or text mode. ★AN UNKNOWN COMMAND IS REFUSED BY NAME AND NEVER SILENTLY
DROPPED: a typesetter that quietly discards what it does not understand produces a formula that is
wrong in a way the reader cannot see, which is worse than no formula at all.
SAFETY. Every character that reaches the output as CONTENT goes through the shared html escaper
(nx_html_escape.nx). The converter never copies raw input into markup, so a formula carrying markup
characters cannot break out of its element -- the same escape-by-construction property the unified
document portal is built on.
license_tier: ORIGINAL
dependencies 3 imports · 3 importers
imports: syscalls.nxnx_html_escape.nxnx_unicode_math.nx
imported by: nx_math_page.nxnx_mathml.nxnx_mathml_gate.nx
structs
| 51 | struct LmCtx |
consts
| 34 | const LM_OK: i64 = 0 |
| 35 | const LM_ERR_UNKNOWN_CMD: i64 = 0 - 1 // a backslash command this subset does not implement |
| 36 | const LM_ERR_SHORT: i64 = 0 - 2 // the output buffer could not hold the result |
| 37 | const LM_ERR_UNBALANCED: i64 = 0 - 3 // a { without its } , or a } with no |
| 38 | const LM_ERR_DEPTH: i64 = 0 - 4 // nesting deeper than LM_MAX_DEPTH |
| 39 | const LM_ERR_EMPTY: i64 = 0 - 5 // nothing to typeset |
| 41 | const LM_MAX_DEPTH: i64 = 32 |
| 42 | const LM_MAX_CMD: i64 = 32 // longest command name accepted, e.g. leftrightarrow |
| 48 | const LM_EXPAND: i64 = 24 |
| 49 | const LM_HEAD_RESERVE: i64 = 128 |
functions
| 66 | func lm_slen(s: *u8) -> i64 |
| 73 | func lm_lit(c: *LmCtx, s: *u8) -> i64 |
| 83 | func lm_text(c: *LmCtx, s: *u8, n: i64) -> i64 |
| 107 | func lm_at(c: *LmCtx) -> i64 |
| 112 | func lm_is_digit(b: i64) -> i64 called by 1: lm_atom |
| 117 | func lm_is_alpha(b: i64) -> i64 called by 1: lm_atom |
| 123 | func lm_is_space(b: i64) -> i64 called by 1: lm_skip_space |
| 131 | func lm_skip_space(c: *LmCtx) -> i64 |
| 137 | func lm_cmd_is(c: *LmCtx, a: i64, len: i64, lit: *u8) -> i64 |
| 150 | func lm_symbol(c: *LmCtx, a: i64, len: i64) -> *u8 called by 1: lm_atom calls 24: lm_cmd_isnx_sym_alphanx_sym_betanx_sym_gammanx_sym_deltanx_sym_epsilon+18 |
| 179 | func lm_blackboard(letter: i64) -> *u8 called by 1: lm_atom calls 5: nx_sym_realsnx_sym_integersnx_sym_complexnx_sym_naturalsnx_sym_rationals |
| 191 | func lm_operator(c: *LmCtx, a: i64, len: i64) -> *u8 |
| 227 | func lm_funcname(c: *LmCtx, a: i64, len: i64) -> *u8 |
| 240 | func lm_group(c: *LmCtx) -> i64; |
| 241 | func lm_atom(c: *LmCtx) -> i64; |
| 242 | func lm_script(c: *LmCtx, open_tag: *u8, close_tag: *u8) -> i64; called by 1: lm_atom |
| 245 | func lm_seq(c: *LmCtx, stop_at_brace: i64) -> i64 |
| 262 | func lm_group(c: *LmCtx) -> i64 |
| 287 | func lm_script(c: *LmCtx, open_tag: *u8, close_tag: *u8) -> i64 |
| 311 | func lm_atom(c: *LmCtx) -> i64 |
| 424 | func lm_err_name(e: i64) -> *u8 |
| 437 | func lm_to_mathml(latex: *u8, n: i64, out: *u8, cap: i64, display: i64, badoff: *i64, badlen: *i64) -> i64 |
| 480 | func lm_out_cap_for(n: i64) -> i64 |