Skip to content

Const and Comptime

Use const for values that should be known before the program runs: fixed sizes, feature flags, target facts, and reusable configuration. Use comptime { ... } to evaluate a block before runtime. To select a module by target, bind an import expression through an alias.

Write a constant with an explicit type:

const Int page_size = 4096;
const Bool tracing_enabled = false;

A const initializer can use literals, other const declarations, enum cases, tuple/array/struct literals, default struct constructors, field access, unary and binary operators, if, block tail expressions, ordinary Jiang function calls, custom init, and generic function or struct constructor calls when every value involved is known at compile time.

Const initializers cannot depend on runtime values and cannot perform runtime side effects such as I/O.

public const makes a compile-time value available to other modules. This is useful for shared configuration and target descriptions:

public enum Os {
    macos,
    linux,
    unsupported,
}

public struct TargetInfo {
    public Os os;
    public Bool link_libc;
}

public const TargetInfo target = TargetInfo(os = .macos, link_libc = true);

Importers access the value through the module namespace:

alias cfg = import "config.jiang";

Bool uses_libc() {
    cfg.target.link_libc
}

Importers use the value like any other public module member. A public const may be a scalar, enum case, tuple, array, or struct value, and fields on a public const struct can be read directly.

The build package provides compile-time facts about the current build target:

import build;

const Bool native_libc = build.target.link_libc;

build.target has fields such as os, arch, abi, and link_libc. Use it in constants, ordinary expressions, or comptime conditions when code needs to adapt to the selected target.

A comptime block returns its result and has its own lexical scope. Its local bindings do not become module declarations. Conditional imports bind the selected namespace through an alias; the alias initializer is evaluated at compile time:

import build;

alias provider = if (build.target.os == .macos) {
    import "os/macos.jiang"
} else {
    import "os/other.jiang"
};

The condition must be a compile-time Bool; only the selected import joins the dependency closure. Unselected branches still need valid syntax. Compile-time calls use ordinary functions when their operations are supported by compile-time evaluation; there is no separate comptime function marker.

Const generic parameters let a declaration receive a compile-time value:

struct StaticCount<N: const Int> {
    Int value;
}

Int const_value<N: const Int>() {
    N
}

The parameter name is a value-level name. It can appear in expressions where a compile-time value is required; it is not a type name.

@where(N: const Int) is the canonical constraint form. The inline N: const Int spelling lowers to the same predicate.

String interpolation and formatting traits are planned for a later release.