Extending Octant
Octant's surface is bounded deliberately: the hand-written parser stays tractable because the supported set is finite. Two extension points are relevant to users. The first adds a function mapping without rebuilding Octant. The second adds a reference pair.
Adding a function mapping with --config
Section titled “Adding a function mapping with --config”If your LaTeX uses a function name Octant does not ship, your firm's
pricing kernel, a distribution not in the standard catalog, you can
register the mapping in a TOML file and pass it with --config. No
rebuild is required.
The file holds one or more [[functions]] tables. Each registers one
LaTeX-to-Chelis-target mapping.
[[functions]]latex_name = "Weibull"chelis_target = "MyDomain.Special.weibull"requires_nautilus = false
[[functions]]latex_name = "LevyStable"chelis_target = "MyDomain.Special.levy_stable"requires_nautilus = falseRun with the config:
octant translate input.tex --config octant-config.tomlNow \Weibull(a, b) in the LaTeX resolves to
MyDomain.Special.weibull(a, b) in the emitted Deep. The Chelis
compiler resolves the symbol at build time against whatever module you
have imported under that name.
Field semantics
Section titled “Field semantics”| Field | Meaning |
|---|---|
latex_name | The LaTeX command without the leading \. ASCII letters only, no spaces, digits, or backslash. |
chelis_target | The Chelis identifier or dotted path to emit. Dotted paths lower to nested access chains. |
requires_nautilus | Metadata flag. Informational. Optional, defaults to false. |
A BuiltinEntry carries no arity or signature data. Octant maps the
LaTeX name to its target without claiming a signature; the Chelis
compiler resolves the actual arity and types at build time and reports
any mismatch there. This keeps Octant's catalog small and the upstream
catalog the single source of truth.
Shadowing and collisions
Section titled “Shadowing and collisions”A config entry whose latex_name matches a built-in entry, for example a
custom \exp, takes effect. Octant prints a warning to stderr noting
that the custom mapping is in use:
config: shadowing builtin `exp` with custom mappingThe shadow does not break translation; it announces that your mapping is preferred over the built-in one.
Two [[functions]] entries in the same file with the same latex_name
is a hard error. Octant rejects the file rather than silently keeping
one. Remove or rename one of them.
Malformed TOML, a missing required field (latex_name or
chelis_target), an unknown extra field, an empty target, and a bad
latex_name shape all surface clean diagnostics naming the offending
field. You should be able to fix the config from the diagnostic alone.
When to use which path
Section titled “When to use which path”Use --config for a function specific to your firm or model. For a
standard math or textbook function that should be available to all Octant
users by default, the path is a contributor change to Octant's built-in
catalog in src/functions.rs, with tests, submitted as a pull request.
The --config path keeps your extension an opt-in surface and leaves the
built-in catalog narrow.
Adding a reference pair
Section titled “Adding a reference pair”The simplest extension. Drop two files into references/:
references/ my_formula.tex # LaTeX source, with % chelis: annotations my_formula.ch # hand-written Chelis referenceThe .tex file is self-contained, expresses one formula, declares every
free identifier with % chelis: <name> : <type>, and optionally imports
any customer-supplied symbols with % chelis: import Module (sym, ...).
The .ch file is a def <name>(<params>) -> <ret> = <body> form,
imports anything the body needs, and aligns its def name with the
LaTeX left-hand side.
The integration test walks references/, runs Octant on each .tex,
runs the Chelis Deep desugaring on the paired .ch, canonicalizes both,
and asserts that they agree on the actual computation. No code changes
are required. The canonicalizer strips metadata, the function wrapper,
and import structure, then compares the computation: operations,
argument order, semantic structure. Commutative operations are not
reordered, so (mul a b) and (mul b a) are treated as different.
If your formula uses a function not in the built-in catalog, add the
mapping first with --config above, or the reference will fail until
the mapping is in place.