diff --git a/Cargo.lock b/Cargo.lock index 01e6ec5..960095a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,6 +70,10 @@ name = "argus-wasm" version = "0.1.4" dependencies = [ "argus", + "js-sys", + "serde", + "serde-wasm-bindgen", + "serde_json", "wasm-bindgen", ] @@ -176,6 +180,22 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "js-sys" +version = "0.3.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "libc" version = "0.2.177" @@ -284,6 +304,12 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + [[package]] name = "semver" version = "1.0.27" @@ -300,6 +326,17 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_core" version = "1.0.228" @@ -320,6 +357,19 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + [[package]] name = "shlex" version = "1.3.0" diff --git a/Cargo.toml b/Cargo.toml index b66f034..715d852 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,5 +7,9 @@ crate-type = ["cdylib"] [dependencies] argus = { git = "https://deemz.org/git/research/argus.git", branch = "dev" } +js-sys = "0.3.82" +serde = { version = "1.0.228", features = ["derive"] } +serde-wasm-bindgen = "0.6.5" +serde_json = "1.0.145" wasm-bindgen = "0.2.105" diff --git a/pkg/argus_wasm.d.ts b/pkg/argus_wasm.d.ts index e0ca6ca..84fbd5a 100644 --- a/pkg/argus_wasm.d.ts +++ b/pkg/argus_wasm.d.ts @@ -1,7 +1,17 @@ /* tslint:disable */ /* eslint-disable */ -export function parse_str(s: string): WrappedExpr; -export class WrappedExpr { +export function eval_boolean(s: string, trace: StateBuddyTrace): StateBuddyEvalResult; +export class StateBuddyEvalResult { + private constructor(); + free(): void; + [Symbol.dispose](): void; +} +export class StateBuddyEvalResultEntry { + private constructor(); + free(): void; + [Symbol.dispose](): void; +} +export class StateBuddyTrace { private constructor(); free(): void; [Symbol.dispose](): void; @@ -11,8 +21,10 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl export interface InitOutput { readonly memory: WebAssembly.Memory; - readonly __wbg_wrappedexpr_free: (a: number, b: number) => void; - readonly parse_str: (a: number, b: number) => number; + readonly __wbg_statebuddytrace_free: (a: number, b: number) => void; + readonly eval_boolean: (a: number, b: number, c: number) => number; + readonly __wbg_statebuddyevalresultentry_free: (a: number, b: number) => void; + readonly __wbg_statebuddyevalresult_free: (a: number, b: number) => void; readonly __wbindgen_externrefs: WebAssembly.Table; readonly __wbindgen_malloc: (a: number, b: number) => number; readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; diff --git a/pkg/argus_wasm.js b/pkg/argus_wasm.js index 24de4f3..4c6a17a 100644 --- a/pkg/argus_wasm.js +++ b/pkg/argus_wasm.js @@ -83,44 +83,92 @@ function passStringToWasm0(arg, malloc, realloc) { WASM_VECTOR_LEN = offset; return ptr; } + +function _assertClass(instance, klass) { + if (!(instance instanceof klass)) { + throw new Error(`expected instance of ${klass.name}`); + } +} /** * @param {string} s - * @returns {WrappedExpr} + * @param {StateBuddyTrace} trace + * @returns {StateBuddyEvalResult} */ -export function parse_str(s) { +export function eval_boolean(s, trace) { const ptr0 = passStringToWasm0(s, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc); const len0 = WASM_VECTOR_LEN; - const ret = wasm.parse_str(ptr0, len0); - return WrappedExpr.__wrap(ret); + _assertClass(trace, StateBuddyTrace); + const ret = wasm.eval_boolean(ptr0, len0, trace.__wbg_ptr); + return StateBuddyEvalResult.__wrap(ret); } -const WrappedExprFinalization = (typeof FinalizationRegistry === 'undefined') +const StateBuddyEvalResultFinalization = (typeof FinalizationRegistry === 'undefined') ? { register: () => {}, unregister: () => {} } - : new FinalizationRegistry(ptr => wasm.__wbg_wrappedexpr_free(ptr >>> 0, 1)); + : new FinalizationRegistry(ptr => wasm.__wbg_statebuddyevalresult_free(ptr >>> 0, 1)); -export class WrappedExpr { +export class StateBuddyEvalResult { static __wrap(ptr) { ptr = ptr >>> 0; - const obj = Object.create(WrappedExpr.prototype); + const obj = Object.create(StateBuddyEvalResult.prototype); obj.__wbg_ptr = ptr; - WrappedExprFinalization.register(obj, obj.__wbg_ptr, obj); + StateBuddyEvalResultFinalization.register(obj, obj.__wbg_ptr, obj); return obj; } __destroy_into_raw() { const ptr = this.__wbg_ptr; this.__wbg_ptr = 0; - WrappedExprFinalization.unregister(this); + StateBuddyEvalResultFinalization.unregister(this); return ptr; } free() { const ptr = this.__destroy_into_raw(); - wasm.__wbg_wrappedexpr_free(ptr, 0); + wasm.__wbg_statebuddyevalresult_free(ptr, 0); } } -if (Symbol.dispose) WrappedExpr.prototype[Symbol.dispose] = WrappedExpr.prototype.free; +if (Symbol.dispose) StateBuddyEvalResult.prototype[Symbol.dispose] = StateBuddyEvalResult.prototype.free; + +const StateBuddyEvalResultEntryFinalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_statebuddyevalresultentry_free(ptr >>> 0, 1)); + +export class StateBuddyEvalResultEntry { + + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + StateBuddyEvalResultEntryFinalization.unregister(this); + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_statebuddyevalresultentry_free(ptr, 0); + } +} +if (Symbol.dispose) StateBuddyEvalResultEntry.prototype[Symbol.dispose] = StateBuddyEvalResultEntry.prototype.free; + +const StateBuddyTraceFinalization = (typeof FinalizationRegistry === 'undefined') + ? { register: () => {}, unregister: () => {} } + : new FinalizationRegistry(ptr => wasm.__wbg_statebuddytrace_free(ptr >>> 0, 1)); + +export class StateBuddyTrace { + + __destroy_into_raw() { + const ptr = this.__wbg_ptr; + this.__wbg_ptr = 0; + StateBuddyTraceFinalization.unregister(this); + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_statebuddytrace_free(ptr, 0); + } +} +if (Symbol.dispose) StateBuddyTrace.prototype[Symbol.dispose] = StateBuddyTrace.prototype.free; const EXPECTED_RESPONSE_TYPES = new Set(['basic', 'cors', 'default']); diff --git a/pkg/argus_wasm_bg.wasm b/pkg/argus_wasm_bg.wasm index 0880b61..be31eb7 100644 Binary files a/pkg/argus_wasm_bg.wasm and b/pkg/argus_wasm_bg.wasm differ diff --git a/pkg/argus_wasm_bg.wasm.d.ts b/pkg/argus_wasm_bg.wasm.d.ts index 2d215e3..9d3e585 100644 --- a/pkg/argus_wasm_bg.wasm.d.ts +++ b/pkg/argus_wasm_bg.wasm.d.ts @@ -1,8 +1,10 @@ /* tslint:disable */ /* eslint-disable */ export const memory: WebAssembly.Memory; -export const __wbg_wrappedexpr_free: (a: number, b: number) => void; -export const parse_str: (a: number, b: number) => number; +export const __wbg_statebuddytrace_free: (a: number, b: number) => void; +export const eval_boolean: (a: number, b: number, c: number) => number; +export const __wbg_statebuddyevalresultentry_free: (a: number, b: number) => void; +export const __wbg_statebuddyevalresult_free: (a: number, b: number) => void; export const __wbindgen_externrefs: WebAssembly.Table; export const __wbindgen_malloc: (a: number, b: number) => number; export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; diff --git a/src/lib.rs b/src/lib.rs index 800e5c8..d92bc9f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,33 +1,134 @@ extern crate wasm_bindgen; extern crate argus; +extern crate serde_json; +extern crate js_sys; +extern crate serde; use wasm_bindgen::prelude::*; -use argus::expr::Expr; -// use chumsky::prelude::Rich; +use argus::expr::{Expr}; +use argus::{Trace, Signal, AnySignal, BooleanSemantics}; +use argus::signals::interpolation; +use std::collections::HashMap; +use std::vec; +use serde::{Serialize, Deserialize}; +use std::time::Duration; +// #[wasm_bindgen] +// pub struct WrappedExpr { +// expr: Expr, +// } -// macro_rules! wasmbind_fn { -// ($name:ident($($arg:ident: $t:ty),*) -> $ret:ty) => { -// #[wasm_bindgen] -// pub fn $name($($arg: $t),*) -> $ret { -// my_lib::$name($($arg),*) -// } +// #[wasm_bindgen] +// pub fn parse_str(s: &str) -> WrappedExpr { +// let expr = argus::parse_str(s); +// return WrappedExpr{ +// expr: expr.expect("fuck!!!!"), // }; // } -// wasmbind_fn!(parse_str(s: &str) -> Result>>); +struct TraceMap<'a> { + events: HashMap<&'a str, Signal>, +} -#[wasm_bindgen] -pub struct WrappedExpr { - expr: Expr, +impl<'a> Trace for TraceMap<'a> { + fn signal_names(&self) -> Vec<&str> { + self.events.keys().cloned().collect() + } + + fn get(&self, name: &str) -> Option<&Signal> { + let sig: &dyn AnySignal = match self.events.get(name) { + Some(signal) => signal, + None => return None, + }; + sig.as_any().downcast_ref::>() + } +} + + + +// type MyTrace = Vec +// struct MyResult { +// ok: , +// } + +// pub struct DefaultFalse; + +// use argus::signals::{InterpolationMethod, Sample}; + +// use argus::core::utils::Neighborhood; + +// impl InterpolationMethod for DefaultFalse { +// fn at(a: &super::Sample, b: &super::Sample, time: std::time::Duration) -> Option { +// if time == a.time { +// Some(a.value) +// } +// else if time == b.time { +// Some(b.value) +// } +// else { +// Some(false) +// } +// } + +// fn find_intersection(_a: &Neighborhood, _b: &Neighborhood) -> Option> { +// None +// } +// } + +#[derive(Serialize, Deserialize)] +pub struct StateBuddyTraceEntry { + simtime: f64, + inputEvent: String, + outputEvents: Vec, } #[wasm_bindgen] -pub fn parse_str(s: &str) -> WrappedExpr { - let expr = argus::parse_str(s); - return WrappedExpr{ - expr: expr.expect("fuck!!!!"), +pub struct StateBuddyTrace { + entries: Vec, +} + + +#[wasm_bindgen] +pub fn eval_boolean(s: &str, trace: &StateBuddyTrace) -> StateBuddyEvalResult { + let mut traceMap = HashMap::<&str, Signal>::new(); + for entry in &trace.entries { + let value = traceMap.entry(entry.inputEvent.as_str()).or_insert_with(|| Signal::::Sampled { + values: vec![], + time_points: vec![], + }); + if let Signal::::Sampled { values, time_points } = value { + values.push(true); + time_points.push(Duration::from_millis(entry.simtime as u64)); + } + else { + panic!("fuck!!!"); + } + } + + let parse_result = argus::parse_str(s); + let expr = parse_result.expect("fuuuckk!!"); + let eval_result = match expr { + Expr::Bool(bool_expr) => BooleanSemantics::eval::(&bool_expr, &TraceMap{events: traceMap}), + _ => panic!("fuuuck"), }; + let mut result = Vec::::new(); + eval_result.expect("fuuuck").iter().for_each(|(timestamp, satisfied), | { + result.push(StateBuddyEvalResultEntry{ + timestamp: timestamp.as_millis() as f64, + satisfied: *satisfied, + }); + }); + StateBuddyEvalResult { entries: result } } +#[wasm_bindgen] +pub struct StateBuddyEvalResultEntry { + timestamp: f64, + satisfied: bool, +} + +#[wasm_bindgen] +pub struct StateBuddyEvalResult { + entries: Vec, +}