Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optional namespaces with shared aliases #448

Merged
merged 4 commits into from
Mar 5, 2017

Conversation

bvssvni
Copy link
Member

@bvssvni bvssvni commented Mar 5, 2017

For design, see #434

  • Published 0.24.0

This PR adds optional namespaces to Dyon as a way to organize code and avoid name collisions. At the moment this is only supported for loaded modules, not external functions.

How dynamic modules work in Dyon

Dyon uses dynamic modules to organize code. In order for one module to depend on another, you write a loader script, like this:

fn main() {
    graphics := unwrap(load("graphics.dyon"))
    program := unwrap(load(source: "main.dyon", imports: [graphics]))
    call(program, "main", [])
}

This puts the functions declared in graphics in the prelude of the module program. You do not have to write any imports, you just call them:

fn main() {
    render() // the `render` function is put in the prelude by loader script
}

This design makes it easy to refactor code, because you can simply copy and paste a function to another module and expect it to work. Since module loading is controlled by the loader script, you can update parts of the program while running.

How optional namespaces work

An optional namespace can be declared at the beginning of the file with the ns keyword:

ns graphics

fn render() { ... }

This puts all functions in this file in an extra namespace graphics.

You can also uses nested namespaces, like this:

ns graphics::animation::skeleton

fn render() { ... }

To use a namespace, you write use after the line with ns and give it an alias:

ns program

use graphics as gfx

fn main() {
    gfx::render() // call the `render` function with the namespace alias `gfx`
}

All use statements requires an alias. This is designed to make refactoring easier, because you can just change the top of the file instead of going through the whole code.

You can also share an alias between multiple imports, like this:

ns program

use game_logic as game
use graphics as game
use window as game

fn main() {
     loop {
         if game::closed() {break}
         // update game logic.
         game::update()
         // render to screen.
         game::render()
     }
}

Notice that you still can use the default namespace, so without any name collisions you can just write like this:

ns program

fn main() {
     loop {
         if closed() {break}
         // update game logic.
         update()
         // render to screen.
         render()
     }
}

Import specific functions while excluding others

ns program

// Only use `render` and `swap_buffer` with the `game` namespace alias
use graphics::{render, swap_buffer} as game

fn main() {
    game::render()
    game::swap_buffer()
}

When importing specific functions, they will shadow any function in global import:

ns program

use graphics::{render} as game
use game_logic as game

fn main() {
    game::render() // always call `graphics::render`, even if `game_logic` adds a `render`.
}

Rename a specific function

ns program

use graphics::{render as present} as game

fn main() {
    game::present() // `render` is now called `present`
}

@bvssvni bvssvni merged commit 662d943 into PistonDevelopers:master Mar 5, 2017
@bvssvni bvssvni deleted the namespace branch March 5, 2017 18:59
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.

None yet

1 participant