Rúnar

Compiler Configuration

The Runar compiler can be configured through the programmatic API, CLI flags, or a project-level configuration file. This page documents all available options and how they affect compilation.

Programmatic API: CompileOptions

When using the compiler as a library via runar-compiler, you pass a CompileOptions object to the compile() function:

import { compile } from 'runar-compiler';

const result = compile(sourceCode, {
  fileName: 'P2PKH.ts',
  constructorArgs: { pubKeyHash: '0x89abcdef...' },
});

Available Options

OptionTypeDefaultDescription
fileNamestring"contract.ts"Source file name. Used in diagnostics and source maps. The file extension determines the parser (.ts, .go, .rs, .py).
parseOnlybooleanfalseStop after the parse pass. Returns only the ContractNode AST.
validateOnlybooleanfalseStop after the validate pass. Returns the AST and validation diagnostics.
typecheckOnlybooleanfalseStop after the type-check pass. Returns the AST with type annotations.
constructorArgsRecord<string, bigint | boolean | string>undefinedConstructor arguments to bake into the compiled script. When provided, the emitter replaces OP_0 placeholders with actual values.
disableConstantFoldingbooleanfalseWhen true, disables the constant folder optimization. Constant folding is enabled by default.

Early Exit Options

The parseOnly, validateOnly, and typecheckOnly options cause the compiler to stop at progressively later stages. This is useful for tooling (IDE integrations, linters) and debugging.

// Parse only -- get the AST for syntax analysis
const parseResult = compile(source, { parseOnly: true });
console.log(parseResult.contract); // ContractNode | null
console.log(parseResult.errors);   // CompilerDiagnostic[]

// Validate only -- check structural rules
const validateResult = compile(source, { validateOnly: true });
console.log(validateResult.errors);   // CompilerDiagnostic[]
console.log(validateResult.warnings); // CompilerDiagnostic[]

// Typecheck only -- verify types without lowering
const typecheckResult = compile(source, { typecheckOnly: true });
console.log(typecheckResult.errors); // CompilerDiagnostic[]

When none of these flags are set, the compiler runs all six passes and produces the full output.

Constructor Arguments

Constructor arguments can be provided at compile time to produce a fully resolved script (no placeholders):

const result = compile(source, {
  constructorArgs: {
    pubKeyHash: '89abcdef01234567890abcdef01234567890abcd',
  },
});

// result.scriptHex is the final script with pubKeyHash embedded
// No OP_0 placeholders remain

If constructorArgs is not provided, the compiled script contains OP_0 placeholders at the positions where constructor arguments should be inserted. The SDK fills these in at deployment time.

Individual Pass Functions

In addition to the unified compile() function, the compiler exports each pass as a standalone function for fine-grained control:

import { parse, validate, typecheck, lowerToANF } from 'runar-compiler';

// Step through passes manually
const parseResult = parse(source, 'Counter.ts');
const validationResult = validate(parseResult.contract);
const typecheckResult = typecheck(validationResult);
const anfProgram = lowerToANF(typecheckResult.typedContract);

Function Signatures

parse(source: string, fileName?: string): ParseResult
// ParseResult: { contract: ContractNode | null; errors: CompilerDiagnostic[] }

validate(contract: ContractNode): ValidationResult
// ValidationResult: { errors: CompilerDiagnostic[]; warnings: CompilerDiagnostic[] }

typecheck(contract: ContractNode): TypeCheckResult
// TypeCheckResult: { typedContract: ContractNode; errors: CompilerDiagnostic[] }

lowerToANF(contract: ContractNode): ANFProgram
// ANFProgram: { contractName: string; properties: ANFProperty[]; methods: ANFMethod[] }

These functions are useful when building custom tooling on top of the Runar compiler, such as IDE plugins, documentation generators, or alternative backends.

CLI Configuration

The runar compile command exposes compiler options as command-line flags.

Basic Usage

runar compile <files...> [options]

The <files...> argument accepts one or more source files or glob patterns:

# Single file
runar compile contracts/P2PKH.runar.ts

# Multiple files
runar compile contracts/P2PKH.runar.ts contracts/Counter.runar.ts

# Glob pattern
runar compile contracts/*.runar.ts

CLI Flags

FlagDescription
--output <dir>Output directory for compiled artifacts. Defaults to ./artifacts.
--irInclude the ANF intermediate representation in the artifact JSON. Useful for debugging and cross-compiler verification.
--asmPrint assembly to stdout (ASM is always included in the artifact).
--disable-constant-foldingDisable the constant folder optimization (enabled by default).

Examples

# Compile with full debug output
runar compile contracts/P2PKH.runar.ts --output ./artifacts --ir --asm

# Compile with constant folding disabled
runar compile contracts/Counter.runar.ts --disable-constant-folding --output ./build

Exit Codes

CodeMeaning
0Compilation succeeded
1Any compilation failure (parse error, validation error, type error, or internal error)

Diagnostics are printed to stderr. The compiled artifact (if any) is written to the output directory.

Optimizer Settings

The compiler includes three optimizer passes. Here is how to control them.

Peephole Optimizer

The peephole optimizer is always enabled and cannot be disabled. It applies safe, mechanical transformations to the Stack IR that reduce script size without changing behavior. These transformations are well-tested and have no tradeoffs.

ANF EC Optimizer

The ANF EC optimizer is enabled by default for contracts that use elliptic curve operations. It applies algebraic simplification rules specific to secp256k1. If your contract does not use EC operations, this optimizer has no effect.

Constant Folder

The constant folder is enabled by default. Disable it with disableConstantFolding: true in the API or --disable-constant-folding on the CLI.

The constant folder evaluates expressions with all-literal arguments at compile time. For example:

// Before constant folding:
let hash = sha256(0x68656c6c6f);

// After constant folding:
let hash = 0x2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824;

Why might you disable it? Constant folding changes the script bytes, which changes the script hash, which changes the contract address. In audit and verification contexts, this can be confusing — the auditor expects to see the sha256 call in the script, not a precomputed constant. Disable constant folding with disableConstantFolding: true or --disable-constant-folding when you need the unfolded script for auditing.

What’s Next