⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⡶⢦⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡔⢫⣮⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⡰⠑⠌⠄⡀⡆⠀⠀⠀⠀⠀⠀⠀⠀⢠⡞⣕⣱⣛⡻⠻⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⣧⠐⠃⡀⢃⡙⡀⠀⠀⠀⠀⠀⠀⡰⣫⡞⢩⡞⠁⡀⠀⣟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢹⣦⠁⡐⠠⠹⣄⠀⠀⠀⠀⠀⡔⢵⡟⠠⠋⡄⠀⠀⡘⠸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⡀⡇⢢⠀⠘⣇⠀⠀⠀⣰⡫⣻⠀⠀⡸⠀⠀⢘⡒⢼⠠⠒⠚⠻⡍⠋⠛⠒⣶⢤⣀⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⡿⠡⡱⡙⢄⠌⢆⠀⢠⠟⡏⢸⡆⠀⠇⠀⣠⣪⠖⣿⠀⠀⠀⡆⠀⠀⠀⠀⠀⠅⢀⡙⢋⠙⠲⡦⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢻⡆⠃⠼⡀⡄⣞⠄⣼⣾⣯⠢⣏⣰⠀⡰⣻⠅⣸⡿⠀⠀⡰⠀⣴⠁⢠⠂⡘⠐⠀⠀⠀⠀⠀⠀⠈⠲⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡆⠄⡖⠅⢳⠎⢹⣿⣿⡾⡢⢻⣾⡸⢠⠇⠤⢫⣧⣇⡖⣷⡺⡫⡆⣡⠎⢀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠶⣄⡀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢾⢦⠃⠀⢃⣾⡛⢿⢻⠇⡨⣻⣷⣏⣠⠊⠍⡼⣿⡇⡘⢀⡕⡱⠀⡠⠂⣈⠔⢁⠔⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣢⡀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⡶⢀⠄⠔⠀⠘⢻⣧⡟⠇⠘⠳⢨⡟⠁⠠⠊⣸⣿⡏⣰⡧⠛⠀⣤⠏⣠⠞⠁⠔⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⢣⡄⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⢏⡐⠋⡰⢁⠞⡀⣼⠺⣧⡎⡔⠀⠈⠉⠀⠀⣰⡿⣿⣷⣿⣧⡾⢾⢛⣍⠌⣠⣤⡠⠄⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠱⡄⠀
⠀⠀⠀⠀⠀⢀⣠⣾⢫⢯⣿⢴⣽⣷⢆⣼⠟⡗⡀⡠⠟⠀⢀⠄⠀⠀⠀⣹⣾⣿⢏⣾⣩⣷⣟⣋⡞⠖⠋⠀⠀⠀⠂⠀⠐⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢱⡀
⠀⠀⠀⠀⢠⡞⣣⣿⢣⣫⡿⣽⠎⢢⠿⢃⠎⠈⡁⠊⠀⡨⠃⠀⠠⢀⡨⠛⣩⣷⣷⠿⣫⡱⠟⠃⠀⠀⣀⡀⠄⠠⠤⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠓
⠀⠀⠀⢰⡏⣰⢃⠃⣼⡿⣿⠋⠀⠀⠀⠁⠀⠀⠀⢀⠜⠀⠠⠖⠂⠁⠀⠀⠘⣹⣿⡉⠋⣡⠔⠀⠀⠀⡀⠀⠀⠒⠐⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⣸⢴⢳⢹⣧⡟⠁⠃⢀⣔⣶⣦⡤⠀⠈⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⢀⣳⣿⠛⠒⠓⢀⠀⡀⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⢠⡿⢸⣿⡖⣇⣇⠀⢴⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⢯⣾⠟⠃⠀⠔⠁⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⣾⢁⣟⣷⣇⠻⠉⢇⠘⠯⣿⣿⡿⠛⠀⠀⠀⠀⣀⠀⠀⠀⠀⠀⢀⠼⣗⡊⠉⠉⣄⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⢸⡿⢟⣟⠫⢏⡆⠀⠨⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣷⡞⠶⠶⠟⠛⠄⠐⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⢸⣷⣹⠐⠁⠀⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠞⠀⠌⠐⠑⠦⠀⠀⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠈⢾⣿⣿⣴⣤⣧⡶⣦⣤⠐⠂⠤⠄⠀⠄⠀⠀⠀⠀⠀⠀⢀⡋⠉⠉⢤⣌⣈⠢⠀⠠⠤⢤⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠘⣿⣿⣿⣿⣾⣷⣯⢧⠼⡢⠐⠂⠀⠀⠀⠀⠀⠀⠀⢠⠀⠀⠀⠰⠦⣿⠁⠒⠗⣤⡀⠀⢢⡀⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⠀⠀⠀⠀⠀⠀
⠀⠀⠈⣿⣿⣆⣻⡿⣹⡀⣦⡚⢦⠁⠁⠀⠀⢠⠀⠐⠀⢐⠀⠀⠈⠂⢄⠙⢧⡍⠑⠠⡉⣷⣤⡠⢭⣆⠱⣕⡖⠂⠀⠀⠀⠀⠀⣤⣿⣷⡯⢍⡓⣤⠀⠀⠀⠀
⠀⠀⠀⡘⠫⠝⠿⣿⣜⣧⣰⢎⢄⢡⠀⠐⠂⠀⠀⠀⠄⠠⢀⠦⣀⡐⠳⣦⣈⡌⣗⣄⣿⣮⡿⣿⡷⢿⢷⠕⡤⢧⡀⠀⠀⠀⣶⣿⣯⣈⡇⢷⠨⣢⡁⣦⡀⠀
⠀⠀⠈⠀⠀⠀⠀⠀⠉⣧⣧⢥⣡⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢩⠏⠻⣮⡹⠦⣵⣼⣿⣿⣿⢿⡜⢾⣜⣦⣿⡜⢿⠢⢵⣤⣷⣿⣿⣏⠻⠿⠦⣄⣟⠁⠀⠈⢁
⠀⠀⠀⠀⠀⠰⠀⠀⠘⠛⠛⠚⠛⣳⣶⣶⣄⠀⠢⡀⠠⠀⢠⠀⢀⢰⣿⣌⣧⣿⡿⠿⠟⠉⠖⢳⠈⠄⡀⢩⢿⣆⣻⣳⣿⣿⣿⣿⣿⢿⡀⣀⣸⡇⢀⠠⠖⠁
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣿⣷⣿⣦⣶⣿⣤⣾⣾⣿⣿⠟⢁⠀⠀⠀⣰⡆⢀⠰⡏⢱⣾⡶⠿⠛⠋⠁⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠛⠛⠛⠟⠿⠿⠿⠿⠿⠿⠿⠿⠟⠒⠻⣀⡶⣳⡿⡇⢀⣿⣣⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠂⠤⠏⠀⠄⠒⠋⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
  

revo's core library

auto-generated from source

you'll see some metamethods here (functions prepended with `__`)
`number.__call("42")` is `number(42)`
`string.__index("qwer", 2)` is `string[2]`

globals

19 entries

assert

assert(value: any) -> any

panics if value is falsy

assert_eq

assert_eq(a: any, b: any) -> any

panics if values are not equal

debug_info

debug_info() -> {flags: {dump: bool, trace: bool, instr: bool, stack: bool}, fiber_id: number, pc: number, stack_depth: number, frame_depth: number, program_len: number, has_debug_info: bool, source_name: string | :nil, source: string | :nil, span_count: number, panic_message: string | :nil}

returns debug info as a table

expect

expect(value: any) -> !any

used in tests, returns value or {:err, :ExpectFailed} tuple

expect_eq

expect_eq(a: any, b: any) -> !any

returns value or {:err, :NotEqual} tuple if values are not equal

fmt

fmt(format: string, args: any...) -> string

formats a string with format specifiers ~ %v is value (plain) ~ %? is debug (quoted strings, multilined tables) ~ %p is pretty (debug with colors)

string literals also support `#{expr}`, `#{expr:?}`, and `#{expr:p}` interpolation
you likely want to use them instead

get_meta

get_meta(value: any) -> table | :undef

returns metatable of value or :undef

hash

hash(val: any) -> number

hashes any value

input

input(?opts: os.InputOpts...) -> !string

reads one line from stdin, or until a custom delimiter (?opts: { delimiter: string|:nil|:eof })

inspect

inspect(value: any) -> any

prints one value and returns it back

len

len(value: any) -> number

returns length of string or table

panic

panic(args: any...) -> never

panics with given message

print

print(args: any...) -> :ok

prints values to stdout with space separator

set_debug

set_debug(flags: {dump: bool?, trace: bool?, instr: bool?, stack: bool?}) -> :ok

sets debug flags from a table (all fields default to :false)

set_meta

set_meta(value: any, meta: table | :undef) -> any

sets metatable of value

sleep

sleep(ms: number) -> :parked

sleeps current fiber for given milliseconds

system

system(args: table<string>) -> !{string, string}

runs a subprocess and returns (stdout, stderr)

to_iter

to_iter(obj: any) -> function

wraps any iterable in a zero-arg callable built-in types (string, table) get a position-based iterator functions return as-is (already callable) tables with __iter metamethod call __iter(obj)

typeof

typeof(value: any) -> atom

returns type of value as atom: nil, number, string, atom, function, table, opaque, resource

modules

module argparse

command-line arguments parsing
4 entries

Opts

(value)

alias for ```revo {err: argparse.ResultMsg?, flags: table<string, string | bool> | :nil, commands: table<string, bool> | :nil, positionals: table<string, string> | :nil, leftover: table<string> | :nil} ```

ResultMsg

(value)

alias for ```revo {token: string, message: string} ```

a parse error, token plus its message

parse

argparse.parse(callback: function, argv: table) -> argparse.Opts

Usage: argparse.parse BUILDER ARGS Parse CLI args with flags, options, commands, and positionals. Subcommands: p:flag(name: atom, opts: table) p:option(name: atom, opts: table) p:command(name: atom, opts: table) p:positional(name: atom, opts: table) All arguments to opts are optional: short string the shorthand for the argument, like -v description string description to be displayed in the usage terminal bool stop parsing after this arg is filled passthrough bool pass remaining args to child prefix bool treat the option as a prefix Examples: ./args.rv ./args.rv -v -o out.txt main.rv ./args.rv compile -v ./args.rv --unknown Output status: result.err: nil | { token = string, message = string } result.flags: table of flag names to values result.commands: table of command names to booleans result.positionals: table of positional names to values result.leftover: table of unconsumed args Report bugs to <https://github.com/if-not-nil/revo/issues>

usage

argparse.usage(result: argparse.Opts) -> string

format a usage string from a parse result

module chan

channels! `chan(5)` makes one with a buffer of 5 and `chan()` makes an unbuffered one
3 entries

__call

chan.__call(capacity: number?) -> resource

metatable key: __call

creates a channel, an unbuffered one waits for a `recv` on every `send`

recv

chan.recv(self: resource) -> any

receives a value from the channel, parks when it's empty

send

chan.send(self: resource, value: any) -> :ok

sends value to the channel, parks when it's full

module dataframe

dataframe functions
6 entries

filter

dataframe.filter(input: table<string, table<any>>, fn: function) -> table<string, table<any>>

filters a dataframe by mapping a predicate function over the rows of the dataframe and keeping only the rows which return :true

len

dataframe.len(input: table<string, table<any>>) -> number

returns the length of the dataframe, ensuring column lengths are equal

map

dataframe.map(input: table<string, table<any>>, new_col: string, fn: function) -> table<string, table<any>>

maps a predicate function over the rows of the dataframe to a new column with the given column name

row

dataframe.row(input: table<string, table<any>>, idx: number) -> table<string, any>

returns the dataframe row at the given index

select

dataframe.select(input: table<string, table<any>>, columns: table<string>) -> table<string, table<any>>

selects only the given columns for a new dataframe, in the input order

sort

dataframe.sort(input: table<string, table<any>>, fn: function) -> table<string, table<any>>

sorts a dataframe using the result of a given function mapped over the dataframe's rows

module datetime

you already know what it is (might merge into time, idk)
1 entries

today

datetime.today() -> string

returns current date in UTC using ISO 8601 (YYYY-MM-DD) date format

module ffi

dynamic c calls, posix only
4 entries

errno

ffi.errno() -> number

errno from the last ffi call on this vm

func

ffi.func(lib: any, name: string, ret: atom, args: table) -> any

declare a c function, call the handle: return type + arg types as atoms

load

ffi.load(path: string) -> any

open a shared library, returns a handle

varfunc

ffi.varfunc(lib: any, name: string, ret: atom, fixed: table, total: number) -> any

declare a variadic c function: fixed prefix types + total count

module fiber

what you get from `spawn`
1 entries

join

fiber.join(self: resource) -> any

parks until the fiber is done and gives you what it returned

module file

file handles
5 entries

close

file.close(self: table) -> !atom

closes a file handle table this is currently a logical close for wrapper handles

open

file.open(path: string, mode: string?) -> !table

wraps a path in a file handle table mode is optional, defaults to "r": "r" opens an existing path, "w" creates or truncates a file, "a" creates or keeps a file use `file.close()` when you're done with the handle

read

file.read(self: table) -> !string

reads the full file contents as a string

stat

file.stat(self: table, follow: bool?) -> !os.Stat

get file metadata as a table; follow optional, defaults to :true: :false leaves symlinks alone

write

file.write(self: table, data: string, append: bool?, permissions: number?) -> !number

overwrites the file with the provided string, or appends when append is :true optional permissions default to the platform file default

module http

http
2 entries

FetchOpts

(value)

alias for ```revo {?headers: table<string, http.HeaderValue>, ?body: string, ?max_redirects: number} ```

fetch options

fetch

http.fetch(method: :get | :post | :put | :delete | :head | :options | :patch | :trace, url: any, ?opts: http.FetchOpts) -> !string

fetch an http request the default Content-Type is json fetch options are `headers` (key-value table), `body`, and `max_redirects` any fetch option can be `:nil` setting `max_redirects` to a number will follow redirects for the specified count. `:nil` leaves redirection up to the caller. examples:

revo
  http.fetch(:get, "https://example.com")
  http.fetch(:post, "https://example.com", {
    body = "{\"foo\":\"bar\"}",
    max_redirects = 3
  })
  

module iter

lazy iterators: mapping, filtering, folding and chaining
22 entries

all?

iter.all?(collection: any, pred: function) -> bool

returns true if function returns true for all elements iter.all?({1, 2, 3}, fn(x) x > 0)

any?

iter.any?(collection: any, pred: function) -> bool

returns true if function returns true for any element iter.any?({1, 2, 3}, fn(x) x > 2)

chunk

iter.chunk(collection: any, n: number) -> function

returns a lazy iterator of n-element table chunks iter.collect(iter.chunk({1, 2, 3, 4, 5}, 2)) # {{1, 2}, {3, 4}, {5}}

collect

iter.collect(iterable: any) -> table

collects all values from an iterable into a table iter.collect(iterable)

collect_string

iter.collect_string(iterable: any) -> string

collects string/number elements from an iterable into a string numbers are clamped to byte values iter.collect_string(iter.filter("hello", fn(c) c != "l"))

count

iter.count(collection: any, ?pred: function) -> number

returns the number of elements, or of those where pred is truthy iter.count({1, 2, 3, 4}) iter.count({1, 2, 3, 4}, fn(x) x > 2)

drop

iter.drop(collection: any, n: number) -> function

returns a lazy iterator without the first n elements iter.collect(iter.drop({1, 2, 3, 4}, 2))

each

iter.each(collection: any, fn: function) -> :ok

iterates over elements, calling function for side effects, returns :ok an arity-2 fn receives (value, index/key) iter.each({a = 1}, fn(v, k) print(k, v))

enumerate

iter.enumerate(collection: any) -> function

returns a lazy iterator of (index, value) pairs iter.collect(iter.enumerate({5, 7})) # {{0, 5}, {1, 7}}

filter

iter.filter(collection: any, fn: function) -> function

returns a lazy iterator that only yields values where fn is truthy an arity-2 fn receives (value, index/key) iter.collect(iter.filter({1, 2, 3, 4}, fn(x) x > 2))

find

iter.find(collection: any, fn: function) -> any | :nil

returns first element where function returns true, or nil iter.find({1, 2, 3, 4}, fn(x) x > 2)

flat_map

iter.flat_map(collection: any, fn: function) -> function

maps each element to an iterable and yields its elements lazily iter.collect(iter.flat_map({1, 2}, fn(x) {x, x * 10})) # {1, 10, 2, 20}

flatten

iter.flatten(collection: any) -> function

returns a lazy iterator that goes one level into nested tables, other elements pass thru iter.collect(iter.flatten({1, {2, 3}, 4})) # {1, 2, 3, 4}

fold

iter.fold(collection: any, fn: function) -> any | :nil

like reduce but without an initial value; first element seeds the fold returns nil for empty collections iter.fold({1, 2, 3, 4}, fn(acc, x) acc + x)

index_of

iter.index_of(collection: any, value: any) -> number | :undef

gives the index of the first element equal to value, or :undef when it's not there iter.index_of({5, 7}, 7) # 1

join

iter.join(collection: any, ?sep: string) -> string

joins the elements into a string, with the default formatting (same as just `print`) iter.join({1, 2, 3}, ", ") # "1, 2, 3"

map

iter.map(collection: any, fn: function) -> function

returns a lazy iterator that transforms each element an arity-2 fn receives (value, index/key); materialize with iter.collect() iter.collect(iter.map({1, 2, 3}, fn(x) x * 2))

reduce

iter.reduce(collection: any, fn: function, init: any) -> any

folds/accumulates elements using function and initial value iter.reduce({1, 2, 3, 4}, fn(acc, x) acc + x, 0) iter.reduce(iter.map({1, 2}, fn(x) x * 2), fn(acc, x) acc + x, 0)

sum

iter.sum(collection: any) -> number

sums numeric elements, skipping non-numbers iter.sum({1, 2, "x", 3})

take

iter.take(collection: any, n: number) -> function

returns a lazy iterator of the first n elements iter.collect(iter.take({1, 2, 3, 4}, 2))

unique

iter.unique(collection: any) -> function

returns a lazy iterator that skips elements it already yielded iter.collect(iter.unique({1, 2, 1, 3})) # {1, 2, 3}

zip

iter.zip(first: any, second: any, rest: any...) -> function

returns a lazy iterator of pairs, one element from each iterable takes two or more, stops at the shortest iter.collect(iter.zip({1, 2}, {3, 4})) # {{1, 3}, {2, 4}}

module json

encode values as json and decode json back into revo values
2 entries

decode

json.decode(source: string) -> !any

decodes json string into revo value

encode

json.encode(value: any, ?pretty: bool) -> !string

encodes value as json string; enabling `pretty` will emit indented json

module math

numeric math
26 entries

abs

math.abs(x: number) -> number

absolute value

acos

math.acos(x: number) -> number

arc-cosine of x (x in radians)

acosh

math.acosh(x: number) -> number

hyperbolic arc-cosine of x (x in radians)

asin

math.asin(x: number) -> number

arc-sine of x (x in radians)

asinh

math.asinh(x: number) -> number

hyperbolic arc-sine of x (x in radians)

atan

math.atan(x: number) -> number

arc-tangent of x (x in radians)

atan2

math.atan2(y: number, x: number) -> number

arc-tangent of y and x (y and x in radians)

atanh

math.atanh(x: number) -> number

hyperbolic arc-tangent of x (x in radians)

ceil

math.ceil(x: number) -> number

ceiling of x

close?

math.close?(x: number, y: number, places: number) -> bool

test whether two values are close within the given number of decimal places

cos

math.cos(x: number) -> number

cosine of x (x in radians)

cosh

math.cosh(x: number) -> number

hyperbolic cosine of x (x in radians)

exp

math.exp(x: number) -> number

e raised to x

floor

math.floor(x: number) -> number

floor of x

hypot

math.hypot(x: number, y: number) -> number

hypotenuse of sides x and y

log

math.log(x: number) -> number

natural logarithm, panics if x <= 0

max

math.max(first: number, args: number...) -> number

max of all arguments, at least one required

min

math.min(first: number, args: number...) -> number

min of all arguments, at least one required

pi

math.pi() -> number

pi, 3.141592653589793

pow

math.pow(base: number, exponent: number) -> number

base raised to exponent

sign

math.sign(value: number) -> number

sign of value (-1, 0, 1)

sin

math.sin(x: number) -> number

sine of x (x in radians)

sinh

math.sinh(x: number) -> number

hyperbolic sine of x (x in radians)

sqrt

math.sqrt(x: number) -> number

square root, errors if x is negative

tan

math.tan(x: number) -> number

tangent of x (x in radians)

tanh

math.tanh(x: number) -> number

hyperbolic tangent of x (x in radians)

module net

tcp sockets: connect, listen, accept, send and receive
2 entries

connect

net.connect(host: string, port: number) -> !table

connects to a remote host and port, returns a socket handle

listen

net.listen(port: number, ?backlog: number...) -> !table

listens for incoming connections on the given port, returns server socket

module number

global number helpers, calllable as `1337:nan?` and `number.nan?(1337)`
8 entries

__call

number.__call(value: string) -> number

metatable key: __call

converts value to number: number("12") => 12

abs

number.abs(self: number) -> number

absolute value

ceil

number.ceil(self: number) -> number

smallest integer >= self

finite?

number.finite?(self: number) -> bool

checks if number is finite

floor

number.floor(self: number) -> number

largest integer <= self

inf?

number.inf?(self: number) -> bool

checks if number is infinite

nan?

number.nan?(self: number) -> bool

checks if number is NaN

round

number.round(self: number) -> number

rounds to nearest integer

module os

the machine you're running on: the process, the environment, the clocks and the filesystem
19 entries

InputOpts

(value)

alias for ```revo {?delimiter: string | :nil | :eof} ```

read input options

Stat

(value)

alias for ```revo {size: number, kind: atom, permissions: number, mtime: number, atime: number, ctime: number} ```

file metadata as returned by file.stat and os.stat

args

os.args() -> table

the command line arguments after the script name, a new table every call

chdir

os.chdir(path: string) -> !atom

changes cwd to the given path

clock

os.clock() -> number

returns monotonic clock in milliseconds

copy

os.copy(src: string, dst: string) -> !atom

copies a file to a new path, overwriting the destination

cwd

os.cwd() -> string

returns current working directory path

env

os.env(?name: string) -> any

the value of an environment variable or :nil when it isn't set. without a name it's a table of all of them, so `os.env().HOME`

exists?

os.exists?(path: string) -> bool

does path exist? answers :false when missing, raises on unexpected io errors

exit

os.exit(status: number) -> never

exits the program with a status

glob

os.glob(pattern: string, recursive: bool?, depth_limit: number?) -> !table

returns a list of files using pattern matching rules similar to the UNIX shell, if no matches are found then the table will be empty. recursive optional, defaults to :false: :true causes "**" to match all directories and subdirectories until it reaches an endpoint, this can be quite cpu heavy on large directories depth_limit optional, defaults to 100: this is used to set an endpoint where glob must stop matching files after a certain recursion depth.

mkdir

os.mkdir(path: string, parents: bool?, permissions: number?) -> !atom

creates a directory; parents optional, defaults to :false: :true creates missing parents like `mkdir -p`. permissions optional, platform default when omitted

now

os.now() -> number

returns current wall-clock time in milliseconds

readdir

os.readdir(path: string) -> !table<{name: string, kind: atom}>

returns table of directory entries

remove

os.remove(path: string, recursive: bool?) -> !atom

removes a file or directory at path recursive is optional, defaults to :false: removes a file or empty directory only, :true deletes the whole tree

rename

os.rename(old_path: string, new_path: string) -> !atom

renames a file or directory

setenv

os.setenv(name: string, value: string) -> :ok

sets an environment variable, returns :ok

stat

os.stat(path: string, follow: bool?) -> !os.Stat

get file metadata as a table from a path; follow optional, defaults to :true

touch

os.touch(path: string) -> !atom

ensures a file exists, creating it empty when missing and leaving existing entries alone

module revo

the revo metaprogramming lib
9 entries

EvalError

(value)

alias for ```revo {message: string, phase: atom, code: string | :nil, line: number | :nil, column: number | :nil, source: string | :nil, rendered: string, kind: string | :nil, trace: table} ```

structured diagnostic returned in `{:err, ...}` by functions that run revo code

  ```
  match revo.eval("let x: number = 'hi'") | {:ok, v} => v | {:err, e} => e.message
  ```

LexToken

(value)

alias for ```revo {type: string, class: string, text: string, line: number, column: number, start: number, end: number} ```

compile

revo.compile(code: string) -> !string

builds it as a module, gives you back its bytecode in a string the string is only useful for writing to a file or executing build failures come back as {:err, revo.EvalError}

dload

revo.dload(path: string) -> table

opens a dll and gives you back its functions in a table `./x` and `../x` resolve from the calling file, anything else goes to the os

  you're meant to type it with a binding
  

revo
  const lib: {add: fn(number, number) -> number} = revo.dload("./lib.so")
  

eval

revo.eval(code: string) -> !any

evaluates it as a module, gives you back its return value you can treat it as a function's body static and runtime failures come back as {:err, revo.EvalError}

lex

revo.lex(code: string) -> !table<revo.LexToken>

lex source into an array of revo.LexToken tables

load

revo.load(path: string, opts: table?) -> !any

dynamic `import`! loads the module at `path` and gives you back its value the path is data, so it resolves from the cwd

`name:x` collections work
shares the module table with `import`, `{fresh = true}` reruns it

threads

revo.threads() -> number

worker thread count (see --threads)

version

revo.version() -> string

version of your revo installation, like "revo v1.2.3"

module rng

pseudo-random numbers with a settable seed
6 entries

choice

rng.choice<T>(input: table<T>) -> T | :nil

Returns a random element from a table, or :nil if empty (note: this function *ignores* key value pairs.)

rand

rng.rand(upper_bound: number) -> number

Returns a random integer in the range [0, upper_bound]

rand_float

rng.rand_float() -> number

Returns a random float in the range [0, 1]

range

rng.range(lower_bound: number, upper_bound: number) -> number

Returns a random integer in the range [lower_bound, upper_bound]

revert_seed

rng.revert_seed()

Reverts seed back to using the current time at the time of generation.

set_seed

rng.set_seed(seed: number)

Statically sets the seed used for generation of pseudo-random numbers.

module socket

tcp sockets: connect, listen, accept, send and receive
5 entries

RecvOpts

(value)

alias for ```revo {?mode: :read_some | :read_all | :read_line, ?max_bytes: number, ?delimiter: string} ```

recv options

accept

socket.accept(self: table) -> !table

accepts an incoming client connection on a server socket

close

socket.close(self: table) -> !atom

closes the socket

recv

socket.recv(self: table, opts: socket.RecvOpts) -> !string

receives data according to opts

send

socket.send(self: table, data: string) -> !number

sends data over the socket, returns number of bytes sent

module stats

statistics functions
5 entries

frequencies

stats.frequencies(input: table<any>) -> table<any, number>

counts frequencies of elements in an array table and returns a mapping of elements to their counts

median

stats.median(input: table<number>) -> number

middle value of input data

mode

stats.mode(input: table<any>) -> any

most frequent occuring value of input data

regression

stats.regression(input1: table<number>, input2: table<number>) -> {n: number, sum_of_products: number, slope: number, intercept: number, correlation: number, covariance: number, sample_covariance: number}

table of regression statistics of the input data

statistics

stats.statistics(input: table<number>) -> {n: number, frequencies: table, mean: number, median: number, mode: number, geomean: number, minimum: number, maximum: number, sum: number, sum_of_squares: number, product: number, stdev: number, sample_stdev: number, variance: number, sample_variance: number, skewness: number, sample_skewness: number, kurtosis: number, sample_kurtosis: number}

table of all statistics of the input data

module string

global string helpers, calllable as `"hello world":split(" ")` and `string.split("hello world", " ")`
24 entries

__call

string.__call(value: any) -> string

metatable key: __call

converts value to string: string(x)

alnum?

string.alnum?(self: string) -> bool

checks if all characters in the string are alphanumeric

alpha?

string.alpha?(self: string) -> bool

checks if all characters in the string are alphabetic

ascii

string.ascii(self: string) -> number

returns ASCII code of first character

"a":ascii() => 97

concat

string.concat(self: string, other: string) -> string

concatenates two strings

contains?

string.contains?(self: string, substr: string) -> bool

checks if string contains substring

ends_with?

string.ends_with?(self: string, suffix: string) -> bool

checks if string ends with suffix

index_of

string.index_of(self: string, substr: string) -> number | :nil

ret 0-based index of substring or nil

join

string.join(table: table<string>, sep: string) -> string

joins table elements into string with separator

len

string.len(self: string) -> number

returns length of string

lower

string.lower(self: string) -> string

converts string to lowercase

lower?

string.lower?(self: string) -> bool

checks if all characters in the string are lower case

of_ascii

string.of_ascii(code: number) -> string

creates string from ASCII code(s)

of_ascii(97) => "a"

punct?

string.punct?(self: string) -> bool

checks if all characters in the string are punctuation

repeat

string.repeat(self: string, n: number) -> string

repeats string n times

replace

string.replace(self: string, old: string, new: string) -> string

replaces all occurrences of old with new

reverse

string.reverse(self: string) -> string

reverses the string

split

string.split(self: string, delim: string) -> table<string>

splits string by delimiter into table

starts_with?

string.starts_with?(self: string, prefix: string) -> bool

checks if string starts with prefix

table

string.table(self: string) -> table<string>

converts string to table of characters

"asdf":table() => {"a", "s", "d", "f"}

trim

string.trim(self: string) -> string

trims whitespace from both ends

upper

string.upper(self: string) -> string

converts string to uppercase

upper?

string.upper?(self: string) -> bool

checks if all characters in the string are upper case

whitespace?

string.whitespace?(self: string) -> bool

checks if all characters in the string are whitespace

module table

global table helpers, calllable as `{1, 2}:at(0)` and `table.at({1, 2}, 0)`
31 entries

alen

table.alen(self: table) -> number

returns length of table array part only

at

table.at<T>(self: table<T>, index: number) -> T | :undef

gets array element at 0-based index, metatable-ignoring returns :undef when out of range

at?

table.at?(self: table, index: number) -> bool

whether a 0-based index holds an array element, metatable-ignoring

contains?

table.contains?(self: table, value: any) -> bool

checks if table contains value

copy

table.copy<T>(self: table<T>) -> table<T>

creates shallow copy of table

deep_copy

table.deep_copy<T>(self: table<T>) -> table<T>

creates a deep copy of the table, duplicating nested tables (cycles map to their in-progress copy)

empty?

table.empty?(self: table) -> bool

reports whether the table holds no entries at all

freeze

table.freeze<T>(self: T) -> T

makes the table read-only. you probably won't need it, it's mostly for pub records

get_meta

table.get_meta(self: table) -> table | :undef

returns metatable of value or :undef

insert

table.insert<T>(self: table<T>, pos: number, value: T) -> :ok

inserts value at position, shifting elements right

key

table.key<V>(self: table<V>, key: any) -> V | :undef

gets map value, metatable-ignoring returns :undef if key missing

key?

table.key?(self: table, key: any) -> bool

whether a key exists, metatable-ignoring

keys

table.keys<K, V>(self: table<K, V>) -> table<K>

returns all keys as table (array indices + hash keys)

klen

table.klen(self: table) -> number

returns length of table keyed entries only

last

table.last(self: table) -> any

the array part's last element

len

table.len(self: table) -> number

returns total length of table (array part + keyed entries)

merge

table.merge<K, V>(self: table<K, V>, other: table<K, V>) -> table<K, V>

merges second table into first later values overwrite earlier ones

pop

table.pop<T>(self: table<T>) -> T | :undef

removes and returns the last array element, or :undef if empty

push

table.push(self: table, values: any...) -> table

inserts elements as last

rawget

table.rawget(self: table, key: any) -> any | :undef

gets value without metamethods returns :undef if key missing

rawset

table.rawset(self: table, key: any, value: any) -> table

sets value without metamethods

remove

table.remove<T>(self: table<T>, key: any) -> T

removes element at position or key, returns removed value

repeat

table.repeat<T>(self: table<T>, n: number) -> table<T>

repeats table array part n times

reverse

table.reverse<T>(self: table<T>) -> table<T>

reverses table array part in place

set_meta

table.set_meta(self: table, meta: :undef | table) -> table

sets the metatable of the table, `:undef` clears it

sort

table.sort<T>(self: table<T>) -> table<T>

sorts table array part in ascending order (numbers < strings)

sort_by

table.sort_by(self: table, fn: function) -> table

sorts table array part using comparison function fn(a, b) -> bool (true if a < b)

unwrap

table.unwrap<T>(self: {:ok, T} | table) -> T

unwraps result, panics if not :ok

unwrap_err

table.unwrap_err<T>(self: {:err, T} | table) -> T

extracts error from result, panics if not :err

update

table.update<T>(self: table<T>, key: any, fn: function) -> table<T>

applies fn to the value at key (missing reads as :nil) and stores the result back, returns self

values

table.values<K, V>(self: table<K, V>) -> table<V>

returns all values as table