Skip to content

hide:

  • toc

Quick reference — Python → TOML → CLI

Each row shows an annotated Python stub, the just-makeit.toml fragment that produces it, and the CLI command that writes that fragment. TOML only means the feature is not reachable from the CLI and must be written by hand, then applied with jm apply (which regenerates the glue files from the manifest).


Object shapes

Python stub TOML CLI
# Scalar in → scalar out
def step(
    self, x: float
) -> float: ...
[comp]
arg_type    = "float"
return_type = "float"
jm object comp \
  --arg-type \
    float \
  --return-type \
    float
# Generator — no input
def step(self) -> complex: ...
[comp]
arg_type    = "void"
return_type = "float _Complex"
mutable     = "true"
jm object comp \
  --arg-type void \
  --return-type \
    "float _Complex" \
  --mutable
# Sink — no output
def step(
    self, x: float
) -> None: ...
[comp]
arg_type    = "float"
return_type = "void"
jm object comp \
  --arg-type \
    float \
  --return-type \
    void
# Buffer step
def step(
    self,
    x: NDArray[np.complex64],
) -> NDArray[np.complex64]: ...
[comp]
arg_type = "float _Complex[]"
jm object comp \
  --arg-type \
    "float _Complex[]"
# Stateful constructor
class Gain:
    def __init__(
        self,
        gain: float = ...,
    ) -> None: ...
[[gain.state]]
name    = "gain"
type    = "double"
default = "1.0"
jm object gain \
  --state \
    gain:double:1.0
# Custom class name
class NCO: ...
[nco]
class_name = "NCO"
jm object nco \
  --class-name NCO

Constructor parameters (--no-state objects)

Python stub TOML CLI
# Scalar with default
def __init__(
    self,
    order: int = 4,
) -> None: ...
[comp]
no_state = "true"

[[comp.init_params]]
name    = "order"
type    = "int"
default = "4"
jm object comp \
  --no-state \
  --init-param order:int:4
# Required array
def __init__(
    self,
    coeff: NDArray[np.complex64],
) -> None: ...
[[comp.init_params]]
name = "coeff"
type = "float _Complex[]"
jm object comp --no-state \
  --init-param \
  "coeff:float _Complex[]"
# Optional 2-D array
def __init__(
    self,
    bank: NDArray[np.float32]
         | None = None,
    rate: float = ...,
) -> None: ...
# bank → fir_create_poly(d0,d1,ptr,rate)
# None → fir_create(rate)
[[comp.init_params]]
name      = "bank"
type      = "float[][]"
optional  = true
create_fn = "fir_create_poly"
jm object comp --no-state \
  --init-param \
    "bank:float[][]:optional:fir_create_poly"
# String-enum choice
from typing import Literal
def __init__(
    self,
    mode: Literal["fast", "hq"]
        = "fast",
) -> None: ...
[[comp.init_params]]
name    = "mode"
type    = "string_enum:fast,hq"
default = "fast"
*TOML only* — add to `just-makeit.toml`, then run `jm apply`.
# Dtype-dispatched array
# int16 → real_create_fn
# other → create_fn
[[comp.init_params]]
name           = "buf"
type           = "float[]"
real_type      = "int16_t"
real_create_fn = "comp_create_i16"
*TOML only*

Methods and functions

Python stub TOML CLI
# Named method
def execute_ctrl(
    self, x: float
) -> float: ...
[[comp.methods]]
name        = "execute_ctrl"
arg_type    = "float"
return_type = "float"
jm method comp execute_ctrl \
  --arg-type \
    float \
  --return-type \
    float
# Variable-length output
def execute(
    self,
    x: NDArray[np.complex64],
) -> NDArray[np.complex64]: ...
[[comp.methods]]
name            = "execute"
variable_output = true
jm method comp execute \
  --variable-output
# Dual output
def execute(
    self,
    x: NDArray[np.uint32],
) -> tuple[
    NDArray[np.uint32],
    NDArray[np.uint8],
]: ...
[[comp.methods]]
name            = "execute"
return_type     = "uint32_t[]"
variable_output = true
multi_output    = ["uint8_t[]"]
jm method comp execute \
  --return-type \
    "uint32_t[]" \
  --variable-output \
  --multi-output \
    "uint8_t[]"
# Struct-list return
def find_peaks(
    self,
    x: NDArray[np.float32],
) -> list[tuple[int, float]]: ...
[[comp.methods]]
name        = "find_peaks"
arg_type    = "float[]"
max_results = 64

[[comp.methods.result_fields]]
name = "index"
type = "size_t"

[[comp.methods.result_fields]]
name = "magnitude"
type = "float"
*TOML only* for field types. Scaffold with `jm method`, then edit `just-makeit.toml` and run `jm apply`.
# Read-only property
@property
def length(self) -> int: ...
[[comp.properties]]
name = "length"
type = "int"
jm property comp length \
  --type \
    int
# Writable property
@property
def gain(self) -> float: ...
@gain.setter
def gain(
    self, value: float
) -> None: ...
[[comp.properties]]
name     = "gain"
type     = "double"
writable = true
jm property comp gain \
  --type \
    double \
  --writable
# Module-level function
def apply(
    x: NDArray[np.float32],
    scale: float,
) -> float: ...
[[module.dsp.functions]]
name        = "apply"
return_type = "float"

[[module.dsp.functions.params]]
name = "x"
type = "float[]"

[[module.dsp.functions.params]]
name = "scale"
type = "float"
jm function apply \
  --module dsp \
  --param "x:float[]" \
  --param "scale:float" \
  --return-type \
    float
# Inline function (header-only)
# same signature; compiler
# can inline at call sites
[[module.dsp.functions]]
name   = "apply"
inline = true
jm function apply \
  --module dsp \
  --inline ...
# Function with array output
def magnitude_db(
    x: NDArray[np.complex64],
    floor: float,
) -> NDArray[np.float32]: ...
[[module.dsp.functions]]
name     = "magnitude_db"
out_type = "float"
jm function magnitude_db \
  --module dsp \
  --param \
    "x:float _Complex[]" \
  --param "floor:float" \
  --return-type void \
  --out-type \
    float
# Path + enum args; raises on failure
def write_header(
    path: str | os.PathLike,
    total: int,
    sample_type: str = "cf32",
    endian: str = "le",
    fs: float = 1e6,
) -> None: ...
# just-makeit.toml — declare the enum first
[[enum]]
name   = "stype"
values = ["cf32", "cf64", "ci32"]

[[module.io.functions]]
name         = "write_header"
return_type  = "int"
check_return = true

[[module.io.functions.params]]
name = "path"
type = "path"

[[module.io.functions.params]]
name = "total"
type = "size_t"

[[module.io.functions.params]]
name    = "sample_type"
type    = "int"
enum    = "stype"
default = "cf32"

[[module.io.functions.params]]
name    = "endian"
type    = "int"
enum    = "endian"
default = "le"

[[module.io.functions.params]]
name    = "fs"
type    = "double"
default = "1e6"
jm function write_header \
  --module io \
  --param path:path \
  --param total:size_t \
  --param \
    sample_type:enum:stype=cf32 \
  --param \
    endian:enum:endian=le \
  --param fs:double=1e6 \
  --return-type int \
  --check-return
# Output length from scalar param
def ciccompmf(
    N: int,
    R: int,
    M: int,
) -> NDArray[np.float64]: ...
[[module.resample.functions]]
name     = "ciccompmf"
out_type = "float64[M]"
*TOML only* — set `out_type` to `"dtype[param]"` after scaffolding, then run `jm apply`.

Advanced

Feature What it does CLI
Lift C body Inject an existing function body into the generated <<IMPLEMENT>> stub --impl path/to/file.c::funcname
Lift line range Inject lines N..M (inclusive, 1-based) instead of a named function body --impl path/to/file.c::12:48
Rename on lift String substitution applied to the extracted body --replace old::new
Custom create() Override generated field assignments in <comp>_create() — add create_impl = """…""" to the object section before any [[comp.state]] entries (uses obj-> for the local pointer) TOML only
Custom reset() Override generated field assignments in <comp>_reset() — add reset_impl = """…""" to the object section before any [[comp.state]] entries (uses state-> for the pointer parameter) TOML only
Custom destroy() Splice teardown into <comp>_destroy() before the trailing free(state) — add destroy_impl = """…""" to the object section before any [[comp.state]] entries (uses state->) TOML only
Opaque state field Declare a pointer/handle struct field with no auto-getter/setter, no kwarg — set opaque = true on a [[comp.state]] entry. Requires create_impl to initialize it (validator enforces). TOML only
Ship a C executable Scaffold main() + CMake target wired to your component jm app --target c
Ship a console script Scaffold argparse CLI in src/<pkg>/cli.py; register in [project.scripts] jm app --target console
Ship a PEP 723 script Scaffold a single .py file runnable with uv run — no install needed jm app --target pep723
Perf annotations Add JM_HOT / JM_FORCEINLINE to every step() just-makeit perf
Reconstruct CLI Print the full command sequence that reproduces the project just-makeit script
Split TOML Move each object section into objects/<name>.toml (objects only; modules stay inline) just-makeit split-objects
Migrate to fragments Move every object and module into objects/<name>.toml / modules/<name>.toml, leaving the manifest with [project] + include globs just-makeit migrate-to-fragments
New with inline manifest Start a fresh project on the legacy single-manifest layout (fragments are the default) jm new <proj> --no-fragments
Generate CI Emit a GitHub Actions / Woodpecker workflow that runs make && make test jm ci [--provider woodpecker]
Apply manifest Regenerate glue (_ext.c, .pyi, CMakeLists.txt) and refresh _core.h declarations from the TOML; _core.c and the inline step() body stay yours, untouched just-makeit apply
Regenerate component Delete every file a component owns and rebuild from the manifest — the deliberate refresh that does overwrite the sacred _core.c. Manifest is left intact (git stash first) just-makeit regenerate <comp>
Dry run Show what would be compiled without building just-makeit dry-run
Extra link libs Link a module against an additional library not owned by jm — add extra_link_libs = ["mylib", "m"] under [module.X] TOML only
Extra types Register a hand-written CPython type from a *_extra.c file in PyInit_ — add extra_types = ["MyType"] under [module.X] TOML only