A reasonable configuration language https://rcl-lang.org
Find a file
Ruud van Asseldonk 6f746f3f8c Add some more ideas
I was thinking today about how the | operator is way briefer than
writing a comprehension in a collection, but writing the comprehension
is nice to format and | is awkward. Also when writing down the type of
the | operator ... it's a challenge (also to typecheck it).

Perhaps, adding a spread/unpack operator will resolve both issues. It
would be slightly more verbose, but not terribly so. And I believe it
would be more readable too.
2024-01-30 23:57:38 +01:00
docs Fix typo in documentation 2024-01-30 23:44:31 +01:00
etc Add String.replace builtin method 2024-01-30 21:22:44 +01:00
examples Finish first draft of the tutorial 2023-12-05 01:01:39 +01:00
fuzz Implement basic evaluator for type expressions 2024-01-30 21:34:56 +01:00
golden Add goldens to seed fuzz corpus for types 2024-01-30 22:14:19 +01:00
ideas Add some more ideas 2024-01-30 23:57:38 +01:00
src Delete unused Default impl for Env 2024-01-30 21:34:56 +01:00
tools Prepend fuzz header from seed_fuzz_corpus.py 2023-12-17 22:38:52 +01:00
.gitignore Add Python venv shell hook 2023-09-24 19:16:53 +02:00
.gitmodules Add basic initial documentation 2023-08-13 21:31:17 +02:00
Cargo.lock Add pretty reporting of errors 2023-08-08 22:20:20 +02:00
Cargo.toml Strip release binary by default 2023-08-28 23:01:58 +02:00
CONTRIBUTING.md Add public repository boilerplate 2023-08-10 17:23:35 +02:00
flake.lock Pin Nixpkgs to a version with Rust 1.70 2023-10-03 21:54:04 +02:00
flake.nix Verify in flake check that examples are executable 2023-10-20 20:58:31 +02:00
LICENSE License the project under the Apache 2.0 license 2023-08-06 00:38:51 +02:00
mkdocs.yml Document the new type system 2024-01-30 22:14:19 +01:00
README.md Manage expectations a bit in the docs 2024-01-30 22:14:19 +01:00
rust-toolchain.toml Pin the toolchain 2023-08-01 23:34:12 +02:00

Ruuds Configuration Language

Ruuds Configuration Language, RCL for short, is a domain-specific language optimized for specifying human-written data with just enough abstraction features to avoid repetition. It is a superset of json that extends it into a simple functional programming language that resembles Python and Nix. Use cases include:

  • Querying json documents, like jq, but with a more familiar language.
  • Generating repetitive configuration files, such as GitHub Actions workflows or Terraform configuration.
  • Enabling large repositories to split configuration into small reusable pieces that can be referenced from a single consistent entry point, in the same way that Nix enables this for Nixpkgs.

Warning

While RCL is usable, it is still in an early exploratory stage with frequent breaking changes. This is a hobby project without stability promise.

Getting started

See the manual for more information. The most useful chapters to get started:

You may also find the examples in the examples directory instructive.

Rationale

Why another config language?

  • HCL is too ad-hoc to be suitable for any serious abstraction (setunion is variadic so it only works with a statically known number of sets; flatten recursively flattens so it cant be typed properly and breaks generic code, for comprehensions cant do nested loops, for_each syntax is bolted on, etc.)

  • Nix-the-language is great but forces the entire Nix store on you when all I want is to evaluate expressions.

  • Python is great but requires some boilerplate for doing the IO if you want to use it as a configuration language. Also the syntactic order of list comprehensions prevents autocomplete in editors.

  • Dhall has the right ideas but the syntax and heavy use of Unicode symbols make it look ugly.

  • CUE and Nickel were not invented here.

Classification

  • Purely functional: RCL consists of expressions and has no statements. It has immutable values and no mutable objects. Functions are values.

  • Gradually typed: Optional type annotations can be used to prevent bugs and to make code more self-documenting. All type annotations are enforced.

  • Vaporware, not fully implemented: RCL is a superset of json.

Usage

Build:

cargo build --release

Print usage:

target/release/rcl
target/release/rcl eval --help

Evaluate an RCL expression to json:

target/release/rcl eval examples/tags.rcl

Query an RCL or json document:

target/release/rcl query examples/tags.rcl input.tags.ams01

Autoformat an RCL expression (non-destructive, prints to stdout):

target/release/rcl fmt examples/tags.rcl

Highlight an RCL expression in your terminal:

target/release/rcl highlight examples/tags.rcl

Development

Run all tests and checks below in one command:

nix flake check

Run golden tests:

cargo build
golden/run.py

Check the grammar for ambiguities:

bison -Werror=all src/grammar.y

Run unit tests and lints:

cargo test
cargo clippy

Typecheck Python sources

mypy --strict .

Check formatting:

cargo fmt
black .

View coverage of the golden tests:

nix build .#coverage --out-link result
xdg-open result/index.html

Run the fuzzer:

cargo +nightly-2023-06-03 fuzz run main -- -dict=fuzz/dictionary.txt

License

RCL is licensed under the Apache 2.0 license. It may be used in free software as well as closed-source applications, both for commercial and non-commercial use under the conditions given in the license. If you want to use RCL in your GPLv2-licensed software, you can add an exception to your copyright notice. Please do not open an issue if you disagree with the choice of license.