Skip to content

if-not-nil/revo

Repository files navigation

`revo, the programming language

homepage & docs | github | learn | chat & discuss

an expressive, dynamically-typed language for the joy of programming

written in Zig version 0.0.0

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")
  |> fn(c)

# ===============================
# 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

simple embedding api

#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);

installing

binary releases are not yet available

you will need the latest stable version of zig to build revo (0.16.0 at the moment)

available on most package managers as zig

on posix (linux/bsd/mac)

git clone https://github.com/if-not-nil/revo --recursive && cd revo
git submodule update --init --recursive
# or -Doptimize=ReleaseSmall for a smaller executable
zig build --fetch -Doptimize=ReleaseFast
cp ./zig-out/bin/revo ~/.local/bin/revo

# should output the version
revo --version

repl

the 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)

packaging:

windows

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 --version

note - 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

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 disassembly

development

building

zig 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")

running tests

zig build test --summary all 
# opt: -Dtest-filter="some test name filter"

revolt (the language server)

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 lsp

the binary lands at zig-out/bin/revolt

neovim setup

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

contributing

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

credits

license

revo is licensed under MIT. see the LICENSE.txt file for details

About

a dynamic language for the joy of programming

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages