Compilers

FPy provides a number of compilers from FPy to other languages.

class fpy2.Backend

Bases: object

Base class for FPy backends.

class fpy2.FPCoreCompiler(*, unsafe_int_cast: bool = False)

Bases: Backend

Compiler from FPy to FPCore.

Mirrors the cpp backend’s Module-driven structure: compile_module is the canonical entry point, and compile is a thin wrapper around a one-entry module. Unlike cpp, fpc does not specialize — FPCore references callees by name (UnknownOperator) rather than inlining or per-call-site monomorphization.

compile(func: Function, ctx: Context | None = None) FPCore

Compile a single Function to an FPCore. Thin wrapper that builds a one-entry module and routes through compile_module() — so single-function and module paths share one pipeline.

compile_module(module: Module) dict[str, FPCore]

Compile a Module to one FPCore per public entry, keyed by export name.

Normalization passes (ConstFold, ForUnpack, ForBundling, WhileBundling, IfBundling) run on every function in the module via Module.map(), so cross-function calls keep referring to consistently-normalized callees. No specialization is performed: FPCore semantics reference callees by name. An entry’s ctx is currently a no-op (TODO); arg_types cannot be expressed in FPCore and is ignored.

unsafe_int_cast: bool

any unrounded integer is automatically compiled under an integer context

class fpy2.CppCompiler(*, unsafe_cast_int: bool = True, optimize: bool = True)

Bases: Backend

Format-inference-driven C++ compiler.

The pipeline runs all pre-analyses and assigns each SSA def to a C++ variable; the emitter then walks the AST and produces source.

Parameters:
  • unsafe_cast_int – When True (default), allow rounded arithmetic under an unbounded-integer context (MPFixedContext(nmin=-1) / fpy2.INTEGER); the compiler compiles these by emitting casts to the widest built-in integer type (currently int64_t) and assuming no overflow occurs. Set False to reject such programs at compile time.

  • optimize

    When True (default), apply optimizing program transformations to each FuncDef before the rest of the pipeline runs:

    • fpy2.transform.ZipElim (pre-monomorphize): skips materializing intermediate std::vector<std::tuple<...>>``s for ``zip iterables.

    • fpy2.transform.RoundElim (post-monomorphize): hoists eliminable rounded operations into with fp.REAL: blocks so the cpp emitter’s lossless-widening dispatch can pick tighter storage for them.

    The pipeline is sound either way. Set False to compile the surface AST verbatim.

compile(func: Function, *, ctx: Context | None = None, arg_types: Collection[Type | None] | None = None) str

Compile func to a C++ source-code string.

Thin wrapper around compile_module() over a one-entry module, so the single-function and module paths share one pipeline.

Parameters:
  • func – The Function to compile.

  • ctx – Optional rounding context to monomorphize against.

  • arg_types – Optional per-argument types to monomorphize against.

compile_module(module: Module) str

Compile a Module to a single C++ translation unit.

Pipeline:
  1. Pre-spec optimizations (ZipElim) on every function in the module via map.

  2. Specialize the module: each (FuncDef, ctx, arg_fmts) becomes one entry; cross-function calls rewire to the appropriate spec.

  3. Post-spec optimizations (RoundElim) on each spec — monomorphic format inference is now available.

  4. Per-spec codegen, leaves-first, one C++ definition per entry.

headers() list[str]

C++ headers required by every emitted unit.

helpers() str

Runtime helper definitions emitted alongside compiled functions. Currently empty — cpp doesn’t yet need custom runtime support beyond <cmath> / std::vector.

prelude() str

Convenience: the headers and helpers concatenated as a single source-ready string. Equivalent to '\n'.join(self.headers()) + '\n' + self.helpers().