Skip to content

z1-0/nix-ast

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

123 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nix-ast

A Nix library that parses, inspects, transforms, and evaluates Nix Abstract Syntax Trees (AST) using Haskell's hnix parser.

nix-ast exposes a full Nix AST API directly in Nix itself (via IFD, Import From Derivation) and uses hnix's Haskell parser and evaluator internally. You can parse any Nix expression into a structured AST, traverse and transform it with pure Nix functions, render it back to source code, and even evaluate it. All from within your Nix expressions.


Features

Feature Description
Parse Parse any Nix expression (file, string, or stdin) into a structured, typed AST
Render Convert an AST back to formatted, importable Nix code
Eval Evaluate ASTs using hnix's evaluator and get the results as JSON values
toAST Convert native Nix values (ints, strings, lists, attrsets) to AST nodes (pure, no IFD)
fromAST Convert an AST back to a native Nix value, the inverse of toAST (pure, no IFD)
Pattern Matching Type-safe tag-based dispatch with match ast { Tag = handler; _ = fallback; }
Traversal Recursive transform, rewrite, universe, children/rebuild, and contexts
Type-checked Constructors All mk* builders validate argument types at runtime with descriptive error messages
CLI Tool nix-ast eval / nix-ast parse / nix-ast render for shell/pipe workflows

Quick Start

Using the Nix Library (Flake)

Add nix-ast to your flake inputs:

inputs.nix-ast.url = "github:z1-0/nix-ast";

The library exposes three main API groups via inputs.nix-ast.lib:

API Description
lib.parse lib.render lib.eval IFD-based: bridge to hnix's parser/evaluator
lib.toAST lib.fromAST Pure Nix: convert between Nix values and ASTs
lib.match lib.syntax lib.traversal Work with AST nodes after construction
# Parse -> Transform -> Render
asts = lib.parse pkgs [./config.nix];
transformed = lib.traversal.transform (node: ...) (builtins.head asts);
outPaths = lib.render pkgs [transformed];
config = import (builtins.head outPaths);

# Parse -> Evaluate (skip rendering)
result = lib.eval pkgs asts;

CLI

# Parse from expression string
nix-ast parse --expr '{ x = 1; }' > ast.json

# Parse files from stdin (one path per line)
echo ./config.nix | nix-ast parse > ast.json

# Render AST back to Nix
nix-ast render --json '{"tag":"Set","recursive":false,"bindings":[...]}'

# Render batch to output directory
nix-ast render < asts.json --out-dir ./out

# Evaluate AST using hnix
nix-ast eval --json '{"tag":"Constant","contents":{"tag":"Int","contents":42}}'

# Pipe workflow: parse -> eval
nix-ast parse --expr '{ x = 1 + 2; }' | nix-ast eval

Architecture

┌─────────────────────────────────────────────────────────┐
│                     Nix (your flake)                     │
│                                                         │
│  lib.parse   lib.render   lib.eval                      │
│       │           │           │                         │
│       ▼           ▼           ▼                         │
│  ┌──────────────────────────────┐                       │
│  │  IFD: nix-ast CLI (Haskell)  │  <- hnix parser/eval  │
│  └──────────────────────────────┘                       │
│                                                         │
│  lib.toAST  lib.fromAST  (pure Nix, no IFD)             │
│  lib.match  lib.syntax  lib.traversal                   │
└─────────────────────────────────────────────────────────┘

parse/render/eval go through Haskell via IFD. toAST/fromAST/match/syntax/traversal run in pure Nix on the AST values.

Installation

# Run directly without installing
nix run github:z1-0/nix-ast -- parse --expr '{ x = 1; }'

# Or add to your flake inputs
inputs.nix-ast.url = "github:z1-0/nix-ast";

Binary Cache

Use the Cachix cache to skip building from source.

nix.settings = {
  substituters = [ "https://z1-0.cachix.org" ];
  trusted-public-keys = [ "z1-0.cachix.org-1:FS7lPgL0StRBOPrlu0RgdCL7LafUI23+U6Iivdw5QK8=" ];
};

Learn more

  • API Reference: parse, render, eval, construct, match, and traverse AST nodes
  • AST Reference: every node type with fields, JSON representation, and examples
    • Expr: 19 expression constructors
    • Atom: primitive constants (Bool, Int, Float, Null, Uri)
    • Binding: Inherit, NamedVar
    • KeyName: StaticKey, DynamicKey
    • Params: Param, ParamSet
    • String: DoubleQuoted, Indented
    • Antiquoted: Plain, Antiquoted, EscapedNewline
  • CLI Reference: nix-ast eval / nix-ast parse / nix-ast render

License

BSD-3-Clause: see LICENSE for details.

Releases

Packages

Contributors

Languages