FUNCTIONS AND SOURCE FILES

Functions and module variables

Add every source file needed by your program. The typed and runtime modes have separate rules for constants, calls, and imports.

The first sections describe typed conversion. For runtime imports, skip to Runtime modules. Select Transpile → Typed, then click Transpile, or use the default CLI/API request. For runtime strings, shared containers, classes, and closures, see Runtime value conversions.

Variables outside functions

BASE: int = 4
EARLIER = BASE
BASE += 3
PREFIX = "hé" + "llo"

def score(text: str) -> int:
    total = BASE + EARLIER
    if text.startswith(PREFIX):
        total += len(text)
    return total

score("héllo") returns 16; score("other") returns 11.

Module assignments are processed in source order: EARLIER is 4, and the function sees the final BASE value of 7. Supported values are int, float, bool, and str, including earlier constants, numeric constant expressions, and the constant string operations.

These values become constants in the C output. They are not writable shared global state. A module assignment cannot call your functions, read a file, or depend on an external Python environment. global and nonlocal writes are unsupported. Declare a module value before referring to it, and avoid names already used by functions, imports, or scalar built-ins.

Include all required files

The workspace converts its open modules together. Through the Python API, supply the source files in a SourceBundle. PyCForge does not search installed packages or read imported files automatically.

Calling your functions

def combine(left: int, *, right: int) -> int:
    return left + right

def use(value: int) -> int:
    return combine(value, right=2)

use(5) returns 7.

You can pass positional arguments, explicit keyword arguments, and required keyword-only arguments. Arguments must match the declared parameter types. Expressions are evaluated once in source order.

Supply every required argument. Default values, *args, **kwargs, argument unpacking, function-valued variables, recursive calls, and arbitrary object methods are unsupported. The string methods documented in String operations are supported separately.

Importing functions from another included file

# math_tools.py — module name: math_tools
def double(value: int) -> int:
    return value * 2

# main.py — module name: main
from math_tools import double

def run(value: int) -> int:
    return double(value)

Add both files before converting. Use from module_name import function_name; an unambiguous as alias is also supported. Plain import module, relative imports, star imports, imports inside functions, and circular imports are unsupported. Importing module constants or record classes is not supported in typed conversion.

Saving the result

The files produce one combined C output. Changing any included file makes the previous output stale. Convert the complete set again before saving.

Runtime modules

Select Transpile → Runtime and open every required file. Use exact module names from the workspace document list. Up to 64 documents produce one C file. Constants-only and empty companion files are accepted; the bundle needs at least one top-level function.

FormRuntime behavior
import prices, import prices as pBind a module value. Read its declared members with p.total or p.LABEL.
from prices import total, LABEL as TITLE, ItemImport functions, immutable constants, or classes. Re-exports preserve the original value's identity.
import shop.prices as pResolve the exact supplied module ID. Dotted imports require an alias; no parent package is created or initialized.
RATE = 2.5, BOUNDS = (1, 10)Immutable scalar/tuple constants, with optional annotations and expressions over declared constants. Assign each module name once.

Save the following as main.py with module name main:

import prices as p
from prices import LABEL

def main() -> int:
    amounts = [p.total(value) for value in (1, 2, 3)]
    print(LABEL, amounts)
    print("Total: {:.2f}".format(sum(amounts)))
    return 0

Save this companion as prices.py with module name prices:

RATE: float = 2.5
LABEL = "Invoice"

def total(value, rate=RATE):
    return round(value * rate, 2)

Open both documents and transpile. When externally compiled and run, the program prints:

Invoice [2.5, 5.0, 7.5]
Total: 15.00

The CLI equivalent supplies each companion explicitly:

pycforge convert main.py --runtime-values --module prices=prices.py --output invoice.c
gcc -std=c11 -DPYCF_RUNTIME_MAIN invoice.c -lm -o invoice

Repeat --module ID=PATH for more files. --module-id ID sets the primary module ID (default: main). Paths may be quoted when they contain spaces. Use SourceBundle with request_options() through the Python API.

Initialization and shared values

Each context initializes its primary module first. At each import statement it initializes the dependency once before binding the imported names. Definitions and constants are processed in source order; defaults can call previously defined converted functions. After the primary, any remaining supplied modules initialize in module-name order. All supplied companions are roots, including unused ones, so their definition-time defaults also run.

A function always reads globals from its own module. Same-named functions/classes in different files stay distinct. Importing or re-exporting a function preserves its shared mutable defaults; importing a class preserves class identity and supports class annotations. Lists, dictionaries, instances, and callbacks can pass between modules. Separate contexts have independent initialization and defaults.

Imports may appear between definitions and constants. A name read before its definition/import reports an error. The optional standalone wrapper uses the primary module's defined or imported main. Runtime errors record the logical source filename as well as the line.

Module limits

Every file must be supplied explicitly; imports never search the filesystem or installed Python packages. Relative/star/local/conditional imports, cyclic imports, automatic submodule lookup, and package initialization are unsupported. A repeated binding name is rejected, including a repeated import under the same name. Use distinct aliases when needed.

Module constants may contain None, Booleans, checked integers, finite floats, strings, and nested immutable tuples. Calls and mutable containers are not constant initializers. General executable module statements, writable globals, rebinding module names, module introspection, and assigning module attributes are unsupported. Ordinary function bodies retain the runtime features documented elsewhere.