release: 0.0.1
This commit is contained in:
commit
34ca011b92
6 changed files with 198 additions and 0 deletions
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
/target
|
||||||
|
/pkg
|
||||||
|
Cargo.lock
|
||||||
|
.claude/
|
||||||
|
.opencode/
|
||||||
22
Cargo.toml
Normal file
22
Cargo.toml
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
[package]
|
||||||
|
name = "bimr-wasm"
|
||||||
|
version = "0.0.1"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
eval = { git = "https://gitaec.org/rvba/bimr-engine.git" }
|
||||||
|
parser = { git = "https://gitaec.org/rvba/bimr-engine.git" }
|
||||||
|
# Pinned to the factory's wasm-bindgen CLI (Makefile WASM_BINDGEN_VERSION).
|
||||||
|
wasm-bindgen = "=0.2.114"
|
||||||
|
|
||||||
|
# Local checkouts override the forge pins (same pattern as bimr-engine's
|
||||||
|
# kernel patch) so the factory builds against sibling repos.
|
||||||
|
[patch."https://gitaec.org/rvba/bimr-engine.git"]
|
||||||
|
eval = { path = "../bimr-engine/eval" }
|
||||||
|
parser = { path = "../bimr-engine/parser" }
|
||||||
|
|
||||||
|
[patch."https://gitaec.org/rvba/bimr-kernel.git"]
|
||||||
|
bimr-kernel = { path = "../bimr-kernel" }
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Milovann Yanatchkov
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
23
Makefile
Normal file
23
Makefile
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
.PHONY: test pkg clean
|
||||||
|
|
||||||
|
# Native tests — wasm_bindgen fns are plain Rust; sessions work on the host.
|
||||||
|
test:
|
||||||
|
cargo test
|
||||||
|
|
||||||
|
# wasm-bindgen web pkg (consumed by the factory `build-wasm-white` and
|
||||||
|
# node/smoke.mjs). Pins mirror the factory: wasm-bindgen 0.2.114, Binaryen.
|
||||||
|
pkg:
|
||||||
|
rustup target add wasm32-unknown-unknown
|
||||||
|
cargo build --release --target wasm32-unknown-unknown
|
||||||
|
$(HOME)/.cargo/bin/wasm-bindgen --target web --out-dir pkg \
|
||||||
|
target/wasm32-unknown-unknown/release/bimr_wasm.wasm
|
||||||
|
command -v wasm-opt >/dev/null && \
|
||||||
|
wasm-opt -O pkg/bimr_wasm_bg.wasm -o pkg/bimr_wasm_bg.wasm || true
|
||||||
|
|
||||||
|
# Node smoke test over the web pkg.
|
||||||
|
smoke: pkg
|
||||||
|
node node/smoke.mjs
|
||||||
|
|
||||||
|
clean:
|
||||||
|
cargo clean
|
||||||
|
rm -rf pkg
|
||||||
60
node/smoke.mjs
Normal file
60
node/smoke.mjs
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
// SPDX-FileCopyrightText: 2026 Milovann Yanatchkov
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
// smoke.mjs — Node test of the wasm-bindgen web pkg (engine.test.mjs pattern
|
||||||
|
// from bimr-web). Run via `make smoke` after `make pkg`.
|
||||||
|
|
||||||
|
import assert from "node:assert/strict";
|
||||||
|
import { readFileSync } from "node:fs";
|
||||||
|
|
||||||
|
function section(name) {
|
||||||
|
console.log(`\n# ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadWasm() {
|
||||||
|
const jsUrl = new URL("../pkg/bimr_wasm.js", import.meta.url).href;
|
||||||
|
const bimrWasm = await import(jsUrl);
|
||||||
|
const wasmBytes = readFileSync(new URL("../pkg/bimr_wasm_bg.wasm", import.meta.url));
|
||||||
|
await bimrWasm.default({ module_or_path: wasmBytes });
|
||||||
|
return bimrWasm;
|
||||||
|
}
|
||||||
|
|
||||||
|
const WALL_SRC = `p1 = Point(0,0,0)
|
||||||
|
p2 = Point(500,0,0)
|
||||||
|
l1 = Line(p1,p2)
|
||||||
|
w1 = Wall(l1,20,300)`;
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const wasm = await loadWasm();
|
||||||
|
|
||||||
|
section("surface — whole-source only (D8)");
|
||||||
|
{
|
||||||
|
const exports = Object.keys(wasm).filter((k) => typeof wasm[k] === "function" && !k.startsWith("__"));
|
||||||
|
assert.deepEqual(
|
||||||
|
exports.sort(),
|
||||||
|
["compile", "default", "initSync"],
|
||||||
|
"no session exports, no side queries",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
section("compile() — wall to IFCX");
|
||||||
|
{
|
||||||
|
const out = wasm.compile(WALL_SRC);
|
||||||
|
assert.match(out, /wall-001/);
|
||||||
|
assert.match(out, /ifcx_alpha/);
|
||||||
|
assert.match(out, /faceVertexIndices/);
|
||||||
|
}
|
||||||
|
|
||||||
|
section("compile() — error handling");
|
||||||
|
{
|
||||||
|
const out = wasm.compile("w1 = Wall(missing)");
|
||||||
|
assert.match(out, /error/);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("\nAll smoke tests passed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((e) => {
|
||||||
|
console.error(e);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
67
src/lib.rs
Normal file
67
src/lib.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
// 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}");
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue