Release - Mun v0.4.0

December 12, 2022, The Mun Team

Guess who’s back?! The previous Mun release dates back over one and a half years. Since then - slowly but steadily - we’ve been working towards Mun v0.4.0 and it’s finally here! This tick-release mainly focuses on language-support for dynamically-sized arrays, but we’ve also transitioned to a monorepo, added support for Apple’s M1 chips and experimental support for iOS, refactored major parts of our backend to support indirect types and recursion - as seen with arrays and pointers - and solved a range of bugs.

What’s Mun?

For those of you who haven’t heard of Mun before, Mun is an embeddable programming language empowering creation through iteration. The idea to create Mun originated out of frustration with the Lua dynamic scripting language and a desire to have similar hot reloading functionality available in Rust. As such, it’s not a direct competitor with Rust, but instead is intended to be used with Rust (or C/C++) as a host/embedded language pairing. Actually, Mun is completely written in Rust, building on similar crates as rust-analyzer and rustc. Its key features include:

  • Ahead of time compilation - Mun is compiled ahead of time (AOT), as opposed to being interpreted or compiled just in time (JIT).

  • Statically typed - Mun resolves types at compilation time instead of at runtime, resulting in immediate feedback when writing code and opening the door for powerful refactoring tools.

  • First class hot-reloading - Every aspect of Mun is designed with hot reloading in mind. Hot reloading is the process of changing code and resources of a live application, removing the need to start, stop and recompile an application whenever a function or value is changed.

What’s new?

Mun v0.4 does not only bring arrays to Mun, but it lays the groundwork for a plethora of language features that require indirect types and recursion. These required a rewrite of Mun’s ABI, allocator, memory mapper, and garbage collector.

But that’s not all! In total, this release contains 111 pull requests made by 5 of our community contributors and our two Core Team members & Dependabot. Thanks for having our back! For a full list have a look at the changelog, but the main improvements are:

  • Dynamically-sized arrays

    pub fn generate() -> [u64] {
      [5, 4, 3, 2, 1]
    }
    
    pub fn add_one(array: [u64], len: usize) -> [u64] {
        let idx = 0;
        loop {
            array[idx] += 1;
            idx += 1;
    
            if idx >= len {
                break array
            }
        }
    }
    
    fn main() {
        add_one(generate(), 5);
    }

    NOTE: Array functionality is still very basic as you cannot resize arrays (incl. pushing elements) at runtime. You can only get, set, and replace array elements. Future releases of Mun will extend this functionality.

  • Simplified function invocations from Rust

    let runtime_ref = runtime.borrow();
    let arg: i64 = runtime_ref.invoke("arg", (a,b)).unwrap();
  • Simplified struct API for Rust

    let builder = Runtime::builder("mun/target/mod.munlib")
      .insert_fn("rand_f32", rand_f32 as extern "C" fn() -> f32);
    
    let runtime = unsafe { builder.finish() }.expect("Failed to load munlib");
    
    let state: StructRef = runtime.invoke("new_state", ()).unwrap();
    let state = state.root();
    let pong = PongGame { runtime, state };
    
    let state = pong.state.as_ref(&pong.runtime);
  • Apple M1 & experimental iOS support

  • Upgrade to LLVM 13

  • Support for runtime usage in entity component systems (ECS)

    fn main() {
      let lib_dir = PathBuf::from(env::args().nth(1).expect("Expected path to a Mun library."));
    
      App::new()
          .add_plugins(MinimalPlugins)
          .add_plugin(MunPlugin { lib_dir })
          .run();
    }
    
    struct MunPlugin {
      lib_dir: PathBuf,
    }
    
    impl Plugin for MunPlugin {
      fn build(&self, app: &mut App) {
          app.insert_resource(self.lib_dir.clone())
              .add_startup_system(setup.exclusive_system())
              .add_system(reload_munlib_every_frame);
      }
    }
    
    fn setup(world: &mut World) {
      let builder = MunRuntime::builder(
          world
              .get_resource::<PathBuf>()
              .expect("Lib path must be added as resource"),
      );
      let mun: MunRuntime = unsafe { builder.finish() }.expect("Failed to spawn Runtime");
      world.insert_non_send_resource(mun);
    
      world.remove_resource::<PathBuf>();
    }
    
    fn reload_munlib_every_frame(
      mut mun: NonSendMut<MunRuntime>,
    ) {
        let _ = unsafe { mun.update() };
    }
  • Adopted monorepo for better developer experience

  • Decreased unsafe code usage and simplified code

  • Assorted bug fixes

What’s next?

Mun is still in early development, so there is a lot to do. The Mun Core Team operates according to a tick-tock release cycle. Development of a tock release (Mun v0.5) focuses on using and improving existing features, whereas a tick release (Mun v0.6) focuses on implementing new features.

When planning Mun v0.4, we decided to limit our focus to adding support for arrays and optimising our Mun ABI format in the hopes of adhering to semiannual release schedule. However, due to our limited availability, it still took us way longer than expected to release. As such, we’re not giving an estimated release date for Mun v0.5 but we can say that it will introduce impl blocks for functions and we’ll be upgrading to LLVM v16.0. For a complete roadmap, please visit our GitHub milestones.

How can I learn more?

To get started, read the Mun Book and have a look at our Rust and C++ examples.

If you are interested in helping develop Mun feel free to reach out to us on Discord or Twitter, or pick up one of our good first issues on GitHub.

If you cannot personally contribute but would still like to support our cause, please consider donating to our Open Collective or Github Sponsors.

Acknowledgments

This release would not have been possible without the incredible contributions from the Mun Community. We are extremely grateful to all of you!