Skip to main content

submilli_engine/runtime/prelude/boolean/
mod.rs

1//! The Rust port of the prelude's `Boolean` surface — `toString` / `toJson`,
2//! both `"true"` / `"false"`. The receiver is the unboxed `i32` (0 = false).
3
4use crate::runtime::host::{abi_arg, abi_result};
5use wasmtime::{FuncType, HeapType, Linker, RefType, Val, ValType};
6
7use crate::runtime::StoreData;
8use crate::runtime::host::{intrinsic_string_type, register_host_fn, write_submilli_string_struct};
9use crate::runtime::prelude::{MODULE_NAME, declare_method};
10use crate::{MangledName, PackageDeclaration, Param, Type};
11
12fn method_key(method: &str) -> MangledName {
13    crate::mangle::extend(&crate::mangle::prelude("Boolean"), method)
14}
15
16pub fn install(linker: &mut Linker<StoreData>) -> wasmtime::Result<()> {
17    let engine = linker.engine().clone();
18    let string_struct = intrinsic_string_type(&engine)?;
19    let string_ref = ValType::Ref(RefType::new(false, HeapType::ConcreteStruct(string_struct)));
20
21    // `toString` and `toJson` are identical for a boolean — both spell the value.
22    for method in ["toString", "toJson"] {
23        let s = string_ref.clone();
24        register_host_fn(
25            linker,
26            MODULE_NAME,
27            method_key(method),
28            FuncType::new(&engine, [ValType::I32], [s]),
29            true,
30            |caller, params, results| {
31                let truthy = match *abi_arg(params, 0)? {
32                    Val::I32(v) => v != 0,
33                    ref other => {
34                        return Err(wasmtime::Error::msg(format!(
35                            "Boolean method expects i32, got {other:?}"
36                        )));
37                    }
38                };
39                let st =
40                    write_submilli_string_struct(caller, if truthy { "true" } else { "false" })?;
41                *abi_result(results, 0)? = Val::AnyRef(Some(st.to_anyref()));
42                Ok(())
43            },
44        )?;
45    }
46    Ok(())
47}
48
49pub fn declare(defs: &mut PackageDeclaration) {
50    let recv = || Param::new("value", Type::Boolean);
51    declare_method(
52        defs,
53        "toString",
54        method_key("toString"),
55        vec![recv()],
56        Type::String,
57    );
58    declare_method(
59        defs,
60        "toJson",
61        method_key("toJson"),
62        vec![recv()],
63        Type::String,
64    );
65}
66
67/// The type/interface surface this module implements — its slice of the
68/// prelude declaration (see `declaration::prelude_package_declaration`).
69#[allow(clippy::too_many_lines)]
70pub(crate) fn declare_types(defs: &mut crate::PackageDeclaration) {
71    use crate::runtime::prelude::declaration::doc;
72    use crate::{Dispatch, MethodSig, Span, Type, TypeKind, TypeSymbol};
73    use std::collections::BTreeMap;
74    defs.types.insert(
75        "Boolean".to_string(),
76        TypeSymbol {
77            name: "Boolean".to_string(),
78            mangled_name: crate::mangle::prelude("Boolean"),
79            declaration_span: Span::at(crate::FileId::PRELUDE),
80            kind: TypeKind::Interface { index: None,
81                generics: Vec::new(),
82                methods: BTreeMap::from([
83                    (
84                        "toString".to_string(),
85                        MethodSig {
86                            optional: false,
87                            generics: Vec::new(),
88                            params: Vec::new(),
89                            ret: Type::String,
90                            predicate: None,
91                            doc: doc("/** Returns `\"true\"` or `\"false\"`. */"),
92                        },
93                    ),
94                    (
95                        "toJson".to_string(),
96                        MethodSig {
97                            optional: false,
98                            generics: Vec::new(),
99                            params: Vec::new(),
100                            ret: Type::String,
101                            predicate: None,
102                            doc: doc(
103                                "/** Returns `\"true\"` or `\"false\"` — same as `toString` (booleans are JSON-native). */",
104                            ),
105                        },
106                    ),
107                ]),
108                properties: BTreeMap::new(),
109                dispatch: Dispatch::Direct,
110                doc: doc("/** The boolean type — `true` or `false`. */"),
111            },
112        },
113    );
114}