1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use cbqn_sys as bindings;
use thiserror::Error as ThisError;

#[derive(ThisError, Debug)]
pub enum Error {
    #[error("CBQN error: {0}")]
    CBQN(String),
    #[error("Invalid type: {0}")]
    InvalidType(String),
    #[error("{0}")]
    NotSupported(String),
}

pub type Result<T> = std::result::Result<T, Error>;

pub use bindings::{
    BQNElType_elt_c16, BQNElType_elt_c32, BQNElType_elt_c8, BQNElType_elt_f64, BQNElType_elt_i16,
    BQNElType_elt_i32, BQNElType_elt_i8, BQNElType_elt_unk, BQNV,
};

#[cfg(feature = "native-backend")]
mod native;

#[cfg(feature = "native-backend")]
mod eval {
    use super::*;
    use crate::BQNValue;
    use once_cell::sync::OnceCell;

    static REBQN: OnceCell<BQNValue> = OnceCell::new();

    pub fn backend_eval(bqn: &str) -> Result<BQNValue> {
        let rebqn = REBQN.get_or_init(|| {
            BQNValue::new(
                bqn_eval(
                    BQNValue::from(
                        r#"r←•ReBQN{repl⇐"strict"}⋄{0‿(R𝕩)}⎊{𝕊: 1‿("Error: "∾•CurrentError@)}"#,
                    )
                    .value,
                )
                .expect("ReBQN"),
            )
        });
        let ret = rebqn.call1(&BQNValue::from(bqn))?;
        let err = bqn_pick(ret.value, 0)?;
        if err != 0 {
            let error = BQNValue::new(bqn_pick(ret.value, 1)?);
            Err(Error::CBQN(error.to_string()?))
        } else {
            Ok(BQNValue::new(bqn_pick(ret.value, 1)?))
        }
    }
}

#[cfg(feature = "native-backend")]
pub use crate::backend::{eval::backend_eval, native::*};

#[cfg(feature = "wasi-backend")]
mod wasi;

#[cfg(feature = "wasi-backend")]
pub use crate::backend::wasi::*;