Skip to content

jprochazk/hebi

Repository files navigation

A snake inside of a gear shape

Hebi

This repository hosts a dynamically typed language, its compiler, and VM.

🚧 This branch contains a rewrite of the language. It is currently heavily WIP! 🚧

Usage

Install the library (currently only available via git):

$ cargo add --git https://github.com/jprochazk/hebi.git --branch v2

Import it, and run some code:

use hebi::Hebi;

fn main() {
  let mut hebi = Hebi::new();

  println!("1 + 1 = {}", hebi.eval("1 + 1").unwrap());
}

Hebi can do much more than this, though! Here are some of its features:

  • Syntax similar to Python, including significant indentation
  • First-class functions
  • Classes with single inheritance
  • Easy Rust function and struct binding
  • Async support

Visit the examples directory to see Hebi in action.

You can run an example using cargo run --example <name>:

$ cargo run --example basic

As well as with the CLI:

$ cargo run -p hebi-cli -- examples/hebi/tic-tac-toe.hebi

Development

The first step is to install Rust and Cargo via rustup.

xtask

This repository uses cargo-xtask for various utilities, scripts, and tasks. That means you don't need anything other than Rust and Cargo. No makefiles, Python, or Bash.

To see all available tasks, run:

$ cargo xtask

To run one of them, use:

$ cargo xtask <task>

Or the slightly shorter:

$ cargo x <task>

For example:

# Run all tests and examples
$ cargo xtask test

Some tasks use tools which you'll have to install, though these are kept to just a select few, and ideally always installed through either rustup or cargo.

  • Miri (rustup +nightly component add miri)
  • Insta (cargo install --locked cargo-insta)
  • mdBook (cargo install --locked mdbook)

CLI

The Hebi CLI provides a few tools for running and debugging scripts. It can be used through cargo run or directly after installing the binary with cargo install --path cli. The examples below demonstrate both ways.

# Print help
$ cargo run -p hebi-cli -- --help
Usage: hebi-cli [FILE] [COMMAND]

Commands:
  run          Execute a Hebi file [default]
  disassemble  Disassemble a Hebi file [aliases: dis]
  repl         
  help         Print this message or the help of the given subcommand(s)

Arguments:
  [FILE]  The path to the Hebi file to process. Required unless code is supplied through stdin

Options:
  -h, --help     Print help
  -V, --version  Print version

# Execute a script
$ echo 'print "Hello, world!"' | hebi 
Hello, world!

# Disassemble a script
$ hebi dis examples/hebi/fib.hebi
function `fib` (registers: 7, length: 57, constants: 2)
.code
  0  | load_smi 0
  2  | store r2
  4  | load_smi 1
  6  | store r3
  8  | load_smi 0
<...>

# Run a script and dump the VM state on exit
$ cargo run -p hebi-cli -- run examples/hebi/count_primes.hebi --dump
π(1000) = 168
Hebi(
    Vm {
        global: Global {
            inner: State {
                globals: {
                    "to_int": Object(
                        BuiltinFunction {
                            name: "to_int",
                        },
                    ),
<...>

Why Hebi?

I thought it was appropriate, because the language is in the Python family, and Hebi (蛇) means snake in Japanese.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.