# letrec

The [name][1] is provisional.

Implements an isolated content-addressable package loading system.

## Import

The process starts with the importer. When you want to use a module,
it first has to be imported into the store along with all the modules
it requires. We analyze the module to identify its dependencies by
using containment to replace `require` with a shim which records the
dependency modules. In the future we could do this by parsing the
source instead since not all requires happen at the top level; the
current approach means that importing only works on well-behaved modules.

Once we determine a module's dependency tree, we walk it down to the
leaves and for each leaf module we checksum it. The checksum is based
on several factors: the contents of the file, the checksum of letrec
itself, and the versions of Fennel and Lua used. The leaf module is
copied into the store using a key based on the checksum. Once the
leaves are imported, we walk back down the tree, but for non-leaf
modules we incorporate the checksums of their dependencies into their
checksums. We also store metadata for each module indicating how the
module names for each dependency map to checksums.

## Loading

After a module and its dependencies have been imported, it can be
loaded. We add a package searcher which knows how to look in the store
for modules. It loads it in a context which has `require` replaced
with a letrec-aware equivalent. This version of `require` looks at the
metadata tree that was generated during import, and whenever a module
needs to load one of its dependencies, it ensures that it always gets
the right one that was locked in at import time.

## Store

Right now we just use a local filesystem directory is the store, but
it's easy to imagine replacing it with a networked store such as IPFS,
git, DAT, etc.

## Glossary

* Import: to take a normal module and import it into the store
* Store: the storage location for imported modules
* Module: a unit of code returning a value referenced by a single name
* Searcher: a function which searches for a module and provides it to require
* Resolve: the process of making a module content-addressable
* Containment: the process of loading a module in an isolated way to analyze it

[1]: https://erlang.org/pipermail/erlang-questions/2011-May/058768.html

Generated by Phil Hagelberg using scpaste at Thu Jun 4 11:01:54 2020. PDT. (original)