Skip to content
This repository was archived by the owner on May 4, 2026. It is now read-only.

Commit cc921a0

Browse files
mohammadfawazclaude
andcommitted
Tighten cross-program interface examples
- Split mapping/storage interface examples into two files so the interface lives with its owning program and call sites are clearly cross-program. - Drop blow-by-blow list of frontend passes in libraries.md in favor of "semantic validation". Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 3275b11 commit cc921a0

2 files changed

Lines changed: 47 additions & 4 deletions

File tree

documentation/language/06_libraries.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ Explicit disambiguation using absolute paths (similar to Rust's `crate::foo::…
183183

184184
## Building a Library
185185

186-
Running `leo build` inside a library package parses the library sources and runs the full frontend pipeline — name validation, global-item collection, path resolution, interface checks, type checking, and static analysis — on the library itself. Type errors, unknown identifiers, interface-cycle errors, and the like are reported at the library package, instead of surfacing only when a downstream program consumes it.
186+
Running `leo build` inside a library package parses the library sources and runs semantic validation on the library itself. Type errors, unknown identifiers, interface-cycle errors, and the like are reported at the library package, instead of surfacing only when a downstream program consumes it.
187187

188188
```bash
189189
cd math_utils

documentation/language/programs_in_practice/interfaces.md

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,33 @@ Interface@(target[, network])::mapping.get_or_use(key, default)
204204

205205
These reads are only valid inside a `final fn` or a `final {}` block — they lower to the AVM `get.dynamic`, `contains.dynamic`, and `get.or_use.dynamic` instructions. Dynamic *writes* are not supported.
206206

207-
```leo
207+
`bank.aleo` declares the `Bank` interface and implements it:
208+
209+
```leo title="bank/src/main.leo"
208210
interface Bank {
209211
mapping balances: address => u64;
210212
}
211213
214+
program bank.aleo: Bank {
215+
mapping balances: address => u64;
216+
217+
fn deposit(user: address, amount: u64) -> Final {
218+
return final { do_deposit(user, amount); };
219+
}
220+
221+
@noupgrade
222+
constructor() {}
223+
}
224+
225+
final fn do_deposit(user: address, amount: u64) {
226+
let prev: u64 = Mapping::get_or_use(balances, user, 0u64);
227+
Mapping::set(balances, user, prev + amount);
228+
}
229+
```
230+
231+
A second program imports `bank.aleo` and reads its mapping through the interface. Since the read is cross-program, the interface name is qualified with `bank.aleo::`:
232+
233+
```leo title="checker/src/main.leo"
212234
import bank.aleo;
213235
214236
program checker.aleo {
@@ -229,7 +251,7 @@ final fn do_read(target: field, user: address) {
229251
}
230252
```
231253

232-
When the interface is in scope without a program qualifier (for example, self-reading from the program that declares it), the leading `program.aleo::` segment can be omitted: `Bank@(target)::balances.get(key)`.
254+
When the reader is inside the same program that declares the interface, drop the program qualifier — `Bank@(target)::balances.get(key)` rather than `bank.aleo::Bank@(target)::balances.get(key)`.
233255

234256
### Dynamic Storage Reads
235257

@@ -243,12 +265,33 @@ Interface@(target[, network])::vector.len() // u32
243265

244266
Singleton storage is read by naming the variable directly (no trailing `.op(...)`). Vector storage supports `.get(index)` (out-of-bounds reads return `none`) and `.len()` (no arguments). Storage writes through the dynamic interface are not supported — use a dynamic call to an entry function that performs the write.
245267

246-
```leo
268+
`logger.aleo` declares the `Logger` interface and implements it:
269+
270+
```leo title="logger/src/main.leo"
247271
interface Logger {
248272
storage counter: u64;
249273
storage entries: [u64];
250274
}
251275
276+
program logger.aleo: Logger {
277+
storage counter: u64;
278+
storage entries: [u64];
279+
280+
fn bump(val: u64) -> Final {
281+
return final {
282+
counter = counter.unwrap_or(0u64) + 1u64;
283+
entries.push(val);
284+
};
285+
}
286+
287+
@noupgrade
288+
constructor() {}
289+
}
290+
```
291+
292+
A second program imports `logger.aleo` and reads its storage variables through the interface. Since the read is cross-program, the interface name is qualified with `logger.aleo::`:
293+
294+
```leo title="reader/src/main.leo"
252295
import logger.aleo;
253296
254297
program reader.aleo {

0 commit comments

Comments
 (0)