Try   HackMD
tags: S-Juvix

On a Modular Image System: Or How I got multiple conflicting packages to live under the same image.

Rough thoughts.

We have two concepts:

  1. Module
  2. Package

Modules are modules we all know and love. Namely it acts like the UNIX filesystem.

Packages describe your project state, what projects we import etc.

All code exists inside both a Module and a Package.

Thus in our Project Juvix, we may be in a module Core.

We can on the fly swap what module we are in. (in-module :Core.Theory)

This means we are in the Project Juvix still and now the module is Core.Theory.

Projects can import other Projects, thus we can import an Array package.

This Array package defines out the module Prelude.Array, which lives in the Base's Prelude module.

By importing the Array package we've added to the standard library of our project. If there exists another package that defines out the module Prelude.Array we would get a conflict and be told to rename either one (thus we can rename the new one to Prelude.SpecialArray, or any other recovery schema).

Little did we know, Prelude.Array used some packages that defined out Core.Theory. This is quite unfortunate as our codebase has Core.Theory.

With the concept of packages, this is no problem, as we do not bring into our resolution scope the Array package's package. Thus there is no conflict in Core.Theory. Only the modules defined in the Array package will be brought into scope with the default import function.

Implementation issues

One big issue with mixing package names is that we can't simply link the same version of a library together. If two packages rely on Base.1.1.1.1, and one package extends it with Array and another does not, a naive resolution system may have to allocate links back to the original, as one Prelude from base has Prelude.Array but the other does not.

However if we utalize functional programming, we can keep the base Prelude around in Package.Base, and when we import it into scope it'll just functionally copy the tree over. When another package hits it, it'll just do tree merging.

This has some issues I need to flesh out

  1. Updating the standard library
    • We should be pinned to a version with a hash
  2. Updating a library while in a package
    • It should know what package we are in, and then update our pinned package to it
  3. When do we generate out Hashes to refer to packages

Some Notes:

  • We mutate the image when we change a defn.

A lot more thought should be had on this, and how much functional sharing loses us, but this technique should work.