13. Modules and projects

More than one file is a project. The directory convention: modules live under src/, and the entry point is src/main.dawn. One .dawn file is one module, and the module path is its path relative to src/.

myapp/
└── src/
    ├── main.dawn
    └── util/
        └── math.dawn      # module util/math

Everything is module-private by default; pub exports. There are two forms of import: use util/math brings in the whole module (accessed qualified, math.double(x), the alias being the last segment of the path), or use util/math.{double} imports selectively (used directly, as double). Types, constructors and constants can only cross a module boundary through a selective import.

src/util/math.dawn:

pub fn double(x: Int) -> Int = x * 2

pub type Shape =
  | Circle(r: Float)
  | Square(side: Float)
  derive Show
Open in playground

src/main.dawn:

use util/math
use util/math.{Shape, Circle, Square}

pub fn main() -> Unit !io = {
  println(to_string(math.double(21)))
  println(to_string(Circle(2.0)))
}
Open in playground

dawn run myapp, given a directory, compiles and runs the whole project; dawn test myapp runs the test blocks of every module, and dawn build myapp packs it into one jar. Single-file dawn run foo.dawn still works. A use cycle is a compile error, and so is a name that collides with an imported module's alias — the two share one namespace.