dust/README.md

174 lines
7.1 KiB
Markdown
Raw Normal View History

2023-08-22 15:40:50 +00:00
# Dust
2024-01-30 04:18:09 +00:00
!!! Dust is an experimental project under active development. !!!
2023-11-18 01:46:18 +00:00
Dust is a general purpose programming language that emphasises concurrency and correctness.
2023-08-22 15:40:50 +00:00
A basic dust program:
```dust
2023-12-30 03:53:32 +00:00
output("Hello world!")
2023-08-22 15:40:50 +00:00
```
2023-08-23 04:38:51 +00:00
Dust can do two (or more) things at the same time with effortless concurrency:
2023-08-22 15:40:50 +00:00
```dust
2023-10-17 01:13:58 +00:00
async {
2023-12-30 03:53:32 +00:00
output('will this one finish first?')
output('or will this one?')
2023-10-17 01:13:58 +00:00
}
2023-10-06 02:07:54 +00:00
```
2024-01-30 04:18:09 +00:00
You can use Dust to run complex operations simply and safely, you can even invoke other programs, run them at the same time, capture their output, and pipe them together.
2023-11-18 01:46:18 +00:00
```dust
2024-01-30 04:18:09 +00:00
# Run each statment in this block in its own thread.
async {
# Invoke another program and capture its output.
ip_info = ^ip address;
# Pipe the output to another program.
^ls -1 --all --long docs/ | ^rg .md | ^echo;
# This block is not async and the statements will be run in order.
{
file = fs:read_file('Cargo.toml')
2024-01-30 04:21:54 +00:00
# This loop will run each iteration in its own thread. If one of them
# reaches a "break" statement, they will all stop.
async for line in str:lines(file) {
2024-01-30 04:18:09 +00:00
if str:contains(line, 'author') {
output(line)
break
}
}
}
2023-11-18 01:46:18 +00:00
}
```
2023-11-27 15:27:44 +00:00
Dust is an interpreted, strictly typed language with first class functions. It emphasises concurrency by allowing any group of statements to be executed in parallel. Dust includes built-in tooling to import and export data in a variety of formats, including JSON, TOML, YAML and CSV.
2023-10-13 15:37:07 +00:00
2023-08-23 21:28:19 +00:00
<!--toc:start-->
- [Dust](#dust)
- [Features](#features)
- [Usage](#usage)
2024-01-30 02:32:56 +00:00
- [Dust Language](#dust-language)
2023-08-23 21:28:19 +00:00
- [Installation](#installation)
2023-11-16 03:33:58 +00:00
- [Benchmarks](#benchmarks)
- [Implementation](#implementation)
2023-12-30 03:53:32 +00:00
- [Acknowledgements](#acknowledgements)
2023-08-23 21:28:19 +00:00
<!--toc:end-->
2023-08-22 15:40:50 +00:00
## Features
2023-10-13 15:37:07 +00:00
- Simplicity: Dust is designed to be easy to learn.
2023-11-27 15:27:44 +00:00
- Speed: Dust is built on [Tree Sitter] and [Rust] to prioritize performance and correctness. See [Benchmarks] below.
2023-12-27 04:30:33 +00:00
- Concurrency: Safe, effortless parallel code using thread pools.
2023-11-27 15:27:44 +00:00
- Safety: Written in safe, stable Rust.
2023-12-02 05:16:00 +00:00
- Correctness: Type checking makes it easy to write good code.
2023-08-22 15:40:50 +00:00
2024-01-30 04:18:09 +00:00
## Installation
You must have the default rust toolchain installed and up-to-date. Install [rustup] if it is not already installed. Run `cargo install dust-lang` then run `dust` to start the interactive shell.
To build from source, clone the repository and build the parser. To do so, enter the `tree-sitter-dust` directory and run `tree-sitter-generate`. In the project root, run `cargo run` to start the shell. To see other command line options, use `cargo run -- --help`.
2023-08-22 15:40:50 +00:00
## Usage
2024-01-30 04:18:09 +00:00
After installation, the command line interpreter can be given source code to run or it can launch the command-line shell.
2023-08-22 15:40:50 +00:00
2023-12-27 04:30:33 +00:00
```sh
cargo install dust-lang
2023-12-30 03:53:32 +00:00
dust -c "output('Hello world!')"
2024-01-30 04:18:09 +00:00
# Output: Hello world!
2023-12-30 03:53:32 +00:00
```
2024-01-30 04:18:09 +00:00
Run `dust --help` to see the available commands and options.
2023-12-30 03:53:32 +00:00
```txt
General purpose programming language
Usage: dust [OPTIONS] [PATH]
Arguments:
[PATH] Location of the file to run
Options:
-c, --command <COMMAND> Dust source code to evaluate
-i, --input <INPUT> Data to assign to the "input" variable
-p, --input-path <INPUT_PATH> A path to file whose contents will be assigned to the "input" variable
-t, --tree Show the syntax tree
-h, --help Print help
-V, --version Print version
2023-08-28 22:05:49 +00:00
```
2024-01-30 02:32:56 +00:00
## Dust Language
2024-01-30 04:18:09 +00:00
See the [Language Reference](/docs/language.md) for more information.
2023-08-23 21:28:19 +00:00
2023-11-16 03:33:58 +00:00
## Benchmarks
2024-01-30 04:18:09 +00:00
Dust is at an early development stage and these tests are overly simple. Better benchmarks are needed to get a realistic idea of how Dust performs real work. For now, these tests are just for fun.
The examples given were tested using [Hyperfine] on a single-core cloud instance with 1024 MB RAM. Each test was run 1000 times. The test script is shown below. Each test asks the program to read a JSON file and count the objects. Dust is a command line shell, programming language and data manipulation tool so three appropriate targets were chosen for comparison: nushell, NodeJS and jq. The programs produced identical output with the exception that NodeJS printed in color.
2023-11-16 03:33:58 +00:00
For the first test, a file with four entries was used.
| Command | Mean [ms] | Min [ms] | Max [ms]
|:---|---:|---:|---:|
| Dust | 3.1 ± 0.5 | 2.4 | 8.4 |
| jq | 33.7 ± 2.2 | 30.0 | 61.8 |
| NodeJS | 226.4 ± 13.1 | 197.6 | 346.2 |
| Nushell | 51.6 ± 3.7 | 45.4 | 104.3 |
2023-11-16 03:33:58 +00:00
The second set of data is from the GitHub API, it consists of 100 commits from the jq GitHub repo.
| Command | Mean [ms] | Min [ms] | Max [ms] |
|:---|---:|---:|---:|
| Dust | 6.8 ± 0.6 | 5.7 | 12.0 | 2.20 ± 0.40 |
| jq | 43.3 ± 3.6 | 37.6 | 81.6 | 13.95 ± 2.49 |
| NodeJS | 224.9 ± 12.3 | 194.8 | 298.5 |
| Nushell | 59.2 ± 5.7 | 49.7 | 125.0 | 19.11 ± 3.55 |
2023-11-16 03:33:58 +00:00
This data came from CERN, it is a massive file of 100,000 entries.
| Command | Mean [ms] | Min [ms] | Max [ms] |
|:---|---:|---:|---:|
| Dust | 1080.8 ± 38.7 | 975.3 | 1326.6 |
| jq | 1305.3 ± 64.3 | 1159.7 | 1925.1 |
| NodeJS | 1850.5 ± 72.5 | 1641.9 | 2395.1 |
| Nushell | 1850.5 ± 86.2 | 1625.5 | 2400.7 |
2023-11-16 03:33:58 +00:00
The tests were run after 5 warmup runs and the cache was cleared before each run.
```sh
hyperfine \
--shell none \
--warmup 5 \
--prepare "rm -rf /root/.cache" \
--runs 1000 \
--parameter-list data_path seaCreatures.json,jq_data.json,dielectron.json \
--export-markdown test_output.md \
"dust -c '(length (from_json input))' -p {data_path}" \
"jq 'length' {data_path}" \
"node --eval \"require('node:fs').readFile('{data_path}',(err,data)=>{console.log(JSON.parse(data).length)})\"" \
"nu -c 'open {data_path} | length'"
```
## Implementation
Dust is formally defined as a Tree Sitter grammar in the tree-sitter-dust directory. Tree sitter generates a parser, written in C, from a set of rules defined in JavaScript. Dust itself is a rust binary that calls the C parser using FFI.
Tests are written in three places: in the Rust library, in Dust as examples and in the Tree Sitter test format. Generally, features are added by implementing and testing the syntax in the tree-sitter-dust repository, then writing library tests to evaluate the new syntax. Implementation tests run the Dust files in the "examples" directory and should be used to demonstrate and verify that features work together.
Tree Sitter generates a concrete syntax tree, which Dust traverses to create an abstract syntax tree that can run the Dust code. The CST generation is an extra step but it allows easy testing of the parser, defining the language in one file and makes the syntax easy to modify and expand. Because it uses Tree Sitter, developer-friendly features like syntax highlighting and code navigation are already available in any text editor that supports Tree Sitter.
2023-12-30 03:53:32 +00:00
## Acknowledgements
Dust began as a fork of [evalexpr]. Some of the original code is still in place but the project has dramatically changed and no longer uses any of its parsing or interpreting.
2023-10-22 19:52:33 +00:00
[Tree Sitter]: https://tree-sitter.github.io/tree-sitter/
[Rust]: https://rust-lang.org
2023-08-22 15:40:50 +00:00
[evalexpr]: https://github.com/ISibboI/evalexpr
2023-08-28 14:18:55 +00:00
[rustup]: https://rustup.rs
[Hyperfine]: https://github.com/sharkdp/hyperfine