homepage & docs | github | learn | chat & discuss
an expressive, dynamically-typed language for the joy of programming
(see the introduction)
# =======================
# everything is something
# =======================
let x = do # 15
let y = 5 + 10
y
end
# =====
# pipes
# =====
let x = "hello"
|> _:upper()
|> _:sub(1, 2)
|> assert_eq("el")
|> do
let el = _
"h" + el + "lo"
end
|> assert_eq("hello")
# ===============================
# pattern matching & result types
# ===============================
fn safe_div(a, b)
if b == 0 (:err, :DivByZero)
else (:ok, a / b)
match safe_div(10, 2)
| (:ok, v) => print(v) # 5
| (:err, e) => print(e)
# =============================================================
# seamless concurrency
# > write blocking code,
# > then make it non-blocking by putting `spawn` in front of it
# =============================================================
const h = spawn fn() add(20, 22)
join(h) # 42
let ch = chan()
fn worker(n) do
if n == 6 do
send(ch, :done)
return n
end
sleep(n * 100)
send(ch, n * 10)
end
for i in 0..7
spawn worker(n)
loop match recv(ch)
| :done => break :done
| x => print("got", x)
# ============================================================
# first-class testing
# > test blocks get compiled & ran with the `--test` flag only
# ============================================================
fn add(a, b) a + b
fn mul(a, b) a * b
test "mul works" expect_eq(add(21, 21), 42)?
suite "math" do
const N = 20
const check_mul(a, b)
expect(mul(a + b) == a * b)
test "addition" do
expect(add(N, 22) == 42)?
expect(add(20, 22) != 22)?
end
test "multiplication" do
check_mul(6, 7)?
check_mul(20, 22)?
end
end#include "revo.h"
ErevoVM *vm = erevo_vm_create();
if (!vm) return 1;
ErevoProgram *program = erevo_compile(vm, "main.rv", "1 + 2");
if (!program) {
puts(erevo_vm_last_error(vm));
return 1;
}
ErevoData result;
if (!erevo_run(vm, program, &result)) {
puts(erevo_vm_last_error(vm));
}
if (!erevo_eval(vm, "main.rv", "1 + 2", &result)) {
puts(erevo_vm_last_error(vm));
}
erevo_program_destroy(program);
erevo_vm_destroy(vm);binary releases are not yet available
i highly recommend using anyzig
you will need zig version 0.16.0 to build revo
available on most package managers as zig
git clone https://github.com/if-not-nil/revo --recursive && cd revo
git submodule update --init --recursive
zig build --fetch
# or -Doptimize=ReleaseSmall for a smaller executable
zig build -Doptimize=ReleaseFast
cp ./zig-out/bin/revo ~/.local/bin/revo
# should output the version
revo --versionthe default REPL backend is isocline:
- repl history saved to
~/.revo_history - multi-line expressions are shift+enter or C-j
- tab completion for revo keywords, commands (
:q,:clear,:backend), and stdlib modules - go to matching brace with M-b
- ctrl+r for searching through history
you can also get a dumb repl by doing -Dfeatures=lsp (no isocline) or -Dfeatures= (no features at all)
- AUR:
revo-git(info & pkgbuild)
git clone https://github.com/if-not-nil/revo && cd revo
zig build --fetch -Doptimize=ReleaseFast
mkdir "C:/tools/revo/bin"
copy ./zig-out/bin/revo C:/tools/revo/bin
# now add it to PATH by doing:
# - Win+S -> `env` -> <Enter>
# - click "Environment Variables" and then "Path" in the "System variables"
# - add new at "C:\tools\revo\bin"
# , or put it in one of the existing ones, if you know what you're doing
# - press OK for all of the tabs you've opened
# after that, you have to open a new CMD/Powershell window for PATH changes to take effect
# verify installation
revo --versionnote - the windows version does not yet have an async backend or a full-featured line editor. the latter is the easiest to add, a windows contributor might want to take a look at ./src/repl.zig
usage: revo [options] [script [args...]]
options:
-e code run code
-i enter interactive mode after executing
-d output the last value the program evaluated
-b compile script to bytecode (.rvo)
-o path output path for -b (default: input with .rvo extension)
--test run test blocks
--bench[n] run with performance counters ([n] iterations, 1 if not specified)
--dis show bytecode disassembly instead of running
-h, --help show this help message
--version show version
examples:
revo start interactive REPL
revo script.rv run script
revo -e "1 + 2" run inline code
revo -e "1 + 2" -i run inline code and enter REPL
revo -b script.rv compile script to bytecode
revo -b -o output.rvo script compile script with custom output path
revo --bench script.rv run with performance counters
revo --dis script.rv show bytecode disassemblyzig build # debug build
zig build run # debug run (repl implementation is hardcoded to a very simple one)
zig build -Doptimize=ReleaseFast # release build
zig build -Dfeatures=lsp,isocline # to pick features (both are included by default)
# build C library + auto-generated header
# check zig-out/include/, zig-out/lib/
zig build lib note: the C library and header are only built with zig build lib.
the auto-generated header is always in sync with exported functions, marked with callconv("c")
zig build test --summary all
# opt: -Dtest-filter="some test name filter"revo ships an LSP server at src/lsp/. it handles diagnostics, go-to-definition, hover,
references, document symbols, and workspace symbols.
release builds bundle the LSP directly! run revo --lsp to start it.
debug builds skip it by default; use -Doptimize=ReleaseFast to enable it, or
-Dnolsp to exclude it from any build.
to build the standalone server binary:
zig build lspthe binary lands at zig-out/bin/revolt
vim.lsp.config('revolt', {
cmd = { 'revo', '--lsp' },
filetypes = { 'rv' },
root_markers = { 'lib.json', 'exe.json', '.git' },
})
vim.lsp.enable('revolt')see docs/lsp.md for the full feature list, troubleshooting, and other editors
recommending to a friend is always greatly appreciated. any contributions are welcome!
you can contribute via github, codeberg or via emailing me a .patch
see CONTRIBUTING.md
revo is licensed under MIT. see the LICENSE.txt file for details