@raviqqe/stak 0.11.9 → 0.11.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
@@ -16,16 +16,23 @@ Stak Scheme aims to be:
16
16
  - A subset of [Chibi Scheme](https://github.com/ashinn/chibi-scheme), [Gauche](https://github.com/shirok/Gauche), and [Guile](https://www.gnu.org/software/guile/)
17
17
  - A portable scripting environment that supports even no-`std` and no-`alloc` platforms
18
18
 
19
- For more information and usage, visit [the full documentation](https://raviqqe.com/stak/install).
19
+ For the usage and examples, see [the documentation](https://raviqqe.com/stak/install).
20
20
 
21
21
  ## Install
22
22
 
23
- ### Interpreter
23
+ ### Commands
24
24
 
25
- To install the Scheme interpreter as a command, run:
25
+ To install [the interpreter](https://crates.io/crates/stak) and [REPL](https://crates.io/crates/stak-repl), run:
26
26
 
27
27
  ```sh
28
28
  cargo install stak
29
+ cargo install stak-repl
30
+ ```
31
+
32
+ To install [the minimal interpreter](https://crates.io/crates/mstak), run:
33
+
34
+ ```sh
35
+ cargo install mstak
29
36
  ```
30
37
 
31
38
  ### Libraries
@@ -38,166 +45,13 @@ cargo add --build stak-build
38
45
  cargo install stak-compile
39
46
  ```
40
47
 
41
- For full examples, see [the `examples` directory](https://github.com/raviqqe/stak/tree/main/examples).
42
-
43
- ## Examples
44
-
45
- ### Dynamic scripting in Rust
46
-
47
- First, prepare a Scheme script named `src/fight.scm`:
48
-
49
- ```scheme
50
- ; Import a base library and the library named `(stak rust)` for Rust integration.
51
- (import (scheme base) (stak rust))
52
-
53
- ; Make two people with a number of pies they have and their dodge rates.
54
- (define me (make-person 4 0.2))
55
- (define friend (make-person 2 0.6))
56
-
57
- ; The fight begins. Let's throw pies to each other!
58
- (do ()
59
- ((or
60
- (person-wasted me)
61
- (person-wasted friend)
62
- (and
63
- (zero? (person-pies me))
64
- (zero? (person-pies friend)))))
65
- (person-throw-pie me friend)
66
- (person-throw-pie friend me))
67
-
68
- ; Output the winner.
69
- (write-string
70
- (cond
71
- ((person-wasted friend)
72
- "You won!")
73
- ((person-wasted me)
74
- "You lost...")
75
- (else
76
- "Draw...")))
77
- ```
78
-
79
- Then, add a build script at `build.rs` to build the Scheme source file
80
- into bytecode.
81
-
82
- ```rust no_run
83
- use stak_build::{build_r7rs, BuildError};
84
-
85
- fn main() -> Result<(), BuildError> {
86
- build_r7rs()
87
- }
88
- ```
89
-
90
- Finally, you can embed and run the Scheme script in a Rust program.
91
-
92
- ```rust
93
- use any_fn::{r#fn, Ref};
94
- use core::error::Error;
95
- use rand::random;
96
- use stak::{
97
- engine::{Engine, EngineError},
98
- include_module,
99
- module::UniversalModule,
100
- };
101
-
102
- const HEAP_SIZE: usize = 1 << 16;
103
-
104
- /// A person who holds pies to throw.
105
- struct Person {
106
- pies: usize,
107
- dodge: f64,
108
- wasted: bool,
109
- }
110
-
111
- impl Person {
112
- /// Creates a person.
113
- pub fn new(pies: usize, dodge: f64) -> Self {
114
- Self {
115
- pies,
116
- dodge,
117
- wasted: false,
118
- }
119
- }
120
-
121
- /// Returns a number of pies the person has.
122
- pub fn pies(&self) -> usize {
123
- self.pies
124
- }
125
-
126
- /// Returns `true` if a person is wasted.
127
- pub fn wasted(&self) -> bool {
128
- self.wasted
129
- }
130
-
131
- /// Throws a pie to another person.
132
- pub fn throw_pie(&mut self, other: &mut Person) {
133
- if self.pies == 0 || self.wasted {
134
- return;
135
- }
136
-
137
- self.pies -= 1;
138
-
139
- if random::<f64>() > other.dodge {
140
- other.wasted = true;
141
- }
142
- }
143
- }
144
-
145
- fn main() -> Result<(), Box<dyn Error>> {
146
- // Include and run the Scheme module.
147
- run_scheme(&include_module!("fight.scm"))?;
148
-
149
- Ok(())
150
- }
151
-
152
- fn run_scheme(module: &UniversalModule) -> Result<(), EngineError> {
153
- // Initialize a heap memory for a Scheme scripting engine.
154
- let mut heap = [Default::default(); HEAP_SIZE];
155
- // Define Rust functions to pass to the engine.
156
- let mut functions = [
157
- ("make-person", r#fn(Person::new)),
158
- ("person-pies", r#fn::<(Ref<_>,), _>(Person::pies)),
159
- ("person-wasted", r#fn::<(Ref<_>,), _>(Person::wasted)),
160
- ("person-throw-pie", r#fn(Person::throw_pie)),
161
- ];
162
- // Initialize the engine.
163
- let mut engine = Engine::new(&mut heap, &mut functions)?;
164
-
165
- // Finally, run the module!
166
- engine.run(module)
167
- }
168
- ```
169
-
170
48
  ## Performance
171
49
 
172
- ### Computational benchmarks
173
-
174
- The Stak Scheme interpreter runs 1.6 to 2.3 times slower than Python 3 at computationally heavy tasks depending on its configuration and benchmarks. For all the benchmark results, see [the GitHub Action](https://github.com/raviqqe/stak/actions/workflows/bench.yaml).
175
-
176
- - Baseline: Python 3.13
177
- - Environment: Ubuntu 24.04, x86-64
178
-
179
- | Benchmark | Stak (minimal [^1]) | Stak (full [^2]) |
180
- | ---------------- | ------------------: | ---------------: |
181
- | Fibonacci number | 1.80x slower | 1.98x slower |
182
- | Integer sum | 1.61x slower | 1.87x slower |
183
- | Tak function | 2.10x slower | 2.27x slower |
184
-
185
- ### Startup benchmarks
186
-
187
- Although Stak Scheme's minimality comes at the cost of speed, it is very fast at startup.
188
-
189
- This means that Stak Scheme is suitable for embedding many small pieces of Scheme programs in Rust due to its tiny overhead on program initialization.
190
-
191
- - Environment: Ubuntu 24.04, x86-64
192
-
193
- | Benchmark | Stak (full [^2]) | Lua 5.4 |
194
- | ---------------- | ---------------: | ------: |
195
- | Empty program | 0.534 us | 48.9 us |
196
- | Integer addition | 22.9 us | 50.0 us |
50
+ See [Performance](https://raviqqe.com/stak/performance).
197
51
 
198
- [^1]: Minimal: Integer-only support + standard libraries based on libc
52
+ ## Limitations
199
53
 
200
- [^2]: Full: 64-bit floating-point number support + standard libraries based on the `std` library in Rust
54
+ See [Limitations](https://raviqqe.com/stak/limitations).
201
55
 
202
56
  ## References
203
57
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@raviqqe/stak",
3
3
  "type": "module",
4
4
  "description": "Stak Scheme in WebAssembly",
5
- "version": "0.11.9",
5
+ "version": "0.11.10",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",
package/stak_wasm.d.ts CHANGED
@@ -1,5 +1,9 @@
1
1
  /* tslint:disable */
2
2
  /* eslint-disable */
3
+ /**
4
+ * Compiles source codes in Scheme.
5
+ */
6
+ export function compile(source: string): Uint8Array;
3
7
  /**
4
8
  * Runs a Scheme script with standard input and returns its standard output.
5
9
  */
@@ -8,10 +12,6 @@ export function run(source: string, input: Uint8Array, heap_size: number): Uint8
8
12
  * Interprets bytecode with standard input and returns its standard output.
9
13
  */
10
14
  export function interpret(bytecode: Uint8Array, input: Uint8Array, heap_size: number): Uint8Array;
11
- /**
12
- * Compiles source codes in Scheme.
13
- */
14
- export function compile(source: string): Uint8Array;
15
15
  /**
16
16
  * Runs a REPL interpreter.
17
17
  */
@@ -33,8 +33,8 @@ export interface InitOutput {
33
33
  readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
34
34
  readonly __externref_table_dealloc: (a: number) => void;
35
35
  readonly __wbindgen_free: (a: number, b: number, c: number) => void;
36
- readonly closure33_externref_shim: (a: number, b: number, c: any) => void;
37
- readonly closure57_externref_shim: (a: number, b: number, c: any, d: any) => void;
36
+ readonly closure19_externref_shim: (a: number, b: number, c: any) => void;
37
+ readonly closure43_externref_shim: (a: number, b: number, c: any, d: any) => void;
38
38
  readonly __wbindgen_start: () => void;
39
39
  }
40
40
 
package/stak_wasm.js CHANGED
@@ -198,13 +198,6 @@ function getDataViewMemory0() {
198
198
  return cachedDataViewMemory0;
199
199
  }
200
200
 
201
- function passArray8ToWasm0(arg, malloc) {
202
- const ptr = malloc(arg.length * 1, 1) >>> 0;
203
- getUint8ArrayMemory0().set(arg, ptr / 1);
204
- WASM_VECTOR_LEN = arg.length;
205
- return ptr;
206
- }
207
-
208
201
  function takeFromExternrefTable0(idx) {
209
202
  const value = wasm.__wbindgen_export_2.get(idx);
210
203
  wasm.__externref_table_dealloc(idx);
@@ -215,6 +208,29 @@ function getArrayU8FromWasm0(ptr, len) {
215
208
  ptr = ptr >>> 0;
216
209
  return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
217
210
  }
211
+ /**
212
+ * Compiles source codes in Scheme.
213
+ * @param {string} source
214
+ * @returns {Uint8Array}
215
+ */
216
+ export function compile(source) {
217
+ const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
218
+ const len0 = WASM_VECTOR_LEN;
219
+ const ret = wasm.compile(ptr0, len0);
220
+ if (ret[3]) {
221
+ throw takeFromExternrefTable0(ret[2]);
222
+ }
223
+ var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
224
+ wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
225
+ return v2;
226
+ }
227
+
228
+ function passArray8ToWasm0(arg, malloc) {
229
+ const ptr = malloc(arg.length * 1, 1) >>> 0;
230
+ getUint8ArrayMemory0().set(arg, ptr / 1);
231
+ WASM_VECTOR_LEN = arg.length;
232
+ return ptr;
233
+ }
218
234
  /**
219
235
  * Runs a Scheme script with standard input and returns its standard output.
220
236
  * @param {string} source
@@ -257,23 +273,6 @@ export function interpret(bytecode, input, heap_size) {
257
273
  return v3;
258
274
  }
259
275
 
260
- /**
261
- * Compiles source codes in Scheme.
262
- * @param {string} source
263
- * @returns {Uint8Array}
264
- */
265
- export function compile(source) {
266
- const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
267
- const len0 = WASM_VECTOR_LEN;
268
- const ret = wasm.compile(ptr0, len0);
269
- if (ret[3]) {
270
- throw takeFromExternrefTable0(ret[2]);
271
- }
272
- var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
273
- wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
274
- return v2;
275
- }
276
-
277
276
  /**
278
277
  * Runs a REPL interpreter.
279
278
  * @param {number} heap_size
@@ -285,11 +284,11 @@ export function repl(heap_size) {
285
284
  }
286
285
 
287
286
  function __wbg_adapter_24(arg0, arg1, arg2) {
288
- wasm.closure33_externref_shim(arg0, arg1, arg2);
287
+ wasm.closure19_externref_shim(arg0, arg1, arg2);
289
288
  }
290
289
 
291
- function __wbg_adapter_45(arg0, arg1, arg2, arg3) {
292
- wasm.closure57_externref_shim(arg0, arg1, arg2, arg3);
290
+ function __wbg_adapter_39(arg0, arg1, arg2, arg3) {
291
+ wasm.closure43_externref_shim(arg0, arg1, arg2, arg3);
293
292
  }
294
293
 
295
294
  async function __wbg_load(module, imports) {
@@ -341,7 +340,7 @@ function __wbg_get_imports() {
341
340
  const a = state0.a;
342
341
  state0.a = 0;
343
342
  try {
344
- return __wbg_adapter_45(a, state0.b, arg0, arg1);
343
+ return __wbg_adapter_39(a, state0.b, arg0, arg1);
345
344
  } finally {
346
345
  state0.a = a;
347
346
  }
@@ -363,7 +362,7 @@ function __wbg_get_imports() {
363
362
  const ret = arg0.queueMicrotask;
364
363
  return ret;
365
364
  };
366
- imports.wbg.__wbg_readstdin_397badeaadecad8a = function() {
365
+ imports.wbg.__wbg_readstdin_fa4d8873c2345612 = function() {
367
366
  const ret = read_stdin();
368
367
  return ret;
369
368
  };
@@ -395,11 +394,11 @@ function __wbg_get_imports() {
395
394
  const ret = arg0.then(arg1, arg2);
396
395
  return ret;
397
396
  };
398
- imports.wbg.__wbg_writestderr_89ebdcb15680582e = function(arg0) {
397
+ imports.wbg.__wbg_writestderr_d506f2ff6c400d2a = function(arg0) {
399
398
  const ret = write_stderr(arg0);
400
399
  return ret;
401
400
  };
402
- imports.wbg.__wbg_writestdout_05ad3300bf790c89 = function(arg0) {
401
+ imports.wbg.__wbg_writestdout_4b685361b836fbaf = function(arg0) {
403
402
  const ret = write_stdout(arg0);
404
403
  return ret;
405
404
  };
@@ -413,7 +412,7 @@ function __wbg_get_imports() {
413
412
  return ret;
414
413
  };
415
414
  imports.wbg.__wbindgen_closure_wrapper84 = function(arg0, arg1, arg2) {
416
- const ret = makeMutClosure(arg0, arg1, 34, __wbg_adapter_24);
415
+ const ret = makeMutClosure(arg0, arg1, 20, __wbg_adapter_24);
417
416
  return ret;
418
417
  };
419
418
  imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
package/stak_wasm_bg.wasm CHANGED
Binary file