Gleam REPL for the JavaScript target, powered by Deno
gleam repl tools
README.md

grepl #

A Gleam REPL for the JavaScript target, powered by Deno.

Usage #

See Building for now. Nix flake usage and prebuilt binaries in progress!

Libraries #

When run from within a Gleam project directory, grepl looks for libraries (including gleam_stdlib) in the build/ directory to copy into memory for use in the REPL.

If you already have a project with a gleam.toml, you can make a package available inside grepl with gleam add $package. You may also need to gleam deps download if you recently gleam cleaned the build directory.

Caveats #

  • All external libraries are copied into a single package at the moment. This works, but is slightly different than how gleam build works, and may fail when gleam build would not (e.g. trying to compile Erlang-only libraries).

  • let bindings don't yet support things like let assert or let #(a, b) = expr. Also, only one binding is allowed at a time, and the final expression value will be used, which may lead to unexpected results:

    let x = 123
    let y = 456
    // x is bound to 456, y is unbound
    

Building #

Requires gleam (>= 1.19) and deno (tested against 2.9.6). Nix users can use nix develop to get a working environment.

To build a standalone executable to build/grepl:

gleam dev

Additional args are passed to deno compile, e.g.

gleam dev -- --target x86_64-unknown-linux-gnu

to "cross-compile" an executable for Linux.

Running locally for testing #

gleam run

For debugging the compiler, try changing this to true in src/grepl/internal/compile_ffi.ts:

wasm.initialise_panic_hook(false);

Notes / How it works #

On startup, the REPL:

  1. Initialized the Gleam WASM compiler
  2. Looks for a directory containing gleam.toml, upward from the current directory
  3. Once found, walks build/packages/ to look for Gleam and JavaScript source files
  4. Copies those files into the WASM compiler's in-memory virtual filesystem
  5. Displays a prompt

After something is entered in the prompt, attempt to parse the input.

If it looks like a valid Gleam module (e.g. top-level fn, const, or import):

  1. Append the input to an in-memory module
  2. Attempt to compile the module, and report any errors
  3. If compilation succeeded, save the new module and continue

If it looks like a Gleam expression, instead:

  1. Generate a function containing the expression, which accepts as parameters all of the stored bindings in the session thus far
  2. Append this function to the in-memory module
  3. Attempt to compile the module, and report any errors
  4. On compile success, import and call the function
  5. Print the function's return value to the console
  6. After successful evaluation, if the first token of the expression was let, store the result as a new binding

Finally, display a new prompt and continue!