Skip to content

Conversation

@mohammadfawaz
Copy link
Collaborator

@mohammadfawaz mohammadfawaz commented Aug 7, 2025

Closes #28770

This PR introduces a structured module system for Leo, enabling multi-file programs under the src/ directory with clear rules for module layout and resolution.

📁 Example Directory Structure

src
├── common.leo
├── main.leo
├── outer.leo
├── outer
│   ├── inner.leo

📦 Modules and Their Access Paths

Given the structure above, the following modules are defined:

  1. common.leo defines module common, accessible from main.leo via: common::<item>
  2. outer.leo defines module outer, accessible from main.leo via: outer::<item>
  3. outer/inner.leo defines submodule outer::inner, accessible from:
    • main.leo: outer::inner::<item>
    • outer.leo: inner::<item>

📏 Module Layout Rules

This PR also enforces new rules to prevent ambiguity and ensure consistency:

  1. Leaf modules (i.e. modules without submodules) must be defined in a single file: foo.leo
  2. Modules with submodules must be defined by an optional top-level foo.leo file and a foo/ directory containing the submodules:
    foo.leo        # defines module `foo` - this is optional
    foo/
      ├── bar.leo  # defines submodule `foo::bar`
    

Only relative paths are implemented so far. That means that items in outer.leo cannot be accessed from items in inner.leo, for example. This is limiting for now but will no longer be an issue when we add absolute paths.

The changes were tedious but not particularly complicated. The largest changes in the compiler is the replacement of Expression::Identifier with Expression::Path.

For now, modules can only have struct, inline, and const. We may decide to relax that restriction in the future.

I've added support for modules in the current interpreter and added some tests. Hopefully mirroring this implementation in the new interpreter won't cause too much trouble.

@mohammadfawaz mohammadfawaz marked this pull request as draft August 7, 2025 15:54
@mohammadfawaz mohammadfawaz changed the title symadd multi file Multi-file Leo Aug 7, 2025
@mohammadfawaz mohammadfawaz force-pushed the mohammadfawaz/modules branch 8 times, most recently from bcad481 to 68be122 Compare August 11, 2025 16:35
@mohammadfawaz mohammadfawaz self-assigned this Aug 12, 2025
@mohammadfawaz mohammadfawaz marked this pull request as ready for review August 12, 2025 16:09
@mohammadfawaz mohammadfawaz requested review from d0cd and mikebenfield and removed request for mikebenfield August 12, 2025 16:10
@mohammadfawaz
Copy link
Collaborator Author

Note: I have not yet updated all the parser tests because that would make this PR very large (~20k lines) due to the Identifier {..} to Path {..} change. Since those changes are trivial, I will make them after the review is done.

@mohammadfawaz mohammadfawaz changed the title Multi-file Leo Module System Aug 12, 2025
@mikebenfield
Copy link
Contributor

more serious review to come

@mikebenfield
Copy link
Contributor

if program a.aleo imports b.aleo, and b.aleo has a struct in a module some_module::SomeStruct, do we intend for a.aleo to be able to refer to that as b.aleo/some_module::SomeStruct ? I think we likely want that, but right now that doesn't parse.

@mohammadfawaz
Copy link
Collaborator Author

mohammadfawaz commented Aug 13, 2025

if program a.aleo imports b.aleo, and b.aleo has a struct in a module some_module::SomeStruct, do we intend for a.aleo to be able to refer to that as b.aleo/some_module::SomeStruct ? I think we likely want that, but right now that doesn't parse.

This doesn't work today even without the module stuff right? And struct naming is global at the moment? But yeah would certainly be nice to have all that stuff working as one would expect.

@mohammadfawaz mohammadfawaz force-pushed the mohammadfawaz/modules branch from b987037 to fef78a1 Compare August 13, 2025 20:40
@mohammadfawaz
Copy link
Collaborator Author

Addressed the first wave of comments in fef78a1

@mohammadfawaz
Copy link
Collaborator Author

if program a.aleo imports b.aleo, and b.aleo has a struct in a module some_module::SomeStruct, do we intend for a.aleo to be able to refer to that as b.aleo/some_module::SomeStruct ? I think we likely want that, but right now that doesn't parse.

Alright so yeah we can make this work but only if b.aleo/ is added so that we can treat this path as a special one and legalize some_module::SomeStruct before looking for it in the symbol table. This is a bit inconsistent though since we don't require b.aleo for external structs at the moment.

@mikebenfield
Copy link
Contributor

This is a bit inconsistent though since we don't require b.aleo for external structs at the moment.

Right yeah I wasn't really thinking about that. Maybe we just don't worry about it until the external structs stuff is complete.

Copy link
Collaborator

@d0cd d0cd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be helpful to have one of the existing leo-examples adapted to use the new module system. Or even add a new one!

Can we also file an issue in leo-docs-source to document this?

Copy link
Collaborator

@d0cd d0cd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, the PR looks good! Left some relatively minor nits and questions. This should be good to go after the parser expectations are in.

There is also a fairly extensive example here: ProvableHQ/leo-examples#17

@mohammadfawaz mohammadfawaz force-pushed the mohammadfawaz/modules branch 5 times, most recently from 7014d1f to c562c39 Compare August 27, 2025 14:07
@mohammadfawaz mohammadfawaz changed the base branch from mainnet to mohammadfawaz/28799 August 27, 2025 14:09
Base automatically changed from mohammadfawaz/28799 to mainnet August 27, 2025 16:35
@mohammadfawaz mohammadfawaz force-pushed the mohammadfawaz/modules branch from c562c39 to 2eb1c11 Compare August 27, 2025 16:36
@mohammadfawaz mohammadfawaz merged commit c935b08 into mainnet Aug 27, 2025
8 checks passed
@mohammadfawaz mohammadfawaz deleted the mohammadfawaz/modules branch August 27, 2025 17:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Basic module system with relative paths

4 participants