Packages and Libraries

IotaGoRustHaskell
global default namespace?"pkg.go.dev""crates.io"a global root
other namespaces?"github.com/", etccargo configurable?cabal configurable?
"project"?module, "go.mod"a cargo workspace or projecta cabal unit
"library"?packagea target in a projecta sub-unit
"binary"?package maina target in a projecta sub-unit
Translation unit?=package=crate=file

module namespaces

Go-style, one implicit global root like "pkg.iota.dev/", optionally other roots like "github.com/org/". These are root packages that include other packages recursively? The universe of packages is just a lazy bag, like in Nix?

A package file tree of a package my-pkg:

my-sub-pkg/
  package.iota
  ...

assets/           # static resources
build/            # like target/ in Cargo
docs/
deps/
  github.com/org/package/import.iota
  github.com/org/pkg/subpkg/import.iota
examples/
exe/              # like cmd/ in Go, app/ in Cabal ?
  binary1.iota
lib/              # like pkg/ in Go
  pubmod1.iota
  pubmod1.test.iota
  pubmod2.iota
src/              # like internal/ in Go
  internal1.iota
test/             # like tests/ in Cargo?
package.iota

It is equivalent to a table:

(
    package = @import("package.iota")
    lib = (
        pubmod1 = @import("lib/pubmod1.iota")
        pubmod2 = @import("lib/pubmod2.iota")
    )
    exe = (
        binary1 = @import("exe/binary1.iota")
    )
    src = (internal1 = @import("src/internal1.iota"))
    deps = (
        `github.com`/org/pkg = @import("deps/github.com/org/package/import.iota")
    )
    ...
)

What's a package?

  • a const-value of:
    • metadata
      • name, description, url, license, etc
      • dependencies
    • list of its modules
  • a const-trait that can build()/test()/etc its values?
    • iotac executable == "iota const evaluator". iota-"cargo" is just a library.
    • $ iotac build --target=binary1 == run const-fn package.build(target = binary1)
    • $ iotac test == run const-fn package.test()
    • ...

package.iota is a go.mod-like project file, an entry point to building. A mix of cargo.toml, Deno's main file, go.mod, etc.

// my_package = package(
// package my_package(ctx: Context)   // shortcut

// like cargo.toml,
// key `name` set to `my_package`:
name = "my_package"
description = "foos bars"
url = "author/lib"     // if uploaded to the main registry

dependencies = (
  "github.com/org/lib" = (version = "v0.1"),
)

require = (
  // the list of capabilities required from the environment
)

// Q: how to describe build targets and tests?

// Q: how to include modules?
// like `mod mod1;` in Rust, Go-style syntactically?

// end

binary vs library

Entry points require a uniq ref to a process resource (borrowed from the OS).

module definition

// shortcut: module main(ctx: Context) (...) { ... }
const main module(ctx: Context) (
    doc = "module documentation goes here?"
    // public definitions, module "signature"
) is

// imports
const std = ctx.import('std')

// private definitions, implementations

end // closes is, optional if EOF

module imports

// full form
self.import(
  "std"                 // std = "pkg.iota.dev/std"
  "github.com/org/lib"  // lib = "github.com/org/lib"
  rename "name"
)

module contexts

The context of a module defines the list of accessible static capabilities.

An executable gets the root dynamic capability from the environment (e.g. from the ELF loader or another loader middleware).

A library gets its capabilities from its importer.

Interop

Goals:

  • make C ABI interop rich and powerful (so it works well)
  • make C headers interop easy, almost seamless technically (~@ cImport).
  • make it complex and demanding, proof-heavy when imported (lots of additional static information)
  • Rust interop via extern "interop_abi"?
  • WIT from WASM?
  • Q: GC-based languages