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
# 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. Runmake helpto view them.test: A collection of (mostly) Gleam projects that serve as integration tests for the
compiler.deny.toml: Configuration for thecargo-denytool 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:
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 codeTesting
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 intest/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 thecargo-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.
# Run the tests
make test
# Interactively verify changes to the snapshots
cargo insta reviewFile: 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.
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.
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.
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
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
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
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
gleam add test_community_packagesimport 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
gleam run # Run the project
gleam test # Run the tests
gleam shell # Run an Erlang shell