Skip to content
LogoLogo

Comptime

Normative model for deterministic phase evaluation

Status: phase evaluation, the compiler-recognized API, type generation, and tracked input requirements are locked. Loader API details and module shapes are open.

Compiler-Recognized API

Comptime MUST use ordinary TypeScript call syntax rather than a VibeLang keyword:

import { comptime } from "vibelang:comptime"

The compiler MUST recognize the resolved imported binding, not the local identifier text. Aliasing the import MUST preserve its meaning, and an unrelated function named comptime MUST remain an ordinary function.

comptime(value) MUST require its argument expression to be evaluated during compilation and MUST replace the call with the resulting value or generated artifact.

When the argument is a function, comptime(functionValue) MUST return a compile-time function; it MUST NOT invoke the function merely because it was passed to comptime. Every call of that function MUST be evaluated during compilation. An immediately called compile-time block therefore uses ordinary call syntax:

const routes = comptime(() => {
  const source = embed("./routes.json")
  return parseRoutes(source)
})()

The vibelang:comptime specifier is a compiler-owned virtual module. The compiler MUST erase or lower recognized imports and calls. Uncompiled JavaScript execution MUST fail during virtual-module loading rather than provide a fallback that could evaluate comptime(...) arguments at runtime.

Evaluation Principle

The compiler MAY evaluate code automatically when its inputs and operations are available at compile time.

An explicit comptime(...) call MUST be evaluated during compilation. Compilation MUST fail if the value or any call of a compile-time function cannot be evaluated under the comptime rules.

Comptime evaluation MUST NOT silently defer explicit work to runtime.

Types as Values

Comptime code MAY consume and produce types. A generated type MUST participate in ordinary checking, declarations, diagnostics, and editor behavior.

The language MUST NOT require a separate runtime type declaration modifier.

Determinism

Comptime evaluation MUST be hermetic and deterministic with respect to its declared inputs.

It MUST NOT observe ambient:

  • filesystem state
  • network state
  • environment variables
  • process state
  • wall clock
  • randomness
  • mutable host state

An equivalent value MAY enter through a compiler-owned, dependency-tracked input API.

Comptime I/O

Compiler-known imports and embedding MUST be supported. The compiler MUST record every such asset as an incremental dependency.

Arbitrary unavailable runtime I/O MUST NOT be performed merely because a call occurs beneath comptime.

Target Selection

The imported comptime binding MUST expose a typed target value as comptime.target.

A target-selected branch resolved at comptime MUST NOT emit unselected runtime code. Target-dependent loaders and derived artifacts MUST include the target in their cache identity.

Asset Loaders

VibeLang MUST support comptime loaders for non-code assets.

A loader MUST:

  1. receive immutable compiler-owned source text or bytes
  2. declare transitive inputs through a tracked context
  3. produce a checked typed module or equivalent checked representation
  4. preserve source spans for diagnostics
  5. participate in incremental caching

A loader MUST NOT use ambient filesystem, network, clock, random, or process access.

Built-In Formats

The toolchain MUST include loaders for JSON, Markdown, and MDX.

VibeLang's const JSON form MUST preserve literal values recursively and expose a deeply readonly type. Existing TypeScript JSON imports MUST retain TypeScript semantics.

Non-code inputs MUST select their loader and mode with standard import attributes. Const JSON MUST use the shape:

import config from "./config.json" with { type: "json", mode: "const" }

Text, bytes, Markdown, MDX, custom formats, and foreign source modules MUST use the same attribute mechanism with an appropriate type string.

Markdown and MDX MUST preserve source locations. Their standard export shapes, JSX runtime selection, component injection, and frontmatter typing are open.

Incremental Identity

A comptime or loader cache key MUST include every semantically relevant input. At minimum this includes:

  • compiler version
  • implementation graph and package resolution
  • configuration and target
  • direct source bytes
  • transitive dependency hashes

File modification time alone SHOULD NOT invalidate content whose semantic key is unchanged.

Resource Limits

A compiler MAY limit comptime CPU, memory, recursion, and output size. Limit failures MUST produce deterministic diagnostics and MUST NOT fall back silently to runtime behavior.