Packages
A Virdant design may be split across multiple files. Each file is a Virdant package. Packages allow you to organize your design into logical units and reuse declarations across files.
Package :=
DocBang PackageStmt*
PackageStmt :=
PackageImport
| Item
A package consists of an optional package-level documentation comment (//!, called DocBang in the grammar), followed by zero or more import statements and item declarations.
Package Structure
Each Virdant source file corresponds to one package. The package name is derived from the filename:
buffer.vir defines the buffer package
top.vir defines the top package
uart/ would define the uart package
The file extension is .vir. Filenames should begin with a lowercase letter and use snake_case for multi-word names.
Import Statements
An import statement makes declarations from another package visible in the current package.
PackageImport :=
"import" Ident
// top.vir
import buffer
mod Top {
incoming clock : Clock
incoming inp : Word[8]
outgoing out : Word[8]
mod buf of buffer::Buffer {
it.clock := clock
it.inp := inp
}
out := buf.out
}
The import keyword is followed by the package name (without the .vir extension). All items marked pub in the imported package become available through their fully-qualified names.
Fully-Qualified Names
Declarations from imported packages are accessed using fully-qualified names with the :: separator.
Ofness :=
Ident | Ident "::" Ident
The first component is the package name, and the second is the declaration name within that package.
import buffer
mod buf of buffer::Buffer
Here, buffer::Buffer refers to the Buffer module defined in the buffer package.
Fully-qualified names are used in type positions (after of, in : Type) and in function call positions.
Within the same package, declarations may be referred to by their simple name without the :: prefix.
Public Declarations (pub)
Only items marked with the pub modifier are visible to other packages.
// buffer.vir
pub mod Buffer {
incoming clock : Clock
incoming inp : Word[8]
outgoing out : Word[8]
reg r : Word[8] on clock
r <= inp
out := r
}
// Not pub: only visible within buffer.vir
mod InternalHelper {
// ...
}
An item without the pub keyword is private to the package. Referencing a non-pub item from another package is an error at the reference site; the import statement itself never fails for visibility reasons. A warning is also emitted at the non-pub item’s definition, naming the package that references it, so the item’s author learns that another package depends on it. The warning is reported once per referencing package, no matter how many times the item is referenced.
The pub modifier is available on every top-level item kind:
Module definitions (mod)
Struct type definitions (struct type)
Union type definitions (union type)
Enum type definitions (enum type)
Builtin type definitions (builtin type)
Socket definitions (socket)
Platform definitions (platform)
Within the defining package, every item is visible to every other item, whether pub or not: pub only matters at package boundaries.
A pub item may not expose a non-pub item to other packages: every type appearing in a pub item’s public surface (module port types, struct/union field types, enum variant payload types, socket cosi/ soci types) must itself be transitively pub. Referencing a type whose head is not pub from a pub item’s surface is an error at the offending type’s span. Generic parameters (T in Word[T]) are exempt: they are bound at the instantiation site. A pub mod may be generic; only the top module named by [prog] top must be non-generic.
Package Dependency
When one package imports another, the compiler must be able to find the imported package’s source file. The compiler searches for imported packages in the same directory as the importing file and in any directories specified as library search paths.
Circular imports are not permitted. If package A imports package B, then B may not import A (directly or transitively).
Package-Level Documentation
A package may have a package-level documentation comment (//!) at the top of the file. This comment serves as package-level documentation.
//! This package contains the UART transmitter and receiver modules.
import clockgen
mod UartTx {
// ...
}