RUNTIME VALUE CONVERSIONS

Runtime conversion and C use

Runtime value conversion generates C11 routines for Python values that are created, shared, and changed while the generated program runs.

Select runtime conversion

Use a source bundle containing one document and choose Transpile → Transpile Runtime Values. The terminal equivalent is:

pycforge convert input.py --runtime-values --output generated.c

For the Python API, use the complete runtime request options shown in Runtime value requests. Runtime conversion uses its own C value representation and does not provide exact ForgeLens mappings or the typed converter's C-IR validation.

Organize the source

Place functions and classes at module level, with at least one top-level function. Module docstrings are accepted. Put changing data and initialization inside functions. Imports, module assignments, nested def or class statements, decorators, and writable globals are unsupported. Use lambdas for closures.

def greeting(name: str) -> str:
    return "Hello, " + name + "!"

def main() -> int:
    print(greeting("café"))
    return 0

This program prints Hello, café! when compiled and run externally.

Values and built-in calls

FormSupported use
None, bool, int, float, strScalar values, compatible arithmetic/comparisons, and truth tests.
len(value)Strings, lists, tuples, and ranges.
bool(value), bool()Truth conversion for admitted runtime values; the empty call returns False.
int(value, base), float(value)Numeric and string conversions. The optional int base is 0 or 2–36 and also accepts a keyword. Empty int/float calls return zero.
str(value), str()Strings, integers, finite floats, Booleans, and None. The empty call returns an empty string. Direct container/object formatting is unsupported.
list(value), tuple(value)Convert a supported string, list, tuple, or range. An omitted argument creates an empty container, like [] or ().
range(stop), range(start, stop, step)Integer ranges, including a calculated nonzero step. Values are generated as needed during iteration.
print(value, ...)Strings, integers, finite floats, Booleans, and None. Optional sep and end keywords accept strings or None. Direct printing of containers or objects, and file/flush options, are unsupported.

Numeric operations

Integers use checked signed 64-bit arithmetic. Overflow and division by zero report runtime errors. Integer // and % follow Python's floor and remainder rules. True division / produces a binary64 floating result. Floating operations require finite binary64 values; floating floor division and remainder are unsupported. Power and bitwise operators are outside the supported expression set.

Convert numeric text

def main() -> int:
    print(int("1_250"), int("ff", base=16), int("0b101", 0))
    print(float("  -1.25e2  "), float("١.٥"))
    print(str(1.5), str(-0.0), str(1e20))
    return 0

Integer parsing accepts an optional sign, surrounding numeric whitespace, Unicode decimal digits, valid underscore separators, and prefixes consistent with the selected base. Base 0 detects 0b, 0o, or 0x; a nonzero decimal value with a leading zero is invalid in that form. An explicit base requires a string. Values must fit signed 64-bit integers.

Float parsing accepts finite decimal text, optional exponent/sign, surrounding numeric whitespace, Unicode decimal digits, and underscores between digits. Invalid text and embedded NULs fail. NaN, infinity, hexadecimal float text, and non-finite results are outside the numeric domain. Underflow may produce a subnormal or signed zero.

Float-to-string conversion uses a shortest round-trip representation with Python's fixed/scientific notation rules, including -0.0. Integer conversion truncates a finite float toward zero and checks the int64 range. The generated C caller must keep a numeric locale whose decimal point is .; decimal parsing reports an error if the host selects a different separator.

Branches and loops

Use if/elif/else, while, and for over strings, lists, tuples, or ranges. break, continue, and loop else follow the usual Python rules: else runs after normal exhaustion, including zero iterations, and is skipped by break.

Conditional expressions, chained comparisons, and short-circuit and/or preserve evaluation order and return the selected operand. Assign locals before reading them; a loop may leave its target unassigned if it never runs. Comprehensions have their own scope, described in List comprehensions.

Call generated functions from C

Generated values use the PV type. A zero-initialized PC context owns all allocations. Create a function value with pv_top_function using its generated symbol from the conversion summary. This initializes module definitions and their defaults once in the context. Call it through pv_call with a positional argument count and PV array; optional parameters may be omitted. For keywords, pv_call_kw additionally takes a keyword count, name array, and value array. Use pv_i for integer arguments and pv_string for UTF-8 bytes with an explicit byte length.

Use the same context for connected calls, shared lists, objects, and closures. Check context.error after each call; context.error_line identifies the reported Python statement. On failure, discard the result. Always finish with pv_destroy(&context), including after an error.

Returned values and captured variables remain valid until their context is destroyed. Do not free individual values, use them afterward, move them to another context, or share one context concurrently between threads. Intermediate allocations remain in the context until destruction, so divide long-running work into independent bounded contexts.

Build a standalone program

If the source defines a main() callable without arguments, including one whose parameters all have defaults, an external C build can enable the supplied entry wrapper. For the example above, with a compatible 64-bit GCC toolchain:

gcc -std=c11 -DPYCF_RUNTIME_MAIN generated.c -o greeting -lm
./greeting

Integer returns from 0 to 255 become process exit statuses; other integers map to 255, and None maps to 0. A runtime failure prints its error and exits with status 1. Other return types are invalid for this wrapper.

The emitted program requires a 64-bit host with binary64 double. It includes its value routines and does not require Python, PySide6, NumPy, Numba, or Ting to run. PyCForge itself only emits C; external building and execution are your separate steps.

Memory and work limits

The default context limit is 64 MiB of allocations, one million counted loop/materialization/type-check steps, and 128 call levels. These are workload limits, not a wall-clock timer. PYCF_RUNTIME_BYTES and PYCF_RUNTIME_STEPS may be configured by the external C build. See Conversion and input limits for source limits and failure handling.