stak_wasm/
lib.rs

1//! A Stak Scheme interpreter in WASM.
2
3use stak_compiler::compile_r7rs;
4use stak_device::ReadWriteDevice;
5use stak_file::{MemoryFileSystem, VoidFileSystem};
6use stak_macro::include_module;
7use stak_module::Module;
8use stak_process_context::{MemoryProcessContext, VoidProcessContext};
9use stak_r7rs::SmallPrimitiveSet;
10use stak_time::VoidClock;
11use stak_vm::Vm;
12use wasm_bindgen::prelude::*;
13
14/// Compiles source codes in Scheme.
15#[wasm_bindgen]
16pub fn compile(source: &str) -> Result<Vec<u8>, JsError> {
17    let mut target = vec![];
18    compile_r7rs(source.as_bytes(), &mut target)?;
19    Ok(target)
20}
21
22/// Interprets bytecodes with standard input and returns its standard output.
23#[wasm_bindgen]
24pub fn interpret(bytecodes: &[u8], input: &[u8], heap_size: usize) -> Result<Vec<u8>, JsError> {
25    let mut heap = vec![Default::default(); heap_size];
26    let mut output = vec![];
27    let mut error = vec![];
28
29    let mut vm = Vm::new(
30        &mut heap,
31        SmallPrimitiveSet::new(
32            ReadWriteDevice::new(input, &mut output, &mut error),
33            VoidFileSystem::new(),
34            VoidProcessContext::new(),
35            VoidClock::new(),
36        ),
37    )?;
38
39    vm.initialize(bytecodes.iter().copied())?;
40    vm.run()?;
41
42    Ok(output)
43}
44
45/// Runs a Scheme script with standard input and returns its standard output.
46#[wasm_bindgen]
47pub fn run(source: &str, input: &[u8], heap_size: usize) -> Result<Vec<u8>, JsError> {
48    const MAIN_FILE: &str = "main.scm";
49
50    let mut heap = vec![Default::default(); heap_size];
51    let mut output = vec![];
52    let mut error = vec![];
53    let files = [(MAIN_FILE.as_bytes(), source.as_bytes())];
54    let mut file_entries = [Default::default(); 1];
55
56    let mut vm = Vm::new(
57        &mut heap,
58        SmallPrimitiveSet::new(
59            ReadWriteDevice::new(input, &mut output, &mut error),
60            MemoryFileSystem::new(&files, &mut file_entries),
61            MemoryProcessContext::new(&["scheme", MAIN_FILE], &[]),
62            VoidClock::new(),
63        ),
64    )?;
65
66    vm.initialize(
67        include_module!("run.scm", stak_module)
68            .bytecode()
69            .iter()
70            .copied(),
71    )?;
72    vm.run()?;
73
74    Ok(output)
75}