Compile-Time Evaluation
Compile-Time Evaluation (SPEC-043)
Section titled “Compile-Time Evaluation (SPEC-043)”Janus provides first-class compile-time evaluation primitives. Code marked comptime executes during compilation — the results are baked into the binary as constants. No runtime cost.
Design principle: The
$meta-sigil makes compiler-phase operations visually distinct from runtime functions. You always know what runs when.
Comptime Blocks
Section titled “Comptime Blocks”Execute a block of statements at compile time:
comptime do let table = build_lookup_table(256)endFor single expressions:
const SIZE = comptime { calculate_optimal_size(PAGE_SIZE) }The $ Meta-Sigil
Section titled “The $ Meta-Sigil”All compiler builtins use the $ prefix. This is not decoration — it signals “this executes in the compiler, not in your binary.”
:core Builtins (Available Everywhere)
Section titled “:core Builtins (Available Everywhere)”| Builtin | Signature | Purpose |
|---|---|---|
$size_of | $size_of(Type) -> i64 | Size of a type in bytes |
$align_of | $align_of(Type) -> i64 | Alignment requirement |
$is_integral | $is_integral(Type) -> bool | True for integer types |
$is_float | $is_float(Type) -> bool | True for floating-point types |
$fmt | $fmt(args...) -> string | Comptime string construction |
$compile_error | $compile_error(msg) -> never | Halt compilation with message |
:service Builtins (Type Introspection)
Section titled “:service Builtins (Type Introspection)”| Builtin | Signature | Purpose |
|---|---|---|
$type_info | $type_info(Type) -> TypeInfo | Full type metadata |
$type_name | $type_name(Type) -> string | Human-readable type name |
$type_id | $type_id(Type) -> u64 | Stable hash identifier |
$fields | $fields(Type) -> []string | List of field names |
$has_field | $has_field(Type, name) -> bool | Check field existence |
$has_decl | $has_decl(Type, name) -> bool | Check declaration existence |
$field_type | $field_type(Type, name) -> string | Type of a named field |
$field | $field(value, name) -> T | Access field by name |
Comptime Parameters
Section titled “Comptime Parameters”Functions can require arguments to be known at compile time:
func make_array(comptime N: usize, fill: i64) [N]i64 do var result: [N]i64 = undefined inline for 0..N |i| do result[i] = fill end return resultend
// N is resolved at compile time -- the loop is fully unrolledconst arr = make_array(4, 0)Inline Control Flow
Section titled “Inline Control Flow”inline for
Section titled “inline for”Unrolls the loop body at compile time. Each iteration becomes straight-line code in the binary:
inline for fields |name| do println(name)endinline switch
Section titled “inline switch”Evaluates the discriminant at compile time and emits only the matching branch:
inline switch $type_info(T).kind { .Int => handle_int(), .Float => handle_float(), _ => $compile_error("unsupported type"),}if comptime
Section titled “if comptime”Conditional compilation — dead branches are eliminated entirely:
if comptime $is_integral(T) do // This code only exists in the binary when T is an integer type optimized_int_path()else generic_path()endProfile Capability Matrix
Section titled “Profile Capability Matrix”Comptime features are progressively disclosed through profiles:
| Capability | :core | :service | :sovereign |
|---|---|---|---|
comptime do...end blocks | Yes | Yes | Yes |
comptime parameters | Yes | Yes | Yes |
$size_of, $align_of | Yes | Yes | Yes |
$is_integral, $is_float | Yes | Yes | Yes |
$fmt, $compile_error | Yes | Yes | Yes |
$type_info, $type_name | — | Yes | Yes |
$type_id, $fields | — | Yes | Yes |
$has_field, $has_decl | — | Yes | Yes |
| Comptime allocation | — | — | Yes |
Resource Limits
Section titled “Resource Limits”The comptime evaluator enforces hard limits to prevent runaway compilation:
| Resource | Limit |
|---|---|
| Evaluation steps | 1,000,000 |
| Memory | 256 MB |
| Recursion depth | 1,000 |
Exceeding any limit produces a clear compile-time error — not a hang or crash.
Arithmetic Safety
Section titled “Arithmetic Safety”Comptime arithmetic uses checked operations. Integer overflow, negative shifts, and out-of-range shift amounts produce compile-time errors — not silent wrapping. This aligns with Janus’s Syntactic Honesty doctrine: if the math is wrong, the compiler tells you.
// Compile error: IntegerOverflowconst bad = comptime { 9223372036854775807 + 1 }
// Compile error: IntegerOverflow (shift amount out of range)const also_bad = comptime { 1 << -1 }Practical Example: Lookup Table Generation
Section titled “Practical Example: Lookup Table Generation”func hex_char(nibble: u4) u8 do const table = comptime do var t: [16]u8 = undefined inline for 0..10 |i| do t[i] = '0' + i end inline for 0..6 |i| do t[10 + i] = 'a' + i end t end return table[nibble]endThe lookup table is computed once during compilation. At runtime, hex_char is a single array index.
Next: Profiles System — understand how comptime capabilities scale across profiles.