mustardscript 0.1.0

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.
Files changed (99) hide show
  1. package/Cargo.lock +1579 -0
  2. package/Cargo.toml +40 -0
  3. package/LICENSE +201 -0
  4. package/README.md +828 -0
  5. package/SECURITY.md +34 -0
  6. package/crates/mustard/Cargo.toml +31 -0
  7. package/crates/mustard/src/cancellation.rs +28 -0
  8. package/crates/mustard/src/diagnostic.rs +145 -0
  9. package/crates/mustard/src/ir.rs +435 -0
  10. package/crates/mustard/src/lib.rs +21 -0
  11. package/crates/mustard/src/limits.rs +22 -0
  12. package/crates/mustard/src/parser/expressions.rs +723 -0
  13. package/crates/mustard/src/parser/mod.rs +115 -0
  14. package/crates/mustard/src/parser/operators.rs +105 -0
  15. package/crates/mustard/src/parser/patterns.rs +123 -0
  16. package/crates/mustard/src/parser/scope.rs +107 -0
  17. package/crates/mustard/src/parser/statements.rs +298 -0
  18. package/crates/mustard/src/parser/tests/acceptance.rs +339 -0
  19. package/crates/mustard/src/parser/tests/mod.rs +2 -0
  20. package/crates/mustard/src/parser/tests/rejections.rs +107 -0
  21. package/crates/mustard/src/runtime/accounting.rs +613 -0
  22. package/crates/mustard/src/runtime/api.rs +192 -0
  23. package/crates/mustard/src/runtime/async_runtime/mod.rs +5 -0
  24. package/crates/mustard/src/runtime/async_runtime/promises.rs +246 -0
  25. package/crates/mustard/src/runtime/async_runtime/reactions.rs +400 -0
  26. package/crates/mustard/src/runtime/async_runtime/scheduler.rs +224 -0
  27. package/crates/mustard/src/runtime/builtins/arrays.rs +1205 -0
  28. package/crates/mustard/src/runtime/builtins/collections.rs +573 -0
  29. package/crates/mustard/src/runtime/builtins/install.rs +501 -0
  30. package/crates/mustard/src/runtime/builtins/intl.rs +553 -0
  31. package/crates/mustard/src/runtime/builtins/mod.rs +25 -0
  32. package/crates/mustard/src/runtime/builtins/objects.rs +405 -0
  33. package/crates/mustard/src/runtime/builtins/primitives.rs +859 -0
  34. package/crates/mustard/src/runtime/builtins/promises.rs +335 -0
  35. package/crates/mustard/src/runtime/builtins/regexp.rs +356 -0
  36. package/crates/mustard/src/runtime/builtins/strings.rs +803 -0
  37. package/crates/mustard/src/runtime/builtins/support.rs +561 -0
  38. package/crates/mustard/src/runtime/bytecode.rs +123 -0
  39. package/crates/mustard/src/runtime/compiler/assignments.rs +690 -0
  40. package/crates/mustard/src/runtime/compiler/bindings.rs +92 -0
  41. package/crates/mustard/src/runtime/compiler/context.rs +46 -0
  42. package/crates/mustard/src/runtime/compiler/control.rs +342 -0
  43. package/crates/mustard/src/runtime/compiler/expressions.rs +372 -0
  44. package/crates/mustard/src/runtime/compiler/mod.rs +173 -0
  45. package/crates/mustard/src/runtime/compiler/statements.rs +459 -0
  46. package/crates/mustard/src/runtime/conversions/boundary.rs +293 -0
  47. package/crates/mustard/src/runtime/conversions/coercions.rs +217 -0
  48. package/crates/mustard/src/runtime/conversions/errors.rs +118 -0
  49. package/crates/mustard/src/runtime/conversions/mod.rs +14 -0
  50. package/crates/mustard/src/runtime/conversions/operators.rs +334 -0
  51. package/crates/mustard/src/runtime/env.rs +355 -0
  52. package/crates/mustard/src/runtime/exceptions.rs +377 -0
  53. package/crates/mustard/src/runtime/gc.rs +595 -0
  54. package/crates/mustard/src/runtime/mod.rs +318 -0
  55. package/crates/mustard/src/runtime/properties.rs +1762 -0
  56. package/crates/mustard/src/runtime/serialization.rs +127 -0
  57. package/crates/mustard/src/runtime/shared.rs +108 -0
  58. package/crates/mustard/src/runtime/snapshot_validation_tests.rs +93 -0
  59. package/crates/mustard/src/runtime/state.rs +652 -0
  60. package/crates/mustard/src/runtime/tests/async_host.rs +104 -0
  61. package/crates/mustard/src/runtime/tests/collections.rs +50 -0
  62. package/crates/mustard/src/runtime/tests/diagnostics.rs +36 -0
  63. package/crates/mustard/src/runtime/tests/exceptions.rs +122 -0
  64. package/crates/mustard/src/runtime/tests/execution.rs +553 -0
  65. package/crates/mustard/src/runtime/tests/gc.rs +533 -0
  66. package/crates/mustard/src/runtime/tests/mod.rs +56 -0
  67. package/crates/mustard/src/runtime/tests/serialization.rs +170 -0
  68. package/crates/mustard/src/runtime/validation/bytecode.rs +484 -0
  69. package/crates/mustard/src/runtime/validation/mod.rs +14 -0
  70. package/crates/mustard/src/runtime/validation/policy.rs +94 -0
  71. package/crates/mustard/src/runtime/validation/snapshot.rs +406 -0
  72. package/crates/mustard/src/runtime/validation/walk.rs +206 -0
  73. package/crates/mustard/src/runtime/vm.rs +1016 -0
  74. package/crates/mustard/src/span.rs +22 -0
  75. package/crates/mustard/src/structured.rs +107 -0
  76. package/crates/mustard-bridge/Cargo.toml +17 -0
  77. package/crates/mustard-bridge/src/codec.rs +46 -0
  78. package/crates/mustard-bridge/src/dto.rs +99 -0
  79. package/crates/mustard-bridge/src/lib.rs +12 -0
  80. package/crates/mustard-bridge/src/operations.rs +142 -0
  81. package/crates/mustard-node/Cargo.toml +24 -0
  82. package/crates/mustard-node/build.rs +3 -0
  83. package/crates/mustard-node/src/lib.rs +236 -0
  84. package/crates/mustard-sidecar/Cargo.toml +21 -0
  85. package/crates/mustard-sidecar/src/lib.rs +134 -0
  86. package/crates/mustard-sidecar/src/main.rs +36 -0
  87. package/dist/index.js +20 -0
  88. package/dist/install.js +117 -0
  89. package/dist/lib/cancellation.js +124 -0
  90. package/dist/lib/errors.js +46 -0
  91. package/dist/lib/executor.js +555 -0
  92. package/dist/lib/policy.js +292 -0
  93. package/dist/lib/progress.js +356 -0
  94. package/dist/lib/runtime.js +109 -0
  95. package/dist/lib/structured.js +286 -0
  96. package/dist/native-loader.js +227 -0
  97. package/index.d.ts +23 -0
  98. package/mustard.d.ts +220 -0
  99. package/package.json +97 -0
@@ -0,0 +1,377 @@
1
+ use super::*;
2
+
3
+ impl Runtime {
4
+ pub(super) fn traceback_frames(&self) -> Vec<TraceFrame> {
5
+ self.frames
6
+ .iter()
7
+ .rev()
8
+ .filter_map(|frame| {
9
+ self.program
10
+ .functions
11
+ .get(frame.function_id)
12
+ .map(|function| TraceFrame {
13
+ function_name: function.name.clone(),
14
+ span: function.span,
15
+ })
16
+ })
17
+ .collect()
18
+ }
19
+
20
+ pub(super) fn annotate_runtime_error(&self, error: MustardError) -> MustardError {
21
+ error.with_traceback(self.traceback_frames())
22
+ }
23
+
24
+ pub(super) fn traceback_snapshots(&self) -> Vec<TraceFrameSnapshot> {
25
+ self.traceback_frames()
26
+ .into_iter()
27
+ .map(|frame| TraceFrameSnapshot {
28
+ function_name: frame.function_name,
29
+ span: frame.span,
30
+ })
31
+ .collect()
32
+ }
33
+
34
+ pub(super) fn compose_traceback(&self, origin: &[TraceFrameSnapshot]) -> Vec<TraceFrame> {
35
+ let mut frames = self.traceback_frames();
36
+ for frame in origin {
37
+ let candidate = TraceFrame {
38
+ function_name: frame.function_name.clone(),
39
+ span: frame.span,
40
+ };
41
+ if !frames.iter().any(|existing| {
42
+ existing.function_name == candidate.function_name && existing.span == candidate.span
43
+ }) {
44
+ frames.push(candidate);
45
+ }
46
+ }
47
+ frames
48
+ }
49
+
50
+ pub(super) fn runtime_error_to_promise_rejection(
51
+ &mut self,
52
+ error: MustardError,
53
+ ) -> MustardResult<PromiseRejection> {
54
+ match error {
55
+ MustardError::Message {
56
+ kind: DiagnosticKind::Runtime,
57
+ message,
58
+ span,
59
+ traceback,
60
+ } => Ok(PromiseRejection {
61
+ value: self.value_from_runtime_message(&message)?,
62
+ span,
63
+ traceback: if traceback.is_empty() {
64
+ self.traceback_snapshots()
65
+ } else {
66
+ traceback
67
+ .into_iter()
68
+ .map(|frame| TraceFrameSnapshot {
69
+ function_name: frame.function_name,
70
+ span: frame.span,
71
+ })
72
+ .collect()
73
+ },
74
+ }),
75
+ other => Err(other),
76
+ }
77
+ }
78
+
79
+ pub(super) fn reject_promise_from_error(
80
+ &mut self,
81
+ target: PromiseKey,
82
+ error: MustardError,
83
+ ) -> MustardResult<()> {
84
+ let rejection = self.runtime_error_to_promise_rejection(error)?;
85
+ self.reject_promise(target, rejection)
86
+ }
87
+
88
+ pub(super) fn root_error_from_rejection(
89
+ &self,
90
+ rejection: PromiseRejection,
91
+ ) -> MustardResult<MustardError> {
92
+ Ok(MustardError::Message {
93
+ kind: DiagnosticKind::Runtime,
94
+ message: self.render_exception(&rejection.value)?,
95
+ span: rejection.span,
96
+ traceback: self.compose_traceback(&rejection.traceback),
97
+ })
98
+ }
99
+
100
+ pub(super) fn handle_runtime_fault(
101
+ &mut self,
102
+ error: MustardError,
103
+ ) -> MustardResult<StepAction> {
104
+ match error {
105
+ MustardError::Message {
106
+ kind: DiagnosticKind::Runtime,
107
+ message,
108
+ span,
109
+ ..
110
+ } => {
111
+ if message == INTERNAL_CALLBACK_THROW_MARKER {
112
+ let rejection = self.pending_internal_exception.take().ok_or_else(|| {
113
+ MustardError::runtime("missing internal callback exception state")
114
+ })?;
115
+ return self.raise_exception_with_origin(
116
+ rejection.value,
117
+ rejection.span,
118
+ Some(rejection.traceback),
119
+ );
120
+ }
121
+ let value = self.value_from_runtime_message(&message)?;
122
+ self.raise_exception(value, span)
123
+ }
124
+ other => Err(other),
125
+ }
126
+ }
127
+
128
+ pub(super) fn store_completion(
129
+ &mut self,
130
+ frame_index: usize,
131
+ completion: CompletionRecord,
132
+ ) -> MustardResult<()> {
133
+ let completion_index = self.frames[frame_index]
134
+ .active_finally
135
+ .last()
136
+ .map(|active| active.completion_index);
137
+ if let Some(completion_index) = completion_index {
138
+ if completion_index >= self.frames[frame_index].pending_completions.len() {
139
+ return Err(MustardError::runtime(
140
+ "active finally references missing completion",
141
+ ));
142
+ }
143
+ self.frames[frame_index].pending_completions[completion_index] = completion;
144
+ } else {
145
+ self.frames[frame_index]
146
+ .pending_completions
147
+ .push(completion);
148
+ }
149
+ Ok(())
150
+ }
151
+
152
+ pub(super) fn restore_handler_state(
153
+ &mut self,
154
+ frame_index: usize,
155
+ handler: &ExceptionHandler,
156
+ ) -> MustardResult<()> {
157
+ let frame = &mut self.frames[frame_index];
158
+ frame.env = handler.env;
159
+ frame.scope_stack.truncate(handler.scope_stack_len);
160
+ frame.stack.truncate(handler.stack_len);
161
+ Ok(())
162
+ }
163
+
164
+ pub(super) fn raise_exception(
165
+ &mut self,
166
+ value: Value,
167
+ span: Option<SourceSpan>,
168
+ ) -> MustardResult<StepAction> {
169
+ self.raise_exception_with_origin(value, span, None)
170
+ }
171
+
172
+ pub(super) fn raise_exception_with_origin(
173
+ &mut self,
174
+ value: Value,
175
+ span: Option<SourceSpan>,
176
+ origin_traceback: Option<Vec<TraceFrameSnapshot>>,
177
+ ) -> MustardResult<StepAction> {
178
+ let traceback = match origin_traceback.as_ref() {
179
+ Some(origin) => self.compose_traceback(origin),
180
+ None => self.traceback_frames(),
181
+ };
182
+ let thrown = value;
183
+
184
+ loop {
185
+ let Some(frame_index) = self.frames.len().checked_sub(1) else {
186
+ return Err(MustardError::runtime("vm lost all frames"));
187
+ };
188
+
189
+ if let Some(handler_index) = self.frames[frame_index]
190
+ .handlers
191
+ .iter()
192
+ .rposition(|handler| handler.catch.is_some() || handler.finally.is_some())
193
+ {
194
+ let handler = self.frames[frame_index].handlers[handler_index].clone();
195
+ self.frames[frame_index].handlers.truncate(handler_index);
196
+ self.restore_handler_state(frame_index, &handler)?;
197
+
198
+ if let Some(catch_ip) = handler.catch {
199
+ self.frames[frame_index].pending_exception = Some(thrown);
200
+ self.frames[frame_index].ip = catch_ip;
201
+ return Ok(StepAction::Continue);
202
+ }
203
+
204
+ if let Some(finally_ip) = handler.finally {
205
+ self.frames[frame_index]
206
+ .pending_completions
207
+ .push(CompletionRecord::Throw(thrown));
208
+ self.frames[frame_index].ip = finally_ip;
209
+ return Ok(StepAction::Continue);
210
+ }
211
+ }
212
+
213
+ if let Some(active) = self.frames[frame_index].active_finally.last().cloned() {
214
+ if active.completion_index >= self.frames[frame_index].pending_completions.len() {
215
+ return Err(MustardError::runtime(
216
+ "active finally references missing completion",
217
+ ));
218
+ }
219
+ self.frames[frame_index].pending_completions[active.completion_index] =
220
+ CompletionRecord::Throw(thrown);
221
+ self.frames[frame_index].ip = active.exit;
222
+ return Ok(StepAction::Continue);
223
+ }
224
+
225
+ if let Some(async_promise) = self.frames[frame_index].async_promise {
226
+ self.frames.pop();
227
+ self.reject_promise(
228
+ async_promise,
229
+ PromiseRejection {
230
+ value: thrown,
231
+ span,
232
+ traceback: traceback
233
+ .iter()
234
+ .map(|frame| TraceFrameSnapshot {
235
+ function_name: frame.function_name.clone(),
236
+ span: frame.span,
237
+ })
238
+ .collect(),
239
+ },
240
+ )?;
241
+ return Ok(StepAction::Continue);
242
+ }
243
+
244
+ if self.frames.len() == 1 {
245
+ let message = self.render_exception(&thrown)?;
246
+ return Err(MustardError::Message {
247
+ kind: DiagnosticKind::Runtime,
248
+ message,
249
+ span,
250
+ traceback,
251
+ });
252
+ }
253
+
254
+ self.frames.pop();
255
+ }
256
+ }
257
+
258
+ pub(super) fn resume_completion(
259
+ &mut self,
260
+ completion: CompletionRecord,
261
+ ) -> MustardResult<StepAction> {
262
+ match completion {
263
+ CompletionRecord::Throw(value) => self.raise_exception(value, None),
264
+ CompletionRecord::Jump {
265
+ target,
266
+ target_handler_depth,
267
+ target_scope_depth,
268
+ } => self.resume_nonthrow_completion(
269
+ target_handler_depth,
270
+ target_scope_depth,
271
+ CompletionRecord::Jump {
272
+ target,
273
+ target_handler_depth,
274
+ target_scope_depth,
275
+ },
276
+ ),
277
+ CompletionRecord::Return(value) => {
278
+ self.resume_nonthrow_completion(0, 0, CompletionRecord::Return(value))
279
+ }
280
+ }
281
+ }
282
+
283
+ pub(super) fn resume_nonthrow_completion(
284
+ &mut self,
285
+ target_handler_depth: usize,
286
+ target_scope_depth: usize,
287
+ completion: CompletionRecord,
288
+ ) -> MustardResult<StepAction> {
289
+ let frame_index = self
290
+ .frames
291
+ .len()
292
+ .checked_sub(1)
293
+ .ok_or_else(|| MustardError::runtime("vm lost all frames"))?;
294
+ let current_depth = self.frames[frame_index].handlers.len();
295
+ if target_handler_depth > current_depth {
296
+ return Err(MustardError::runtime(
297
+ "completion targets missing handler depth",
298
+ ));
299
+ }
300
+ if target_scope_depth > self.frames[frame_index].scope_stack.len() {
301
+ return Err(MustardError::runtime(
302
+ "completion targets missing scope depth",
303
+ ));
304
+ }
305
+
306
+ let restore_state = if target_handler_depth < current_depth {
307
+ self.frames[frame_index]
308
+ .handlers
309
+ .get(target_handler_depth)
310
+ .cloned()
311
+ } else {
312
+ None
313
+ };
314
+
315
+ if let Some(handler_index) = (target_handler_depth..current_depth)
316
+ .rev()
317
+ .find(|index| self.frames[frame_index].handlers[*index].finally.is_some())
318
+ {
319
+ let handler = self.frames[frame_index].handlers[handler_index].clone();
320
+ self.frames[frame_index].handlers.truncate(handler_index);
321
+ self.restore_handler_state(frame_index, &handler)?;
322
+ self.frames[frame_index]
323
+ .pending_completions
324
+ .push(completion);
325
+ self.frames[frame_index].ip = handler
326
+ .finally
327
+ .ok_or_else(|| MustardError::runtime("missing finally target"))?;
328
+ return Ok(StepAction::Continue);
329
+ }
330
+
331
+ if let Some(handler) = restore_state.as_ref() {
332
+ self.restore_handler_state(frame_index, handler)?;
333
+ }
334
+ self.frames[frame_index]
335
+ .handlers
336
+ .truncate(target_handler_depth);
337
+
338
+ match completion {
339
+ CompletionRecord::Jump { target, .. } => {
340
+ if self.frames[frame_index].scope_stack.len() < target_scope_depth {
341
+ return Err(MustardError::runtime(
342
+ "completion targets missing scope depth",
343
+ ));
344
+ }
345
+ while self.frames[frame_index].scope_stack.len() > target_scope_depth {
346
+ let restored = self.frames[frame_index]
347
+ .scope_stack
348
+ .pop()
349
+ .ok_or_else(|| MustardError::runtime("scope stack underflow"))?;
350
+ self.frames[frame_index].env = restored;
351
+ }
352
+ self.frames[frame_index].ip = target;
353
+ Ok(StepAction::Continue)
354
+ }
355
+ CompletionRecord::Return(value) => self.complete_return(value),
356
+ CompletionRecord::Throw(_) => unreachable!(),
357
+ }
358
+ }
359
+
360
+ pub(super) fn complete_return(&mut self, value: Value) -> MustardResult<StepAction> {
361
+ let frame = self
362
+ .frames
363
+ .pop()
364
+ .ok_or_else(|| MustardError::runtime("vm lost all frames"))?;
365
+ if let Some(async_promise) = frame.async_promise {
366
+ self.resolve_promise(async_promise, value)?;
367
+ return Ok(StepAction::Continue);
368
+ }
369
+ if let Some(parent) = self.frames.last_mut() {
370
+ parent.stack.push(value);
371
+ Ok(StepAction::Continue)
372
+ } else {
373
+ self.root_result = Some(value);
374
+ Ok(StepAction::Continue)
375
+ }
376
+ }
377
+ }