release: 0.0.1
This commit is contained in:
commit
0b9f5898c3
7 changed files with 229 additions and 0 deletions
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/target
|
||||
/pkg
|
||||
Cargo.lock
|
||||
.claude/
|
||||
.opencode/
|
||||
31
AGENTS.md
Normal file
31
AGENTS.md
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# AGENTS.md — bimr-wasm
|
||||
|
||||
WASM adapter for the [`bimr-engine`](../bimr-engine) eval — the
|
||||
`compile()` surface consumed by bimr-web. Plan:
|
||||
[`task/refactor/2026-08-13/white_wasm_surface.md`](../task/refactor/2026-08-13/white_wasm_surface.md).
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
make test # native cargo test (wasm_bindgen fns are plain Rust)
|
||||
make pkg # wasm32 build -> wasm-bindgen web pkg -> wasm-opt
|
||||
make smoke # pkg + Node smoke test (node/smoke.mjs)
|
||||
```
|
||||
|
||||
## Rules
|
||||
|
||||
- **Whole-source only** (D8, batch-DSL / Alternative A): the surface is
|
||||
exactly **one export**, `compile(src)` — no session API, no per-call
|
||||
construction, no side-query projections. Python emits `.bimr` text and
|
||||
calls `compile()` once, the same path as the CLI. The incumbent session
|
||||
bridge was retired with the classic stack (bimr-black).
|
||||
- The adapter stays **thin**: no engine logic here — no geometry pre-pass
|
||||
(meshes compute at serialize time), no lazy materialisation, no parameter
|
||||
parsing. Everything goes through `eval`'s public surface.
|
||||
- Errors return `{"error": "..."}` JSON strings.
|
||||
- Dependencies on `eval`/`parser` are git pins on
|
||||
`bimr-engine` with local `[patch]` overrides — same pattern as the
|
||||
engine's kernel pin.
|
||||
- `pkg/` and `target/` are build artifacts — never commit them.
|
||||
|
||||
*This document should be updated as the codebase evolves.*
|
||||
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 = "ssh://git@git.rvba.fr:229/rvba/bimr-engine.git" }
|
||||
parser = { git = "ssh://git@git.rvba.fr:229/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."ssh://git@git.rvba.fr:229/rvba/bimr-engine.git"]
|
||||
eval = { path = "../bimr-engine/eval" }
|
||||
parser = { path = "../bimr-engine/parser" }
|
||||
|
||||
[patch."ssh://git@git.rvba.fr:229/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