@raviqqe/stak 0.11.9 → 0.11.11

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.11",
6
6
  "license": "MIT",
7
7
  "repository": {
8
8
  "type": "git",
package/stak_wasm.d.ts CHANGED
@@ -1,17 +1,17 @@
1
1
  /* tslint:disable */
2
2
  /* eslint-disable */
3
3
  /**
4
- * Runs a Scheme script with standard input and returns its standard output.
4
+ * Compiles source codes in Scheme.
5
5
  */
6
- export function run(source: string, input: Uint8Array, heap_size: number): Uint8Array;
6
+ export function compile(source: string): Uint8Array;
7
7
  /**
8
8
  * Interprets bytecode with standard input and returns its standard output.
9
9
  */
10
10
  export function interpret(bytecode: Uint8Array, input: Uint8Array, heap_size: number): Uint8Array;
11
11
  /**
12
- * Compiles source codes in Scheme.
12
+ * Runs a Scheme script with standard input and returns its standard output.
13
13
  */
14
- export function compile(source: string): Uint8Array;
14
+ export function run(source: string, input: Uint8Array, heap_size: number): 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);
@@ -216,26 +209,28 @@ function getArrayU8FromWasm0(ptr, len) {
216
209
  return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
217
210
  }
218
211
  /**
219
- * Runs a Scheme script with standard input and returns its standard output.
212
+ * Compiles source codes in Scheme.
220
213
  * @param {string} source
221
- * @param {Uint8Array} input
222
- * @param {number} heap_size
223
214
  * @returns {Uint8Array}
224
215
  */
225
- export function run(source, input, heap_size) {
216
+ export function compile(source) {
226
217
  const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
227
218
  const len0 = WASM_VECTOR_LEN;
228
- const ptr1 = passArray8ToWasm0(input, wasm.__wbindgen_malloc);
229
- const len1 = WASM_VECTOR_LEN;
230
- const ret = wasm.run(ptr0, len0, ptr1, len1, heap_size);
219
+ const ret = wasm.compile(ptr0, len0);
231
220
  if (ret[3]) {
232
221
  throw takeFromExternrefTable0(ret[2]);
233
222
  }
234
- var v3 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
223
+ var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
235
224
  wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
236
- return v3;
225
+ return v2;
237
226
  }
238
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
+ }
239
234
  /**
240
235
  * Interprets bytecode with standard input and returns its standard output.
241
236
  * @param {Uint8Array} bytecode
@@ -258,20 +253,24 @@ export function interpret(bytecode, input, heap_size) {
258
253
  }
259
254
 
260
255
  /**
261
- * Compiles source codes in Scheme.
256
+ * Runs a Scheme script with standard input and returns its standard output.
262
257
  * @param {string} source
258
+ * @param {Uint8Array} input
259
+ * @param {number} heap_size
263
260
  * @returns {Uint8Array}
264
261
  */
265
- export function compile(source) {
262
+ export function run(source, input, heap_size) {
266
263
  const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
267
264
  const len0 = WASM_VECTOR_LEN;
268
- const ret = wasm.compile(ptr0, len0);
265
+ const ptr1 = passArray8ToWasm0(input, wasm.__wbindgen_malloc);
266
+ const len1 = WASM_VECTOR_LEN;
267
+ const ret = wasm.run(ptr0, len0, ptr1, len1, heap_size);
269
268
  if (ret[3]) {
270
269
  throw takeFromExternrefTable0(ret[2]);
271
270
  }
272
- var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
271
+ var v3 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
273
272
  wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
274
- return v2;
273
+ return v3;
275
274
  }
276
275
 
277
276
  /**
@@ -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_3bf4dcd8f2b8f9d7 = 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_a813e552f8d790ee = 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_80b2bfe386799c6e = 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