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.
- package/Cargo.lock +1579 -0
- package/Cargo.toml +40 -0
- package/LICENSE +201 -0
- package/README.md +828 -0
- package/SECURITY.md +34 -0
- package/crates/mustard/Cargo.toml +31 -0
- package/crates/mustard/src/cancellation.rs +28 -0
- package/crates/mustard/src/diagnostic.rs +145 -0
- package/crates/mustard/src/ir.rs +435 -0
- package/crates/mustard/src/lib.rs +21 -0
- package/crates/mustard/src/limits.rs +22 -0
- package/crates/mustard/src/parser/expressions.rs +723 -0
- package/crates/mustard/src/parser/mod.rs +115 -0
- package/crates/mustard/src/parser/operators.rs +105 -0
- package/crates/mustard/src/parser/patterns.rs +123 -0
- package/crates/mustard/src/parser/scope.rs +107 -0
- package/crates/mustard/src/parser/statements.rs +298 -0
- package/crates/mustard/src/parser/tests/acceptance.rs +339 -0
- package/crates/mustard/src/parser/tests/mod.rs +2 -0
- package/crates/mustard/src/parser/tests/rejections.rs +107 -0
- package/crates/mustard/src/runtime/accounting.rs +613 -0
- package/crates/mustard/src/runtime/api.rs +192 -0
- package/crates/mustard/src/runtime/async_runtime/mod.rs +5 -0
- package/crates/mustard/src/runtime/async_runtime/promises.rs +246 -0
- package/crates/mustard/src/runtime/async_runtime/reactions.rs +400 -0
- package/crates/mustard/src/runtime/async_runtime/scheduler.rs +224 -0
- package/crates/mustard/src/runtime/builtins/arrays.rs +1205 -0
- package/crates/mustard/src/runtime/builtins/collections.rs +573 -0
- package/crates/mustard/src/runtime/builtins/install.rs +501 -0
- package/crates/mustard/src/runtime/builtins/intl.rs +553 -0
- package/crates/mustard/src/runtime/builtins/mod.rs +25 -0
- package/crates/mustard/src/runtime/builtins/objects.rs +405 -0
- package/crates/mustard/src/runtime/builtins/primitives.rs +859 -0
- package/crates/mustard/src/runtime/builtins/promises.rs +335 -0
- package/crates/mustard/src/runtime/builtins/regexp.rs +356 -0
- package/crates/mustard/src/runtime/builtins/strings.rs +803 -0
- package/crates/mustard/src/runtime/builtins/support.rs +561 -0
- package/crates/mustard/src/runtime/bytecode.rs +123 -0
- package/crates/mustard/src/runtime/compiler/assignments.rs +690 -0
- package/crates/mustard/src/runtime/compiler/bindings.rs +92 -0
- package/crates/mustard/src/runtime/compiler/context.rs +46 -0
- package/crates/mustard/src/runtime/compiler/control.rs +342 -0
- package/crates/mustard/src/runtime/compiler/expressions.rs +372 -0
- package/crates/mustard/src/runtime/compiler/mod.rs +173 -0
- package/crates/mustard/src/runtime/compiler/statements.rs +459 -0
- package/crates/mustard/src/runtime/conversions/boundary.rs +293 -0
- package/crates/mustard/src/runtime/conversions/coercions.rs +217 -0
- package/crates/mustard/src/runtime/conversions/errors.rs +118 -0
- package/crates/mustard/src/runtime/conversions/mod.rs +14 -0
- package/crates/mustard/src/runtime/conversions/operators.rs +334 -0
- package/crates/mustard/src/runtime/env.rs +355 -0
- package/crates/mustard/src/runtime/exceptions.rs +377 -0
- package/crates/mustard/src/runtime/gc.rs +595 -0
- package/crates/mustard/src/runtime/mod.rs +318 -0
- package/crates/mustard/src/runtime/properties.rs +1762 -0
- package/crates/mustard/src/runtime/serialization.rs +127 -0
- package/crates/mustard/src/runtime/shared.rs +108 -0
- package/crates/mustard/src/runtime/snapshot_validation_tests.rs +93 -0
- package/crates/mustard/src/runtime/state.rs +652 -0
- package/crates/mustard/src/runtime/tests/async_host.rs +104 -0
- package/crates/mustard/src/runtime/tests/collections.rs +50 -0
- package/crates/mustard/src/runtime/tests/diagnostics.rs +36 -0
- package/crates/mustard/src/runtime/tests/exceptions.rs +122 -0
- package/crates/mustard/src/runtime/tests/execution.rs +553 -0
- package/crates/mustard/src/runtime/tests/gc.rs +533 -0
- package/crates/mustard/src/runtime/tests/mod.rs +56 -0
- package/crates/mustard/src/runtime/tests/serialization.rs +170 -0
- package/crates/mustard/src/runtime/validation/bytecode.rs +484 -0
- package/crates/mustard/src/runtime/validation/mod.rs +14 -0
- package/crates/mustard/src/runtime/validation/policy.rs +94 -0
- package/crates/mustard/src/runtime/validation/snapshot.rs +406 -0
- package/crates/mustard/src/runtime/validation/walk.rs +206 -0
- package/crates/mustard/src/runtime/vm.rs +1016 -0
- package/crates/mustard/src/span.rs +22 -0
- package/crates/mustard/src/structured.rs +107 -0
- package/crates/mustard-bridge/Cargo.toml +17 -0
- package/crates/mustard-bridge/src/codec.rs +46 -0
- package/crates/mustard-bridge/src/dto.rs +99 -0
- package/crates/mustard-bridge/src/lib.rs +12 -0
- package/crates/mustard-bridge/src/operations.rs +142 -0
- package/crates/mustard-node/Cargo.toml +24 -0
- package/crates/mustard-node/build.rs +3 -0
- package/crates/mustard-node/src/lib.rs +236 -0
- package/crates/mustard-sidecar/Cargo.toml +21 -0
- package/crates/mustard-sidecar/src/lib.rs +134 -0
- package/crates/mustard-sidecar/src/main.rs +36 -0
- package/dist/index.js +20 -0
- package/dist/install.js +117 -0
- package/dist/lib/cancellation.js +124 -0
- package/dist/lib/errors.js +46 -0
- package/dist/lib/executor.js +555 -0
- package/dist/lib/policy.js +292 -0
- package/dist/lib/progress.js +356 -0
- package/dist/lib/runtime.js +109 -0
- package/dist/lib/structured.js +286 -0
- package/dist/native-loader.js +227 -0
- package/index.d.ts +23 -0
- package/mustard.d.ts +220 -0
- package/package.json +97 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
mod expressions;
|
|
2
|
+
mod operators;
|
|
3
|
+
mod patterns;
|
|
4
|
+
mod scope;
|
|
5
|
+
mod statements;
|
|
6
|
+
|
|
7
|
+
#[cfg(test)]
|
|
8
|
+
mod tests;
|
|
9
|
+
|
|
10
|
+
use std::collections::HashSet;
|
|
11
|
+
|
|
12
|
+
use oxc_allocator::Allocator;
|
|
13
|
+
use oxc_ast::ast::*;
|
|
14
|
+
use oxc_parser::{ParseOptions, Parser};
|
|
15
|
+
use oxc_span::{GetSpan, SourceType};
|
|
16
|
+
|
|
17
|
+
use crate::{
|
|
18
|
+
diagnostic::{Diagnostic, MustardError, MustardResult},
|
|
19
|
+
ir::*,
|
|
20
|
+
span::SourceSpan,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const FORBIDDEN_AMBIENT_GLOBALS: &[&str] = &[
|
|
24
|
+
"arguments",
|
|
25
|
+
"eval",
|
|
26
|
+
"process",
|
|
27
|
+
"module",
|
|
28
|
+
"exports",
|
|
29
|
+
"global",
|
|
30
|
+
"require",
|
|
31
|
+
"Function",
|
|
32
|
+
"setTimeout",
|
|
33
|
+
"setInterval",
|
|
34
|
+
"queueMicrotask",
|
|
35
|
+
"fetch",
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
pub fn compile(source: &str) -> MustardResult<CompiledProgram> {
|
|
39
|
+
let allocator = Allocator::default();
|
|
40
|
+
let parser = Parser::new(&allocator, source, SourceType::default().with_script(true))
|
|
41
|
+
.with_options(ParseOptions {
|
|
42
|
+
allow_return_outside_function: false,
|
|
43
|
+
..ParseOptions::default()
|
|
44
|
+
});
|
|
45
|
+
let parsed = parser.parse();
|
|
46
|
+
let mut diagnostics = Vec::new();
|
|
47
|
+
diagnostics.extend(
|
|
48
|
+
parsed
|
|
49
|
+
.errors
|
|
50
|
+
.into_iter()
|
|
51
|
+
.map(|error| Diagnostic::parse(error.to_string(), None)),
|
|
52
|
+
);
|
|
53
|
+
if parsed.panicked {
|
|
54
|
+
return Err(MustardError::Diagnostics(diagnostics));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let mut lowerer = Lowerer::new(source);
|
|
58
|
+
let script = lowerer.lower_program(&parsed.program);
|
|
59
|
+
diagnostics.extend(lowerer.diagnostics);
|
|
60
|
+
if !diagnostics.is_empty() {
|
|
61
|
+
return Err(MustardError::Diagnostics(diagnostics));
|
|
62
|
+
}
|
|
63
|
+
Ok(CompiledProgram {
|
|
64
|
+
source: source.to_string(),
|
|
65
|
+
script,
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
struct Lowerer<'a> {
|
|
70
|
+
diagnostics: Vec<Diagnostic>,
|
|
71
|
+
_source: &'a str,
|
|
72
|
+
scopes: Vec<HashSet<String>>,
|
|
73
|
+
internal_name_counter: usize,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
impl<'a> Lowerer<'a> {
|
|
77
|
+
fn new(source: &'a str) -> Self {
|
|
78
|
+
Self {
|
|
79
|
+
diagnostics: Vec::new(),
|
|
80
|
+
_source: source,
|
|
81
|
+
scopes: vec![HashSet::new()],
|
|
82
|
+
internal_name_counter: 0,
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
fn lower_program(&mut self, program: &Program<'a>) -> Script {
|
|
87
|
+
self.predeclare_block(&program.body);
|
|
88
|
+
let body = program
|
|
89
|
+
.body
|
|
90
|
+
.iter()
|
|
91
|
+
.filter_map(|statement| self.lower_stmt(statement))
|
|
92
|
+
.collect();
|
|
93
|
+
Script {
|
|
94
|
+
span: program.span.into(),
|
|
95
|
+
body,
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
fn unsupported(&mut self, message: impl Into<String>, span: Option<SourceSpan>) {
|
|
100
|
+
self.diagnostics
|
|
101
|
+
.push(Diagnostic::validation(message.into(), span));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
fn fresh_internal_name(&mut self, prefix: &str) -> String {
|
|
105
|
+
let name = format!("\0mustard_{prefix}_{}", self.internal_name_counter);
|
|
106
|
+
self.internal_name_counter += 1;
|
|
107
|
+
name
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
fn source_snippet(&self, span: SourceSpan) -> String {
|
|
111
|
+
let start = span.start as usize;
|
|
112
|
+
let end = span.end as usize;
|
|
113
|
+
self._source.get(start..end).unwrap_or_default().to_string()
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
use super::*;
|
|
2
|
+
|
|
3
|
+
impl<'a> Lowerer<'a> {
|
|
4
|
+
pub(super) fn lower_property_name(&mut self, key: &PropertyKey<'a>) -> Option<PropertyName> {
|
|
5
|
+
match key {
|
|
6
|
+
PropertyKey::StaticIdentifier(identifier) => Some(PropertyName::Identifier(
|
|
7
|
+
identifier.name.as_str().to_string(),
|
|
8
|
+
)),
|
|
9
|
+
PropertyKey::StringLiteral(literal) => {
|
|
10
|
+
Some(PropertyName::String(literal.value.as_str().to_string()))
|
|
11
|
+
}
|
|
12
|
+
PropertyKey::NumericLiteral(literal) => Some(PropertyName::Number(literal.value)),
|
|
13
|
+
_ => {
|
|
14
|
+
self.unsupported("unsupported property key in v1", Some(key.span().into()));
|
|
15
|
+
None
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
pub(super) fn lower_unary_op(
|
|
21
|
+
&mut self,
|
|
22
|
+
op: UnaryOperator,
|
|
23
|
+
span: oxc_span::Span,
|
|
24
|
+
) -> Option<UnaryOp> {
|
|
25
|
+
match op {
|
|
26
|
+
UnaryOperator::UnaryPlus => Some(UnaryOp::Plus),
|
|
27
|
+
UnaryOperator::UnaryNegation => Some(UnaryOp::Minus),
|
|
28
|
+
UnaryOperator::LogicalNot => Some(UnaryOp::Not),
|
|
29
|
+
UnaryOperator::Typeof => Some(UnaryOp::Typeof),
|
|
30
|
+
UnaryOperator::Void => Some(UnaryOp::Void),
|
|
31
|
+
UnaryOperator::Delete => {
|
|
32
|
+
self.unsupported("delete is not supported in v1", Some(span.into()));
|
|
33
|
+
None
|
|
34
|
+
}
|
|
35
|
+
_ => {
|
|
36
|
+
self.unsupported("unsupported unary operator in v1", Some(span.into()));
|
|
37
|
+
None
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
pub(super) fn lower_binary_op(
|
|
43
|
+
&mut self,
|
|
44
|
+
op: BinaryOperator,
|
|
45
|
+
span: oxc_span::Span,
|
|
46
|
+
) -> Option<BinaryOp> {
|
|
47
|
+
match op {
|
|
48
|
+
BinaryOperator::Addition => Some(BinaryOp::Add),
|
|
49
|
+
BinaryOperator::Subtraction => Some(BinaryOp::Sub),
|
|
50
|
+
BinaryOperator::Multiplication => Some(BinaryOp::Mul),
|
|
51
|
+
BinaryOperator::Division => Some(BinaryOp::Div),
|
|
52
|
+
BinaryOperator::Remainder => Some(BinaryOp::Rem),
|
|
53
|
+
BinaryOperator::Exponential => Some(BinaryOp::Pow),
|
|
54
|
+
BinaryOperator::In => Some(BinaryOp::In),
|
|
55
|
+
BinaryOperator::Instanceof => Some(BinaryOp::Instanceof),
|
|
56
|
+
BinaryOperator::Equality => Some(BinaryOp::Eq),
|
|
57
|
+
BinaryOperator::Inequality => Some(BinaryOp::NotEq),
|
|
58
|
+
BinaryOperator::StrictEquality => Some(BinaryOp::StrictEq),
|
|
59
|
+
BinaryOperator::StrictInequality => Some(BinaryOp::StrictNotEq),
|
|
60
|
+
BinaryOperator::LessThan => Some(BinaryOp::LessThan),
|
|
61
|
+
BinaryOperator::LessEqualThan => Some(BinaryOp::LessThanEq),
|
|
62
|
+
BinaryOperator::GreaterThan => Some(BinaryOp::GreaterThan),
|
|
63
|
+
BinaryOperator::GreaterEqualThan => Some(BinaryOp::GreaterThanEq),
|
|
64
|
+
_ => {
|
|
65
|
+
self.unsupported("unsupported binary operator in v1", Some(span.into()));
|
|
66
|
+
None
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
pub(super) fn lower_logical_op(
|
|
72
|
+
&mut self,
|
|
73
|
+
op: LogicalOperator,
|
|
74
|
+
_span: oxc_span::Span,
|
|
75
|
+
) -> Option<LogicalOp> {
|
|
76
|
+
match op {
|
|
77
|
+
LogicalOperator::And => Some(LogicalOp::And),
|
|
78
|
+
LogicalOperator::Or => Some(LogicalOp::Or),
|
|
79
|
+
LogicalOperator::Coalesce => Some(LogicalOp::NullishCoalesce),
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
pub(super) fn lower_assign_op(
|
|
84
|
+
&mut self,
|
|
85
|
+
op: AssignmentOperator,
|
|
86
|
+
span: oxc_span::Span,
|
|
87
|
+
) -> Option<AssignOp> {
|
|
88
|
+
match op {
|
|
89
|
+
AssignmentOperator::Assign => Some(AssignOp::Assign),
|
|
90
|
+
AssignmentOperator::Addition => Some(AssignOp::AddAssign),
|
|
91
|
+
AssignmentOperator::Subtraction => Some(AssignOp::SubAssign),
|
|
92
|
+
AssignmentOperator::Multiplication => Some(AssignOp::MulAssign),
|
|
93
|
+
AssignmentOperator::Division => Some(AssignOp::DivAssign),
|
|
94
|
+
AssignmentOperator::Remainder => Some(AssignOp::RemAssign),
|
|
95
|
+
AssignmentOperator::Exponential => Some(AssignOp::PowAssign),
|
|
96
|
+
AssignmentOperator::LogicalOr => Some(AssignOp::OrAssign),
|
|
97
|
+
AssignmentOperator::LogicalAnd => Some(AssignOp::AndAssign),
|
|
98
|
+
AssignmentOperator::LogicalNullish => Some(AssignOp::NullishAssign),
|
|
99
|
+
_ => {
|
|
100
|
+
self.unsupported("unsupported assignment operator in v1", Some(span.into()));
|
|
101
|
+
None
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
use super::*;
|
|
2
|
+
|
|
3
|
+
type LoweredFunctionParams = (Vec<Pattern>, Option<Pattern>, Vec<Stmt>, usize);
|
|
4
|
+
|
|
5
|
+
impl<'a> Lowerer<'a> {
|
|
6
|
+
pub(super) fn lower_pattern(&mut self, pattern: &BindingPattern<'a>) -> Option<Pattern> {
|
|
7
|
+
match pattern {
|
|
8
|
+
BindingPattern::BindingIdentifier(identifier) => Some(Pattern::Identifier {
|
|
9
|
+
span: identifier.span.into(),
|
|
10
|
+
name: identifier.name.as_str().to_string(),
|
|
11
|
+
}),
|
|
12
|
+
BindingPattern::ObjectPattern(pattern) => Some(Pattern::Object {
|
|
13
|
+
span: pattern.span.into(),
|
|
14
|
+
properties: pattern
|
|
15
|
+
.properties
|
|
16
|
+
.iter()
|
|
17
|
+
.filter_map(|property| {
|
|
18
|
+
Some(ObjectPatternProperty {
|
|
19
|
+
span: property.span.into(),
|
|
20
|
+
key: self.lower_property_name(&property.key)?,
|
|
21
|
+
value: self.lower_pattern(&property.value)?,
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
.collect(),
|
|
25
|
+
rest: pattern
|
|
26
|
+
.rest
|
|
27
|
+
.as_ref()
|
|
28
|
+
.and_then(|rest| self.lower_pattern(&rest.argument))
|
|
29
|
+
.map(Box::new),
|
|
30
|
+
}),
|
|
31
|
+
BindingPattern::ArrayPattern(pattern) => Some(Pattern::Array {
|
|
32
|
+
span: pattern.span.into(),
|
|
33
|
+
elements: pattern
|
|
34
|
+
.elements
|
|
35
|
+
.iter()
|
|
36
|
+
.map(|element| {
|
|
37
|
+
element
|
|
38
|
+
.as_ref()
|
|
39
|
+
.and_then(|pattern| self.lower_pattern(pattern))
|
|
40
|
+
})
|
|
41
|
+
.collect(),
|
|
42
|
+
rest: pattern
|
|
43
|
+
.rest
|
|
44
|
+
.as_ref()
|
|
45
|
+
.and_then(|rest| self.lower_pattern(&rest.argument))
|
|
46
|
+
.map(Box::new),
|
|
47
|
+
}),
|
|
48
|
+
BindingPattern::AssignmentPattern(pattern) => Some(Pattern::Default {
|
|
49
|
+
span: pattern.span.into(),
|
|
50
|
+
target: Box::new(self.lower_pattern(&pattern.left)?),
|
|
51
|
+
default_value: self.lower_expr(&pattern.right)?,
|
|
52
|
+
}),
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
pub(super) fn lower_function_params(
|
|
57
|
+
&mut self,
|
|
58
|
+
params: &FormalParameters<'a>,
|
|
59
|
+
) -> Option<LoweredFunctionParams> {
|
|
60
|
+
let mut lowered = Vec::with_capacity(params.items.len());
|
|
61
|
+
let mut param_init = Vec::new();
|
|
62
|
+
let mut function_length = 0usize;
|
|
63
|
+
let mut counted_default = false;
|
|
64
|
+
for param in ¶ms.items {
|
|
65
|
+
if !counted_default {
|
|
66
|
+
let has_default = param.initializer.is_some()
|
|
67
|
+
|| matches!(param.pattern, BindingPattern::AssignmentPattern(_));
|
|
68
|
+
if has_default {
|
|
69
|
+
counted_default = true;
|
|
70
|
+
} else {
|
|
71
|
+
function_length += 1;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
let temp_name = self.fresh_internal_name("param");
|
|
75
|
+
lowered.push(Pattern::Identifier {
|
|
76
|
+
span: param.span.into(),
|
|
77
|
+
name: temp_name.clone(),
|
|
78
|
+
});
|
|
79
|
+
let mut pattern = self.lower_pattern(¶m.pattern)?;
|
|
80
|
+
if let Some(initializer) = ¶m.initializer {
|
|
81
|
+
pattern = Pattern::Default {
|
|
82
|
+
span: param.span.into(),
|
|
83
|
+
target: Box::new(pattern),
|
|
84
|
+
default_value: self.lower_expr(initializer)?,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
param_init.push(Stmt::VariableDecl {
|
|
88
|
+
span: param.span.into(),
|
|
89
|
+
kind: BindingKind::Let,
|
|
90
|
+
declarators: vec![Declarator {
|
|
91
|
+
span: param.span.into(),
|
|
92
|
+
pattern,
|
|
93
|
+
initializer: Some(Expr::Identifier {
|
|
94
|
+
span: param.span.into(),
|
|
95
|
+
name: temp_name,
|
|
96
|
+
}),
|
|
97
|
+
}],
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
let rest = if let Some(rest) = ¶ms.rest {
|
|
101
|
+
let temp_name = self.fresh_internal_name("rest");
|
|
102
|
+
param_init.push(Stmt::VariableDecl {
|
|
103
|
+
span: rest.span.into(),
|
|
104
|
+
kind: BindingKind::Let,
|
|
105
|
+
declarators: vec![Declarator {
|
|
106
|
+
span: rest.span.into(),
|
|
107
|
+
pattern: self.lower_pattern(&rest.rest.argument)?,
|
|
108
|
+
initializer: Some(Expr::Identifier {
|
|
109
|
+
span: rest.span.into(),
|
|
110
|
+
name: temp_name.clone(),
|
|
111
|
+
}),
|
|
112
|
+
}],
|
|
113
|
+
});
|
|
114
|
+
Some(Pattern::Identifier {
|
|
115
|
+
span: rest.span.into(),
|
|
116
|
+
name: temp_name,
|
|
117
|
+
})
|
|
118
|
+
} else {
|
|
119
|
+
None
|
|
120
|
+
};
|
|
121
|
+
Some((lowered, rest, param_init, function_length))
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
use super::*;
|
|
2
|
+
|
|
3
|
+
impl<'a> Lowerer<'a> {
|
|
4
|
+
fn declare_name_in_current_scope(&mut self, name: &str, span: SourceSpan) {
|
|
5
|
+
if let Some(scope) = self.scopes.last_mut()
|
|
6
|
+
&& !scope.insert(name.to_string())
|
|
7
|
+
{
|
|
8
|
+
self.unsupported(
|
|
9
|
+
format!("SyntaxError: Identifier `{name}` has already been declared"),
|
|
10
|
+
Some(span),
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
pub(super) fn push_scope(&mut self) {
|
|
16
|
+
self.scopes.push(HashSet::new());
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
pub(super) fn pop_scope(&mut self) {
|
|
20
|
+
self.scopes.pop();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
pub(super) fn is_bound(&self, name: &str) -> bool {
|
|
24
|
+
self.scopes.iter().rev().any(|scope| scope.contains(name))
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
pub(super) fn predeclare_block(&mut self, statements: &[Statement<'a>]) {
|
|
28
|
+
for statement in statements {
|
|
29
|
+
self.predeclare_stmt(statement);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
pub(super) fn predeclare_stmt(&mut self, statement: &Statement<'a>) {
|
|
34
|
+
match statement {
|
|
35
|
+
Statement::FunctionDeclaration(function) => {
|
|
36
|
+
if let Some(id) = &function.id {
|
|
37
|
+
self.declare_name_in_current_scope(id.name.as_str(), id.span.into());
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
Statement::VariableDeclaration(decl) => {
|
|
41
|
+
if decl.kind == VariableDeclarationKind::Var
|
|
42
|
+
|| decl.kind == VariableDeclarationKind::Using
|
|
43
|
+
|| decl.kind == VariableDeclarationKind::AwaitUsing
|
|
44
|
+
{
|
|
45
|
+
self.unsupported("only let and const are supported", Some(decl.span.into()));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
for declarator in &decl.declarations {
|
|
49
|
+
self.collect_pattern_bindings(&declarator.id);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
_ => {}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
pub(super) fn collect_pattern_bindings(&mut self, pattern: &BindingPattern<'a>) {
|
|
57
|
+
match pattern {
|
|
58
|
+
BindingPattern::BindingIdentifier(identifier) => {
|
|
59
|
+
self.declare_name_in_current_scope(identifier.name.as_str(), identifier.span.into())
|
|
60
|
+
}
|
|
61
|
+
BindingPattern::ObjectPattern(pattern) => {
|
|
62
|
+
for property in &pattern.properties {
|
|
63
|
+
self.collect_pattern_bindings(&property.value);
|
|
64
|
+
}
|
|
65
|
+
if let Some(rest) = &pattern.rest {
|
|
66
|
+
self.collect_pattern_bindings(&rest.argument);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
BindingPattern::ArrayPattern(pattern) => {
|
|
70
|
+
for element in pattern.elements.iter().flatten() {
|
|
71
|
+
self.collect_pattern_bindings(element);
|
|
72
|
+
}
|
|
73
|
+
if let Some(rest) = &pattern.rest {
|
|
74
|
+
self.collect_pattern_bindings(&rest.argument);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
BindingPattern::AssignmentPattern(pattern) => {
|
|
78
|
+
self.collect_pattern_bindings(&pattern.left);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
pub(super) fn collect_ir_pattern_bindings(&mut self, pattern: &Pattern) {
|
|
84
|
+
match pattern {
|
|
85
|
+
Pattern::Identifier { name, span } => self.declare_name_in_current_scope(name, *span),
|
|
86
|
+
Pattern::Object {
|
|
87
|
+
properties, rest, ..
|
|
88
|
+
} => {
|
|
89
|
+
for property in properties {
|
|
90
|
+
self.collect_ir_pattern_bindings(&property.value);
|
|
91
|
+
}
|
|
92
|
+
if let Some(rest) = rest {
|
|
93
|
+
self.collect_ir_pattern_bindings(rest);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
Pattern::Array { elements, rest, .. } => {
|
|
97
|
+
for element in elements.iter().flatten() {
|
|
98
|
+
self.collect_ir_pattern_bindings(element);
|
|
99
|
+
}
|
|
100
|
+
if let Some(rest) = rest {
|
|
101
|
+
self.collect_ir_pattern_bindings(rest);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
Pattern::Default { target, .. } => self.collect_ir_pattern_bindings(target),
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|