Skip to main content

blr_lang/
lib.rs

1//! Implementation of blr the language.
2
3pub mod compiler;
4mod debug;
5mod exec;
6mod external_type;
7pub mod runtime;
8pub mod snapshot_diff;
9
10use std::path::PathBuf;
11
12use compiler::{Database, ItemSource, TypeError};
13use runtime::{binary, conv};
14use snafu::{ResultExt as _, Snafu};
15use tokio::fs;
16use wac_graph::{EncodeError, PlugError};
17use wasmtime::component::Val;
18
19pub type Result<T, E = Error> = std::result::Result<T, E>;
20
21#[derive(Debug, Snafu)]
22pub enum Error {
23    #[snafu(display("parse error: {}", message))]
24    Parse {
25        // TODO: Preserve actual diagnostics
26        message: String,
27    },
28    #[snafu(display("type error"))]
29    Type { source: TypeError },
30    // TODO Collapse Link errors into a single error enum
31    #[snafu(display("link error"))]
32    Link { source: anyhow::Error },
33    #[snafu(display("link plugging error"))]
34    LinkPlug { source: PlugError },
35    #[snafu(display("link encode error"))]
36    LinkEncode { source: EncodeError },
37    #[snafu(display("io error at {path}"))]
38    IO {
39        source: std::io::Error,
40        path: String,
41    },
42    #[snafu(display("execution error"))]
43    Exec { source: snafu::Whatever },
44}
45
46pub async fn run(src: &str, path_root: impl Into<PathBuf>) -> Result<Val> {
47    let mut item_source = ItemSource::default();
48    binary::register_binary_operator_functions(&mut item_source);
49    conv::register_conversion_funcs(&mut item_source);
50    let mut db = Database::new(path_root, src.to_string(), item_source);
51    let code = compiler::root_component(&mut db).await?;
52
53    if let Ok(prefix) = std::env::var("BLR_SNAPSHOT") {
54        // TODO sanitize the path
55        let file_path = PathBuf::from(prefix).with_extension("blr.wasm");
56        fs::write(&file_path, &code).await.unwrap();
57        tracing::debug!(file_path = %file_path.display(), "snapshot saved");
58    }
59
60    exec::run_wasm(&code).await.context(ExecSnafu)
61}
62
63pub fn val_to_string(val: Val) -> String {
64    match val {
65        Val::S32(v) => v.to_string(),
66        Val::S64(v) => v.to_string(),
67        Val::Bool(v) => v.to_string(),
68        Val::S8(v) => v.to_string(),
69        Val::U8(v) => v.to_string(),
70        Val::S16(v) => v.to_string(),
71        Val::U16(v) => v.to_string(),
72        Val::U32(v) => v.to_string(),
73        Val::U64(v) => v.to_string(),
74        Val::Float32(v) => v.to_string(),
75        Val::Float64(v) => v.to_string(),
76        Val::Char(v) => v.to_string(),
77        //TODO Escape string
78        Val::String(v) => v,
79        Val::List(_vals) => todo!(),
80        Val::Record(fields) => format!("{:?}", fields),
81        Val::Tuple(_vals) => todo!(),
82        Val::Variant(_, _val) => todo!(),
83        Val::Enum(_) => todo!(),
84        Val::Option(_val) => todo!(),
85        Val::Result(_val) => todo!(),
86        Val::Flags(_items) => todo!(),
87        Val::Resource(_resource_any) => todo!(),
88        Val::Future(_future_any) => todo!(),
89        Val::Stream(_stream_any) => todo!(),
90        Val::ErrorContext(_error_context_any) => todo!(),
91    }
92}