Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions crates/moonbit/src/async/ev.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
/// source; `owned_coroutines` contains only runtime bridge coroutines.
priv struct ComponentTaskState {
lane : TaskLane
subscribers : Map[Int, Subscriber]
subscribers : @sorted_map.SortedMap[Int, Subscriber]
task : Coroutine
owned_coroutines : @set.Set[Coroutine]
mut resolution : TaskResolution
Expand Down Expand Up @@ -52,7 +52,7 @@ fn current_waitableset() -> WaitableSet {

///|
fn component_task_state(waitable_set : WaitableSet) -> ComponentTaskState? {
component_tasks.get(waitable_set)
component_tasks.get(waitable_set.0)
}

///|
Expand All @@ -66,7 +66,7 @@ fn finish_waitableset(
}
drop_task_wakeup(task_state)
guard task_state.subscribers.is_empty() else { panic() }
component_tasks.remove(waitable_set)
component_tasks.remove(waitable_set.0)
waitable_set.drop()
tls_set(0)
}
Expand Down Expand Up @@ -154,13 +154,13 @@ pub fn with_waitableset(f : async () -> Unit) -> Int {
let task = spawn_owned(f, lane, None)
let task_state = {
lane,
subscribers: Map([]),
subscribers: SortedMap([]),
task,
owned_coroutines: Set([]),
resolution: Pending,
cancellation_pending: false,
}
component_tasks.set(waitable_set, task_state)
component_tasks.set(waitable_set.0, task_state)
reschedule(lane)
next_callback(waitable_set, task_state)
}
Expand Down Expand Up @@ -215,7 +215,9 @@ pub fn cb(event : Int, waitable_id : Int, code : Int) -> Int {
}

///|
let component_tasks : Map[WaitableSet, ComponentTaskState] = Map([])
// Host handles need not be dense. An ordered map bounds lookup cost without
// hashing or allocating storage up to the largest handle.
let component_tasks : @sorted_map.SortedMap[Int, ComponentTaskState] = SortedMap([])

///|
/// Spawn a coroutine owned by the current component-model async task.
Expand Down
1 change: 1 addition & 0 deletions crates/moonbit/src/async/moon.pkg
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
"moonbitlang/core/deque" @deque,
"moonbitlang/core/ref" @ref,
"moonbitlang/core/set" @set,
"moonbitlang/core/sorted_map" @sorted_map,
}

warnings = "-44"
Expand Down
13 changes: 9 additions & 4 deletions crates/moonbit/src/async_support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1256,6 +1256,11 @@ impl<'a> InterfaceGenerator<'a> {
.world_gen
.pkg_resolver
.qualify_package(&helper_package, ASYNC_CORE_DIR);
let sorted_map = endpoint_use.lower.then(|| {
self.world_gen
.pkg_resolver
.qualify_external_package(&helper_package, "moonbitlang/core/sorted_map")
});

let elem_size = result_type
.map(|ty| self.world_gen.sizes.size(ty).size_wasm32())
Expand Down Expand Up @@ -1754,7 +1759,7 @@ fn wasm{symbol_name}FutureLowerCommitted(future : {ffi}Future[{result}]) -> Int
)
})
.unwrap_or_default();
let lower_bridge = if endpoint_use.lower {
let lower_bridge = if let Some(sorted_map) = &sorted_map {
format!(
r#"
///|
Expand All @@ -1764,7 +1769,7 @@ priv struct Wasm{symbol_name}FutureProducer {{
}}

///|
let wasm{symbol_name}FutureProducers : Map[Int, Wasm{symbol_name}FutureProducer] = Map([])
let wasm{symbol_name}FutureProducers : {sorted_map}SortedMap[Int, Wasm{symbol_name}FutureProducer] = {sorted_map}SortedMap([])

{reject_prepared_func}

Expand Down Expand Up @@ -2094,7 +2099,7 @@ fn wasm{symbol_name}StreamLowerCommitted(stream : {ffi}Stream[{result}]) -> Int
)
})
.unwrap_or_default();
let lower_bridge = if endpoint_use.lower {
let lower_bridge = if let Some(sorted_map) = &sorted_map {
format!(
r#"
///|
Expand All @@ -2104,7 +2109,7 @@ priv struct Wasm{symbol_name}StreamProducer {{
}}

///|
let wasm{symbol_name}StreamProducers : Map[Int, Wasm{symbol_name}StreamProducer] = Map([])
let wasm{symbol_name}StreamProducers : {sorted_map}SortedMap[Int, Wasm{symbol_name}StreamProducer] = {sorted_map}SortedMap([])

{reject_prepared_func}

Expand Down
49 changes: 49 additions & 0 deletions crates/moonbit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@ impl MoonBit {
.packages
.iter()
.map(|(k, v)| format!("\"{}/{}\" @{},", self.project_name, k.replace(".", "/"), v))
.chain(
imports
.external_packages
.iter()
.map(|(path, alias)| format!("\"{path}\" @{alias},")),
)
.collect::<Vec<_>>();
deps.sort();
uwriteln!(moon_pkg, "{}", deps.join("\n"));
Expand Down Expand Up @@ -3458,6 +3464,49 @@ mod tests {
);
}

#[test]
fn producer_tables_import_ordered_maps_without_changing_wit_maps() {
let files = generate(
r#"
package a:b;

interface outgoing {
send: func(ready: future<u32>, values: stream<u8>, labels: map<string, u32>);
}

interface incoming {
receive: func() -> tuple<future<u32>, stream<u8>>;
}

world runner {
import outgoing;
import incoming;
export incoming;
}
"#,
"runner",
);

for package in ["interface/a/b/outgoing", "gen/interface/a/b/incoming"] {
let manifest = file(&files, &format!("{package}/moon.pkg"));
assert!(
manifest.contains("\"moonbitlang/core/sorted_map\" @sorted_map,"),
"{manifest}"
);
let ffi = file(&files, &format!("{package}/ffi.mbt"));
for kind in ["Future", "Stream"] {
assert!(
ffi.contains(&format!("{kind}Producers : @sorted_map.SortedMap[Int,")),
"{ffi}"
);
}
}
let incoming = file(&files, "interface/a/b/incoming/moon.pkg");
assert!(!incoming.contains("sorted_map"), "{incoming}");
let outgoing = file(&files, "interface/a/b/outgoing/top.mbt");
assert!(outgoing.contains("Map[String, UInt]"), "{outgoing}");
}

#[test]
fn fixed_primitive_streams_use_four_kibibyte_buffer_budget() {
for (wit_type, expected_window) in [
Expand Down
26 changes: 26 additions & 0 deletions crates/moonbit/src/pkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub(crate) const ASYNC_CORE_DIR: &str = "async-core";
#[derive(Default)]
pub(crate) struct Imports {
pub packages: HashMap<String, String>,
pub external_packages: HashMap<String, String>,
ns: Ns,
}

Expand All @@ -33,6 +34,15 @@ pub(crate) struct PkgResolver {
}

impl PkgResolver {
pub(crate) fn qualify_external_package(&mut self, this: &str, path: &str) -> String {
let imports = self.package_import.entry(this.to_string()).or_default();
let alias = imports
.external_packages
.entry(path.to_string())
.or_insert_with(|| imports.ns.tmp(path.rsplit('/').next().unwrap()));
format!("@{alias}.")
}

pub(crate) fn qualify_package(&mut self, this: &str, name: &str) -> String {
if name != this {
let imports = self.package_import.entry(this.to_string()).or_default();
Expand Down Expand Up @@ -388,6 +398,22 @@ impl PkgResolver {
mod tests {
use super::*;

#[test]
fn external_imports_share_the_generated_package_alias_namespace() {
let mut packages = PkgResolver::default();
let generated = packages.qualify_package("gen", "interface.a.b.sorted_map");
let external = packages.qualify_external_package("gen", "moonbitlang/core/sorted_map");
assert_ne!(generated, external);
assert_eq!(
packages.qualify_external_package("gen", "moonbitlang/core/sorted_map"),
external
);
assert_eq!(
packages.qualify_package("gen", "interface.a.b.sorted_map"),
generated
);
}

#[test]
fn package_names_and_aliases_preserve_kebab_case() {
let mut resolve = Resolve::default();
Expand Down
Loading