feat: load canonical directory packages
This commit is contained in:
@@ -18,6 +18,10 @@ run a source file with the interpreter:
|
||||
./build/honey run example.hon
|
||||
```
|
||||
|
||||
`run`, `emit-llvm` and `build` also accept a directory. directory inputs compile its `.hon` and `.bro` files in bytewise filename order, excluding `.test.hon`/`.test.bro` and non-file entries; a file input still compiles only that file, not its siblings. declarations share a scope within each package, while dependencies have separate scopes and cannot supply the root package's `main`.
|
||||
|
||||
bare `import "../library"` and aliased `library :: import "@library"` declarations discover dependencies. relative paths start at the importing package directory; `@` starts at the nearest ancestor containing `build.hon` or `build.bro`, falling back to the entry package directory. package directories are canonicalized through symlinks and loaded once. cycles, missing/empty dependencies and invalid import paths produce source diagnostics. absolute paths and empty, escaped or control-containing import strings are rejected. production loading ignores test-only imports. namespace aliases are not bound yet, and qualified calls such as `library.add(...)` remain unsupported.
|
||||
|
||||
```hon
|
||||
add proc(left, right int) int {
|
||||
return left + right
|
||||
@@ -91,9 +95,9 @@ range bounds that are compound or unary expressions require their own parenthese
|
||||
|
||||
name resolution (`@source/sema`) runs after parsing. it predeclares package names and each block's direct locals, allowing forward references and mutually recursive functions. parameters and top-level function-body locals share a scope; each conditional arm and loop body introduces a child scope whose names do not escape it. signatures resolve names in the enclosing package scope. shadowing is forbidden, including reuse of builtin type names (`int`, `float`, `i64`, `f64`, `usize`, `bool`, `string`, `void`); sibling scopes may independently reuse names.
|
||||
|
||||
the driver uses `@source/compilation` to own loaded source buffers, copied paths, ASTs, package membership and a shared identifier pool. `add_source` scans/parses a source and transfers its `ArrayList(u8)` allocation only on success, resetting the caller's list; failure leaves the bytes caller-owned. `deinit` releases all retained frontend storage. source metadata borrows are invalidated by registration growth, but `SourceId` and `PackageId` remain stable within their compilation.
|
||||
the driver uses `@source/compilation` to own loaded source buffers, copied paths, one AST arena, the package graph and a shared identifier pool. `add_source` transfers its `ArrayList(u8)` allocation only on success, resetting the caller's list; infrastructure failure leaves the bytes caller-owned and rolls back the source registration, partial AST and source diagnostics. interned names may remain in the shared pool. `deinit` releases all retained frontend storage. metadata borrows are invalidated by registration growth, but source/package/node IDs remain stable within their compilation.
|
||||
|
||||
AST `NodeId` values remain source-local. cross-source declarations use `compilation.DeclarationId { source, node }`, so identical local node numbers from different files cannot alias. `compilation.compile` currently checks/lowers one registered source into independently owned IR; package IDs and source membership do not yet implement directory loading, imports or cross-source name resolution. CLI commands still compile one file, and multi-source diagnostic reporting remains a later package milestone.
|
||||
AST `NodeId` values are compilation-wide, so declarations in different files cannot alias. spans carry their originating `diagnostics.SourceId`; `ast.source_files` exposes borrowed paths and text. `compilation.compile` resolves each package independently, checks the complete arena and lowers one independently owned IR module, selecting an entry only from the requested root package. interpreter diagnostics and generated native traps retain the originating filename and local line/byte-column. borrowed `ast.view` trees must be refreshed after builder mutation and must not be passed to `ast.deinit`.
|
||||
|
||||
identifier interning is compilation-owned: initialize a `strpool.StringPool`, pass it to `lexer.scan` and `sema.resolve` before the diagnostic store, and release it after lowering. scanning interns identifier spellings once per pool; parsing preserves their IDs in compact AST storage, exposed through `ast.name_id`, while retaining source spans for diagnostics. name resolution keys scopes by those IDs and interns builtin names into the same pool, so identifier hashing and equality do not scan spelling bytes. IDs are meaningful only within their originating pool; independent compilations may assign the same numeric ID to different names. interning failures propagate as infrastructure errors rather than producing an invalid identifier ID. IR retains no pool dependency.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user