@raviqqe/stak 0.3.9 → 0.3.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -37,7 +37,7 @@ cargo install stak-interpret
37
37
 
38
38
  ## Examples
39
39
 
40
- ### Running a Scheme script
40
+ ### Embedding Scheme scripts in Rust
41
41
 
42
42
  First, prepare a Scheme script at `src/hello.scm`.
43
43
 
@@ -57,46 +57,127 @@ fn main() -> Result<(), BuildError> {
57
57
  }
58
58
  ```
59
59
 
60
- Now, you can include the Scheme script into a program in Rust using [the `stak::include_bytecode` macro](https://docs.rs/stak/latest/stak).
60
+ Now, you can include the Scheme script into a program in Rust using [the `stak::include_module` macro](https://docs.rs/stak/latest/stak/macro.include_bytecode.html).
61
61
 
62
62
  ```rust
63
63
  use core::error::Error;
64
64
  use stak::{
65
65
  device::StdioDevice,
66
66
  file::VoidFileSystem,
67
- include_bytecode,
67
+ include_module,
68
68
  process_context::VoidProcessContext,
69
+ module::{Module, UniversalModule},
69
70
  r7rs::{SmallError, SmallPrimitiveSet},
70
71
  time::VoidClock,
71
72
  vm::Vm,
72
73
  };
73
74
 
74
75
  const HEAP_SIZE: usize = 1 << 16;
75
- const BYTECODES: &[u8] = include_bytecode!("hello.scm");
76
+
77
+ // Include a Scheme script in the bytecode format built by the build script above.
78
+ static MODULE: UniversalModule = include_module!("hello.scm");
76
79
 
77
80
  fn main() -> Result<(), Box<dyn Error>> {
78
- run(BYTECODES)?;
81
+ run(&MODULE.bytecode())?;
79
82
 
80
83
  Ok(())
81
84
  }
82
85
 
83
86
  fn run(bytecodes: &[u8]) -> Result<(), SmallError> {
87
+ // Prepare a heap memory of a virtual machine.
84
88
  let mut heap = [Default::default(); HEAP_SIZE];
89
+ // Create a virtual machine with its heap memory primitive procedures.
85
90
  let mut vm = Vm::new(
86
91
  &mut heap,
87
92
  SmallPrimitiveSet::new(
93
+ // Attach standard input, output, and error of this process to a virtual machine.
88
94
  StdioDevice::new(),
95
+ // Use void system interfaces for security because we don't need them for this example.
89
96
  VoidFileSystem::new(),
90
97
  VoidProcessContext::new(),
91
98
  VoidClock::new(),
92
99
  ),
93
100
  )?;
94
101
 
102
+ // Initialize a virtual machine with bytecodes.
95
103
  vm.initialize(bytecodes.iter().copied())?;
104
+ // Run bytecodes on a virtual machine.
96
105
  vm.run()
97
106
  }
98
107
  ```
99
108
 
109
+ ### Communication between Scheme and Rust
110
+
111
+ Currently, in-memory standard input (`stdin`) and output (`stdout`) to Scheme scripts are the only way to communicate information between Rust programs and Scheme scripts.
112
+
113
+ ```rust
114
+ use core::{error::Error, ffi::CStr, str::FromStr};
115
+ use stak::{
116
+ device::ReadWriteDevice,
117
+ file::VoidFileSystem,
118
+ include_module,
119
+ process_context::VoidProcessContext,
120
+ module::{Module, UniversalModule},
121
+ r7rs::{SmallError, SmallPrimitiveSet},
122
+ time::VoidClock,
123
+ vm::Vm,
124
+ };
125
+
126
+ const BUFFER_SIZE: usize = 1 << 8;
127
+ const HEAP_SIZE: usize = 1 << 16;
128
+
129
+ static MODULE: UniversalModule = include_module!("fibonacci.scm");
130
+
131
+ fn main() -> Result<(), Box<dyn Error>> {
132
+ let mut input = 24;
133
+ let mut output = [0u8; BUFFER_SIZE];
134
+ let mut error = [0u8; BUFFER_SIZE];
135
+
136
+ run(&MODULE.bytecode(), input.to_string().as_bytes(), &mut output, &mut error)?;
137
+
138
+ let error = decode_buffer(&error)?;
139
+
140
+ // If stderr is not empty, we assume that some error has occurred.
141
+ if !error.is_empty() {
142
+ return Err(error.into());
143
+ }
144
+
145
+ // Decode and print the output.
146
+ println!("Answer: {}", isize::from_str(&decode_buffer(&output)?)?);
147
+
148
+ Ok(())
149
+ }
150
+
151
+ fn run(
152
+ bytecodes: &[u8],
153
+ input: &[u8],
154
+ output: &mut [u8],
155
+ error: &mut [u8],
156
+ ) -> Result<(), SmallError> {
157
+ let mut heap = [Default::default(); HEAP_SIZE];
158
+ let mut vm = Vm::new(
159
+ &mut heap,
160
+ SmallPrimitiveSet::new(
161
+ // Create and attach an in-memory I/O device.
162
+ ReadWriteDevice::new(input, output, error),
163
+ VoidFileSystem::new(),
164
+ VoidProcessContext::new(),
165
+ VoidClock::new(),
166
+ ),
167
+ )?;
168
+
169
+ vm.initialize(bytecodes.iter().copied())?;
170
+ vm.run()
171
+ }
172
+
173
+ fn decode_buffer(buffer: &[u8]) -> Result<String, Box<dyn Error>> {
174
+ Ok(CStr::from_bytes_until_nul(buffer)
175
+ .map_err(|error| error.to_string())?
176
+ .to_string_lossy()
177
+ .into())
178
+ }
179
+ ```
180
+
100
181
  ## License
101
182
 
102
183
  [MIT](https://github.com/raviqqe/stak/blob/main/LICENSE)
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@raviqqe/stak",
3
3
  "type": "module",
4
4
  "description": "Stak Scheme VM in WebAssembly",
5
- "version": "0.3.9",
5
+ "version": "0.3.10",
6
6
  "license": "SEE LICENSE IN ../LICENSE",
7
7
  "repository": {
8
8
  "type": "git",
package/stak_wasm_bg.wasm CHANGED
Binary file