Skip to content
LogoLogo

Comptime

Evaluate deterministic code and produce types during compilation

VibeLang uses compile-time execution for work that the compiler can prove depends only on compiler-known inputs. The imported comptime(...) compiler intrinsic requires evaluation and reports an error when the work cannot be completed during the build. It is ordinary call syntax, not a language keyword.

Automatic Evaluation

The compiler may evaluate ordinary code when every input is known and evaluation is useful:

const kibibyte = 1024
const bufferSize = kibibyte * 64

You do not need to mark routine constant folding.

Required Evaluation

Import comptime when the result must exist during compilation:

import { comptime } from "vibelang:comptime"
 
const routes = comptime(parseRoutes(embed("./routes.json")))

If parseRoutes depends on a runtime value or unavailable capability, compilation fails at that expression instead of moving the work silently to runtime.

The compiler recognizes the imported binding, not the word comptime. Aliasing the import works; a project function that happens to have the same name is still an ordinary function.

Passing a function marks and returns a compile-time function. It does not call the function immediately:

const parseRoutesAtBuild = comptime(parseRoutes)
const routes = parseRoutesAtBuild(embed("./routes.json"))

Use an ordinary immediate call when a multi-statement compile-time block is convenient:

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

Generating Types

Comptime values can produce types:

import { comptime } from "vibelang:comptime"
 
const definition = comptime(JSON.parse(embed("./api.json")))
const Api = comptime(deriveApi(definition))

Api is a type-valued compile-time binding and is a normal checked type everywhere it is used. Generated declarations participate in editor tooling and diagnostics.

This removes the usual split between a code generator, its output files, and the build step that must remember to refresh them.

Target Selection

comptime.target describes the selected output environment:

import { comptime } from "vibelang:comptime"
 
const transports = {
  browser: BrowserTransport,
  node: NodeTransport,
  bun: BunTransport,
  deno: DenoTransport,
  edge: FetchTransport,
  native: NativeTransport,
  wasm: WasiTransport,
}
 
const defaultTransport = comptime(transports[comptime.target])

Branches for other targets are removed from the artifact. Their implementations do not need to be loadable at runtime.

Compiler-Known Inputs

Comptime can read source assets through tracked imports and embedding APIs:

import { comptime } from "vibelang:comptime"
import query from "./find-user.sql" with { type: "text" }
 
const plan = comptime(optimize(query))

The compiler records the asset, loader implementation, options, target, and transitive inputs in its incremental graph.

Hermetic Execution

Comptime code cannot observe ambient runtime state:

  • no undeclared filesystem access
  • no network access
  • no process environment
  • no wall clock
  • no randomness
  • no mutable host globals

A loader receives a compiler-owned context for importing additional assets. Those reads become dependency edges automatically.

Hermetic does not mean isolated from all input. It means every input is declared, stable, and available to the build graph.

Comptime and Runtime Code

The same function may be callable in both phases when its operations are valid in both:

import { comptime } from "vibelang:comptime"
 
function slugify(value: string): string {
  return value.trim().toLowerCase().replaceAll(" ", "-")
}
 
const slugifyAtBuild = comptime(slugify)
const route = slugifyAtBuild("Account Settings")
const userSlug = slugify(form.name)

Phase-specific capabilities are checked. A function that needs HttpClient cannot run at comptime unless a comptime-safe implementation and declared input model exist.

Incremental Builds

Comptime results are content-addressed. A result is conceptually keyed by the compiler version, evaluated code, options, target, source assets, and transitive dependency hashes.

Changing one input invalidates its dependent cone. Touching a file without changing its content does not need to invalidate the result.

Common Uses

Comptime is the shared foundation for:

  • deriving validators and codecs
  • producing types from JSON or schemas
  • compiling Markdown, MDX, SQL, and GraphQL
  • generating Zig and Rust bindings
  • selecting platform implementations
  • supplying compiler-known values captured by durable Flows

Durable Flow lowering is a separate compiler pass initiated by durable(...); it does not execute a Flow through the comptime evaluator.

Each feature uses the same deterministic evaluator and dependency graph instead of inventing a separate code-generation system.