// SPDX-FileCopyrightText: 2026 Milovann Yanatchkov // SPDX-License-Identifier: MIT //! bimr-wasm — browser adapter for the [`bimr-engine`](https://git.rvba.fr/rvba/bimr-engine) eval. //! //! **Whole-source only**: the adapter exposes exactly one export — //! `compile(src)`. There is no session layer, no per-call construction, and //! no side queries: Python emits `.bimr` text and calls `compile()` once, //! the same path as the CLI. The `.bimr` intermediate is the compatibility //! layer; whole-source is the single entry point for the CLI, web Python, //! and LLM paths. //! //! Errors return `{"error": "..."}` JSON strings. use wasm_bindgen::prelude::*; fn parse_or_error(src: &str) -> Result { parser::parse(src).map_err(|errors| { let msg = errors .iter() .map(|e| format!("{e:?}")) .collect::>() .join("; "); format!("{{\"error\": \"{}\"}}", msg.replace('"', "'")) }) } /// Compile a `.bimr` source string to IFCX JSON. /// /// Returns a JSON string — either an IFCX document on success, or /// `{"error": "..."}` on parse/eval failure. #[wasm_bindgen] pub fn compile(src: &str) -> String { let program = match parse_or_error(src) { Ok(p) => p, Err(e) => return e, }; match eval::eval_program(&program, "model.bimr") { Ok(store) => eval::to_ifcx(&store), Err(e) => format!("{{\"error\": \"{e}\"}}"), } } #[cfg(test)] mod tests { use super::*; const WALL_SRC: &str = "\ p1 = Point(0,0,0) p2 = Point(500,0,0) l1 = Line(p1,p2) w1 = Wall(l1,20,300)"; #[test] fn compile_wall_to_ifcx() { let out = compile(WALL_SRC); assert!(out.contains("wall-001"), "missing wall-001: {out}"); assert!(out.contains("ifcx_alpha")); assert!(out.contains("faceVertexIndices")); } #[test] fn compile_errors_are_error_json() { let out = compile("w1 = Wall(missing)"); assert!(out.contains("error"), "expected error json: {out}"); } }