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.