coil

coil is a statically typed scripting language with type inference. Programs are compiled to bytecode and executed on a custom virtual machine. Source files use the .hy extension (short for henry, the SI unit of inductance — the measure of a coil); compiled archives are stored as .hyc files.

For developers who want a small typed scripting language with more structure than a typical script, and a bytecode runtime they can keep thin.

The language targets embeddable scripting: you get real type checking and inference without a heavyweight build pipeline, plus optional FFI for calling into C libraries or host-provided Rust closures.

Quick start#

Download the toolkit for your OS. When a GitHub Release exists, use GitHub Releases (latest). There is no tagged release yet. Until then, the current build is the latest release-binaries workflow on main (binaries-<triple> artifacts, 30-day retention). See Getting Started.

use io::{stdout};
use io::sync::{write_all};
use string::{to_bytes};
fn main() {
    write_all(stdout(), to_bytes("hello"));
}

With coil on your PATH, from a clone of the repository with coil-stdlib cloned beside it:

coil --root ../coil-stdlib/src examples/print_literal.hy

Expected output: hello

How programs run#

Parse → typecheck → typed HIR (inlining, optimization passes) → stack IL + MIR tiers / lower/fuse-select → bytecode → VM executes main. coil <file.hy> compiles in memory on every run; coil compile writes a versioned .hyc archive (packed major.minor) that coil run executes. Full stage notes: Internals — Pipeline.

Language at a glance#

AreaStatus
Primitivesint, float, string, bool, byte
Functions, let / const, if/else, while / forSupported
Named call-site arguments (f(name: v))Supported (positional prefix then named; named holes on partials allowed)
Arity / type overloads / first-class fn values / lambdas (use)Supported (examples/overload.hy, type_overload.hy, fn_value.hy, lambda.hy)
Rest parameters (T... xs / tuple ... xs)Supported (trailing only; T... packs to Vec<T>, bare ... packs to a tuple)
Call-site spread (f(...pack))Supported (tuple, [T; N], and Vec<T> operands)
User-defined attr decoratorsSupported (attr decl + #[name(...)] on fn, methods, class constructors)
Let destructuring (let (a, b) = …, let { x, y } = …)Supported (tuple / record; no enum ctor patterns in let)
break / continueSupported
Enums, match, record variants, scalar #[repr]Supported (Enum::Variant; catch-all is default =>)
Built-in Option / Result, raise, ?, ??, ?.Supported (desugar to match/return)
Tuples, fixed arrays ([T; N] / len), Vec<T>, records { x: 1 }Supported
Type aliases (type Name = T;, lexically scoped)Supported
Generics and traitsSupported: generic functions/enums/aliases/classes, higher-kinded type parameters, associated types/GATs, existentials, coherence checks
Modules / namespaces (use, mod)Supported (multi-file CLI via --root; spool reads coil.toml)
Field access (p.x, chained p.x.y)Supported
FFI (extern blocks, dload/declare/invoke, C varargs ..., struct/callback returns)Supported (requires libffi)
IO streams (use io::{…};, Vec<byte>, files, sync adapters, TCP, UDP)Supported (non-blocking L0)
Classes (class / impl / new, fields, methods)Supported
Coroutines (gen fn, yield, resume, yield from, done)Supported
for x in (Iterator / IntoIterator)Supported (arrays, homogeneous tuples, ranges, coroutines, user impls)
Integer arithmetic+ - * / % ** and unary - on int panic on overflow in every build; float is IEEE. Wrapping / checked / saturating helpers are the userland arith module
Effects and capabilities (pure fn, uses {…}, --allow-*)Supported (effects, permissions)
Contracts (requires, ensures, invariant, decreases)Supported; coil verify proves them with an SMT solver (contracts)
Tasks (task::scope, spawn, join, channels) and OS threadsSupported (tasks, threads)
Ranges (a..b / a..=b)Supported — lazy Range<T: Ord>; for / .to_vec() step int/byte/float; non-numeric Ord is a type error (syntax)
String concat via +Supported (string + string → string)
string::format(...)Supported compiler intrinsic (returns string; literal specifiers are checked)

Browse runnable demos in Examples. Multi-file showcase apps (todo board, text adventure, TCP echo) live under examples/projects/.

Documentation#

Docs are split into three trees:

TreeAudienceStart here
ManualLearnersGetting started, tutorial chapters 01–16, examples catalog
ReferencesLookupSyntax, types, keywords, per-API builtin pages
InternalsContributors / embeddersPipeline, debug info, opcodes, grammar

Manual (tutorial)#

ChapterTopic
Getting startedInstall, first program, spool projects
01 — BasicsRunning files, functions, let, control flow
02 — Types and variablesNumbers, strings, bools, conversions, constants
03 — CollectionsArrays, Vec, tuples, HashMap, ranges
04 — ClassesFields, methods, new, derives
05 — Enums and matchCases with data, match, Option, if let
06 — Error handlingResult, ?, ??, panics
07 — Traits and genericsGeneric functions and types, traits, impl
08 — ClosuresLambdas, captures, functions as values
09 — ModulesFiles as modules, use, mod, packages
10 — Files and IOReading and writing files, streams, stdin
11 — Testingcoil test, assertions, test files
12 — Generatorsgen fn, yield, resume, yield from
13 — Taskstask::scope, channels, timeouts, a TCP server
14 — Threadsspawn, join, channels, mutexes
15 — MacrosFunction-style macros, attribute macros, derives
16 — Calling Cextern blocks, dload, permission flags
Examples catalogRunnable demos in examples/ (see catalog for expected output)
Showcase projectsMulti-file apps + co-located tests
Userland stdlibcoil-stdlib: consume, modules, IO adapters

Full API index: Reference.

Repository layout#

coil/
├── common/          # Shared types: opcodes, values, archive format
├── parser/          # Pratt parser and AST
├── compiler/        # Typechecker, HIR optimizations, stack IL / MIR lowering, pipeline
├── machine/         # VM, heap/GC, FFI (libffi)
├── coil-*/          # CLI helpers: test, fmt, lsp, debug, dissect, verify, embed
├── examples/        # Runnable .hy demos (see manual/examples.md)
│   └── projects/    # Showcase multi-file apps + co-located tests
├── docs/internals/  # Pipeline, VM notes, grammar (user docs live on this site)
└── src/main.rs      # CLI: default build+run, compile, run, test

Running#

CommandRole
(no subcommand) <file.hy>Compile in memory → run (no out.hyc)
compile <file.hy> [-o path]Compile entry file to a .hyc archive
run <file.hyc>Execute a compiled archive
package <file.hy> [-o path] [--check-native]Single executable (embeds .hyc into coil-embed by default)
test [path] [--fail-fast]Compile+run all [path]/**/*.hy (default ./tests); continue after failures unless --fail-fast
lspStart the Coil language server over stdin/stdout

For FFI examples you also need libffi (e.g. libffi-dev on Debian/Ubuntu, libffi on Arch). To build from a checkout, see Getting Started.

Learn by example#

GoalStart with
First programgetting-started.md → examples/fib.hy
Enums & pattern matchingexamples/option.hy, examples/result.hy
Record-shaped variantsexamples/record.hy, examples/mixed.hy
Dicts / anonymous recordsexamples/dict.hy
Generics & traitsexamples/generics.hy, examples/hkt_bifunctor.hy, examples/gat_pointer.hy, examples/existential_show.hy
Modulesexamples/modules.hy (see examples.md for setup)
FFIexamples/ffi_extern.hy, examples/ffi_sum.hy, examples/ffi_varargs.hy
IO streamsexamples/io_bytes.hy, examples/io_file.hy, examples/io_eof.hy, examples/io_udp.hy
Coroutinesexamples/coro.hy, examples/coro_gen.hy, examples/coro_send.hy, examples/for_in_coro.hy
Full catalogexamples.md

Source for the language is ardax-corp/coil-lang. Internals stay in that repository.

↑ ↓ navigate ↵ open