mustardscript 0.1.0 → 0.1.2

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 (96) hide show
  1. package/README.md +65 -22
  2. package/SECURITY.md +1 -1
  3. package/dist/index.js +2 -0
  4. package/dist/lib/executor.js +16 -1
  5. package/dist/lib/policy.js +301 -22
  6. package/dist/lib/progress.js +499 -113
  7. package/dist/lib/runtime.js +109 -40
  8. package/dist/lib/structured.js +327 -11
  9. package/dist/native-loader.js +11 -12
  10. package/index.d.ts +54 -6
  11. package/mustard.d.ts +23 -1
  12. package/package.json +34 -25
  13. package/Cargo.lock +0 -1579
  14. package/Cargo.toml +0 -40
  15. package/crates/mustard/Cargo.toml +0 -31
  16. package/crates/mustard/src/cancellation.rs +0 -28
  17. package/crates/mustard/src/diagnostic.rs +0 -145
  18. package/crates/mustard/src/ir.rs +0 -435
  19. package/crates/mustard/src/lib.rs +0 -21
  20. package/crates/mustard/src/limits.rs +0 -22
  21. package/crates/mustard/src/parser/expressions.rs +0 -723
  22. package/crates/mustard/src/parser/mod.rs +0 -115
  23. package/crates/mustard/src/parser/operators.rs +0 -105
  24. package/crates/mustard/src/parser/patterns.rs +0 -123
  25. package/crates/mustard/src/parser/scope.rs +0 -107
  26. package/crates/mustard/src/parser/statements.rs +0 -298
  27. package/crates/mustard/src/parser/tests/acceptance.rs +0 -339
  28. package/crates/mustard/src/parser/tests/mod.rs +0 -2
  29. package/crates/mustard/src/parser/tests/rejections.rs +0 -107
  30. package/crates/mustard/src/runtime/accounting.rs +0 -613
  31. package/crates/mustard/src/runtime/api.rs +0 -192
  32. package/crates/mustard/src/runtime/async_runtime/mod.rs +0 -5
  33. package/crates/mustard/src/runtime/async_runtime/promises.rs +0 -246
  34. package/crates/mustard/src/runtime/async_runtime/reactions.rs +0 -400
  35. package/crates/mustard/src/runtime/async_runtime/scheduler.rs +0 -224
  36. package/crates/mustard/src/runtime/builtins/arrays.rs +0 -1205
  37. package/crates/mustard/src/runtime/builtins/collections.rs +0 -573
  38. package/crates/mustard/src/runtime/builtins/install.rs +0 -501
  39. package/crates/mustard/src/runtime/builtins/intl.rs +0 -553
  40. package/crates/mustard/src/runtime/builtins/mod.rs +0 -25
  41. package/crates/mustard/src/runtime/builtins/objects.rs +0 -405
  42. package/crates/mustard/src/runtime/builtins/primitives.rs +0 -859
  43. package/crates/mustard/src/runtime/builtins/promises.rs +0 -335
  44. package/crates/mustard/src/runtime/builtins/regexp.rs +0 -356
  45. package/crates/mustard/src/runtime/builtins/strings.rs +0 -803
  46. package/crates/mustard/src/runtime/builtins/support.rs +0 -561
  47. package/crates/mustard/src/runtime/bytecode.rs +0 -123
  48. package/crates/mustard/src/runtime/compiler/assignments.rs +0 -690
  49. package/crates/mustard/src/runtime/compiler/bindings.rs +0 -92
  50. package/crates/mustard/src/runtime/compiler/context.rs +0 -46
  51. package/crates/mustard/src/runtime/compiler/control.rs +0 -342
  52. package/crates/mustard/src/runtime/compiler/expressions.rs +0 -372
  53. package/crates/mustard/src/runtime/compiler/mod.rs +0 -173
  54. package/crates/mustard/src/runtime/compiler/statements.rs +0 -459
  55. package/crates/mustard/src/runtime/conversions/boundary.rs +0 -293
  56. package/crates/mustard/src/runtime/conversions/coercions.rs +0 -217
  57. package/crates/mustard/src/runtime/conversions/errors.rs +0 -118
  58. package/crates/mustard/src/runtime/conversions/mod.rs +0 -14
  59. package/crates/mustard/src/runtime/conversions/operators.rs +0 -334
  60. package/crates/mustard/src/runtime/env.rs +0 -355
  61. package/crates/mustard/src/runtime/exceptions.rs +0 -377
  62. package/crates/mustard/src/runtime/gc.rs +0 -595
  63. package/crates/mustard/src/runtime/mod.rs +0 -318
  64. package/crates/mustard/src/runtime/properties.rs +0 -1762
  65. package/crates/mustard/src/runtime/serialization.rs +0 -127
  66. package/crates/mustard/src/runtime/shared.rs +0 -108
  67. package/crates/mustard/src/runtime/snapshot_validation_tests.rs +0 -93
  68. package/crates/mustard/src/runtime/state.rs +0 -652
  69. package/crates/mustard/src/runtime/tests/async_host.rs +0 -104
  70. package/crates/mustard/src/runtime/tests/collections.rs +0 -50
  71. package/crates/mustard/src/runtime/tests/diagnostics.rs +0 -36
  72. package/crates/mustard/src/runtime/tests/exceptions.rs +0 -122
  73. package/crates/mustard/src/runtime/tests/execution.rs +0 -553
  74. package/crates/mustard/src/runtime/tests/gc.rs +0 -533
  75. package/crates/mustard/src/runtime/tests/mod.rs +0 -56
  76. package/crates/mustard/src/runtime/tests/serialization.rs +0 -170
  77. package/crates/mustard/src/runtime/validation/bytecode.rs +0 -484
  78. package/crates/mustard/src/runtime/validation/mod.rs +0 -14
  79. package/crates/mustard/src/runtime/validation/policy.rs +0 -94
  80. package/crates/mustard/src/runtime/validation/snapshot.rs +0 -406
  81. package/crates/mustard/src/runtime/validation/walk.rs +0 -206
  82. package/crates/mustard/src/runtime/vm.rs +0 -1016
  83. package/crates/mustard/src/span.rs +0 -22
  84. package/crates/mustard/src/structured.rs +0 -107
  85. package/crates/mustard-bridge/Cargo.toml +0 -17
  86. package/crates/mustard-bridge/src/codec.rs +0 -46
  87. package/crates/mustard-bridge/src/dto.rs +0 -99
  88. package/crates/mustard-bridge/src/lib.rs +0 -12
  89. package/crates/mustard-bridge/src/operations.rs +0 -142
  90. package/crates/mustard-node/Cargo.toml +0 -24
  91. package/crates/mustard-node/build.rs +0 -3
  92. package/crates/mustard-node/src/lib.rs +0 -236
  93. package/crates/mustard-sidecar/Cargo.toml +0 -21
  94. package/crates/mustard-sidecar/src/lib.rs +0 -134
  95. package/crates/mustard-sidecar/src/main.rs +0 -36
  96. package/dist/install.js +0 -117
@@ -1,334 +0,0 @@
1
- use super::*;
2
- use crate::ir::UpdateOp;
3
-
4
- impl Runtime {
5
- pub(in crate::runtime) fn apply_update(
6
- &mut self,
7
- operator: UpdateOp,
8
- value: Value,
9
- ) -> MustardResult<Value> {
10
- let delta = match operator {
11
- UpdateOp::Increment => 1.0,
12
- UpdateOp::Decrement => -1.0,
13
- };
14
- match value {
15
- Value::BigInt(value) => Ok(Value::BigInt(match operator {
16
- UpdateOp::Increment => value + BigInt::from(1u8),
17
- UpdateOp::Decrement => value - BigInt::from(1u8),
18
- })),
19
- other => Ok(Value::Number(self.to_number(other)? + delta)),
20
- }
21
- }
22
-
23
- pub(in crate::runtime) fn apply_unary(
24
- &mut self,
25
- operator: UnaryOp,
26
- value: Value,
27
- ) -> MustardResult<Value> {
28
- match operator {
29
- UnaryOp::Plus => match value {
30
- Value::BigInt(_) => Err(MustardError::runtime(
31
- "TypeError: unary plus is not supported for BigInt values",
32
- )),
33
- other => Ok(Value::Number(self.to_number(other)?)),
34
- },
35
- UnaryOp::Minus => match value {
36
- Value::BigInt(value) => Ok(Value::BigInt(-value)),
37
- other => Ok(Value::Number(-self.to_number(other)?)),
38
- },
39
- UnaryOp::Not => Ok(Value::Bool(!is_truthy(&value))),
40
- UnaryOp::Typeof => Ok(Value::String(
41
- match value {
42
- Value::Undefined => "undefined",
43
- Value::Null => "object",
44
- Value::Bool(_) => "boolean",
45
- Value::Number(_) => "number",
46
- Value::BigInt(_) => "bigint",
47
- Value::String(_) => "string",
48
- Value::Closure(_) | Value::BuiltinFunction(_) | Value::HostFunction(_) => {
49
- "function"
50
- }
51
- Value::Object(object) => {
52
- if self.objects.get(object).is_some_and(|object| {
53
- matches!(object.kind, ObjectKind::BoundFunction(_))
54
- }) {
55
- "function"
56
- } else {
57
- "object"
58
- }
59
- }
60
- Value::Array(_)
61
- | Value::Map(_)
62
- | Value::Set(_)
63
- | Value::Iterator(_)
64
- | Value::Promise(_) => "object",
65
- }
66
- .to_string(),
67
- )),
68
- UnaryOp::Void => Ok(Value::Undefined),
69
- }
70
- }
71
-
72
- pub(in crate::runtime) fn apply_binary(
73
- &mut self,
74
- operator: BinaryOp,
75
- left: Value,
76
- right: Value,
77
- ) -> MustardResult<Value> {
78
- match operator {
79
- BinaryOp::Add => {
80
- if matches!(left, Value::String(_)) || matches!(right, Value::String(_)) {
81
- Ok(Value::String(format!(
82
- "{}{}",
83
- self.to_string(left)?,
84
- self.to_string(right)?
85
- )))
86
- } else if matches!(left, Value::BigInt(_)) || matches!(right, Value::BigInt(_)) {
87
- self.apply_bigint_binary(BinaryOp::Add, left, right)
88
- } else {
89
- Ok(Value::Number(
90
- self.to_number(left)? + self.to_number(right)?,
91
- ))
92
- }
93
- }
94
- BinaryOp::Sub | BinaryOp::Mul | BinaryOp::Div | BinaryOp::Rem | BinaryOp::Pow
95
- if matches!(left, Value::BigInt(_)) || matches!(right, Value::BigInt(_)) =>
96
- {
97
- self.apply_bigint_binary(operator, left, right)
98
- }
99
- BinaryOp::Sub => Ok(Value::Number(
100
- self.to_number(left)? - self.to_number(right)?,
101
- )),
102
- BinaryOp::Mul => Ok(Value::Number(
103
- self.to_number(left)? * self.to_number(right)?,
104
- )),
105
- BinaryOp::Div => Ok(Value::Number(
106
- self.to_number(left)? / self.to_number(right)?,
107
- )),
108
- BinaryOp::Rem => Ok(Value::Number(
109
- self.to_number(left)? % self.to_number(right)?,
110
- )),
111
- BinaryOp::Pow => Ok(Value::Number(
112
- self.to_number(left)?.powf(self.to_number(right)?),
113
- )),
114
- BinaryOp::In => Ok(Value::Bool(
115
- self.has_property_in_supported_surface(right, left)?,
116
- )),
117
- BinaryOp::Instanceof => {
118
- Ok(Value::Bool(self.instanceof_supported_surface(left, right)?))
119
- }
120
- BinaryOp::Eq | BinaryOp::StrictEq => Ok(Value::Bool(strict_equal(&left, &right))),
121
- BinaryOp::NotEq | BinaryOp::StrictNotEq => {
122
- Ok(Value::Bool(!strict_equal(&left, &right)))
123
- }
124
- BinaryOp::LessThan
125
- | BinaryOp::LessThanEq
126
- | BinaryOp::GreaterThan
127
- | BinaryOp::GreaterThanEq
128
- if matches!(left, Value::BigInt(_)) || matches!(right, Value::BigInt(_)) =>
129
- {
130
- let (left, right) = bigint_operands(left, right, mixed_bigint_comparison_error)?;
131
- Ok(Value::Bool(match operator {
132
- BinaryOp::LessThan => left < right,
133
- BinaryOp::LessThanEq => left <= right,
134
- BinaryOp::GreaterThan => left > right,
135
- BinaryOp::GreaterThanEq => left >= right,
136
- _ => unreachable!(),
137
- }))
138
- }
139
- BinaryOp::LessThan
140
- | BinaryOp::LessThanEq
141
- | BinaryOp::GreaterThan
142
- | BinaryOp::GreaterThanEq
143
- if matches!((&left, &right), (Value::String(_), Value::String(_))) =>
144
- {
145
- let (Value::String(left), Value::String(right)) = (left, right) else {
146
- unreachable!()
147
- };
148
- Ok(Value::Bool(match operator {
149
- BinaryOp::LessThan => left < right,
150
- BinaryOp::LessThanEq => left <= right,
151
- BinaryOp::GreaterThan => left > right,
152
- BinaryOp::GreaterThanEq => left >= right,
153
- _ => unreachable!(),
154
- }))
155
- }
156
- BinaryOp::LessThan => Ok(Value::Bool(self.to_number(left)? < self.to_number(right)?)),
157
- BinaryOp::LessThanEq => {
158
- Ok(Value::Bool(self.to_number(left)? <= self.to_number(right)?))
159
- }
160
- BinaryOp::GreaterThan => {
161
- Ok(Value::Bool(self.to_number(left)? > self.to_number(right)?))
162
- }
163
- BinaryOp::GreaterThanEq => {
164
- Ok(Value::Bool(self.to_number(left)? >= self.to_number(right)?))
165
- }
166
- }
167
- }
168
- }
169
-
170
- impl Runtime {
171
- fn instanceof_supported_surface(&self, left: Value, right: Value) -> MustardResult<bool> {
172
- match right {
173
- Value::BuiltinFunction(function) => match function {
174
- BuiltinFunction::FunctionCtor => Ok(match left {
175
- Value::Closure(_) | Value::BuiltinFunction(_) | Value::HostFunction(_) => true,
176
- Value::Object(object) => self
177
- .objects
178
- .get(object)
179
- .is_some_and(|object| matches!(object.kind, ObjectKind::BoundFunction(_))),
180
- _ => false,
181
- }),
182
- BuiltinFunction::ArrayCtor => Ok(matches!(left, Value::Array(_))),
183
- BuiltinFunction::ObjectCtor => Ok(matches!(
184
- left,
185
- Value::Object(_)
186
- | Value::Array(_)
187
- | Value::Map(_)
188
- | Value::Set(_)
189
- | Value::Iterator(_)
190
- | Value::Promise(_)
191
- | Value::Closure(_)
192
- | Value::BuiltinFunction(_)
193
- | Value::HostFunction(_)
194
- )),
195
- BuiltinFunction::MapCtor => Ok(matches!(left, Value::Map(_))),
196
- BuiltinFunction::SetCtor => Ok(matches!(left, Value::Set(_))),
197
- BuiltinFunction::PromiseCtor => Ok(matches!(left, Value::Promise(_))),
198
- BuiltinFunction::NumberCtor => Ok(matches!(
199
- left,
200
- Value::Object(object)
201
- if self.objects.get(object).is_some_and(
202
- |object| matches!(object.kind, ObjectKind::NumberObject(_))
203
- )
204
- )),
205
- BuiltinFunction::DateCtor => Ok(matches!(
206
- left,
207
- Value::Object(object)
208
- if self
209
- .objects
210
- .get(object)
211
- .is_some_and(|object| matches!(object.kind, ObjectKind::Date(_)))
212
- )),
213
- BuiltinFunction::RegExpCtor => Ok(matches!(
214
- left,
215
- Value::Object(object)
216
- if self
217
- .objects
218
- .get(object)
219
- .is_some_and(|object| matches!(object.kind, ObjectKind::RegExp(_)))
220
- )),
221
- BuiltinFunction::StringCtor => Ok(matches!(
222
- left,
223
- Value::Object(object)
224
- if self.objects.get(object).is_some_and(
225
- |object| matches!(object.kind, ObjectKind::StringObject(_))
226
- )
227
- )),
228
- BuiltinFunction::BooleanCtor => Ok(matches!(
229
- left,
230
- Value::Object(object)
231
- if self.objects.get(object).is_some_and(
232
- |object| matches!(object.kind, ObjectKind::BooleanObject(_))
233
- )
234
- )),
235
- BuiltinFunction::ErrorCtor => Ok(matches!(
236
- left,
237
- Value::Object(object)
238
- if self
239
- .objects
240
- .get(object)
241
- .is_some_and(|object| matches!(object.kind, ObjectKind::Error(_)))
242
- )),
243
- BuiltinFunction::TypeErrorCtor => Ok(self.error_kind_matches(left, "TypeError")),
244
- BuiltinFunction::ReferenceErrorCtor => {
245
- Ok(self.error_kind_matches(left, "ReferenceError"))
246
- }
247
- BuiltinFunction::RangeErrorCtor => Ok(self.error_kind_matches(left, "RangeError")),
248
- BuiltinFunction::SyntaxErrorCtor => {
249
- Ok(self.error_kind_matches(left, "SyntaxError"))
250
- }
251
- _ => Err(MustardError::runtime(
252
- "TypeError: right-hand side of instanceof must be a supported constructor",
253
- )),
254
- },
255
- Value::Closure(_) => Ok(false),
256
- _ => Err(MustardError::runtime(
257
- "TypeError: right-hand side of instanceof must be a supported constructor",
258
- )),
259
- }
260
- }
261
-
262
- fn error_kind_matches(&self, value: Value, expected: &str) -> bool {
263
- matches!(
264
- value,
265
- Value::Object(object)
266
- if self
267
- .objects
268
- .get(object)
269
- .is_some_and(|object| matches!(&object.kind, ObjectKind::Error(name) if name == expected))
270
- )
271
- }
272
- }
273
-
274
- impl Runtime {
275
- fn apply_bigint_binary(
276
- &self,
277
- operator: BinaryOp,
278
- left: Value,
279
- right: Value,
280
- ) -> MustardResult<Value> {
281
- let (left, right) = bigint_operands(left, right, mixed_bigint_number_error)?;
282
- match operator {
283
- BinaryOp::Add => Ok(Value::BigInt(left + right)),
284
- BinaryOp::Sub => Ok(Value::BigInt(left - right)),
285
- BinaryOp::Mul => Ok(Value::BigInt(left * right)),
286
- BinaryOp::Div => {
287
- if right.is_zero() {
288
- Err(MustardError::runtime("RangeError: BigInt division by zero"))
289
- } else {
290
- Ok(Value::BigInt(left / right))
291
- }
292
- }
293
- BinaryOp::Rem => {
294
- if right.is_zero() {
295
- Err(MustardError::runtime("RangeError: BigInt division by zero"))
296
- } else {
297
- Ok(Value::BigInt(left % right))
298
- }
299
- }
300
- BinaryOp::Pow => {
301
- if right < BigInt::zero() {
302
- return Err(MustardError::runtime(
303
- "RangeError: BigInt exponent must be non-negative",
304
- ));
305
- }
306
- let exponent = right.to_u32().ok_or_else(|| {
307
- MustardError::runtime("RangeError: BigInt exponent is too large")
308
- })?;
309
- Ok(Value::BigInt(left.pow(exponent)))
310
- }
311
- _ => unreachable!(),
312
- }
313
- }
314
- }
315
-
316
- fn bigint_operands(
317
- left: Value,
318
- right: Value,
319
- mixed_error: fn() -> MustardError,
320
- ) -> MustardResult<(BigInt, BigInt)> {
321
- match (left, right) {
322
- (Value::BigInt(left), Value::BigInt(right)) => Ok((left, right)),
323
- (Value::BigInt(_), _) | (_, Value::BigInt(_)) => Err(mixed_error()),
324
- _ => unreachable!(),
325
- }
326
- }
327
-
328
- fn mixed_bigint_number_error() -> MustardError {
329
- MustardError::runtime("TypeError: cannot mix BigInt and Number values in arithmetic")
330
- }
331
-
332
- fn mixed_bigint_comparison_error() -> MustardError {
333
- MustardError::runtime("TypeError: cannot compare BigInt and Number values")
334
- }
@@ -1,355 +0,0 @@
1
- use super::*;
2
-
3
- impl Runtime {
4
- pub(super) fn global_object_key(&self) -> Option<ObjectKey> {
5
- let cell = self
6
- .envs
7
- .get(self.globals)?
8
- .bindings
9
- .get("globalThis")
10
- .copied()?;
11
- match self.cells.get(cell)?.value {
12
- Value::Object(object) => Some(object),
13
- _ => None,
14
- }
15
- }
16
-
17
- fn global_property_value(&self, name: &str) -> Option<Value> {
18
- let global_object = self.global_object_key()?;
19
- self.objects
20
- .get(global_object)?
21
- .properties
22
- .get(name)
23
- .cloned()
24
- }
25
-
26
- fn set_global_property_value(&mut self, name: String, value: Value) -> MustardResult<()> {
27
- let Some(global_object) = self.global_object_key() else {
28
- return Ok(());
29
- };
30
- self.objects
31
- .get_mut(global_object)
32
- .ok_or_else(|| MustardError::runtime("global object missing"))?
33
- .properties
34
- .insert(name, value);
35
- self.refresh_object_accounting(global_object)?;
36
- Ok(())
37
- }
38
-
39
- pub(super) fn infer_closure_name(&mut self, value: &Value, name: &str) -> MustardResult<()> {
40
- let Value::Closure(closure) = value else {
41
- return Ok(());
42
- };
43
- let needs_name = self
44
- .closures
45
- .get(*closure)
46
- .ok_or_else(|| MustardError::runtime("closure missing"))?
47
- .name
48
- .is_none();
49
- if !needs_name {
50
- return Ok(());
51
- }
52
- self.closures
53
- .get_mut(*closure)
54
- .ok_or_else(|| MustardError::runtime("closure missing"))?
55
- .name = Some(name.to_string());
56
- self.refresh_closure_accounting(*closure)?;
57
- Ok(())
58
- }
59
-
60
- pub(super) fn new_env(&mut self, parent: Option<EnvKey>) -> MustardResult<EnvKey> {
61
- self.insert_env(parent)
62
- }
63
-
64
- pub(super) fn define_global(
65
- &mut self,
66
- name: String,
67
- value: Value,
68
- mutable: bool,
69
- ) -> MustardResult<()> {
70
- let binding_name = name.clone();
71
- let cell = self.insert_cell(value, mutable, true)?;
72
- self.envs
73
- .get_mut(self.globals)
74
- .ok_or_else(|| MustardError::runtime("missing globals environment"))?
75
- .bindings
76
- .insert(name, cell);
77
- self.refresh_env_accounting(self.globals)?;
78
- let value = self
79
- .cells
80
- .get(cell)
81
- .ok_or_else(|| MustardError::runtime("binding cell missing"))?
82
- .value
83
- .clone();
84
- self.set_global_property_value(binding_name, value)?;
85
- Ok(())
86
- }
87
-
88
- pub(super) fn declare_name(
89
- &mut self,
90
- env: EnvKey,
91
- name: String,
92
- mutable: bool,
93
- ) -> MustardResult<()> {
94
- if self
95
- .envs
96
- .get(env)
97
- .ok_or_else(|| MustardError::runtime("environment missing"))?
98
- .bindings
99
- .contains_key(&name)
100
- {
101
- return Ok(());
102
- }
103
- let cell = self.insert_cell(Value::Undefined, mutable, false)?;
104
- self.envs
105
- .get_mut(env)
106
- .ok_or_else(|| MustardError::runtime("environment missing"))?
107
- .bindings
108
- .insert(name, cell);
109
- self.refresh_env_accounting(env)?;
110
- Ok(())
111
- }
112
-
113
- pub(super) fn lookup_name(&self, env: EnvKey, name: &str) -> MustardResult<Value> {
114
- let Some(cell) = self.find_cell(env, name) else {
115
- if let Some(value) = self.global_property_value(name) {
116
- return Ok(value);
117
- }
118
- return Err(MustardError::Message {
119
- kind: DiagnosticKind::Runtime,
120
- message: format!("ReferenceError: `{name}` is not defined"),
121
- span: None,
122
- traceback: Vec::new(),
123
- });
124
- };
125
- let cell = self
126
- .cells
127
- .get(cell)
128
- .ok_or_else(|| MustardError::runtime("binding cell missing"))?;
129
- if !cell.initialized {
130
- return Err(MustardError::runtime(format!(
131
- "ReferenceError: `{name}` accessed before initialization"
132
- )));
133
- }
134
- Ok(cell.value.clone())
135
- }
136
-
137
- pub(super) fn assign_name(
138
- &mut self,
139
- env: EnvKey,
140
- name: &str,
141
- value: Value,
142
- ) -> MustardResult<()> {
143
- self.infer_closure_name(&value, name)?;
144
- let Some(cell_key) = self.find_cell(env, name) else {
145
- if self.global_property_value(name).is_some() {
146
- return self.set_global_property_value(name.to_string(), value);
147
- }
148
- return Err(MustardError::runtime(format!(
149
- "ReferenceError: `{name}` is not defined"
150
- )));
151
- };
152
- {
153
- let cell = self
154
- .cells
155
- .get_mut(cell_key)
156
- .ok_or_else(|| MustardError::runtime("binding cell missing"))?;
157
- if !cell.initialized {
158
- return Err(MustardError::runtime(format!(
159
- "ReferenceError: `{name}` accessed before initialization"
160
- )));
161
- }
162
- if !cell.mutable {
163
- return Err(MustardError::runtime(format!(
164
- "TypeError: assignment to constant variable `{name}`"
165
- )));
166
- }
167
- cell.value = value;
168
- }
169
- self.refresh_cell_accounting(cell_key)?;
170
- if self
171
- .envs
172
- .get(self.globals)
173
- .and_then(|globals| globals.bindings.get(name))
174
- .is_some_and(|bound| *bound == cell_key)
175
- {
176
- let value = self
177
- .cells
178
- .get(cell_key)
179
- .ok_or_else(|| MustardError::runtime("binding cell missing"))?
180
- .value
181
- .clone();
182
- self.set_global_property_value(name.to_string(), value)?;
183
- }
184
- Ok(())
185
- }
186
-
187
- pub(super) fn initialize_name_in_env(
188
- &mut self,
189
- env: EnvKey,
190
- name: &str,
191
- value: Value,
192
- ) -> MustardResult<()> {
193
- self.infer_closure_name(&value, name)?;
194
- let cell_key = self
195
- .envs
196
- .get(env)
197
- .and_then(|env| env.bindings.get(name).copied())
198
- .ok_or_else(|| {
199
- MustardError::runtime(format!("binding `{name}` missing in current scope"))
200
- })?;
201
- let mut was_initialized = false;
202
- {
203
- let cell = self
204
- .cells
205
- .get_mut(cell_key)
206
- .ok_or_else(|| MustardError::runtime("binding cell missing"))?;
207
- if cell.initialized {
208
- if !cell.mutable {
209
- return Err(MustardError::runtime(format!(
210
- "TypeError: binding `{name}` was already initialized"
211
- )));
212
- }
213
- cell.value = value;
214
- was_initialized = true;
215
- } else {
216
- cell.value = value;
217
- cell.initialized = true;
218
- }
219
- }
220
- self.refresh_cell_accounting(cell_key)?;
221
- if env == self.globals {
222
- let value = self
223
- .cells
224
- .get(cell_key)
225
- .ok_or_else(|| MustardError::runtime("binding cell missing"))?
226
- .value
227
- .clone();
228
- self.set_global_property_value(name.to_string(), value)?;
229
- }
230
- if was_initialized {
231
- return Ok(());
232
- }
233
- Ok(())
234
- }
235
-
236
- pub(super) fn find_cell(&self, env: EnvKey, name: &str) -> Option<CellKey> {
237
- let mut current = Some(env);
238
- while let Some(key) = current {
239
- let env = self.envs.get(key)?;
240
- if let Some(cell) = env.bindings.get(name) {
241
- return Some(*cell);
242
- }
243
- current = env.parent;
244
- }
245
- None
246
- }
247
-
248
- pub(super) fn initialize_pattern(
249
- &mut self,
250
- env: EnvKey,
251
- pattern: &Pattern,
252
- value: Value,
253
- ) -> MustardResult<()> {
254
- match pattern {
255
- Pattern::Identifier { name, .. } => self.initialize_name_in_env(env, name, value),
256
- Pattern::Default {
257
- target,
258
- default_value,
259
- ..
260
- } => {
261
- let value = if matches!(value, Value::Undefined) {
262
- let bytecode = BytecodeProgram {
263
- functions: vec![FunctionPrototype {
264
- name: None,
265
- length: 0,
266
- display_source: String::new(),
267
- params: Vec::new(),
268
- rest: None,
269
- code: Vec::new(),
270
- is_async: false,
271
- is_arrow: false,
272
- span: SourceSpan::new(0, 0),
273
- }],
274
- root: 0,
275
- };
276
- drop(bytecode);
277
- return Err(MustardError::runtime(format!(
278
- "default pattern initialization at runtime requires compiled evaluation support: {:?}",
279
- default_value
280
- )));
281
- } else {
282
- value
283
- };
284
- self.initialize_pattern(env, target, value)
285
- }
286
- Pattern::Array { elements, rest, .. } => {
287
- let items = self.to_array_items(value)?;
288
- for (index, pattern) in elements.iter().enumerate() {
289
- if let Some(pattern) = pattern {
290
- self.initialize_pattern(
291
- env,
292
- pattern,
293
- items.get(index).cloned().unwrap_or(Value::Undefined),
294
- )?;
295
- }
296
- }
297
- if let Some(rest) = rest {
298
- let array = self.insert_array(
299
- items.into_iter().skip(elements.len()).collect(),
300
- IndexMap::new(),
301
- )?;
302
- self.initialize_pattern(env, rest, Value::Array(array))?;
303
- }
304
- Ok(())
305
- }
306
- Pattern::Object {
307
- properties, rest, ..
308
- } => {
309
- let mut seen = HashSet::new();
310
- for property in properties {
311
- let key = property_name_to_key(&property.key);
312
- let prop_value =
313
- self.get_property(value.clone(), Value::String(key.clone()), false)?;
314
- seen.insert(key);
315
- self.initialize_pattern(env, &property.value, prop_value)?;
316
- }
317
- if let Some(rest_pattern) = rest {
318
- let mut rest_object = IndexMap::new();
319
- match value {
320
- Value::Object(object) => {
321
- if let Some(object) = self.objects.get(object) {
322
- for (key, value) in &object.properties {
323
- if !seen.contains(key) {
324
- rest_object.insert(key.clone(), value.clone());
325
- }
326
- }
327
- }
328
- }
329
- Value::Null | Value::Undefined => {
330
- return Err(MustardError::runtime(
331
- "cannot destructure object pattern from nullish value",
332
- ));
333
- }
334
- _ => {}
335
- }
336
- let rest = self.insert_object(rest_object, ObjectKind::Plain)?;
337
- self.initialize_pattern(env, rest_pattern, Value::Object(rest))?;
338
- }
339
- Ok(())
340
- }
341
- }
342
- }
343
-
344
- pub(super) fn capability_value(&self, name: &str) -> Option<Value> {
345
- let cell = self.find_cell(self.globals, name)?;
346
- let cell = self.cells.get(cell)?;
347
- if !cell.initialized {
348
- return None;
349
- }
350
- match &cell.value {
351
- Value::HostFunction(_) => Some(cell.value.clone()),
352
- _ => None,
353
- }
354
- }
355
- }