THE FHERMA CLI
The fherma-lang tool
fherma-lang is the language as a standalone package: lexer, parser,
checker and emitters. Text in, structure out. It knows nothing about any
platform and has no dependencies — it is what the fherma command, the
server and the editor all build on, and the single implementation of the
language.
pip install fherma-lang
Most people arrive through the fherma CLI, which brings it along. Install
it directly when you want the language and nothing else — a build step, an
editor, a server validating signatures.
Reading a declaration
$ fherma-lang parse sig.fhk
specification negacyclic 1.0.0
Negacyclic, with a wide modulus
refines kernel polymul
parameters
N : u32
W : u32
arguments
%a tensor<N x W x u64>
%b tensor<N x W x u64>
%q tensor<W x u64>
results
%c tensor<N x W x u64>
--json prints the parse result for another tool to consume — and it can be
fed straight back into emit, which tells declarations and stored parse
results apart by the first character. Failures carry a
diagnostic code, the place, and something to do about
it.
Emitting a scaffold
A scaffold is a pure function of a declaration: the same signature always gives the same tree, which is what lets the CLI and a web button hand out identical bundles without coordinating.
fherma-lang emit --testing sig.fhk # the bundle fherma-lang emit --testing sig.fhk --oracle # one part of it fherma-lang emit --solution sig.fhk --lang cpp # the answering side
--testing emits the bundle: types, harness and
the three stubs. --solution emits the
implementation skeleton in Python, C++ or Rust.
A scaffold needs every parameter settled — there is no honest generated type
for an open one. A kernel that pins all its parameters scaffolds fine; one
that says type T: Numeric is refused with E-SPEC-3 and the hint to pick
one, as in type T = i64.
The vocabularies
fherma-lang vocabulary
The closed vocabularies as JSON — scalar types with widths and signedness, value types, class membership — so anything with a type picker asks instead of keeping a copy that goes stale.
As a library
from fherma_lang import parse, emit, reference
declaration = parse(open("sig.fhk").read())
for file in emit(declaration, kind="testing"):
print(file.path, file.generated)
reference(declaration) # "polynomial-multiplication/negacyclic@1.0.0"
reference is what a declaration calls itself, defined in exactly one place
because more than one thing depends on the exact string: it keys the
deterministic stream, and a bundle records it as its own origin.
Exit codes: 0 done · 1 the declaration was rejected · 2 called
wrongly.