bimr-wasm/src/lib.rs
2026-09-01 10:37:09 +02:00

67 lines
2 KiB
Rust

// 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::ast::Program, String> {
parser::parse(src).map_err(|errors| {
let msg = errors
.iter()
.map(|e| format!("{e:?}"))
.collect::<Vec<_>>()
.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}");
}
}