gleam Documentation

️ A friendly language for building type-safe, scalable systems!

21,733 stars Rust Rust 1 file · ~3,626 tokens #compiler#erlang#gleam#programming-language#statically-typed
RAW Doc

File: README.md

 

Gleam is a friendly language for building type-safe systems that scale! For more
information see the website.

Support Gleam!

Gleam is not owned by a corporation, instead it is kindly supported by its
sponsors. If you like Gleam please consider sponsoring the project or members
of the core team
.

Thank you so much! 💖


File: compiler-wasm/README.md

Compiler WASM

sh
# Install the build tool with cargo or brew etc
cargo install wasm-pack

# Build the wasm library
wasm-pack build --release --target web

# Make a tarball to attach to a release
tar -C pkg/ -czvf gleam-v1.1.0-browser.tar.gz .

File: docs/compiler/README.md

Compiler documentation

Hello! Welcome to the documentation for the Gleam compiler. I hope you have fun
with the project!

Project structure

The project is made up of several Rust crates (projects):

  • compiler-core: This project parses, analyses, and compiles Gleam projects.
    It is entirely pure and has no IO so that is provided by the other Rust crates
    that wrap this one.
  • language-server: This project contains code for the Gleam language server,
    including autocomplete, code actions, hover and other features.
  • compiler-cli: A command line interface that wraps the core compiler and
    language server, providing IO to files and to the console.
  • compiler-wasm: A JavaScript interface to the core compiler via web assembly.
    Suitable for running in a web browser.

In addition to the Rust code there are these components:

  • Makefile: A makefile that defines shortcut commands for common tasks when
    working in the Gleam codebase. Run make help to view them.
  • test: A collection of (mostly) Gleam projects that serve as integration tests for the
    compiler.
  • deny.toml: Configuration for the cargo-deny tool which is used to ensure
    that the Rust libraries the compiler depends on adhere to our expectations.
  • containers: A collection of docker-files used to produce OCI containers for
    each Gleam release.
  • .github/workflows: GitHub Actions workflow definitions, used to build, test,
    and release new versions of the project.
  • docs: You're looking at it pal.

Compilation flow

The process for compiling Gleam modules within the compiler looks roughly like
this:

txt
Gleam source code       .cache binaries
          ▼                         ▼
┌────────────────────┐ ┌───────────────────────┐
│       Parser       │ │ Metadata deserializer │
└────────────────────┘ └───────────────────────┘
          │                         │
      Untyped AST            Module metadata
          └─────────┐   ┌────────┘     │
                    ▼   ▼              │
           ┌─────────────────────┐     │
           │  Dependency sorter  │     │
           └─────────────────────┘     │
                      │                │
                 Untyped AST           │
              (sorted by deps)         │
                      ▼                │
            ┌───────────────────┐      │
            │   Type checker    │◄─────┘
            └───────────────────┘
                      │
          ┌────── Typed AST ──────┐
          ▼                       ▼
┌────────────────────┐ ┌─────────────────────┐
│   Code generator   │ │ Metadata serializer │
└────────────────────┘ └─────────────────────┘
          │                       │
          │                       ▼
 Erlang or JavaScript   .cache binaries
   printing algebra
          ▼
┌────────────────────┐
│   Pretty printer   │
└────────────────────┘
          │
          ▼
 Erlang or JavaScript
     source code

Testing

We like automated tests! They're a great way to verify that the compiler is
doing what we expect it do as we make changes.

Running the tests

  • make test: Run all the tests. Worth doing before committing any changes.
  • make test-watch: Run the Rust unit tests when files are saved.
  • make language-test: Run the cross-platform language integration tests in
    test/language.
  • make language-test-watch: Run said tests when files are saved.
  • make javascript-prelude-test: Run the unit tests for the JavaScript code
    that implements the Gleam prelude when compiling to JavaScript.
  • make javascript-prelude-test-watch: Run said tests when files are saved.

The *-watch commands require the watchexec program to be
installed.

Snapshot testing

The compiler makes heavy use of snapshot testing using the
cargo-insta tool.

If you're not familiar with snapshot testing instead of writing an input and an
expected output (as in normal example based tests) you write only the input. The
snapshot testing tool can then be used to mark any new outputs as accepted and
saved into the repository as snap files. If an output for one of the tests
changes then it is considered a failed test and the programmer has the option to
either reject the new version (as it is an incorrect result) or accept it as the
new correct output.

This style of testing saves us huge amounts of time as manually updating all the
expected output when we make changes to the output format of the compiler or
error messaging is time-consuming and very dull. With snapshot testing it takes
seconds.

sh
# Run the tests
make test

# Interactively verify changes to the snapshots
cargo insta review

File: docs/annoyances.md

Annoyances

This document contains a list of issues and annoyances that we have writing
Gleam code today, so that we can devise solutions to them in future.

There are other annoyances that have known solutions that are yet to be
implemented. These are tracked in the Gleam issue tracker instead.

Bundling compiled JavaScript is non-obvious

Cannot shift repeated work to compile or initialise time

For example, regex compilation.

JavaScript custom type representation could be faster

There's performance improvements to be had. Would would be optimal?


File: docs/runtime-errors.md

Runtime errors

There are several runtime errors that Gleam code can throw. This documentation
lists them and their runtime properties.

On Erlang runtime errors are Erlang maps thrown with erlang:error/1, having at
least these properties:

Key Type Value
gleam_error Atom See individual errors
message String See individual errors
file String A path to the original source file location
module String The module the error occurred in
function String The function the error occurred in
line Int The line number the error occurred on

On JavaScript runtime errors are instances of the JavaScript Error class,
having at least these properties added to them:

Key Type Value
gleam_error String See individual errors
message String See individual errors
module String The module the error occurred in
function String The function the error occurred in
line Number The line number the error occurred on

Todo

A panic that indicates that the code has not yet been completed, intended for
use in development.

gleam
todo
todo as "some message"
Key Erlang Value JavaScript Value
gleam_error todo "todo"
message The given message The given message

Panic

An explicit panic to unconditionally error.

gleam
panic
panic as "some message"
Key Erlang Value JavaScript Value
gleam_error panic "panic"
message The given message The given message

Let assert

An inexhaustive pattern match, erroring if the pattern does not match.

gleam
let assert Ok(x) = something()
let assert Error(e) = something() as "This should fail"
Key Erlang Value JavaScript Value
gleam_error let_assert "let_assert"
message The given message The given message
value The unmatched value The unmatched value
start The byte-index of the start of the let assert statement The byte-index of the start of the let assert statement
end The byte-index of the end of the let assert statement The byte-index of the end of the let assert statement
pattern_start The byte-index of the start of the asserted pattern The byte-index of the start of the asserted pattern
pattern_end The byte-index of the end of the asserted pattern The byte-index of the end of the asserted pattern

Assert

An assertion of a boolean value.

The error format of assert differs based on the expression that is asserted.
It always has these fields:

Key Erlang Value JavaScript Value
gleam_error assert "assert"
message The given message The given message
kind The kind of asserted expression The kind of asserted expression
start The byte-index of the start of the assert statement The byte-index of the start of the assert statement
end The byte-index of the end of the assert expression The byte-index of the end of the assert expression
expression_start The byte-index of the start of the asserted expression The byte-index of the start of the asserted expression

But, depending on the expression that was asserted, it contains additional
information which can be used to diagnose the error.

Binary operators

gleam
assert level >= 30
Key Erlang Type JavaScript Type Value
kind Atom String binary_operator
operator Atom String The binary operator that was used
left Map Object The left hand side of the operator
right Map Object The left hand side of the operator

Function calls

gleam
assert check_some_property(a, b, c)
Key Erlang Type JavaScript Type Value
kind Atom String function_call
arguments List of map Array of objects The arguments of the asserted function

Other expressions

gleam
assert other_expression
Key Erlang Type JavaScript Type Value
kind Atom String expression
expression Map Object The value of the asserted expression

The expression maps have this structure:

Key Erlang Type JavaScript Type Value
value any any the value the expression evaluated to at runtime
kind Atom String literal or expression or unevaluated
start Int Number The byte-index of the start of this expression in the source code
end Int Number The byte-index of the end of this expression in the source code

If the expression is a literal, such as True or 15, it will have the literal
kind. This signals that its value is not runtime dependent, and may not need to
be printed.

If the expression is on the right hand side of a short-circuiting operator, like
|| or &&, it might not be evaluated. If the operator short-circuits, the right
hand side expression will have kind unevaluated.


File: test-community-packages/README.md

test_community_packages


sh
gleam add test_community_packages
gleam
import test_community_packages

pub fn main() {
  // TODO: An example of the project in use
}

Further documentation can be found at https://test-community-packages.hexdocs.pm.

Development

sh
gleam run   # Run the project
gleam test  # Run the tests
gleam shell # Run an Erlang shell