mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-01-08 21:18:04 -05:00
Make clippy a happy chappy
This commit is contained in:
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -20,5 +20,6 @@
|
||||
"rust-analyzer.inlayHints.typeHints.enable": false,
|
||||
"[rust]": {
|
||||
"editor.defaultFormatter": "rust-lang.rust-analyzer"
|
||||
}
|
||||
},
|
||||
"rust-analyzer.check.command": "clippy"
|
||||
}
|
||||
|
||||
@@ -21,8 +21,7 @@ fn main() {
|
||||
|
||||
let mut failed_paths = HashSet::<PathBuf>::new();
|
||||
|
||||
let mut files =
|
||||
get_files_recursively(&input_dir_path.to_path_buf()).expect("Failed to get files");
|
||||
let mut files = get_files_recursively(&input_dir_path).expect("Failed to get files");
|
||||
|
||||
files.sort();
|
||||
|
||||
@@ -52,7 +51,7 @@ fn main() {
|
||||
});
|
||||
|
||||
for (path, diagnostics) in compile_result.diagnostics.iter() {
|
||||
if diagnostics.len() > 0 {
|
||||
if !diagnostics.is_empty() {
|
||||
dbg!(&path.path, diagnostics);
|
||||
}
|
||||
|
||||
@@ -80,7 +79,7 @@ fn main() {
|
||||
|
||||
let bytecode = Rc::new(Bytecode::new(assemble(&module)));
|
||||
|
||||
let mut vm = VirtualMachine::new();
|
||||
let mut vm = VirtualMachine::default();
|
||||
|
||||
let mut file_results = Vec::<f64>::new();
|
||||
|
||||
@@ -96,7 +95,7 @@ fn main() {
|
||||
file_results.push(duration_ms as f64);
|
||||
|
||||
if let Err(result) = result {
|
||||
assert!(false, "{} failed: {}", friendly_file_path, result.codify());
|
||||
panic!("{} failed: {}", friendly_file_path, result.codify());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +116,7 @@ fn main() {
|
||||
println!("{:<37} {:>6.1}ms", "Score", score);
|
||||
|
||||
if !failed_paths.is_empty() {
|
||||
assert!(false, "See failures above");
|
||||
panic!("See failures above");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,9 +150,7 @@ pub fn resolve_entry_path(entry_path: &String) -> ResolvedPath {
|
||||
.to_string(),
|
||||
};
|
||||
|
||||
let resolved_entry_path = resolve_path(&cwd_file, entry_path);
|
||||
|
||||
resolved_entry_path
|
||||
resolve_path(&cwd_file, entry_path)
|
||||
}
|
||||
|
||||
fn geometric_mean(vals: &[f64]) -> f64 {
|
||||
|
||||
@@ -82,7 +82,7 @@ pub fn fib(n: Val) -> Result<Val, Val> {
|
||||
let mut _tmp3 = fib(_tmp1)?;
|
||||
_return = op_plus(&_tmp2, &_tmp3)?;
|
||||
|
||||
return Ok(_return);
|
||||
Ok(_return)
|
||||
}
|
||||
|
||||
// 0.120s
|
||||
@@ -91,5 +91,5 @@ pub fn fib2(n: f64) -> f64 {
|
||||
return n;
|
||||
}
|
||||
|
||||
return fib2(n - 1.0) + fib2(n - 2.0);
|
||||
fib2(n - 1.0) + fib2(n - 2.0)
|
||||
}
|
||||
|
||||
@@ -98,7 +98,5 @@ fn resolve_entry_path(entry_path: &String) -> ResolvedPath {
|
||||
.to_string(),
|
||||
};
|
||||
|
||||
let resolved_entry_path = resolve_path(&cwd_file, entry_path);
|
||||
|
||||
resolved_entry_path
|
||||
resolve_path(&cwd_file, entry_path)
|
||||
}
|
||||
|
||||
@@ -18,10 +18,9 @@ pub struct Module {
|
||||
impl Module {
|
||||
pub fn as_lines(&self) -> Vec<String> {
|
||||
let assembly_str = self.to_string();
|
||||
let assembly_lines = assembly_str.split("\n");
|
||||
let assembly_lines_vec = assembly_lines.map(|s| s.to_string()).collect();
|
||||
let assembly_lines = assembly_str.split('\n');
|
||||
|
||||
return assembly_lines_vec;
|
||||
assembly_lines.map(|s| s.to_string()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,13 +36,13 @@ impl Default for Module {
|
||||
|
||||
impl std::fmt::Display for Module {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
if self.export_star.properties.len() == 0 {
|
||||
if self.export_star.properties.is_empty() {
|
||||
write!(f, "export {} {}", self.export_default, self.export_star)?;
|
||||
} else {
|
||||
write!(f, "export {} {{\n", self.export_default)?;
|
||||
writeln!(f, "export {} {{", self.export_default)?;
|
||||
|
||||
for (name, value) in &self.export_star.properties {
|
||||
write!(f, " {}: {},\n", name, value)?;
|
||||
writeln!(f, " {}: {},", name, value)?;
|
||||
}
|
||||
|
||||
write!(f, "}}")?;
|
||||
@@ -53,7 +52,7 @@ impl std::fmt::Display for Module {
|
||||
write!(f, "\n\n{}", definition)?;
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,14 +137,14 @@ impl std::fmt::Display for Function {
|
||||
}
|
||||
write!(f, "{}", parameter)?;
|
||||
}
|
||||
write!(f, ") {{\n")?;
|
||||
writeln!(f, ") {{")?;
|
||||
for fn_line in &self.body {
|
||||
match fn_line {
|
||||
FnLine::Instruction(instruction) => write!(f, " {}\n", instruction)?,
|
||||
FnLine::Label(label) => write!(f, " {}\n", label)?,
|
||||
FnLine::Empty => write!(f, "\n")?,
|
||||
FnLine::Comment(message) => write!(f, " // {}\n", message)?,
|
||||
FnLine::Release(reg) => write!(f, " (release {})\n", reg)?,
|
||||
FnLine::Instruction(instruction) => writeln!(f, " {}", instruction)?,
|
||||
FnLine::Label(label) => writeln!(f, " {}", label)?,
|
||||
FnLine::Empty => writeln!(f)?,
|
||||
FnLine::Comment(message) => writeln!(f, " // {}", message)?,
|
||||
FnLine::Release(reg) => writeln!(f, " (release {})", reg)?,
|
||||
}
|
||||
}
|
||||
write!(f, "}}")
|
||||
@@ -169,12 +168,12 @@ impl std::fmt::Display for Class {
|
||||
|
||||
match &self.prototype {
|
||||
Value::Object(object) => {
|
||||
if object.properties.len() == 0 {
|
||||
if object.properties.is_empty() {
|
||||
writeln!(f, "{{}},")?;
|
||||
} else {
|
||||
write!(f, "{{\n")?;
|
||||
writeln!(f, "{{")?;
|
||||
for (name, method) in &object.properties {
|
||||
write!(f, " {}: {},\n", name, method)?;
|
||||
writeln!(f, " {}: {},", name, method)?;
|
||||
}
|
||||
writeln!(f, " }},")?;
|
||||
}
|
||||
@@ -188,12 +187,12 @@ impl std::fmt::Display for Class {
|
||||
|
||||
match &self.static_ {
|
||||
Value::Object(object) => {
|
||||
if object.properties.len() == 0 {
|
||||
if object.properties.is_empty() {
|
||||
writeln!(f, "{{}},")?;
|
||||
} else {
|
||||
write!(f, "{{\n")?;
|
||||
writeln!(f, "{{")?;
|
||||
for (name, method) in &object.properties {
|
||||
write!(f, " {}: {},\n", name, method)?;
|
||||
writeln!(f, " {}: {},", name, method)?;
|
||||
}
|
||||
writeln!(f, " }},")?;
|
||||
}
|
||||
@@ -205,7 +204,7 @@ impl std::fmt::Display for Class {
|
||||
|
||||
write!(f, "}}")?;
|
||||
|
||||
return Ok(());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,26 +255,23 @@ impl Register {
|
||||
}
|
||||
|
||||
pub fn is_return(&self) -> bool {
|
||||
return self.name == "return";
|
||||
self.name == "return"
|
||||
}
|
||||
|
||||
pub fn is_this(&self) -> bool {
|
||||
return self.name == "this";
|
||||
self.name == "this"
|
||||
}
|
||||
|
||||
pub fn is_named(&self) -> bool {
|
||||
match self.name.as_str() {
|
||||
"return" | "this" | "ignore" => false,
|
||||
_ => true,
|
||||
}
|
||||
!matches!(self.name.as_str(), "return" | "this" | "ignore")
|
||||
}
|
||||
|
||||
pub fn is_ignore(&self) -> bool {
|
||||
return self.name == "ignore";
|
||||
self.name == "ignore"
|
||||
}
|
||||
|
||||
pub fn is_special(&self) -> bool {
|
||||
return self.is_return() || self.is_this() || self.is_ignore();
|
||||
self.is_return() || self.is_this() || self.is_ignore()
|
||||
}
|
||||
|
||||
pub fn value_type(&self) -> ValueType {
|
||||
@@ -398,7 +394,7 @@ impl Value {
|
||||
|
||||
pub fn visit_values_mut<F>(&mut self, visit: &mut F)
|
||||
where
|
||||
F: FnMut(&mut Value) -> (),
|
||||
F: FnMut(&mut Value),
|
||||
{
|
||||
visit(self);
|
||||
|
||||
@@ -429,7 +425,7 @@ impl Value {
|
||||
|
||||
pub fn visit_registers_mut_rev<F>(&mut self, visit: &mut F)
|
||||
where
|
||||
F: FnMut(RegisterVisitMut) -> (),
|
||||
F: FnMut(RegisterVisitMut),
|
||||
{
|
||||
match self {
|
||||
Value::Array(array) => {
|
||||
@@ -499,15 +495,15 @@ pub struct Lazy {
|
||||
|
||||
impl std::fmt::Display for Lazy {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "lazy {{\n")?;
|
||||
writeln!(f, "lazy {{")?;
|
||||
|
||||
for fn_line in &self.body {
|
||||
match fn_line {
|
||||
FnLine::Instruction(instruction) => write!(f, " {}\n", instruction)?,
|
||||
FnLine::Label(label) => write!(f, " {}\n", label)?,
|
||||
FnLine::Empty => write!(f, "\n")?,
|
||||
FnLine::Comment(message) => write!(f, " // {}\n", message)?,
|
||||
FnLine::Release(reg) => write!(f, " (release {})\n", reg)?,
|
||||
FnLine::Instruction(instruction) => writeln!(f, " {}", instruction)?,
|
||||
FnLine::Label(label) => writeln!(f, " {}", label)?,
|
||||
FnLine::Empty => writeln!(f)?,
|
||||
FnLine::Comment(message) => writeln!(f, " // {}", message)?,
|
||||
FnLine::Release(reg) => writeln!(f, " (release {})", reg)?,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,7 +547,7 @@ pub struct Object {
|
||||
|
||||
impl std::fmt::Display for Object {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if self.properties.len() == 0 {
|
||||
if self.properties.is_empty() {
|
||||
return write!(f, "{{}}");
|
||||
}
|
||||
|
||||
|
||||
@@ -395,7 +395,7 @@ impl Assembler {
|
||||
self.output.push(ValueType::Builtin as u8);
|
||||
|
||||
let builtin_name = BuiltinName::from_str(&builtin.name)
|
||||
.expect(format!("Unknown builtin: {}", builtin.name).as_str());
|
||||
.unwrap_or_else(|_| panic!("Unknown builtin: {}", builtin.name));
|
||||
|
||||
self.varsize_uint(builtin_name.to_code());
|
||||
}
|
||||
@@ -476,7 +476,7 @@ impl LocationMap {
|
||||
output.push(0xff); // TODO: Support >65535
|
||||
}
|
||||
|
||||
fn resolve(&self, output: &mut Vec<u8>) {
|
||||
fn resolve(&self, output: &mut [u8]) {
|
||||
for (name, ref_locations) in &self.references {
|
||||
let location_optional = self.found_locations.get(name);
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ impl<'a> AssemblyParser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
return LineCol { line, col };
|
||||
LineCol { line, col }
|
||||
}
|
||||
|
||||
fn get_lines(&self) -> Vec<&str> {
|
||||
@@ -116,7 +116,7 @@ impl<'a> AssemblyParser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
true
|
||||
}
|
||||
|
||||
fn parse_whitespace(&mut self) {
|
||||
@@ -154,9 +154,8 @@ impl<'a> AssemblyParser<'a> {
|
||||
|
||||
fn parse_line(&mut self) {
|
||||
loop {
|
||||
match self.pos.next() {
|
||||
Some('\n') => return,
|
||||
_ => {}
|
||||
if let Some('\n') = self.pos.next() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -285,12 +284,7 @@ impl<'a> AssemblyParser<'a> {
|
||||
|
||||
advance_chars(&mut pos, word.len());
|
||||
|
||||
return match pos.next() {
|
||||
None => true,
|
||||
Some(' ') => true,
|
||||
Some('\n') => true,
|
||||
_ => false,
|
||||
};
|
||||
matches!(pos.next(), None | Some(' ') | Some('\n'))
|
||||
}
|
||||
|
||||
fn test_identifier(&self) -> Option<String> {
|
||||
@@ -326,7 +320,7 @@ impl<'a> AssemblyParser<'a> {
|
||||
};
|
||||
}
|
||||
|
||||
return Some(res);
|
||||
Some(res)
|
||||
}
|
||||
|
||||
fn parse_identifier(&mut self) -> String {
|
||||
@@ -339,7 +333,7 @@ impl<'a> AssemblyParser<'a> {
|
||||
let identifier = optional_identifier.unwrap();
|
||||
advance_chars(&mut self.pos, identifier.len());
|
||||
|
||||
return identifier;
|
||||
identifier
|
||||
}
|
||||
|
||||
fn parse_exact(&mut self, chars: &str) {
|
||||
@@ -415,7 +409,7 @@ impl<'a> AssemblyParser<'a> {
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
result
|
||||
}
|
||||
|
||||
fn assemble_function(&mut self) -> Function {
|
||||
@@ -513,15 +507,10 @@ impl<'a> AssemblyParser<'a> {
|
||||
|
||||
let optional_label = self.test_label();
|
||||
|
||||
if optional_label.is_some() {
|
||||
function
|
||||
.body
|
||||
.push(FnLine::Label(self.assemble_label(optional_label.unwrap())));
|
||||
} else {
|
||||
function
|
||||
.body
|
||||
.push(FnLine::Instruction(self.assemble_instruction()));
|
||||
}
|
||||
function.body.push(match optional_label {
|
||||
Some(label) => FnLine::Label(self.assemble_label(label)),
|
||||
None => FnLine::Instruction(self.assemble_instruction()),
|
||||
});
|
||||
}
|
||||
|
||||
function
|
||||
@@ -779,7 +768,7 @@ impl<'a> AssemblyParser<'a> {
|
||||
|
||||
match self.pos.peek() {
|
||||
None => {
|
||||
panic!("{}", self.render_pos(0, &format!("Expected value")));
|
||||
panic!("{}", self.render_pos(0, &"Expected value".to_string()));
|
||||
}
|
||||
Some('%') => Value::Register(self.assemble_register()),
|
||||
Some('@') => {
|
||||
@@ -844,7 +833,7 @@ impl<'a> AssemblyParser<'a> {
|
||||
None => {
|
||||
panic!(
|
||||
"{}",
|
||||
self.render_pos(0, &format!("Expected value or array end"))
|
||||
self.render_pos(0, &"Expected value or array end".to_string())
|
||||
);
|
||||
}
|
||||
Some(']') => {
|
||||
@@ -878,7 +867,7 @@ impl<'a> AssemblyParser<'a> {
|
||||
let take = self.parse_one_of(&["!", ""]) == "!";
|
||||
let name = self.parse_identifier();
|
||||
|
||||
return Register { take, name };
|
||||
Register { take, name }
|
||||
}
|
||||
|
||||
fn assemble_builtin(&mut self) -> Builtin {
|
||||
@@ -894,13 +883,7 @@ impl<'a> AssemblyParser<'a> {
|
||||
}
|
||||
|
||||
fn test_label(&self) -> Option<String> {
|
||||
let optional_identifier = self.test_identifier();
|
||||
|
||||
if optional_identifier.is_none() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let identifier = optional_identifier.unwrap();
|
||||
let identifier = self.test_identifier()?;
|
||||
|
||||
let mut pos = self.pos.clone();
|
||||
advance_chars(&mut pos, identifier.len());
|
||||
@@ -909,7 +892,7 @@ impl<'a> AssemblyParser<'a> {
|
||||
return Some(identifier);
|
||||
}
|
||||
|
||||
return None;
|
||||
None
|
||||
}
|
||||
|
||||
fn assemble_label(&mut self, name: String) -> Label {
|
||||
@@ -932,18 +915,11 @@ impl<'a> AssemblyParser<'a> {
|
||||
|
||||
let mut num_string = "".to_string();
|
||||
|
||||
loop {
|
||||
match self.pos.peek() {
|
||||
Some('-' | '.' | 'e' | 'n' | '0'..='9') => {
|
||||
num_string.push(self.pos.next().unwrap());
|
||||
}
|
||||
_ => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while let Some('-' | '.' | 'e' | 'n' | '0'..='9') = self.pos.peek() {
|
||||
num_string.push(self.pos.next().unwrap());
|
||||
}
|
||||
|
||||
if num_string.chars().last() == Some('n') {
|
||||
if num_string.ends_with('n') {
|
||||
num_string.pop();
|
||||
|
||||
match BigInt::parse_bytes(num_string.as_bytes(), 10) {
|
||||
@@ -953,7 +929,7 @@ impl<'a> AssemblyParser<'a> {
|
||||
"{}",
|
||||
self.render_pos(
|
||||
-(num_string.len() as isize + 1),
|
||||
&format!("Expected valid number")
|
||||
&"Expected valid number".to_string()
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -967,7 +943,7 @@ impl<'a> AssemblyParser<'a> {
|
||||
"{}",
|
||||
self.render_pos(
|
||||
-(num_string.len() as isize),
|
||||
&format!("Expected valid number")
|
||||
&"Expected valid number".to_string()
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -1031,11 +1007,11 @@ pub fn parse_module(content: &str) -> Module {
|
||||
}
|
||||
|
||||
fn is_leading_identifier_char(c: char) -> bool {
|
||||
return c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
|
||||
c == '_' || ('a'..='z').contains(&c) || ('A'..='Z').contains(&c)
|
||||
}
|
||||
|
||||
fn is_identifier_char(c: char) -> bool {
|
||||
return c == '_' || ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
|
||||
c == '_' || ('0'..='9').contains(&c) || ('a'..='z').contains(&c) || ('A'..='Z').contains(&c)
|
||||
}
|
||||
|
||||
fn advance_chars(iter: &mut std::iter::Peekable<std::str::Chars>, len: usize) {
|
||||
|
||||
@@ -20,7 +20,7 @@ pub fn compile_enum_value(
|
||||
};
|
||||
|
||||
let init_value = match &member.init {
|
||||
Some(init) => match static_eval_expr(&init) {
|
||||
Some(init) => match static_eval_expr(init) {
|
||||
Some(init_value) => match init_value {
|
||||
Value::Number(Number(n)) => {
|
||||
next_default_id = Some(n + 1.0);
|
||||
@@ -50,7 +50,7 @@ pub fn compile_enum_value(
|
||||
None => {
|
||||
diagnostics.push(Diagnostic {
|
||||
level: DiagnosticLevel::Error,
|
||||
message: format!("Missing required initializer"),
|
||||
message: "Missing required initializer".to_string(),
|
||||
span: member.span,
|
||||
});
|
||||
|
||||
|
||||
@@ -42,13 +42,13 @@ impl Diagnostic {
|
||||
Level::FailureNote => return None,
|
||||
};
|
||||
|
||||
return Some(Diagnostic {
|
||||
Some(Diagnostic {
|
||||
level,
|
||||
message: swc_diagnostic.message(),
|
||||
span: swc_diagnostic
|
||||
.span
|
||||
.primary_span()
|
||||
.unwrap_or(swc_common::DUMMY_SP),
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,14 +34,14 @@ impl ReleaseChecker {
|
||||
impl CompiledExpression {
|
||||
pub fn empty() -> CompiledExpression {
|
||||
CompiledExpression {
|
||||
value: Value::Void, // TODO: Allocate register instead (why?)
|
||||
value: Value::Void,
|
||||
nested_registers: vec![],
|
||||
release_checker: ReleaseChecker::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(value: Value, nested_registers: Vec<Register>) -> CompiledExpression {
|
||||
let has_unreleased_registers = nested_registers.len() > 0;
|
||||
let has_unreleased_registers = !nested_registers.is_empty();
|
||||
|
||||
CompiledExpression {
|
||||
value,
|
||||
@@ -86,147 +86,107 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
use swc_ecma_ast::Expr::*;
|
||||
|
||||
match expr {
|
||||
This(_) => {
|
||||
return Value::Register(Register::this()).to_ce();
|
||||
}
|
||||
Array(array_exp) => {
|
||||
return self.array_expression(array_exp, target_register);
|
||||
}
|
||||
Object(object_exp) => {
|
||||
return self.object_expression(object_exp, target_register);
|
||||
}
|
||||
Fn(fn_) => {
|
||||
return self.fn_expression(fn_, target_register);
|
||||
}
|
||||
Unary(un_exp) => {
|
||||
return self.unary_expression(un_exp, target_register);
|
||||
}
|
||||
Update(update_exp) => {
|
||||
return self.update_expression(update_exp, target_register);
|
||||
}
|
||||
Bin(bin_exp) => {
|
||||
return self.binary_expression(bin_exp, target_register);
|
||||
}
|
||||
Assign(assign_exp) => {
|
||||
return self.assign_expression(assign_exp, false, target_register);
|
||||
}
|
||||
Member(member_exp) => {
|
||||
return self.member_expression(member_exp, target_register);
|
||||
}
|
||||
This(_) => Value::Register(Register::this()).to_ce(),
|
||||
Array(array_exp) => self.array_expression(array_exp, target_register),
|
||||
Object(object_exp) => self.object_expression(object_exp, target_register),
|
||||
Fn(fn_) => self.fn_expression(fn_, target_register),
|
||||
Unary(un_exp) => self.unary_expression(un_exp, target_register),
|
||||
Update(update_exp) => self.update_expression(update_exp, target_register),
|
||||
Bin(bin_exp) => self.binary_expression(bin_exp, target_register),
|
||||
Assign(assign_exp) => self.assign_expression(assign_exp, false, target_register),
|
||||
Member(member_exp) => self.member_expression(member_exp, target_register),
|
||||
SuperProp(super_prop) => {
|
||||
self.fnc.todo(super_prop.span, "SuperProp expression");
|
||||
return CompiledExpression::empty();
|
||||
CompiledExpression::empty()
|
||||
}
|
||||
Cond(cond_exp) => {
|
||||
return self.cond_expression(cond_exp, target_register);
|
||||
}
|
||||
Call(call_exp) => {
|
||||
return match &call_exp.callee {
|
||||
swc_ecma_ast::Callee::Expr(callee_expr) => match &**callee_expr {
|
||||
swc_ecma_ast::Expr::Member(member_expr) => {
|
||||
self.method_call_expression(&member_expr, &call_exp.args, target_register)
|
||||
}
|
||||
_ => self.call_expression(call_exp, target_register),
|
||||
},
|
||||
_ => {
|
||||
self
|
||||
.fnc
|
||||
.todo(call_exp.callee.span(), "non-expression callee");
|
||||
|
||||
CompiledExpression::empty()
|
||||
Cond(cond_exp) => self.cond_expression(cond_exp, target_register),
|
||||
Call(call_exp) => match &call_exp.callee {
|
||||
swc_ecma_ast::Callee::Expr(callee_expr) => match &**callee_expr {
|
||||
swc_ecma_ast::Expr::Member(member_expr) => {
|
||||
self.method_call_expression(member_expr, &call_exp.args, target_register)
|
||||
}
|
||||
};
|
||||
}
|
||||
New(new_exp) => {
|
||||
return self.new_expression(new_exp, target_register);
|
||||
}
|
||||
_ => self.call_expression(call_exp, target_register),
|
||||
},
|
||||
_ => {
|
||||
self
|
||||
.fnc
|
||||
.todo(call_exp.callee.span(), "non-expression callee");
|
||||
|
||||
CompiledExpression::empty()
|
||||
}
|
||||
},
|
||||
New(new_exp) => self.new_expression(new_exp, target_register),
|
||||
Seq(seq_exp) => {
|
||||
for i in 0..(seq_exp.exprs.len() - 1) {
|
||||
self.compile_into(&seq_exp.exprs[i], Register::ignore());
|
||||
}
|
||||
|
||||
return self.compile(seq_exp.exprs.last().unwrap(), target_register);
|
||||
}
|
||||
Ident(ident) => {
|
||||
return self.identifier(ident, target_register);
|
||||
}
|
||||
Lit(lit) => {
|
||||
return self.compile_literal(lit).to_ce();
|
||||
}
|
||||
Tpl(tpl) => {
|
||||
return self.template_literal(tpl, target_register);
|
||||
self.compile(seq_exp.exprs.last().unwrap(), target_register)
|
||||
}
|
||||
Ident(ident) => self.identifier(ident, target_register),
|
||||
Lit(lit) => self.compile_literal(lit).to_ce(),
|
||||
Tpl(tpl) => self.template_literal(tpl, target_register),
|
||||
TaggedTpl(tagged_tpl) => {
|
||||
self.fnc.todo(tagged_tpl.span, "TaggedTpl expression");
|
||||
return CompiledExpression::empty();
|
||||
CompiledExpression::empty()
|
||||
}
|
||||
Arrow(arrow) => return self.arrow_expression(arrow, target_register),
|
||||
Arrow(arrow) => self.arrow_expression(arrow, target_register),
|
||||
Class(class_exp) => {
|
||||
self.fnc.todo(class_exp.span(), "Class expression");
|
||||
return CompiledExpression::empty();
|
||||
}
|
||||
Yield(yield_expr) => {
|
||||
return self.yield_expr(yield_expr, target_register);
|
||||
CompiledExpression::empty()
|
||||
}
|
||||
Yield(yield_expr) => self.yield_expr(yield_expr, target_register),
|
||||
MetaProp(meta_prop) => {
|
||||
self.fnc.todo(meta_prop.span, "MetaProp expression");
|
||||
return CompiledExpression::empty();
|
||||
CompiledExpression::empty()
|
||||
}
|
||||
Await(await_exp) => {
|
||||
self.fnc.todo(await_exp.span, "Await expression");
|
||||
return CompiledExpression::empty();
|
||||
}
|
||||
Paren(p) => {
|
||||
return self.compile(&*p.expr, target_register);
|
||||
CompiledExpression::empty()
|
||||
}
|
||||
Paren(p) => self.compile(&p.expr, target_register),
|
||||
JSXMember(jsx_member) => {
|
||||
self.fnc.todo(jsx_member.span(), "JSXMember expression");
|
||||
return CompiledExpression::empty();
|
||||
CompiledExpression::empty()
|
||||
}
|
||||
JSXNamespacedName(jsx_namespaced_name) => {
|
||||
self
|
||||
.fnc
|
||||
.todo(jsx_namespaced_name.span(), "JSXNamespacedName expression");
|
||||
return CompiledExpression::empty();
|
||||
CompiledExpression::empty()
|
||||
}
|
||||
JSXEmpty(jsx_empty) => {
|
||||
self.fnc.todo(jsx_empty.span(), "JSXEmpty expression");
|
||||
return CompiledExpression::empty();
|
||||
CompiledExpression::empty()
|
||||
}
|
||||
JSXElement(jsx_element) => {
|
||||
self.fnc.todo(jsx_element.span(), "JSXElement expression");
|
||||
return CompiledExpression::empty();
|
||||
CompiledExpression::empty()
|
||||
}
|
||||
JSXFragment(jsx_fragment) => {
|
||||
self.fnc.todo(jsx_fragment.span(), "JSXFragment expression");
|
||||
return CompiledExpression::empty();
|
||||
}
|
||||
TsTypeAssertion(ts_type_assertion) => {
|
||||
return self.compile(&ts_type_assertion.expr, target_register);
|
||||
CompiledExpression::empty()
|
||||
}
|
||||
TsTypeAssertion(ts_type_assertion) => self.compile(&ts_type_assertion.expr, target_register),
|
||||
TsConstAssertion(ts_const_assertion) => {
|
||||
return self.compile(&ts_const_assertion.expr, target_register);
|
||||
}
|
||||
TsNonNull(ts_non_null_exp) => {
|
||||
return self.compile(&ts_non_null_exp.expr, target_register);
|
||||
}
|
||||
TsAs(ts_as_exp) => {
|
||||
return self.compile(&ts_as_exp.expr, target_register);
|
||||
self.compile(&ts_const_assertion.expr, target_register)
|
||||
}
|
||||
TsNonNull(ts_non_null_exp) => self.compile(&ts_non_null_exp.expr, target_register),
|
||||
TsAs(ts_as_exp) => self.compile(&ts_as_exp.expr, target_register),
|
||||
TsInstantiation(ts_instantiation) => {
|
||||
self
|
||||
.fnc
|
||||
.todo(ts_instantiation.span, "TsInstantiation expression");
|
||||
|
||||
return CompiledExpression::empty();
|
||||
CompiledExpression::empty()
|
||||
}
|
||||
PrivateName(private_name) => {
|
||||
self.fnc.todo(private_name.span, "PrivateName expression");
|
||||
return CompiledExpression::empty();
|
||||
CompiledExpression::empty()
|
||||
}
|
||||
OptChain(opt_chain) => {
|
||||
self.fnc.todo(opt_chain.span, "OptChain expression");
|
||||
return CompiledExpression::empty();
|
||||
CompiledExpression::empty()
|
||||
}
|
||||
Invalid(invalid) => {
|
||||
self.fnc.diagnostics.push(Diagnostic {
|
||||
@@ -235,9 +195,9 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
span: invalid.span,
|
||||
});
|
||||
|
||||
return CompiledExpression::empty();
|
||||
CompiledExpression::empty()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compile_into(&mut self, expr: &swc_ecma_ast::Expr, target_register: Register) {
|
||||
@@ -294,7 +254,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
|
||||
self.fnc.release_ce(arg);
|
||||
|
||||
return CompiledExpression::new(Value::Register(target), nested_registers);
|
||||
CompiledExpression::new(Value::Register(target), nested_registers)
|
||||
}
|
||||
|
||||
pub fn binary_expression(
|
||||
@@ -329,7 +289,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
self.fnc.release_ce(left);
|
||||
self.fnc.release_ce(right);
|
||||
|
||||
return CompiledExpression::new(Value::Register(target), nested_registers);
|
||||
CompiledExpression::new(Value::Register(target), nested_registers)
|
||||
}
|
||||
|
||||
pub fn get_register_for_ident_mutation(&mut self, ident: &swc_ecma_ast::Ident) -> Register {
|
||||
@@ -339,8 +299,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
None,
|
||||
Some(format!(
|
||||
"Invalid: Can't mutate {} because its lookup result is {:?}",
|
||||
ident.sym.to_string(),
|
||||
lookup_result,
|
||||
ident.sym, lookup_result,
|
||||
)),
|
||||
),
|
||||
};
|
||||
@@ -348,7 +307,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
if let Some(err_msg) = err_msg {
|
||||
self.fnc.diagnostics.push(Diagnostic {
|
||||
level: DiagnosticLevel::Error,
|
||||
message: err_msg.to_string(),
|
||||
message: err_msg,
|
||||
span: ident.span,
|
||||
});
|
||||
}
|
||||
@@ -402,10 +361,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
false => self.compile(&assign_expr.right, None),
|
||||
};
|
||||
|
||||
let at_is_register = match &at {
|
||||
TargetAccessor::Register(_) => true,
|
||||
_ => false,
|
||||
};
|
||||
let at_is_register = matches!(&at, TargetAccessor::Register(_));
|
||||
|
||||
if is_top_level && at_is_register {
|
||||
// at is already assigned by compiling directly into at.direct_register()
|
||||
@@ -452,7 +408,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
use swc_ecma_ast::PatOrExpr;
|
||||
|
||||
let mut target = match &assign_expr.left {
|
||||
PatOrExpr::Expr(expr) => TargetAccessor::compile(self, &expr, true),
|
||||
PatOrExpr::Expr(expr) => TargetAccessor::compile(self, expr, true),
|
||||
PatOrExpr::Pat(pat) => match &**pat {
|
||||
Pat::Ident(ident) => {
|
||||
TargetAccessor::Register(self.get_register_for_ident_mutation(&ident.id))
|
||||
@@ -464,7 +420,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
span: pat.span(),
|
||||
});
|
||||
|
||||
let bad_reg = self.fnc.allocate_numbered_reg(&"_bad_lvalue".to_string());
|
||||
let bad_reg = self.fnc.allocate_numbered_reg("_bad_lvalue");
|
||||
|
||||
TargetAccessor::Register(bad_reg)
|
||||
}
|
||||
@@ -504,7 +460,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
));
|
||||
}
|
||||
|
||||
target.assign_and_packup(self, &Value::Register(target_read.clone()), false);
|
||||
target.assign_and_packup(self, &Value::Register(target_read), false);
|
||||
|
||||
CompiledExpression::new(Value::Register(rhs_reg), nested_registers)
|
||||
}
|
||||
@@ -569,7 +525,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
return match target_register {
|
||||
match target_register {
|
||||
None => CompiledExpression::new(Value::Object(Box::new(object_asm)), sub_nested_registers),
|
||||
Some(tr) => {
|
||||
self.fnc.push(Instruction::Mov(
|
||||
@@ -583,7 +539,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
|
||||
CompiledExpression::new(Value::Register(tr), vec![])
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prop_name(&mut self, prop_name: &swc_ecma_ast::PropName) -> CompiledExpression {
|
||||
@@ -620,7 +576,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
member_prop: &swc_ecma_ast::MemberProp,
|
||||
target_register: Option<Register>,
|
||||
) -> CompiledExpression {
|
||||
return match member_prop {
|
||||
match member_prop {
|
||||
swc_ecma_ast::MemberProp::Ident(ident) => Value::String(ident.sym.to_string()).to_ce(),
|
||||
swc_ecma_ast::MemberProp::Computed(computed) => self.compile(&computed.expr, target_register),
|
||||
swc_ecma_ast::MemberProp::PrivateName(private_name) => {
|
||||
@@ -630,7 +586,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
|
||||
CompiledExpression::empty()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn member_expression(
|
||||
@@ -683,17 +639,11 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
self.compile_into(&cond_exp.test, dst.clone());
|
||||
|
||||
let true_label = Label {
|
||||
name: self
|
||||
.fnc
|
||||
.label_allocator
|
||||
.allocate_numbered(&"cond_true".to_string()),
|
||||
name: self.fnc.label_allocator.allocate_numbered("cond_true"),
|
||||
};
|
||||
|
||||
let cond_end_label = Label {
|
||||
name: self
|
||||
.fnc
|
||||
.label_allocator
|
||||
.allocate_numbered(&"cond_end".to_string()),
|
||||
name: self.fnc.label_allocator.allocate_numbered("cond_end"),
|
||||
};
|
||||
|
||||
self.fnc.push(Instruction::JmpIf(
|
||||
@@ -800,7 +750,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
|
||||
target.assign_and_packup(self, &Value::Register(target_read), false);
|
||||
|
||||
return res;
|
||||
res
|
||||
}
|
||||
|
||||
pub fn call_expression(
|
||||
@@ -811,7 +761,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
let mut nested_registers = Vec::<Register>::new();
|
||||
|
||||
let callee = match &call_exp.callee {
|
||||
swc_ecma_ast::Callee::Expr(expr) => self.compile(&*expr, None),
|
||||
swc_ecma_ast::Callee::Expr(expr) => self.compile(expr, None),
|
||||
_ => {
|
||||
self
|
||||
.fnc
|
||||
@@ -821,7 +771,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
}
|
||||
};
|
||||
|
||||
let args = call_exp.args.iter().map(|x| Some(x));
|
||||
let args = call_exp.args.iter().map(Some);
|
||||
let compiled_args = self.args(args, None);
|
||||
|
||||
let dest = match target_register {
|
||||
@@ -858,9 +808,9 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
let callee = self.compile(&new_exp.callee, None);
|
||||
|
||||
let compiled_args = match &new_exp.args {
|
||||
None => CompiledExpression::new(Value::Array(Box::new(Array::default())), vec![]),
|
||||
None => CompiledExpression::new(Value::Array(Box::default()), vec![]),
|
||||
Some(new_exp_args) => {
|
||||
let args = new_exp_args.iter().map(|x| Some(x));
|
||||
let args = new_exp_args.iter().map(Some);
|
||||
self.args(args, None)
|
||||
}
|
||||
};
|
||||
@@ -890,7 +840,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
pub fn method_call_expression(
|
||||
&mut self,
|
||||
callee_expr: &swc_ecma_ast::MemberExpr,
|
||||
args: &Vec<swc_ecma_ast::ExprOrSpread>,
|
||||
args: &[swc_ecma_ast::ExprOrSpread],
|
||||
target_register: Option<Register>,
|
||||
) -> CompiledExpression {
|
||||
let mut nested_registers = Vec::<Register>::new();
|
||||
@@ -923,7 +873,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
sub_nested_registers.append(&mut prop.nested_registers);
|
||||
|
||||
let compiled_args = {
|
||||
let args_iter = args.iter().map(|x| Some(x));
|
||||
let args_iter = args.iter().map(Some);
|
||||
self.args(args_iter, None)
|
||||
};
|
||||
|
||||
@@ -982,7 +932,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
self.fnc.release_reg(®);
|
||||
}
|
||||
|
||||
CompiledExpression::new(Value::Register(dest.clone()), nested_registers)
|
||||
CompiledExpression::new(Value::Register(dest), nested_registers)
|
||||
}
|
||||
|
||||
pub fn fn_expression(
|
||||
@@ -990,14 +940,11 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
fn_: &swc_ecma_ast::FnExpr,
|
||||
target_register: Option<Register>,
|
||||
) -> CompiledExpression {
|
||||
let fn_name = fn_
|
||||
.ident
|
||||
.clone()
|
||||
.and_then(|ident| Some(ident.sym.to_string()));
|
||||
let fn_name = fn_.ident.clone().map(|ident| ident.sym.to_string());
|
||||
|
||||
let definition_pointer = match &fn_name {
|
||||
Some(name) => self.fnc.allocate_defn(&name),
|
||||
None => self.fnc.allocate_defn_numbered(&"_anon".to_string()),
|
||||
Some(name) => self.fnc.allocate_defn(name),
|
||||
None => self.fnc.allocate_defn_numbered("_anon"),
|
||||
};
|
||||
|
||||
let capture_params = self
|
||||
@@ -1035,7 +982,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
arrow_expr: &swc_ecma_ast::ArrowExpr,
|
||||
target_register: Option<Register>,
|
||||
) -> CompiledExpression {
|
||||
let definition_pointer = self.fnc.allocate_defn_numbered(&"_anon".to_string());
|
||||
let definition_pointer = self.fnc.allocate_defn_numbered("_anon");
|
||||
|
||||
let capture_params = self
|
||||
.fnc
|
||||
@@ -1077,15 +1024,15 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
let reg = match target_register {
|
||||
None => {
|
||||
let alloc_reg = match &fn_name {
|
||||
Some(name) => self.fnc.allocate_reg(&name),
|
||||
None => self.fnc.allocate_numbered_reg(&"_anon".to_string()),
|
||||
Some(name) => self.fnc.allocate_reg(name),
|
||||
None => self.fnc.allocate_numbered_reg("_anon"),
|
||||
};
|
||||
|
||||
nested_registers.push(alloc_reg.clone());
|
||||
|
||||
alloc_reg
|
||||
}
|
||||
Some(tr) => tr.clone(),
|
||||
Some(tr) => tr,
|
||||
};
|
||||
|
||||
let mut bind_values = Array::default();
|
||||
@@ -1180,7 +1127,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
reg.clone(),
|
||||
));
|
||||
|
||||
return CompiledExpression::new(Value::Register(reg), nested_registers);
|
||||
CompiledExpression::new(Value::Register(reg), nested_registers)
|
||||
}
|
||||
|
||||
pub fn template_literal(
|
||||
@@ -1235,7 +1182,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
|
||||
let last_str = tpl.quasis[len].raw.to_string();
|
||||
|
||||
if last_str != "" {
|
||||
if !last_str.is_empty() {
|
||||
self.fnc.push(Instruction::OpPlus(
|
||||
Value::Register(acc_reg.clone()),
|
||||
Value::String(last_str),
|
||||
@@ -1243,7 +1190,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
));
|
||||
}
|
||||
|
||||
return CompiledExpression::new(Value::Register(acc_reg), nested_registers);
|
||||
CompiledExpression::new(Value::Register(acc_reg), nested_registers)
|
||||
}
|
||||
|
||||
pub fn yield_expr(
|
||||
@@ -1274,7 +1221,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
|
||||
self.fnc.release_ce(arg_compiled);
|
||||
|
||||
return CompiledExpression::new(Value::Register(dst), nested_registers);
|
||||
CompiledExpression::new(Value::Register(dst), nested_registers)
|
||||
}
|
||||
|
||||
pub fn identifier(
|
||||
@@ -1338,10 +1285,9 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
// Otherwise, we need to capture the current value for the result of the expression
|
||||
let new_reg = self.fnc.allocate_tmp();
|
||||
|
||||
self.fnc.push(Instruction::Mov(
|
||||
Value::Register(reg.clone()),
|
||||
new_reg.clone(),
|
||||
));
|
||||
self
|
||||
.fnc
|
||||
.push(Instruction::Mov(Value::Register(reg), new_reg.clone()));
|
||||
|
||||
CompiledExpression::new(Value::Register(new_reg.clone()), vec![new_reg])
|
||||
}
|
||||
@@ -1355,7 +1301,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
Ok(value) => value,
|
||||
Err(err) => {
|
||||
self.fnc.todo(lit.span(), err);
|
||||
return Value::Register(self.fnc.allocate_numbered_reg("_todo_unsupported_literal"));
|
||||
Value::Register(self.fnc.allocate_numbered_reg("_todo_unsupported_literal"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1372,9 +1318,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
level: DiagnosticLevel::InternalError,
|
||||
message: format!(
|
||||
"Register mismatch for parameter {} (expected {}, got {})",
|
||||
ident.id.sym.to_string(),
|
||||
ident_reg,
|
||||
register
|
||||
ident.id.sym, ident_reg, register
|
||||
),
|
||||
span: pat.span(),
|
||||
});
|
||||
@@ -1537,7 +1481,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
})));
|
||||
}
|
||||
|
||||
let mut compiled_elem = self.compile(&*arg.expr, None);
|
||||
let mut compiled_elem = self.compile(&arg.expr, None);
|
||||
|
||||
if arg.spread.is_some() {
|
||||
segments.push(compiled_elem.value);
|
||||
@@ -1601,7 +1545,7 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
pub fn make_unary_op(op: swc_ecma_ast::UnaryOp, arg: Value, dst: Register) -> Option<Instruction> {
|
||||
use swc_ecma_ast::UnaryOp::*;
|
||||
|
||||
return match op {
|
||||
match op {
|
||||
Minus => Some(Instruction::UnaryMinus(arg, dst)),
|
||||
Plus => Some(Instruction::UnaryPlus(arg, dst)),
|
||||
Bang => Some(Instruction::OpNot(arg, dst)),
|
||||
@@ -1609,7 +1553,7 @@ pub fn make_unary_op(op: swc_ecma_ast::UnaryOp, arg: Value, dst: Register) -> Op
|
||||
TypeOf => Some(Instruction::TypeOf(arg, dst)),
|
||||
Void => None, // TODO
|
||||
Delete => None, // TODO
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_binary_op(
|
||||
@@ -1655,7 +1599,7 @@ pub fn get_binary_op_for_assign_op(
|
||||
use swc_ecma_ast::AssignOp;
|
||||
use swc_ecma_ast::BinaryOp;
|
||||
|
||||
return match assign_op {
|
||||
match assign_op {
|
||||
AssignOp::Assign => None,
|
||||
AssignOp::AddAssign => Some(BinaryOp::Add),
|
||||
AssignOp::SubAssign => Some(BinaryOp::Sub),
|
||||
@@ -1672,7 +1616,7 @@ pub fn get_binary_op_for_assign_op(
|
||||
AssignOp::AndAssign => Some(BinaryOp::LogicalAnd),
|
||||
AssignOp::OrAssign => Some(BinaryOp::LogicalOr),
|
||||
AssignOp::NullishAssign => Some(BinaryOp::NullishCoalescing),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_update_op(op: swc_ecma_ast::UpdateOp, register: Register) -> Instruction {
|
||||
|
||||
@@ -7,8 +7,8 @@ use std::rc::Rc;
|
||||
use swc_common::Spanned;
|
||||
|
||||
use crate::asm::{
|
||||
Array, Builtin, Definition, DefinitionContent, FnLine, Function, Instruction, Label, Pointer,
|
||||
Register, Value,
|
||||
Builtin, Definition, DefinitionContent, FnLine, Function, Instruction, Label, Pointer, Register,
|
||||
Value,
|
||||
};
|
||||
use crate::compile_enum_value::compile_enum_value;
|
||||
use crate::diagnostic::{Diagnostic, DiagnosticLevel};
|
||||
@@ -39,7 +39,7 @@ impl Functionish {
|
||||
pub fn owner_id(&self) -> OwnerId {
|
||||
match self {
|
||||
Functionish::Fn(ident, fn_) => fn_to_owner_id(ident, fn_),
|
||||
_ => OwnerId::Span(self.span().clone()),
|
||||
_ => OwnerId::Span(self.span()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,7 @@ impl FunctionCompiler {
|
||||
None => RegAllocator::default(),
|
||||
};
|
||||
|
||||
return FunctionCompiler {
|
||||
FunctionCompiler {
|
||||
current: Function::default(),
|
||||
definitions: vec![],
|
||||
owner_id,
|
||||
@@ -105,7 +105,7 @@ impl FunctionCompiler {
|
||||
is_returning_register: None,
|
||||
finally_labels: vec![],
|
||||
diagnostics: vec![],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(&mut self, mut instruction: Instruction) {
|
||||
@@ -164,7 +164,7 @@ impl FunctionCompiler {
|
||||
pub fn error(&mut self, span: swc_common::Span, message: &str) {
|
||||
self.diagnostics.push(Diagnostic {
|
||||
level: DiagnosticLevel::Error,
|
||||
message: format!("{}", message),
|
||||
message: message.to_string(),
|
||||
span,
|
||||
});
|
||||
}
|
||||
@@ -172,7 +172,7 @@ impl FunctionCompiler {
|
||||
pub fn internal_error(&mut self, span: swc_common::Span, message: &str) {
|
||||
self.diagnostics.push(Diagnostic {
|
||||
level: DiagnosticLevel::InternalError,
|
||||
message: format!("{}", message),
|
||||
message: message.to_string(),
|
||||
span,
|
||||
});
|
||||
}
|
||||
@@ -192,7 +192,7 @@ impl FunctionCompiler {
|
||||
let allocated_name = self
|
||||
.definition_allocator
|
||||
.borrow_mut()
|
||||
.allocate_numbered(&name.to_string());
|
||||
.allocate_numbered(name);
|
||||
|
||||
Pointer {
|
||||
name: allocated_name,
|
||||
@@ -203,11 +203,11 @@ impl FunctionCompiler {
|
||||
self.reg_allocator.allocate_numbered("_tmp")
|
||||
}
|
||||
|
||||
pub fn allocate_reg(&mut self, based_on: &String) -> Register {
|
||||
pub fn allocate_reg(&mut self, based_on: &str) -> Register {
|
||||
self.reg_allocator.allocate(based_on)
|
||||
}
|
||||
|
||||
pub fn allocate_reg_fresh(&mut self, based_on: &String) -> Register {
|
||||
pub fn allocate_reg_fresh(&mut self, based_on: &str) -> Register {
|
||||
self.reg_allocator.allocate_fresh(based_on)
|
||||
}
|
||||
|
||||
@@ -216,9 +216,7 @@ impl FunctionCompiler {
|
||||
}
|
||||
|
||||
pub fn allocate_numbered_reg_fresh(&mut self, prefix: &str) -> Register {
|
||||
self
|
||||
.reg_allocator
|
||||
.allocate_numbered_fresh(&prefix.to_string())
|
||||
self.reg_allocator.allocate_numbered_fresh(prefix)
|
||||
}
|
||||
|
||||
pub fn release_reg(&mut self, reg: &Register) {
|
||||
@@ -250,7 +248,7 @@ impl FunctionCompiler {
|
||||
self_
|
||||
.queue
|
||||
.add(QueuedFunction {
|
||||
definition_pointer: definition_pointer.clone(),
|
||||
definition_pointer,
|
||||
fn_name,
|
||||
functionish,
|
||||
})
|
||||
@@ -258,17 +256,12 @@ impl FunctionCompiler {
|
||||
|
||||
self_.process_queue();
|
||||
|
||||
return (self_.definitions, self_.diagnostics);
|
||||
(self_.definitions, self_.diagnostics)
|
||||
}
|
||||
|
||||
pub fn process_queue(&mut self) {
|
||||
loop {
|
||||
match self.queue.remove() {
|
||||
Ok(qfn) => self.compile_functionish(qfn.definition_pointer, &qfn.functionish),
|
||||
Err(_) => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while let Ok(qfn) = self.queue.remove() {
|
||||
self.compile_functionish(qfn.definition_pointer, &qfn.functionish);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,10 +312,8 @@ impl FunctionCompiler {
|
||||
|
||||
let param_registers = self.get_param_registers(functionish);
|
||||
|
||||
for reg in ¶m_registers {
|
||||
if let Some(reg) = reg {
|
||||
self.current.parameters.push(reg.clone());
|
||||
}
|
||||
for reg in param_registers.iter().flatten() {
|
||||
self.current.parameters.push(reg.clone());
|
||||
}
|
||||
|
||||
self.add_param_code(functionish, ¶m_registers);
|
||||
@@ -423,7 +414,7 @@ impl FunctionCompiler {
|
||||
}
|
||||
};
|
||||
|
||||
return param_registers;
|
||||
param_registers
|
||||
}
|
||||
|
||||
pub fn get_pattern_register_opt(&mut self, param_pat: &swc_ecma_ast::Pat) -> Option<Register> {
|
||||
@@ -435,11 +426,11 @@ impl FunctionCompiler {
|
||||
_ => self.get_variable_register(&ident.id),
|
||||
},
|
||||
Pat::Assign(assign) => return self.get_pattern_register_opt(&assign.left),
|
||||
Pat::Array(_) => self.allocate_numbered_reg(&"_array_pat".to_string()),
|
||||
Pat::Object(_) => self.allocate_numbered_reg(&"_object_pat".to_string()),
|
||||
Pat::Invalid(_) => self.allocate_numbered_reg(&"_invalid_pat".to_string()),
|
||||
Pat::Rest(_) => self.allocate_numbered_reg(&"_rest_pat".to_string()),
|
||||
Pat::Expr(_) => self.allocate_numbered_reg(&"_expr_pat".to_string()),
|
||||
Pat::Array(_) => self.allocate_numbered_reg("_array_pat"),
|
||||
Pat::Object(_) => self.allocate_numbered_reg("_object_pat"),
|
||||
Pat::Invalid(_) => self.allocate_numbered_reg("_invalid_pat"),
|
||||
Pat::Rest(_) => self.allocate_numbered_reg("_rest_pat"),
|
||||
Pat::Expr(_) => self.allocate_numbered_reg("_expr_pat"),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -448,7 +439,7 @@ impl FunctionCompiler {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
self.error(param_pat.span(), "Invalid pattern");
|
||||
self.allocate_reg(&"_invalid_pattern".to_string())
|
||||
self.allocate_reg("_invalid_pattern")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -461,18 +452,17 @@ impl FunctionCompiler {
|
||||
level: DiagnosticLevel::InternalError,
|
||||
message: format!(
|
||||
"Register should have been allocated for variable {}, instead: {:?}",
|
||||
ident.sym.to_string(),
|
||||
lookup_result,
|
||||
ident.sym, lookup_result,
|
||||
),
|
||||
span: ident.span(),
|
||||
});
|
||||
|
||||
self.allocate_numbered_reg(&"_error_variable_without_register".to_string())
|
||||
self.allocate_numbered_reg("_error_variable_without_register")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn add_param_code(&mut self, functionish: &Functionish, param_registers: &Vec<Option<Register>>) {
|
||||
fn add_param_code(&mut self, functionish: &Functionish, param_registers: &[Option<Register>]) {
|
||||
match functionish {
|
||||
Functionish::Fn(_, fn_) => {
|
||||
for (i, p) in fn_.params.iter().enumerate() {
|
||||
@@ -500,7 +490,7 @@ impl FunctionCompiler {
|
||||
let field_name = match &tpp.param {
|
||||
swc_ecma_ast::TsParamPropParam::Ident(bi) => bi.id.sym.to_string(),
|
||||
swc_ecma_ast::TsParamPropParam::Assign(assign) => {
|
||||
ec.assign_pat(&assign, reg);
|
||||
ec.assign_pat(assign, reg);
|
||||
|
||||
match &*assign.left {
|
||||
swc_ecma_ast::Pat::Ident(bi) => bi.id.sym.to_string(),
|
||||
@@ -558,15 +548,15 @@ impl FunctionCompiler {
|
||||
if !fn_last {
|
||||
if let Some(finally_label) = self.finally_labels.last().cloned() {
|
||||
let is_returning = match self.is_returning_register.clone() {
|
||||
Some(is_returning) => is_returning.clone(),
|
||||
Some(is_returning) => is_returning,
|
||||
None => {
|
||||
let is_returning = self.allocate_reg_fresh(&"_is_returning".to_string());
|
||||
let is_returning = self.allocate_reg_fresh("_is_returning");
|
||||
self.is_returning_register = Some(is_returning.clone());
|
||||
is_returning
|
||||
}
|
||||
};
|
||||
|
||||
self.push(Instruction::Mov(Value::Bool(true), is_returning.clone()));
|
||||
self.push(Instruction::Mov(Value::Bool(true), is_returning));
|
||||
self.push(Instruction::Jmp(finally_label.ref_()));
|
||||
} else {
|
||||
self.insert_all_releases();
|
||||
@@ -674,10 +664,10 @@ impl FunctionCompiler {
|
||||
let mut ec = ExpressionCompiler { fnc: self };
|
||||
|
||||
let cond_reg = ec.fnc.allocate_numbered_reg("_cond");
|
||||
ec.compile_into(&*if_.test, cond_reg.clone());
|
||||
ec.compile_into(&if_.test, cond_reg.clone());
|
||||
|
||||
let else_label = Label {
|
||||
name: self.label_allocator.allocate_numbered(&"else".to_string()),
|
||||
name: self.label_allocator.allocate_numbered("else"),
|
||||
};
|
||||
|
||||
self.push(Instruction::JmpIfNot(
|
||||
@@ -687,7 +677,7 @@ impl FunctionCompiler {
|
||||
|
||||
self.release_reg(&cond_reg);
|
||||
|
||||
self.statement(&*if_.cons, false);
|
||||
self.statement(&if_.cons, false);
|
||||
|
||||
match &if_.alt {
|
||||
None => {
|
||||
@@ -695,15 +685,13 @@ impl FunctionCompiler {
|
||||
}
|
||||
Some(alt) => {
|
||||
let after_else_label = Label {
|
||||
name: self
|
||||
.label_allocator
|
||||
.allocate_numbered(&"after_else".to_string()),
|
||||
name: self.label_allocator.allocate_numbered("after_else"),
|
||||
};
|
||||
|
||||
self.push(Instruction::Jmp(after_else_label.ref_()));
|
||||
|
||||
self.label(else_label);
|
||||
self.statement(&*alt, false);
|
||||
self.statement(alt, false);
|
||||
self.label(after_else_label);
|
||||
}
|
||||
}
|
||||
@@ -716,10 +704,7 @@ impl FunctionCompiler {
|
||||
ec.compile_into(&switch.discriminant, sw_expr_reg.clone());
|
||||
|
||||
let end_label = Label {
|
||||
name: ec
|
||||
.fnc
|
||||
.label_allocator
|
||||
.allocate_numbered(&"sw_end".to_string()),
|
||||
name: ec.fnc.label_allocator.allocate_numbered("sw_end"),
|
||||
};
|
||||
|
||||
ec.fnc.loop_labels.push(LoopLabels {
|
||||
@@ -794,12 +779,10 @@ impl FunctionCompiler {
|
||||
let (catch_label, after_catch_label) = match try_.handler {
|
||||
Some(_) => (
|
||||
Some(Label {
|
||||
name: self.label_allocator.allocate_numbered(&"catch".to_string()),
|
||||
name: self.label_allocator.allocate_numbered("catch"),
|
||||
}),
|
||||
Some(Label {
|
||||
name: self
|
||||
.label_allocator
|
||||
.allocate_numbered(&"after_catch".to_string()),
|
||||
name: self.label_allocator.allocate_numbered("after_catch"),
|
||||
}),
|
||||
),
|
||||
None => (None, None),
|
||||
@@ -807,9 +790,7 @@ impl FunctionCompiler {
|
||||
|
||||
let finally_label = match &try_.finalizer {
|
||||
Some(_) => Some(Label {
|
||||
name: self
|
||||
.label_allocator
|
||||
.allocate_numbered(&"finally".to_string()),
|
||||
name: self.label_allocator.allocate_numbered("finally"),
|
||||
}),
|
||||
None => None,
|
||||
};
|
||||
@@ -892,7 +873,7 @@ impl FunctionCompiler {
|
||||
if let Some(param) = &catch_clause.param {
|
||||
let mut ec = ExpressionCompiler { fnc: self };
|
||||
|
||||
let pattern_reg = ec.fnc.get_pattern_register(¶m);
|
||||
let pattern_reg = ec.fnc.get_pattern_register(param);
|
||||
|
||||
// TODO: Set up this register through set_catch instead of copying into it
|
||||
ec.fnc.push(Instruction::Mov(
|
||||
@@ -900,12 +881,12 @@ impl FunctionCompiler {
|
||||
pattern_reg.clone(),
|
||||
));
|
||||
|
||||
ec.pat(¶m, &pattern_reg, false);
|
||||
ec.pat(param, &pattern_reg, false);
|
||||
}
|
||||
|
||||
self.block_statement(&catch_clause.body);
|
||||
|
||||
if let Some(_) = finally_label {
|
||||
if finally_label.is_some() {
|
||||
self.pop_catch_setting();
|
||||
}
|
||||
|
||||
@@ -935,7 +916,7 @@ impl FunctionCompiler {
|
||||
None => None,
|
||||
};
|
||||
|
||||
self.block_statement(&finally_clause);
|
||||
self.block_statement(finally_clause);
|
||||
|
||||
self.push(Instruction::Throw(Value::Register(
|
||||
finally_error_reg.unwrap(),
|
||||
@@ -956,7 +937,7 @@ impl FunctionCompiler {
|
||||
};
|
||||
|
||||
self.push(Instruction::JmpIf(
|
||||
Value::Register(local_is_returning.clone()),
|
||||
Value::Register(local_is_returning),
|
||||
end_label.ref_(),
|
||||
));
|
||||
} else {
|
||||
@@ -967,13 +948,11 @@ impl FunctionCompiler {
|
||||
));
|
||||
|
||||
let after_finally_label = Label {
|
||||
name: self
|
||||
.label_allocator
|
||||
.allocate_numbered(&"after_finally".to_string()),
|
||||
name: self.label_allocator.allocate_numbered("after_finally"),
|
||||
};
|
||||
|
||||
self.push(Instruction::JmpIf(
|
||||
Value::Register(local_is_returning.clone()),
|
||||
Value::Register(local_is_returning),
|
||||
after_finally_label.ref_(),
|
||||
));
|
||||
|
||||
@@ -1006,15 +985,13 @@ impl FunctionCompiler {
|
||||
self.apply_catch_setting();
|
||||
}
|
||||
|
||||
fn while_(self: &mut Self, while_: &swc_ecma_ast::WhileStmt) {
|
||||
fn while_(&mut self, while_: &swc_ecma_ast::WhileStmt) {
|
||||
let start_label = Label {
|
||||
name: self.label_allocator.allocate_numbered(&"while".to_string()),
|
||||
name: self.label_allocator.allocate_numbered("while"),
|
||||
};
|
||||
|
||||
let end_label = Label {
|
||||
name: self
|
||||
.label_allocator
|
||||
.allocate_numbered(&"while_end".to_string()),
|
||||
name: self.label_allocator.allocate_numbered("while_end"),
|
||||
};
|
||||
|
||||
self.loop_labels.push(LoopLabels {
|
||||
@@ -1026,8 +1003,8 @@ impl FunctionCompiler {
|
||||
|
||||
let mut ec = ExpressionCompiler { fnc: self };
|
||||
|
||||
let cond_reg = ec.fnc.allocate_numbered_reg(&"_cond".to_string());
|
||||
ec.compile_into(&*while_.test, cond_reg.clone());
|
||||
let cond_reg = ec.fnc.allocate_numbered_reg("_cond");
|
||||
ec.compile_into(&while_.test, cond_reg.clone());
|
||||
|
||||
self.push(Instruction::JmpIfNot(
|
||||
Value::Register(cond_reg.clone()),
|
||||
@@ -1035,30 +1012,24 @@ impl FunctionCompiler {
|
||||
));
|
||||
|
||||
self.release_reg(&cond_reg);
|
||||
self.statement(&*while_.body, false);
|
||||
self.statement(&while_.body, false);
|
||||
self.push(Instruction::Jmp(start_label.ref_()));
|
||||
self.label(end_label);
|
||||
|
||||
self.loop_labels.pop();
|
||||
}
|
||||
|
||||
fn do_while(self: &mut Self, do_while: &swc_ecma_ast::DoWhileStmt) {
|
||||
fn do_while(&mut self, do_while: &swc_ecma_ast::DoWhileStmt) {
|
||||
let start_label = Label {
|
||||
name: self
|
||||
.label_allocator
|
||||
.allocate_numbered(&"do_while".to_string()),
|
||||
name: self.label_allocator.allocate_numbered("do_while"),
|
||||
};
|
||||
|
||||
let continue_label = Label {
|
||||
name: self
|
||||
.label_allocator
|
||||
.allocate_numbered(&"do_while_continue".to_string()),
|
||||
name: self.label_allocator.allocate_numbered("do_while_continue"),
|
||||
};
|
||||
|
||||
let end_label = Label {
|
||||
name: self
|
||||
.label_allocator
|
||||
.allocate_numbered(&"do_while_end".to_string()),
|
||||
name: self.label_allocator.allocate_numbered("do_while_end"),
|
||||
};
|
||||
|
||||
self.loop_labels.push(LoopLabels {
|
||||
@@ -1068,11 +1039,11 @@ impl FunctionCompiler {
|
||||
|
||||
self.label(start_label.clone());
|
||||
|
||||
self.statement(&*do_while.body, false);
|
||||
self.statement(&do_while.body, false);
|
||||
|
||||
let mut expression_compiler = ExpressionCompiler { fnc: self };
|
||||
|
||||
let condition = expression_compiler.compile(&*do_while.test, None);
|
||||
let condition = expression_compiler.compile(&do_while.test, None);
|
||||
|
||||
self.label(continue_label);
|
||||
|
||||
@@ -1102,21 +1073,15 @@ impl FunctionCompiler {
|
||||
}
|
||||
|
||||
let for_test_label = Label {
|
||||
name: self
|
||||
.label_allocator
|
||||
.allocate_numbered(&"for_test".to_string()),
|
||||
name: self.label_allocator.allocate_numbered("for_test"),
|
||||
};
|
||||
|
||||
let for_continue_label = Label {
|
||||
name: self
|
||||
.label_allocator
|
||||
.allocate_numbered(&"for_continue".to_string()),
|
||||
name: self.label_allocator.allocate_numbered("for_continue"),
|
||||
};
|
||||
|
||||
let for_end_label = Label {
|
||||
name: self
|
||||
.label_allocator
|
||||
.allocate_numbered(&"for_end".to_string()),
|
||||
name: self.label_allocator.allocate_numbered("for_end"),
|
||||
};
|
||||
|
||||
self.label(for_test_label.clone());
|
||||
@@ -1175,9 +1140,9 @@ impl FunctionCompiler {
|
||||
|
||||
let value_reg = ec.fnc.get_pattern_register(pat);
|
||||
|
||||
let iter_reg = ec.fnc.allocate_numbered_reg(&"_iter".to_string());
|
||||
let iter_res_reg = ec.fnc.allocate_numbered_reg(&"_iter_res".to_string());
|
||||
let done_reg = ec.fnc.allocate_numbered_reg(&"_done".to_string());
|
||||
let iter_reg = ec.fnc.allocate_numbered_reg("_iter");
|
||||
let iter_res_reg = ec.fnc.allocate_numbered_reg("_iter_res");
|
||||
let done_reg = ec.fnc.allocate_numbered_reg("_done");
|
||||
|
||||
ec.compile_into(&for_of.right, iter_reg.clone());
|
||||
|
||||
@@ -1186,29 +1151,20 @@ impl FunctionCompiler {
|
||||
Value::Builtin(Builtin {
|
||||
name: "SymbolIterator".to_string(),
|
||||
}),
|
||||
Value::Array(Box::new(Array::default())),
|
||||
Value::Array(Box::default()),
|
||||
iter_reg.clone(),
|
||||
));
|
||||
|
||||
let for_test_label = Label {
|
||||
name: ec
|
||||
.fnc
|
||||
.label_allocator
|
||||
.allocate_numbered(&"for_test".to_string()),
|
||||
name: ec.fnc.label_allocator.allocate_numbered("for_test"),
|
||||
};
|
||||
|
||||
let for_continue_label = Label {
|
||||
name: ec
|
||||
.fnc
|
||||
.label_allocator
|
||||
.allocate_numbered(&"for_continue".to_string()),
|
||||
name: ec.fnc.label_allocator.allocate_numbered("for_continue"),
|
||||
};
|
||||
|
||||
let for_end_label = Label {
|
||||
name: ec
|
||||
.fnc
|
||||
.label_allocator
|
||||
.allocate_numbered(&"for_end".to_string()),
|
||||
name: ec.fnc.label_allocator.allocate_numbered("for_end"),
|
||||
};
|
||||
|
||||
ec.fnc.push(Instruction::Jmp(for_continue_label.ref_()));
|
||||
|
||||
@@ -54,12 +54,7 @@ where
|
||||
})
|
||||
.expect("Failed to add to queue");
|
||||
|
||||
loop {
|
||||
let dependency = match dependencies.remove() {
|
||||
Ok(dependency) => dependency,
|
||||
Err(_) => break,
|
||||
};
|
||||
|
||||
while let Ok(dependency) = dependencies.remove() {
|
||||
let file_contents = match read_file(&dependency.path.path) {
|
||||
Ok(file_contents) => file_contents,
|
||||
Err(err) => {
|
||||
|
||||
@@ -105,7 +105,7 @@ impl<'a> RegisterVisitMut<'a> {
|
||||
impl Instruction {
|
||||
pub fn visit_fields_mut<F>(&mut self, visit: &mut F)
|
||||
where
|
||||
F: FnMut(InstructionFieldMut) -> (),
|
||||
F: FnMut(InstructionFieldMut),
|
||||
{
|
||||
use Instruction::*;
|
||||
|
||||
@@ -222,7 +222,7 @@ impl Instruction {
|
||||
|
||||
pub fn visit_registers_mut_rev<F>(&mut self, visit: &mut F)
|
||||
where
|
||||
F: FnMut(RegisterVisitMut) -> (),
|
||||
F: FnMut(RegisterVisitMut),
|
||||
{
|
||||
use Instruction::*;
|
||||
|
||||
|
||||
@@ -26,9 +26,8 @@ struct DiagnosticCollector {
|
||||
|
||||
impl Emitter for DiagnosticCollector {
|
||||
fn emit(&mut self, db: &DiagnosticBuilder<'_>) {
|
||||
match Diagnostic::from_swc(&**db) {
|
||||
Some(diagnostic) => self.diagnostics.lock().unwrap().push(diagnostic),
|
||||
None => {}
|
||||
if let Some(diagnostic) = Diagnostic::from_swc(db) {
|
||||
self.diagnostics.lock().unwrap().push(diagnostic)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,7 +61,7 @@ pub fn parse(source: &str) -> (Option<swc_ecma_ast::Program>, Vec<Diagnostic>) {
|
||||
let mut diagnostics = Vec::<Diagnostic>::new();
|
||||
std::mem::swap(&mut diagnostics, &mut *diagnostics_arc.lock().unwrap());
|
||||
|
||||
return (result.ok(), diagnostics);
|
||||
(result.ok(), diagnostics)
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -72,12 +71,12 @@ pub struct CompilerOutput {
|
||||
}
|
||||
|
||||
pub fn compile_program(program: &swc_ecma_ast::Program) -> CompilerOutput {
|
||||
let compiler = ModuleCompiler::compile_program(&program);
|
||||
let compiler = ModuleCompiler::compile_program(program);
|
||||
|
||||
return CompilerOutput {
|
||||
CompilerOutput {
|
||||
diagnostics: compiler.diagnostics,
|
||||
module: compiler.module,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compile_module(source: &str) -> CompilerOutput {
|
||||
@@ -91,7 +90,7 @@ pub fn compile_module(source: &str) -> CompilerOutput {
|
||||
diagnostics.append(&mut compiler_output.diagnostics);
|
||||
compiler_output.diagnostics = diagnostics;
|
||||
|
||||
return compiler_output;
|
||||
compiler_output
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -134,7 +133,7 @@ impl ModuleCompiler {
|
||||
let allocated_name = self
|
||||
.definition_allocator
|
||||
.borrow_mut()
|
||||
.allocate_numbered(&name.to_string());
|
||||
.allocate_numbered(name);
|
||||
|
||||
Pointer {
|
||||
name: allocated_name,
|
||||
@@ -202,10 +201,10 @@ impl ModuleCompiler {
|
||||
ExportDefaultDecl(edd) => self.compile_export_default_decl(edd),
|
||||
ExportDefaultExpr(ede) => {
|
||||
let value = match &*ede.expr {
|
||||
swc_ecma_ast::Expr::Ident(ident) => match self.scope_analysis.lookup(ident) {
|
||||
Some(name) => Some(name.value.clone()),
|
||||
None => None,
|
||||
},
|
||||
swc_ecma_ast::Expr::Ident(ident) => self
|
||||
.scope_analysis
|
||||
.lookup(ident)
|
||||
.map(|name| name.value.clone()),
|
||||
expr => static_eval_expr(expr),
|
||||
};
|
||||
|
||||
@@ -290,7 +289,7 @@ impl ModuleCompiler {
|
||||
_ => {
|
||||
self.diagnostics.push(Diagnostic {
|
||||
level: DiagnosticLevel::Error,
|
||||
message: format!("const variable without initializer"),
|
||||
message: "const variable without initializer".to_string(),
|
||||
span: decl.init.span(),
|
||||
});
|
||||
|
||||
@@ -298,50 +297,47 @@ impl ModuleCompiler {
|
||||
}
|
||||
};
|
||||
|
||||
match (ident, init) {
|
||||
(Some(ident), Some(init)) => {
|
||||
let value = match static_eval_expr(init) {
|
||||
Some(value) => value,
|
||||
None => {
|
||||
self.todo(
|
||||
init.span(),
|
||||
"Determine whether initializer can be statically evaluated",
|
||||
);
|
||||
if let (Some(ident), Some(init)) = (ident, init) {
|
||||
let value = match static_eval_expr(init) {
|
||||
Some(value) => value,
|
||||
None => {
|
||||
self.todo(
|
||||
init.span(),
|
||||
"Determine whether initializer can be statically evaluated",
|
||||
);
|
||||
|
||||
Value::String("(Static eval failed)".to_string())
|
||||
}
|
||||
};
|
||||
Value::String("(Static eval failed)".to_string())
|
||||
}
|
||||
};
|
||||
|
||||
let pointer = match self.scope_analysis.lookup(ident) {
|
||||
Some(name) => match &name.value {
|
||||
Value::Pointer(p) => p.clone(),
|
||||
_ => {
|
||||
self.diagnostics.push(Diagnostic {
|
||||
level: DiagnosticLevel::InternalError,
|
||||
message: "Expected pointer for module constant".to_string(),
|
||||
span: ident.span(),
|
||||
});
|
||||
|
||||
continue;
|
||||
}
|
||||
},
|
||||
None => {
|
||||
let pointer = match self.scope_analysis.lookup(ident) {
|
||||
Some(name) => match &name.value {
|
||||
Value::Pointer(p) => p.clone(),
|
||||
_ => {
|
||||
self.diagnostics.push(Diagnostic {
|
||||
level: DiagnosticLevel::InternalError,
|
||||
message: "Failed to lookup name".to_string(),
|
||||
message: "Expected pointer for module constant".to_string(),
|
||||
span: ident.span(),
|
||||
});
|
||||
|
||||
continue;
|
||||
}
|
||||
};
|
||||
},
|
||||
None => {
|
||||
self.diagnostics.push(Diagnostic {
|
||||
level: DiagnosticLevel::InternalError,
|
||||
message: "Failed to lookup name".to_string(),
|
||||
span: ident.span(),
|
||||
});
|
||||
|
||||
self.module.definitions.push(Definition {
|
||||
pointer,
|
||||
content: DefinitionContent::Value(value),
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
self.module.definitions.push(Definition {
|
||||
pointer,
|
||||
content: DefinitionContent::Value(value),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -472,7 +468,7 @@ impl ModuleCompiler {
|
||||
match &ed.decl {
|
||||
Decl::Class(class) => {
|
||||
let class_name = class.ident.sym.to_string();
|
||||
self.compile_class(Some(class_name.clone()), Some(&class.ident), &class.class);
|
||||
self.compile_class(Some(class_name), Some(&class.ident), &class.class);
|
||||
}
|
||||
Decl::Fn(fn_) => self.compile_fn_decl(true, fn_),
|
||||
Decl::Var(var_decl) => {
|
||||
@@ -558,7 +554,7 @@ impl ModuleCompiler {
|
||||
}
|
||||
None => match self
|
||||
.scope_analysis
|
||||
.lookup_value(&OwnerId::Module, &orig_name)
|
||||
.lookup_value(&OwnerId::Module, orig_name)
|
||||
{
|
||||
Some(Value::Pointer(p)) => Some(p),
|
||||
lookup_result => {
|
||||
@@ -881,34 +877,31 @@ impl ModuleCompiler {
|
||||
let mut has_constructor = false;
|
||||
|
||||
for class_member in &class.body {
|
||||
match class_member {
|
||||
swc_ecma_ast::ClassMember::Constructor(ctor) => {
|
||||
has_constructor = true;
|
||||
if let swc_ecma_ast::ClassMember::Constructor(ctor) = class_member {
|
||||
has_constructor = true;
|
||||
|
||||
let ctor_defn_name = self.allocate_defn(&format!("{}_constructor", defn_name.name));
|
||||
let ctor_defn_name = self.allocate_defn(&format!("{}_constructor", defn_name.name));
|
||||
|
||||
dependent_definitions.append(&mut self.compile_fn(
|
||||
ctor_defn_name.clone(),
|
||||
None,
|
||||
Functionish::Constructor(
|
||||
member_initializers_assembly.clone(),
|
||||
class.span,
|
||||
ctor.clone(),
|
||||
),
|
||||
));
|
||||
dependent_definitions.append(&mut self.compile_fn(
|
||||
ctor_defn_name.clone(),
|
||||
None,
|
||||
Functionish::Constructor(
|
||||
member_initializers_assembly.clone(),
|
||||
class.span,
|
||||
ctor.clone(),
|
||||
),
|
||||
));
|
||||
|
||||
constructor = Value::Pointer(ctor_defn_name);
|
||||
}
|
||||
_ => {}
|
||||
constructor = Value::Pointer(ctor_defn_name);
|
||||
}
|
||||
}
|
||||
|
||||
if member_initializers_assembly.len() > 0 && !has_constructor {
|
||||
if !member_initializers_assembly.is_empty() && !has_constructor {
|
||||
let ctor_defn_name = self.allocate_defn(&format!("{}_constructor", defn_name.name));
|
||||
|
||||
constructor = Value::Pointer(ctor_defn_name.clone());
|
||||
dependent_definitions.push(Definition {
|
||||
pointer: ctor_defn_name.clone(),
|
||||
pointer: ctor_defn_name,
|
||||
content: DefinitionContent::Function(Function {
|
||||
is_generator: false,
|
||||
parameters: vec![],
|
||||
@@ -941,11 +934,8 @@ impl ModuleCompiler {
|
||||
}
|
||||
};
|
||||
|
||||
let method_defn_name = self.allocate_defn(&ident_from_str(&format!(
|
||||
"{}_{}",
|
||||
defn_name.name,
|
||||
name.to_string()
|
||||
)));
|
||||
let method_defn_name =
|
||||
self.allocate_defn(&ident_from_str(&format!("{}_{}", defn_name.name, name)));
|
||||
|
||||
dependent_definitions.append(&mut self.compile_fn(
|
||||
method_defn_name.clone(),
|
||||
|
||||
@@ -10,17 +10,14 @@ pub struct NameAllocator {
|
||||
|
||||
impl NameAllocator {
|
||||
pub fn allocate(&mut self, based_on_name: &String) -> String {
|
||||
match self.released_names.pop() {
|
||||
Some(name) => {
|
||||
// FIXME: When reallocating a register we need to ensure we don't read
|
||||
// the leftover value
|
||||
self.used_names.insert(name.clone());
|
||||
return name;
|
||||
}
|
||||
None => {}
|
||||
if let Some(name) = self.released_names.pop() {
|
||||
// FIXME: When reallocating a register we need to ensure we don't read
|
||||
// the leftover value
|
||||
self.used_names.insert(name.clone());
|
||||
return name;
|
||||
};
|
||||
|
||||
return self.allocate_fresh(based_on_name);
|
||||
self.allocate_fresh(based_on_name)
|
||||
}
|
||||
|
||||
pub fn allocate_fresh(&mut self, based_on_name: &String) -> String {
|
||||
@@ -29,28 +26,25 @@ impl NameAllocator {
|
||||
return based_on_name.clone();
|
||||
}
|
||||
|
||||
return self.allocate_numbered(&(based_on_name.clone() + "_"));
|
||||
self.allocate_numbered(&(based_on_name.clone() + "_"))
|
||||
}
|
||||
|
||||
pub fn allocate_numbered(&mut self, prefix: &String) -> String {
|
||||
match self.released_names.pop() {
|
||||
Some(name) => {
|
||||
// FIXME: When reallocating a register we need to ensure we don't read
|
||||
// the leftover value
|
||||
self.used_names.insert(name.clone());
|
||||
return name;
|
||||
}
|
||||
None => {}
|
||||
pub fn allocate_numbered(&mut self, prefix: &str) -> String {
|
||||
if let Some(name) = self.released_names.pop() {
|
||||
// FIXME: When reallocating a register we need to ensure we don't read
|
||||
// the leftover value
|
||||
self.used_names.insert(name.clone());
|
||||
return name;
|
||||
};
|
||||
|
||||
return self.allocate_numbered_fresh(prefix);
|
||||
self.allocate_numbered_fresh(prefix)
|
||||
}
|
||||
|
||||
pub fn allocate_numbered_fresh(&mut self, prefix: &String) -> String {
|
||||
pub fn allocate_numbered_fresh(&mut self, prefix: &str) -> String {
|
||||
let mut i = 0_u64;
|
||||
|
||||
loop {
|
||||
let candidate = prefix.clone() + &i.to_string();
|
||||
let candidate = prefix.to_string() + &i.to_string();
|
||||
|
||||
if !self.used_names.contains(&candidate) {
|
||||
self.used_names.insert(candidate.clone());
|
||||
@@ -61,8 +55,8 @@ impl NameAllocator {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mark_used(&mut self, name: &String) {
|
||||
self.used_names.insert(name.clone());
|
||||
pub fn mark_used(&mut self, name: &str) {
|
||||
self.used_names.insert(name.to_string());
|
||||
}
|
||||
|
||||
pub fn release(&mut self, name: &String) {
|
||||
@@ -138,12 +132,12 @@ impl RegAllocator {
|
||||
}
|
||||
|
||||
pub fn allocate_numbered(&mut self, prefix: &str) -> Register {
|
||||
let name = self.alloc.allocate_numbered(&prefix.to_string());
|
||||
let name = self.alloc.allocate_numbered(prefix);
|
||||
Register::named(name)
|
||||
}
|
||||
|
||||
pub fn allocate_numbered_fresh(&mut self, prefix: &str) -> Register {
|
||||
let name = self.alloc.allocate_numbered_fresh(&prefix.to_string());
|
||||
let name = self.alloc.allocate_numbered_fresh(prefix);
|
||||
Register::named(name)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,12 +17,12 @@ pub fn extract_constants(module: &mut Module, pointer_allocator: &mut NameAlloca
|
||||
instr.visit_fields_mut(&mut |field| match field {
|
||||
InstructionFieldMut::Value(value) => {
|
||||
value.visit_values_mut(&mut |sub_value| {
|
||||
if let Some(p) = constants.get(&sub_value) {
|
||||
if let Some(p) = constants.get(sub_value) {
|
||||
*sub_value = Value::Pointer(p.clone());
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(name) = should_extract_value_as_constant(&sub_value) {
|
||||
if let Some(name) = should_extract_value_as_constant(sub_value) {
|
||||
let p = Pointer {
|
||||
name: pointer_allocator.allocate(&name),
|
||||
};
|
||||
@@ -82,14 +82,14 @@ fn should_extract_value_as_constant(value: &Value) -> Option<String> {
|
||||
}
|
||||
}
|
||||
Value::Array(array) => {
|
||||
if array.values.len() >= 1 && array.values.iter().all(is_constant) {
|
||||
if !array.values.is_empty() && array.values.iter().all(is_constant) {
|
||||
Some("array".to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Value::Object(object) => {
|
||||
if object.properties.len() >= 1
|
||||
if !object.properties.is_empty()
|
||||
&& object
|
||||
.properties
|
||||
.iter()
|
||||
@@ -123,7 +123,7 @@ fn is_constant(value: &Value) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn mangle_string(s: &String) -> String {
|
||||
fn mangle_string(s: &str) -> String {
|
||||
let mut res = "s_".to_string();
|
||||
|
||||
for c in s.chars() {
|
||||
|
||||
@@ -69,7 +69,7 @@ pub struct Object {
|
||||
impl Kal {
|
||||
fn visit_kals_mut<F>(&mut self, visit: &mut F)
|
||||
where
|
||||
F: FnMut(&mut Kal) -> (),
|
||||
F: FnMut(&mut Kal),
|
||||
{
|
||||
visit(self);
|
||||
|
||||
@@ -302,17 +302,14 @@ impl FnState {
|
||||
let mut new_reg: Option<String> = None;
|
||||
|
||||
for kal in self.registers.values_mut() {
|
||||
match kal {
|
||||
Kal::Register(reg) => {
|
||||
if ®.name == changed_reg {
|
||||
// When it's just a register, avoid using new_reg. This would just create spurious
|
||||
// renames. The real point of new_reg is to improve the *inner* knowledge of registers
|
||||
// that contain the changed_reg.
|
||||
*kal = Kal::Unknown;
|
||||
continue;
|
||||
}
|
||||
if let Kal::Register(reg) = kal {
|
||||
if ®.name == changed_reg {
|
||||
// When it's just a register, avoid using new_reg. This would just create spurious
|
||||
// renames. The real point of new_reg is to improve the *inner* knowledge of registers
|
||||
// that contain the changed_reg.
|
||||
*kal = Kal::Unknown;
|
||||
continue;
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
kal.visit_kals_mut(&mut |sub_kal| {
|
||||
@@ -573,10 +570,11 @@ impl FnState {
|
||||
| OpRightShiftUnsigned(_, _, dst)
|
||||
| InstanceOf(_, _, dst)
|
||||
| In(_, _, dst)
|
||||
| Sub(_, _, dst) => match self.get(dst.name.clone()).try_to_value() {
|
||||
Some(value) => *instr = Instruction::Mov(value, dst.clone()),
|
||||
None => {}
|
||||
},
|
||||
| Sub(_, _, dst) => {
|
||||
if let Some(value) = self.get(dst.name.clone()).try_to_value() {
|
||||
*instr = Instruction::Mov(value, dst.clone())
|
||||
}
|
||||
}
|
||||
|
||||
End
|
||||
| Mov(_, _)
|
||||
|
||||
@@ -69,7 +69,7 @@ fn remove_unused_registers_fn(fn_: &mut Function) {
|
||||
}
|
||||
|
||||
for param in &fn_.parameters {
|
||||
if ¶m.name == &single_return_dep {
|
||||
if param.name == single_return_dep {
|
||||
break 'b;
|
||||
}
|
||||
}
|
||||
@@ -113,7 +113,7 @@ fn reg_is_always_returned(body: &mut Vec<FnLine>, reg: &String) -> bool {
|
||||
last_was_return_reg
|
||||
}
|
||||
|
||||
fn rename_register_in_body(body: &mut Vec<FnLine>, from: &String, to: &String) {
|
||||
fn rename_register_in_body(body: &mut Vec<FnLine>, from: &String, to: &str) {
|
||||
// Note: This only does the rename in the body and basically assumes that %from is not a
|
||||
// parameter.
|
||||
|
||||
@@ -127,7 +127,7 @@ fn rename_register_in_body(body: &mut Vec<FnLine>, from: &String, to: &String) {
|
||||
if &rvm.register.name == from {
|
||||
// TODO: Preserving `.take=true` can cause problems. Is just using `.take=false` the right
|
||||
// solution?
|
||||
*rvm.register = Register::named(to.clone());
|
||||
*rvm.register = Register::named(to.to_owned());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -41,8 +41,8 @@ pub fn shake_tree(module: &mut Module) {
|
||||
include_pointer(
|
||||
&p,
|
||||
&mut ordered_pointers,
|
||||
&mut dependency_graph,
|
||||
&mut reverse_dependency_graph,
|
||||
&dependency_graph,
|
||||
&reverse_dependency_graph,
|
||||
&mut pointers_in_progress,
|
||||
&required_pointers,
|
||||
);
|
||||
@@ -77,7 +77,7 @@ pub fn shake_tree(module: &mut Module) {
|
||||
if required_pointers.contains(&pointer) {
|
||||
let defn = new_definitions_map.get_mut(&pointer).unwrap();
|
||||
|
||||
if defn.pointer.name == "" {
|
||||
if defn.pointer.name.is_empty() {
|
||||
// "" isn't a valid pointer name - this happens when `take` has already been used on the
|
||||
// definition
|
||||
continue;
|
||||
|
||||
@@ -25,7 +25,7 @@ pub fn simplify(module: &mut Module, take_registers: bool) {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_mutation_releases(body: &mut Vec<FnLine>, i: usize, take_registers: bool) {
|
||||
fn handle_mutation_releases(body: &mut [FnLine], i: usize, take_registers: bool) {
|
||||
let mut calls = Vec::<(Register, usize)>::new();
|
||||
|
||||
match &mut body[i] {
|
||||
@@ -49,7 +49,7 @@ fn handle_mutation_releases(body: &mut Vec<FnLine>, i: usize, take_registers: bo
|
||||
}
|
||||
|
||||
fn handle_release(
|
||||
body: &mut Vec<FnLine>,
|
||||
body: &mut [FnLine],
|
||||
i: usize,
|
||||
released_reg: Register,
|
||||
skips_needed: usize,
|
||||
|
||||
@@ -18,7 +18,7 @@ fn simplify_jumps_fn(fn_: &mut Function) {
|
||||
|
||||
for i in 0..fn_.body.len() {
|
||||
if let FnLine::Instruction(Instruction::End) = &fn_.body[i] {
|
||||
if next_instruction_index(&fn_.body, i) == None {
|
||||
if next_instruction_index(&fn_.body, i).is_none() {
|
||||
// Remove `end` instructions when we're already at the end of the function.
|
||||
substitutions.insert(i, FnLine::Comment(fn_.body[i].to_string()));
|
||||
continue;
|
||||
@@ -41,13 +41,10 @@ fn simplify_jumps_fn(fn_: &mut Function) {
|
||||
|
||||
// Find matching label
|
||||
while j < fn_.body.len() {
|
||||
match &fn_.body[j] {
|
||||
FnLine::Label(label) => {
|
||||
if label.name == label_ref.name {
|
||||
break;
|
||||
}
|
||||
if let FnLine::Label(label) = &fn_.body[j] {
|
||||
if label.name == label_ref.name {
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
j += 1;
|
||||
|
||||
@@ -131,7 +131,7 @@ impl ScopeAnalysis {
|
||||
|
||||
sa.diagnose_tdz_violations();
|
||||
|
||||
return sa;
|
||||
sa
|
||||
}
|
||||
|
||||
pub fn lookup(&self, ident: &swc_ecma_ast::Ident) -> Option<&Name> {
|
||||
@@ -168,7 +168,7 @@ impl ScopeAnalysis {
|
||||
self
|
||||
.reg_allocators
|
||||
.entry(scope.clone())
|
||||
.or_insert_with(|| RegAllocator::default())
|
||||
.or_insert_with(RegAllocator::default)
|
||||
.allocate(based_on_name)
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ impl ScopeAnalysis {
|
||||
|
||||
scope.set(
|
||||
&origin_ident.sym,
|
||||
name.id.clone(),
|
||||
name.id,
|
||||
origin_ident.span,
|
||||
&mut self.diagnostics,
|
||||
);
|
||||
@@ -287,7 +287,7 @@ impl ScopeAnalysis {
|
||||
let reg = self
|
||||
.reg_allocators
|
||||
.entry(captor_id.clone())
|
||||
.or_insert_with(|| RegAllocator::default())
|
||||
.or_insert_with(RegAllocator::default)
|
||||
.allocate(&name.sym);
|
||||
|
||||
self.capture_values.insert(key, Value::Register(reg));
|
||||
@@ -310,21 +310,21 @@ impl ScopeAnalysis {
|
||||
ModuleItem::ModuleDecl(module_decl) => match module_decl {
|
||||
ModuleDecl::Import(_) => {}
|
||||
ModuleDecl::ExportDecl(ed) => {
|
||||
self.decl(&scope, &ed.decl);
|
||||
self.decl(scope, &ed.decl);
|
||||
}
|
||||
ModuleDecl::ExportNamed(en) => match en.src {
|
||||
Some(_) => {}
|
||||
None => {
|
||||
for specifier in &en.specifiers {
|
||||
self.export_specifier(&scope, specifier);
|
||||
self.export_specifier(scope, specifier);
|
||||
}
|
||||
}
|
||||
},
|
||||
ModuleDecl::ExportDefaultDecl(edd) => {
|
||||
self.default_decl(&scope, &edd.decl);
|
||||
self.default_decl(scope, &edd.decl);
|
||||
}
|
||||
ModuleDecl::ExportDefaultExpr(ede) => {
|
||||
self.expr(&scope, &ede.expr);
|
||||
self.expr(scope, &ede.expr);
|
||||
}
|
||||
ModuleDecl::ExportAll(_) => {}
|
||||
ModuleDecl::TsImportEquals(ts_import_equals) => {
|
||||
@@ -350,14 +350,14 @@ impl ScopeAnalysis {
|
||||
}
|
||||
},
|
||||
ModuleItem::Stmt(stmt) => {
|
||||
self.stmt(&scope, &stmt);
|
||||
self.stmt(scope, stmt);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn import_decl(&mut self, scope: &Scope, import_decl: &swc_ecma_ast::ImportDecl) {
|
||||
for specifier in &import_decl.specifiers {
|
||||
self.import_specifier(&scope, specifier);
|
||||
self.import_specifier(scope, specifier);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,7 +431,7 @@ impl ScopeAnalysis {
|
||||
}
|
||||
Decl::Var(var_decl) => {
|
||||
for decl in &var_decl.decls {
|
||||
self.var_declarator(&scope, var_decl.kind, decl);
|
||||
self.var_declarator(scope, decl);
|
||||
}
|
||||
}
|
||||
Decl::TsInterface(_) => {}
|
||||
@@ -443,7 +443,7 @@ impl ScopeAnalysis {
|
||||
|
||||
for member in &ts_enum.members {
|
||||
if let Some(init) = &member.init {
|
||||
self.expr(scope, &init);
|
||||
self.expr(scope, init);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -474,8 +474,8 @@ impl ScopeAnalysis {
|
||||
}
|
||||
|
||||
for body in &function.body {
|
||||
self.function_level_hoists(&child_scope, &body);
|
||||
self.block_stmt(&child_scope, &body);
|
||||
self.function_level_hoists(&child_scope, body);
|
||||
self.block_stmt(&child_scope, body);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,14 +492,14 @@ impl ScopeAnalysis {
|
||||
match module_item {
|
||||
ModuleItem::ModuleDecl(module_decl) => match module_decl {
|
||||
ModuleDecl::Import(import_decl) => {
|
||||
self.import_decl(&scope, import_decl);
|
||||
self.import_decl(scope, import_decl);
|
||||
}
|
||||
ModuleDecl::ExportDecl(ed) => match &ed.decl {
|
||||
swc_ecma_ast::Decl::Class(class_decl) => {
|
||||
self.insert_pointer_name(&scope, NameType::Class, &class_decl.ident);
|
||||
self.insert_pointer_name(scope, NameType::Class, &class_decl.ident);
|
||||
}
|
||||
swc_ecma_ast::Decl::Fn(fn_decl) => {
|
||||
self.insert_pointer_name(&scope, NameType::Function, &fn_decl.ident);
|
||||
self.insert_pointer_name(scope, NameType::Function, &fn_decl.ident);
|
||||
}
|
||||
swc_ecma_ast::Decl::Var(var_decl) => {
|
||||
let name_type = match var_decl.kind {
|
||||
@@ -510,7 +510,7 @@ impl ScopeAnalysis {
|
||||
|
||||
for decl in &var_decl.decls {
|
||||
for ident in self.get_pat_idents(&decl.name) {
|
||||
self.insert_pointer_name(&scope, name_type, &ident);
|
||||
self.insert_pointer_name(scope, name_type, &ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -527,12 +527,12 @@ impl ScopeAnalysis {
|
||||
ModuleDecl::ExportDefaultDecl(edd) => match &edd.decl {
|
||||
swc_ecma_ast::DefaultDecl::Class(class_decl) => {
|
||||
if let Some(ident) = &class_decl.ident {
|
||||
self.insert_pointer_name(&scope, NameType::Class, ident);
|
||||
self.insert_pointer_name(scope, NameType::Class, ident);
|
||||
}
|
||||
}
|
||||
swc_ecma_ast::DefaultDecl::Fn(fn_decl) => {
|
||||
if let Some(ident) = &fn_decl.ident {
|
||||
self.insert_pointer_name(&scope, NameType::Function, ident);
|
||||
self.insert_pointer_name(scope, NameType::Function, ident);
|
||||
}
|
||||
}
|
||||
swc_ecma_ast::DefaultDecl::TsInterfaceDecl(_) => {}
|
||||
@@ -550,8 +550,8 @@ impl ScopeAnalysis {
|
||||
}
|
||||
},
|
||||
ModuleItem::Stmt(stmt) => {
|
||||
self.function_level_hoists_stmt(&scope, stmt);
|
||||
self.block_level_hoists_stmt(&scope, stmt);
|
||||
self.function_level_hoists_stmt(scope, stmt);
|
||||
self.block_level_hoists_stmt(scope, stmt);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -625,41 +625,41 @@ impl ScopeAnalysis {
|
||||
Stmt::With(_) => {}
|
||||
Stmt::Return(_) => {}
|
||||
Stmt::Labeled(labeled_stmt) => {
|
||||
self.function_level_hoists_stmt(&scope, &labeled_stmt.body);
|
||||
self.function_level_hoists_stmt(scope, &labeled_stmt.body);
|
||||
}
|
||||
Stmt::Break(_) => {}
|
||||
Stmt::Continue(_) => {}
|
||||
Stmt::If(if_) => {
|
||||
self.function_level_hoists_stmt(&scope, &if_.cons);
|
||||
self.function_level_hoists_stmt(scope, &if_.cons);
|
||||
|
||||
for alt in &if_.alt {
|
||||
self.function_level_hoists_stmt(&scope, alt);
|
||||
self.function_level_hoists_stmt(scope, alt);
|
||||
}
|
||||
}
|
||||
Stmt::Switch(switch_) => {
|
||||
for case in &switch_.cases {
|
||||
for stmt in &case.cons {
|
||||
self.function_level_hoists_stmt(&scope, stmt);
|
||||
self.function_level_hoists_stmt(scope, stmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
Stmt::Throw(_) => {}
|
||||
Stmt::Try(try_) => {
|
||||
self.function_level_hoists(&scope, &try_.block);
|
||||
self.function_level_hoists(scope, &try_.block);
|
||||
|
||||
for catch in &try_.handler {
|
||||
self.function_level_hoists(&scope, &catch.body);
|
||||
self.function_level_hoists(scope, &catch.body);
|
||||
}
|
||||
|
||||
for finally in &try_.finalizer {
|
||||
self.function_level_hoists(&scope, finally);
|
||||
self.function_level_hoists(scope, finally);
|
||||
}
|
||||
}
|
||||
Stmt::While(while_) => {
|
||||
self.function_level_hoists_stmt(&scope, &while_.body);
|
||||
self.function_level_hoists_stmt(scope, &while_.body);
|
||||
}
|
||||
Stmt::DoWhile(do_while_) => {
|
||||
self.function_level_hoists_stmt(&scope, &do_while_.body);
|
||||
self.function_level_hoists_stmt(scope, &do_while_.body);
|
||||
}
|
||||
Stmt::Expr(_) => {}
|
||||
}
|
||||
@@ -740,10 +740,8 @@ impl ScopeAnalysis {
|
||||
idents.push(ident.id.clone());
|
||||
}
|
||||
Pat::Array(array_pat) => {
|
||||
for elem in &array_pat.elems {
|
||||
if let Some(elem) = elem {
|
||||
self.get_pat_idents_impl(idents, elem);
|
||||
}
|
||||
for elem in array_pat.elems.iter().flatten() {
|
||||
self.get_pat_idents_impl(idents, elem);
|
||||
}
|
||||
}
|
||||
Pat::Rest(rest_pat) => {
|
||||
@@ -785,7 +783,7 @@ impl ScopeAnalysis {
|
||||
}
|
||||
|
||||
fn arrow(&mut self, scope: &Scope, arrow: &swc_ecma_ast::ArrowExpr) {
|
||||
let child_scope = scope.nest(Some(OwnerId::Span(arrow.span.clone())));
|
||||
let child_scope = scope.nest(Some(OwnerId::Span(arrow.span)));
|
||||
|
||||
for param in &arrow.params {
|
||||
self.param_pat(&child_scope, param);
|
||||
@@ -801,16 +799,14 @@ impl ScopeAnalysis {
|
||||
}
|
||||
}
|
||||
|
||||
fn var_declarator_pat(&mut self, scope: &Scope, type_: NameType, pat: &swc_ecma_ast::Pat) {
|
||||
fn var_declarator_pat(&mut self, scope: &Scope, pat: &swc_ecma_ast::Pat) {
|
||||
use swc_ecma_ast::Pat;
|
||||
|
||||
match pat {
|
||||
Pat::Ident(_) => {}
|
||||
Pat::Array(array) => {
|
||||
for elem in &array.elems {
|
||||
if let Some(elem) = elem {
|
||||
self.var_declarator_pat(scope, type_, elem);
|
||||
}
|
||||
for elem in array.elems.iter().flatten() {
|
||||
self.var_declarator_pat(scope, elem);
|
||||
}
|
||||
}
|
||||
Pat::Object(object) => {
|
||||
@@ -818,7 +814,7 @@ impl ScopeAnalysis {
|
||||
match prop {
|
||||
swc_ecma_ast::ObjectPatProp::KeyValue(key_value) => {
|
||||
self.prop_key(scope, &key_value.key);
|
||||
self.var_declarator_pat(scope, type_, &key_value.value);
|
||||
self.var_declarator_pat(scope, &key_value.value);
|
||||
}
|
||||
swc_ecma_ast::ObjectPatProp::Assign(assign) => {
|
||||
if let Some(value) = &assign.value {
|
||||
@@ -826,16 +822,16 @@ impl ScopeAnalysis {
|
||||
}
|
||||
}
|
||||
swc_ecma_ast::ObjectPatProp::Rest(rest) => {
|
||||
self.var_declarator_pat(scope, type_, &rest.arg);
|
||||
self.var_declarator_pat(scope, &rest.arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Pat::Rest(rest) => {
|
||||
self.var_declarator_pat(scope, type_, &rest.arg);
|
||||
self.var_declarator_pat(scope, &rest.arg);
|
||||
}
|
||||
Pat::Assign(assign) => {
|
||||
self.var_declarator_pat(scope, type_, &assign.left);
|
||||
self.var_declarator_pat(scope, &assign.left);
|
||||
self.expr(scope, &assign.right);
|
||||
}
|
||||
Pat::Invalid(invalid) => {
|
||||
@@ -855,19 +851,8 @@ impl ScopeAnalysis {
|
||||
}
|
||||
}
|
||||
|
||||
fn var_declarator(
|
||||
&mut self,
|
||||
scope: &Scope,
|
||||
kind: swc_ecma_ast::VarDeclKind,
|
||||
var_declarator: &swc_ecma_ast::VarDeclarator,
|
||||
) {
|
||||
let type_ = match kind {
|
||||
swc_ecma_ast::VarDeclKind::Var => NameType::Var,
|
||||
swc_ecma_ast::VarDeclKind::Let => NameType::Let,
|
||||
swc_ecma_ast::VarDeclKind::Const => NameType::Const,
|
||||
};
|
||||
|
||||
self.var_declarator_pat(scope, type_, &var_declarator.name);
|
||||
fn var_declarator(&mut self, scope: &Scope, var_declarator: &swc_ecma_ast::VarDeclarator) {
|
||||
self.var_declarator_pat(scope, &var_declarator.name);
|
||||
|
||||
for init in &var_declarator.init {
|
||||
self.expr(scope, init);
|
||||
@@ -879,10 +864,10 @@ impl ScopeAnalysis {
|
||||
|
||||
match &default_decl {
|
||||
DefaultDecl::Class(class_expr) => {
|
||||
self.class_(&scope, &class_expr.ident, &class_expr.class);
|
||||
self.class_(scope, &class_expr.ident, &class_expr.class);
|
||||
}
|
||||
DefaultDecl::Fn(fn_expr) => {
|
||||
self.fn_expr(&scope, fn_expr);
|
||||
self.fn_expr(scope, fn_expr);
|
||||
}
|
||||
DefaultDecl::TsInterfaceDecl(_) => {}
|
||||
}
|
||||
@@ -965,7 +950,7 @@ impl ScopeAnalysis {
|
||||
}
|
||||
Empty(_) => {}
|
||||
StaticBlock(static_block) => {
|
||||
self.block_stmt(&scope, &static_block.body);
|
||||
self.block_stmt(scope, &static_block.body);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -984,10 +969,8 @@ impl ScopeAnalysis {
|
||||
}
|
||||
Expr::Lit(_) => {}
|
||||
Expr::Array(array) => {
|
||||
for elem in &array.elems {
|
||||
if let Some(elem) = elem {
|
||||
self.expr(scope, &elem.expr);
|
||||
}
|
||||
for elem in array.elems.iter().flatten() {
|
||||
self.expr(scope, &elem.expr);
|
||||
}
|
||||
}
|
||||
Expr::Object(object) => {
|
||||
@@ -1176,11 +1159,8 @@ impl ScopeAnalysis {
|
||||
swc_ecma_ast::Callee::Expr(expr) => {
|
||||
self.expr(scope, expr);
|
||||
|
||||
match &**expr {
|
||||
swc_ecma_ast::Expr::Member(member) => {
|
||||
self.mutate_expr(scope, &member.obj, true);
|
||||
}
|
||||
_ => {}
|
||||
if let swc_ecma_ast::Expr::Member(member) = &**expr {
|
||||
self.mutate_expr(scope, &member.obj, true);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1198,10 +1178,8 @@ impl ScopeAnalysis {
|
||||
self.ident(scope, &ident.id);
|
||||
}
|
||||
Pat::Array(array) => {
|
||||
for elem in &array.elems {
|
||||
if let Some(elem) = elem {
|
||||
self.pat(scope, elem);
|
||||
}
|
||||
for elem in array.elems.iter().flatten() {
|
||||
self.pat(scope, elem);
|
||||
}
|
||||
}
|
||||
Pat::Rest(rest) => {
|
||||
@@ -1489,10 +1467,8 @@ impl ScopeAnalysis {
|
||||
self.mutate_ident(scope, &ident.id, false);
|
||||
}
|
||||
Pat::Array(array_pat) => {
|
||||
for elem in &array_pat.elems {
|
||||
if let Some(elem) = elem {
|
||||
self.mutate_pat(scope, elem);
|
||||
}
|
||||
for elem in array_pat.elems.iter().flatten() {
|
||||
self.mutate_pat(scope, elem);
|
||||
}
|
||||
}
|
||||
Pat::Rest(rest_pat) => {
|
||||
@@ -1536,7 +1512,7 @@ impl ScopeAnalysis {
|
||||
});
|
||||
}
|
||||
Pat::Expr(expr) => {
|
||||
self.mutate_expr(&scope, expr, false);
|
||||
self.mutate_expr(scope, expr, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1617,7 +1593,7 @@ impl ScopeAnalysis {
|
||||
}
|
||||
};
|
||||
|
||||
if &name.owner_id != &scope.borrow().owner_id {
|
||||
if name.owner_id != scope.borrow().owner_id {
|
||||
self.insert_capture(&scope.borrow().owner_id, &name_id, ident.span);
|
||||
}
|
||||
}
|
||||
@@ -1642,7 +1618,7 @@ impl ScopeAnalysis {
|
||||
match prop_or_spread {
|
||||
PropOrSpread::Prop(prop) => match &**prop {
|
||||
swc_ecma_ast::Prop::Shorthand(ident) => {
|
||||
self.ident(scope, &ident);
|
||||
self.ident(scope, ident);
|
||||
}
|
||||
swc_ecma_ast::Prop::KeyValue(key_value) => {
|
||||
self.prop_key(scope, &key_value.key);
|
||||
@@ -1652,7 +1628,7 @@ impl ScopeAnalysis {
|
||||
self.prop_key(scope, &getter.key);
|
||||
|
||||
if let Some(body) = &getter.body {
|
||||
self.block_stmt(&scope, body);
|
||||
self.block_stmt(scope, body);
|
||||
}
|
||||
}
|
||||
swc_ecma_ast::Prop::Setter(setter) => {
|
||||
@@ -1660,7 +1636,7 @@ impl ScopeAnalysis {
|
||||
self.param_pat(scope, &setter.param);
|
||||
|
||||
if let Some(body) = &setter.body {
|
||||
self.block_stmt(&scope, body);
|
||||
self.block_stmt(scope, body);
|
||||
}
|
||||
}
|
||||
swc_ecma_ast::Prop::Method(method) => {
|
||||
@@ -1686,7 +1662,7 @@ impl ScopeAnalysis {
|
||||
|
||||
match stmt {
|
||||
Stmt::Block(block) => {
|
||||
self.block_stmt(&scope, block);
|
||||
self.block_stmt(scope, block);
|
||||
}
|
||||
Stmt::Empty(_) => {}
|
||||
Stmt::Debugger(_) => {}
|
||||
@@ -1699,24 +1675,24 @@ impl ScopeAnalysis {
|
||||
}
|
||||
Stmt::Return(return_) => {
|
||||
if let Some(arg) = &return_.arg {
|
||||
self.expr(&scope, arg);
|
||||
self.expr(scope, arg);
|
||||
}
|
||||
}
|
||||
Stmt::Labeled(labeled_stmt) => {
|
||||
self.stmt(&scope, &labeled_stmt.body);
|
||||
self.stmt(scope, &labeled_stmt.body);
|
||||
}
|
||||
Stmt::Break(_) => {}
|
||||
Stmt::Continue(_) => {}
|
||||
Stmt::If(if_) => {
|
||||
self.expr(&scope, &if_.test);
|
||||
self.stmt(&scope, &if_.cons);
|
||||
self.expr(scope, &if_.test);
|
||||
self.stmt(scope, &if_.cons);
|
||||
|
||||
for alt in &if_.alt {
|
||||
self.stmt(&scope, alt);
|
||||
self.stmt(scope, alt);
|
||||
}
|
||||
}
|
||||
Stmt::Switch(switch_) => {
|
||||
self.expr(&scope, &switch_.discriminant);
|
||||
self.expr(scope, &switch_.discriminant);
|
||||
let child_scope = scope.nest(None);
|
||||
|
||||
for case in &switch_.cases {
|
||||
@@ -1730,10 +1706,10 @@ impl ScopeAnalysis {
|
||||
}
|
||||
}
|
||||
Stmt::Throw(throw) => {
|
||||
self.expr(&scope, &throw.arg);
|
||||
self.expr(scope, &throw.arg);
|
||||
}
|
||||
Stmt::Try(try_) => {
|
||||
self.block_stmt(&scope, &try_.block);
|
||||
self.block_stmt(scope, &try_.block);
|
||||
|
||||
for catch in &try_.handler {
|
||||
let child_scope = scope.nest(None);
|
||||
@@ -1747,16 +1723,16 @@ impl ScopeAnalysis {
|
||||
}
|
||||
|
||||
for finally in &try_.finalizer {
|
||||
self.block_stmt(&scope, finally);
|
||||
self.block_stmt(scope, finally);
|
||||
}
|
||||
}
|
||||
Stmt::While(while_) => {
|
||||
self.expr(&scope, &while_.test);
|
||||
self.stmt(&scope, &while_.body);
|
||||
self.expr(scope, &while_.test);
|
||||
self.stmt(scope, &while_.body);
|
||||
}
|
||||
Stmt::DoWhile(do_while_) => {
|
||||
self.stmt(&scope, &do_while_.body);
|
||||
self.expr(&scope, &do_while_.test);
|
||||
self.stmt(scope, &do_while_.body);
|
||||
self.expr(scope, &do_while_.test);
|
||||
}
|
||||
Stmt::For(for_) => {
|
||||
let child_scope = scope.nest(None);
|
||||
@@ -1819,10 +1795,10 @@ impl ScopeAnalysis {
|
||||
self.stmt(&child_scope, &for_of.body);
|
||||
}
|
||||
Stmt::Decl(decl) => {
|
||||
self.decl(&scope, decl);
|
||||
self.decl(scope, decl);
|
||||
}
|
||||
Stmt::Expr(expr) => {
|
||||
self.expr(&scope, &expr.expr);
|
||||
self.expr(scope, &expr.expr);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1844,44 +1820,44 @@ impl ScopeAnalysis {
|
||||
|
||||
match param_pat {
|
||||
Pat::Ident(ident) => {
|
||||
self.insert_reg_name(&scope, NameType::Param, &ident.id, None);
|
||||
self.insert_reg_name(scope, NameType::Param, &ident.id, None);
|
||||
}
|
||||
Pat::Array(array_pat) => {
|
||||
for elem in &array_pat.elems {
|
||||
match elem {
|
||||
Some(pat) => self.param_pat(&scope, pat),
|
||||
Some(pat) => self.param_pat(scope, pat),
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Pat::Rest(rest_pat) => {
|
||||
self.param_pat(&scope, &rest_pat.arg);
|
||||
self.param_pat(scope, &rest_pat.arg);
|
||||
}
|
||||
Pat::Object(object_pat) => {
|
||||
for prop in &object_pat.props {
|
||||
match prop {
|
||||
swc_ecma_ast::ObjectPatProp::KeyValue(key_value) => {
|
||||
self.param_pat(&scope, &key_value.value);
|
||||
self.param_pat(scope, &key_value.value);
|
||||
}
|
||||
swc_ecma_ast::ObjectPatProp::Assign(assign) => {
|
||||
self.insert_reg_name(&scope, NameType::Param, &assign.key, None);
|
||||
self.insert_reg_name(scope, NameType::Param, &assign.key, None);
|
||||
|
||||
if let Some(default) = &assign.value {
|
||||
self.expr(&scope, default);
|
||||
self.expr(scope, default);
|
||||
}
|
||||
}
|
||||
swc_ecma_ast::ObjectPatProp::Rest(rest) => {
|
||||
self.param_pat(&scope, &rest.arg);
|
||||
self.param_pat(scope, &rest.arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Pat::Assign(assign_pat) => {
|
||||
self.param_pat(&scope, &assign_pat.left);
|
||||
self.expr(&scope, &assign_pat.right);
|
||||
self.param_pat(scope, &assign_pat.left);
|
||||
self.expr(scope, &assign_pat.right);
|
||||
}
|
||||
Pat::Expr(expr) => {
|
||||
self.expr(&scope, &expr);
|
||||
self.expr(scope, expr);
|
||||
}
|
||||
Pat::Invalid(invalid) => {
|
||||
self.diagnostics.push(Diagnostic {
|
||||
@@ -1895,13 +1871,13 @@ impl ScopeAnalysis {
|
||||
|
||||
fn var_decl(&mut self, scope: &Scope, var_decl: &swc_ecma_ast::VarDecl) {
|
||||
for decl in &var_decl.decls {
|
||||
self.var_declarator(&scope, var_decl.kind, decl);
|
||||
self.var_declarator(scope, decl);
|
||||
}
|
||||
}
|
||||
|
||||
fn find_capture_mutations(&mut self) {
|
||||
for (name_id, name) in &self.names {
|
||||
if name.captures.len() > 0 {
|
||||
if !name.captures.is_empty() {
|
||||
if name.type_ == NameType::Let {
|
||||
match name_id {
|
||||
NameId::Span(span) => {
|
||||
@@ -1962,7 +1938,7 @@ impl ScopeAnalysis {
|
||||
}
|
||||
|
||||
fn expand_captures(&mut self) {
|
||||
let captors: Vec<OwnerId> = self.captures.keys().map(|k| k.clone()).collect();
|
||||
let captors: Vec<OwnerId> = self.captures.keys().cloned().collect();
|
||||
|
||||
for captor in captors {
|
||||
let mut full_captures = HashSet::<NameId>::new();
|
||||
@@ -1973,12 +1949,7 @@ impl ScopeAnalysis {
|
||||
|
||||
let mut owners_processed = HashSet::<OwnerId>::new();
|
||||
|
||||
loop {
|
||||
let owner = match owners_to_process.get(owners_to_process_i) {
|
||||
Some(o) => o,
|
||||
None => break,
|
||||
};
|
||||
|
||||
while let Some(owner) = owners_to_process.get(owners_to_process_i) {
|
||||
owners_to_process_i += 1;
|
||||
|
||||
let inserted = owners_processed.insert(owner.clone());
|
||||
@@ -1987,7 +1958,7 @@ impl ScopeAnalysis {
|
||||
continue;
|
||||
}
|
||||
|
||||
let captures = match self.captures.get(&owner) {
|
||||
let captures = match self.captures.get(owner) {
|
||||
Some(captures) => captures.clone(),
|
||||
None => continue,
|
||||
};
|
||||
@@ -2022,7 +1993,7 @@ impl ScopeAnalysis {
|
||||
let reg = self
|
||||
.reg_allocators
|
||||
.entry(captor.clone())
|
||||
.or_insert_with(|| RegAllocator::default())
|
||||
.or_insert_with(RegAllocator::default)
|
||||
.allocate(&name.sym);
|
||||
|
||||
Value::Register(reg)
|
||||
@@ -2037,7 +2008,7 @@ impl ScopeAnalysis {
|
||||
}
|
||||
|
||||
fn expand_effectively_const(&mut self) {
|
||||
for (_, name) in &mut self.names {
|
||||
for name in self.names.values_mut() {
|
||||
if !name.captures.is_empty() {
|
||||
name.effectively_const = true;
|
||||
}
|
||||
@@ -2047,7 +2018,7 @@ impl ScopeAnalysis {
|
||||
fn diagnose_const_mutations(&mut self) {
|
||||
let mut diagnostics = Vec::<Diagnostic>::new();
|
||||
|
||||
for (_, name) in &self.names {
|
||||
for name in self.names.values() {
|
||||
if !name.captures.is_empty() {
|
||||
// More specific diagnostics are emitted for these mutations elsewhere
|
||||
continue;
|
||||
@@ -2071,7 +2042,7 @@ impl ScopeAnalysis {
|
||||
let mut new_mutations = Vec::<(swc_common::Span, NameId)>::new();
|
||||
|
||||
for (span, name_id) in &self.optional_mutations {
|
||||
let name = self.names.get(&name_id).expect("Name not found");
|
||||
let name = self.names.get(name_id).expect("Name not found");
|
||||
|
||||
if !name.effectively_const {
|
||||
new_mutations.push((*span, name_id.clone()));
|
||||
@@ -2089,7 +2060,7 @@ impl ScopeAnalysis {
|
||||
fn diagnose_tdz_violations(&mut self) {
|
||||
let mut diagnostics = Vec::<Diagnostic>::new();
|
||||
|
||||
for (_, ref_) in &self.refs {
|
||||
for ref_ in self.refs.values() {
|
||||
let name = self.names.get(&ref_.name_id).expect("Name not found");
|
||||
|
||||
if ref_.owner_id != name.owner_id {
|
||||
|
||||
@@ -166,7 +166,7 @@ fn as_symbol_iterator(expr: &swc_ecma_ast::Expr) -> Option<Value> {
|
||||
_ => return None,
|
||||
}
|
||||
|
||||
return Some(Value::Builtin(Builtin {
|
||||
Some(Value::Builtin(Builtin {
|
||||
name: "SymbolIterator".to_string(),
|
||||
}));
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -101,15 +101,15 @@ impl TargetAccessor {
|
||||
}
|
||||
|
||||
pub fn compile_ident(ec: &mut ExpressionCompiler, ident: &swc_ecma_ast::Ident) -> TargetAccessor {
|
||||
return TargetAccessor::Register(ec.get_register_for_ident_mutation(ident));
|
||||
TargetAccessor::Register(ec.get_register_for_ident_mutation(ident))
|
||||
}
|
||||
|
||||
pub fn make_bad(ec: &mut ExpressionCompiler) -> TargetAccessor {
|
||||
return TargetAccessor::Register(ec.fnc.allocate_numbered_reg(&"_bad_lvalue".to_string()));
|
||||
TargetAccessor::Register(ec.fnc.allocate_numbered_reg("_bad_lvalue"))
|
||||
}
|
||||
|
||||
pub fn make_todo(ec: &mut ExpressionCompiler) -> TargetAccessor {
|
||||
return TargetAccessor::Register(ec.fnc.allocate_numbered_reg(&"_todo_lvalue".to_string()));
|
||||
TargetAccessor::Register(ec.fnc.allocate_numbered_reg("_todo_lvalue"))
|
||||
}
|
||||
|
||||
pub fn assign_and_packup(
|
||||
@@ -154,7 +154,7 @@ impl TargetAccessor {
|
||||
pub fn read(&self, ec: &mut ExpressionCompiler) -> Register {
|
||||
use TargetAccessor::*;
|
||||
|
||||
return match self {
|
||||
match self {
|
||||
Register(reg) => reg.clone(),
|
||||
Nested(nta) => {
|
||||
ec.fnc.push(Instruction::Sub(
|
||||
@@ -165,25 +165,21 @@ impl TargetAccessor {
|
||||
|
||||
nta.register.clone()
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register(&self) -> Register {
|
||||
use TargetAccessor::*;
|
||||
|
||||
return match self {
|
||||
Register(reg) => reg.clone(),
|
||||
Nested(nta) => nta.register.clone(),
|
||||
};
|
||||
match self {
|
||||
TargetAccessor::Register(reg) => reg.clone(),
|
||||
TargetAccessor::Nested(nta) => nta.register.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn direct_register(&self) -> Option<Register> {
|
||||
use TargetAccessor::*;
|
||||
|
||||
return match self {
|
||||
Register(reg) => Some(reg.clone()),
|
||||
Nested(_) => None,
|
||||
};
|
||||
match self {
|
||||
TargetAccessor::Register(reg) => Some(reg.clone()),
|
||||
TargetAccessor::Nested(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn packup(&mut self, ec: &mut ExpressionCompiler, uses_this_subcall: bool) {
|
||||
@@ -213,17 +209,17 @@ impl TargetAccessor {
|
||||
}
|
||||
|
||||
pub fn targets_this(&self) -> bool {
|
||||
return match self {
|
||||
match self {
|
||||
TargetAccessor::Register(reg) => reg == &Register::this(),
|
||||
TargetAccessor::Nested(nta) => nta.obj.targets_this(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_expr_type_str(expr: &swc_ecma_ast::Expr) -> &'static str {
|
||||
use swc_ecma_ast::Expr::*;
|
||||
|
||||
return match expr {
|
||||
match expr {
|
||||
This(_) => "This",
|
||||
Ident(_) => "Ident",
|
||||
Array(_) => "Array",
|
||||
@@ -261,5 +257,5 @@ pub fn get_expr_type_str(expr: &swc_ecma_ast::Expr) -> &'static str {
|
||||
JSXElement(_) => "JSXElement",
|
||||
JSXFragment(_) => "JSXFragment",
|
||||
TsInstantiation(_) => "TsInstantiation",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::asm::{
|
||||
|
||||
pub fn visit_pointers<Visitor>(module: &mut Module, visitor: Visitor)
|
||||
where
|
||||
Visitor: FnMut(PointerVisitation) -> (),
|
||||
Visitor: FnMut(PointerVisitation),
|
||||
{
|
||||
let mut pointer_visitor = VisitPointerImpl::new(visitor);
|
||||
pointer_visitor.module(module);
|
||||
@@ -19,14 +19,14 @@ pub enum PointerVisitation<'a> {
|
||||
|
||||
struct VisitPointerImpl<Visitor>
|
||||
where
|
||||
Visitor: FnMut(PointerVisitation) -> (),
|
||||
Visitor: FnMut(PointerVisitation),
|
||||
{
|
||||
visitor: Visitor,
|
||||
}
|
||||
|
||||
impl<Visitor> VisitPointerImpl<Visitor>
|
||||
where
|
||||
Visitor: FnMut(PointerVisitation) -> (),
|
||||
Visitor: FnMut(PointerVisitation),
|
||||
{
|
||||
fn new(visitor: Visitor) -> Self {
|
||||
Self { visitor }
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::{process::exit, rc::Rc};
|
||||
use valuescript_vm::{Bytecode, VirtualMachine};
|
||||
|
||||
pub fn main() {
|
||||
let mut vm = VirtualMachine::new();
|
||||
let mut vm = VirtualMachine::default();
|
||||
let result = vm.run(
|
||||
Rc::new(Bytecode::new(vec![
|
||||
//
|
||||
|
||||
@@ -3,6 +3,7 @@ use super::super::vs_value::{Val, ValTrait};
|
||||
use super::array_mapping_frame::{ArrayMappingFrame, ArrayMappingState};
|
||||
|
||||
pub static EVERY: NativeFrameFunction = NativeFrameFunction {
|
||||
#[allow(clippy::box_default)]
|
||||
make_frame: || Box::new(ArrayMappingFrame::new(Box::new(EveryState::default()))),
|
||||
};
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ use super::super::vs_value::{Val, ValTrait};
|
||||
use super::array_mapping_frame::{ArrayMappingFrame, ArrayMappingState};
|
||||
|
||||
pub static FILTER: NativeFrameFunction = NativeFrameFunction {
|
||||
#[allow(clippy::box_default)]
|
||||
make_frame: || Box::new(ArrayMappingFrame::new(Box::new(FilterState::default()))),
|
||||
};
|
||||
|
||||
@@ -19,7 +20,7 @@ impl ArrayMappingState for FilterState {
|
||||
self.filter_results.push(element.clone());
|
||||
}
|
||||
|
||||
return None;
|
||||
None
|
||||
}
|
||||
|
||||
fn finish(&mut self) -> Val {
|
||||
|
||||
@@ -3,6 +3,7 @@ use super::super::vs_value::{Val, ValTrait};
|
||||
use super::array_mapping_frame::{ArrayMappingFrame, ArrayMappingState};
|
||||
|
||||
pub static FIND: NativeFrameFunction = NativeFrameFunction {
|
||||
#[allow(clippy::box_default)]
|
||||
make_frame: || Box::new(ArrayMappingFrame::new(Box::new(FindState::default()))),
|
||||
};
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ use super::super::vs_value::{Val, ValTrait};
|
||||
use super::array_mapping_frame::{ArrayMappingFrame, ArrayMappingState};
|
||||
|
||||
pub static FIND_INDEX: NativeFrameFunction = NativeFrameFunction {
|
||||
#[allow(clippy::box_default)]
|
||||
make_frame: || Box::new(ArrayMappingFrame::new(Box::new(FindIndexState::default()))),
|
||||
};
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ use super::super::vs_value::{Val, ValTrait};
|
||||
use super::array_mapping_frame::{ArrayMappingFrame, ArrayMappingState};
|
||||
|
||||
pub static FLAT_MAP: NativeFrameFunction = NativeFrameFunction {
|
||||
#[allow(clippy::box_default)]
|
||||
make_frame: || Box::new(ArrayMappingFrame::new(Box::new(FlatMapState::default()))),
|
||||
};
|
||||
|
||||
@@ -24,7 +25,7 @@ impl ArrayMappingState for FlatMapState {
|
||||
}
|
||||
}
|
||||
|
||||
return None;
|
||||
None
|
||||
}
|
||||
|
||||
fn finish(&mut self) -> Val {
|
||||
|
||||
@@ -5,6 +5,7 @@ use super::super::vs_value::Val;
|
||||
use super::array_mapping_frame::{ArrayMappingFrame, ArrayMappingState};
|
||||
|
||||
pub static MAP: NativeFrameFunction = NativeFrameFunction {
|
||||
#[allow(clippy::box_default)]
|
||||
make_frame: || Box::new(ArrayMappingFrame::new(Box::new(MapState::default()))),
|
||||
};
|
||||
|
||||
@@ -16,7 +17,7 @@ struct MapState {
|
||||
impl ArrayMappingState for MapState {
|
||||
fn process(&mut self, _i: usize, _element: &Val, mapped: Val) -> Option<Val> {
|
||||
self.map_results.push(mapped);
|
||||
return None;
|
||||
None
|
||||
}
|
||||
|
||||
fn finish(&mut self) -> Val {
|
||||
|
||||
@@ -34,15 +34,15 @@ pub struct ArrayMappingFrame {
|
||||
|
||||
impl ArrayMappingFrame {
|
||||
pub fn new(state: Box<dyn ArrayMappingState>) -> ArrayMappingFrame {
|
||||
return ArrayMappingFrame {
|
||||
state: state,
|
||||
ArrayMappingFrame {
|
||||
state,
|
||||
early_exit: None,
|
||||
this: None,
|
||||
array_i: 0,
|
||||
mapper: Val::Void,
|
||||
this_arg: Val::Undefined,
|
||||
param_i: 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ impl StackFrameTrait for ArrayMappingFrame {
|
||||
self.early_exit = self
|
||||
.state
|
||||
.process(array_i, element, call_result.return_)
|
||||
.map(|v| Ok(v));
|
||||
.map(Ok);
|
||||
}
|
||||
|
||||
fn get_call_result(&mut self) -> CallResult {
|
||||
|
||||
@@ -3,6 +3,7 @@ use super::super::vs_value::{Val, ValTrait};
|
||||
use super::array_mapping_frame::{ArrayMappingFrame, ArrayMappingState};
|
||||
|
||||
pub static SOME: NativeFrameFunction = NativeFrameFunction {
|
||||
#[allow(clippy::box_default)]
|
||||
make_frame: || Box::new(ArrayMappingFrame::new(Box::new(SomeState::default()))),
|
||||
};
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ impl SortTreeNode {
|
||||
|
||||
let mid = vals.start + (vals.end - vals.start) / 2;
|
||||
|
||||
return SortTreeNode {
|
||||
SortTreeNode {
|
||||
data: SortTreeNodeData::Branch(
|
||||
Box::new(SortTreeNode::new(VecSlice {
|
||||
vec: vals.vec,
|
||||
@@ -97,33 +97,27 @@ impl SortTreeNode {
|
||||
end: vals.end,
|
||||
})),
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn get_compare_elements(&self) -> Option<(Val, Val)> {
|
||||
match &self.data {
|
||||
SortTreeNodeData::Branch(left, right) => {
|
||||
return left
|
||||
.get_compare_elements()
|
||||
.or_else(|| right.get_compare_elements());
|
||||
}
|
||||
SortTreeNodeData::Branch(left, right) => left
|
||||
.get_compare_elements()
|
||||
.or_else(|| right.get_compare_elements()),
|
||||
SortTreeNodeData::Sorting(_vals, left, right) => {
|
||||
let lval_opt = left.vec.get(left.pos);
|
||||
let rval_opt = right.vec.get(right.pos);
|
||||
|
||||
match (lval_opt, rval_opt) {
|
||||
(Some(lval), Some(rval)) => {
|
||||
return Some((lval.clone(), rval.clone()));
|
||||
}
|
||||
(Some(lval), Some(rval)) => Some((lval.clone(), rval.clone())),
|
||||
_ => {
|
||||
panic!("Failed to get compare elements from sorting state");
|
||||
}
|
||||
}
|
||||
}
|
||||
SortTreeNodeData::Sorted(_) => {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
SortTreeNodeData::Sorted(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_outcome(&mut self, should_swap: bool) {
|
||||
@@ -136,26 +130,23 @@ impl SortTreeNode {
|
||||
SortTreeNodeData::Sorted(left_vals) => {
|
||||
right.apply_outcome(should_swap);
|
||||
|
||||
match &mut right.data {
|
||||
SortTreeNodeData::Sorted(right_vals) => {
|
||||
let mut owned_left_vals = vec![];
|
||||
std::mem::swap(&mut owned_left_vals, left_vals);
|
||||
let mut owned_right_vals = vec![];
|
||||
std::mem::swap(&mut owned_right_vals, right_vals);
|
||||
if let SortTreeNodeData::Sorted(right_vals) = &mut right.data {
|
||||
let mut owned_left_vals = vec![];
|
||||
std::mem::swap(&mut owned_left_vals, left_vals);
|
||||
let mut owned_right_vals = vec![];
|
||||
std::mem::swap(&mut owned_right_vals, right_vals);
|
||||
|
||||
self.data = SortTreeNodeData::Sorting(
|
||||
vec![],
|
||||
VecPos {
|
||||
vec: owned_left_vals,
|
||||
pos: 0,
|
||||
},
|
||||
VecPos {
|
||||
vec: owned_right_vals,
|
||||
pos: 0,
|
||||
},
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
self.data = SortTreeNodeData::Sorting(
|
||||
vec![],
|
||||
VecPos {
|
||||
vec: owned_left_vals,
|
||||
pos: 0,
|
||||
},
|
||||
VecPos {
|
||||
vec: owned_right_vals,
|
||||
pos: 0,
|
||||
},
|
||||
);
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -220,12 +211,9 @@ impl StackFrameTrait for SortFrame {
|
||||
}
|
||||
|
||||
fn write_param(&mut self, param: Val) {
|
||||
match self.param_i {
|
||||
0 => {
|
||||
self.comparator = param;
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
if self.param_i == 0 {
|
||||
self.comparator = param;
|
||||
}
|
||||
|
||||
self.param_i += 1;
|
||||
}
|
||||
@@ -241,9 +229,7 @@ impl StackFrameTrait for SortFrame {
|
||||
Val::Void => {
|
||||
let array_data_mut = Rc::make_mut(array_data);
|
||||
|
||||
array_data_mut
|
||||
.elements
|
||||
.sort_by(|a, b| a.to_string().cmp(&b.to_string()));
|
||||
array_data_mut.elements.sort_by_key(|a| a.to_string());
|
||||
|
||||
return Ok(FrameStepOk::Pop(CallResult {
|
||||
return_: Val::Array(array_data.clone()),
|
||||
|
||||
@@ -81,10 +81,10 @@ pub fn op_sub_array_index(array: &mut Rc<VsArray>, index: usize) -> Result<Val,
|
||||
None => array.elements[index].clone(),
|
||||
};
|
||||
|
||||
return Ok(match res {
|
||||
Ok(match res {
|
||||
Val::Void => Val::Undefined,
|
||||
_ => res,
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
static AT: NativeFunction = native_fn(|this, params| {
|
||||
@@ -230,7 +230,7 @@ static FILL: NativeFunction = native_fn(|mut this, params| {
|
||||
static FLAT: NativeFunction = native_fn(|this, params| {
|
||||
Ok(match this.get() {
|
||||
Val::Array(array_data) => {
|
||||
if params.len() > 0 {
|
||||
if !params.is_empty() {
|
||||
return Err("TODO: .flat depth parameter".to_internal_error());
|
||||
}
|
||||
|
||||
@@ -300,7 +300,7 @@ static INDEX_OF: NativeFunction = native_fn(|this, params| {
|
||||
static JOIN: NativeFunction = native_fn(|this, params| {
|
||||
Ok(match this.get() {
|
||||
Val::Array(vals) => {
|
||||
if vals.elements.len() == 0 {
|
||||
if vals.elements.is_empty() {
|
||||
return Ok("".to_val());
|
||||
}
|
||||
|
||||
@@ -359,7 +359,7 @@ static POP: NativeFunction = native_fn(|mut this, _params| {
|
||||
|
||||
Ok(match this {
|
||||
Val::Array(array_data) => {
|
||||
if array_data.elements.len() == 0 {
|
||||
if array_data.elements.is_empty() {
|
||||
return Ok(Val::Undefined);
|
||||
}
|
||||
|
||||
@@ -396,7 +396,7 @@ static REVERSE: NativeFunction = native_fn(|mut this, _params| {
|
||||
|
||||
Ok(match this {
|
||||
Val::Array(array_data) => {
|
||||
if array_data.elements.len() == 0 {
|
||||
if array_data.elements.is_empty() {
|
||||
// Treating this as an edge case because rust protects us from
|
||||
// underflow when computing last below.
|
||||
return Ok(this.clone());
|
||||
@@ -423,7 +423,7 @@ static SHIFT: NativeFunction = native_fn(|mut this, _params| {
|
||||
|
||||
Ok(match this {
|
||||
Val::Array(array_data) => {
|
||||
if array_data.elements.len() == 0 {
|
||||
if array_data.elements.is_empty() {
|
||||
return Ok(Val::Undefined);
|
||||
}
|
||||
|
||||
@@ -496,9 +496,8 @@ static SPLICE: NativeFunction = native_fn(|mut this, params| {
|
||||
let replace_len = min(insert_len, delete_count);
|
||||
|
||||
if insert_len > replace_len {
|
||||
for i in 0..replace_len {
|
||||
array_data_mut.elements[start + i] = params[i + 2].clone();
|
||||
}
|
||||
array_data_mut.elements[start..(replace_len + start)]
|
||||
.clone_from_slice(¶ms[2..(replace_len + 2)]);
|
||||
|
||||
let gap = insert_len - replace_len;
|
||||
|
||||
@@ -510,13 +509,11 @@ static SPLICE: NativeFunction = native_fn(|mut this, params| {
|
||||
array_data_mut.elements[i + gap] = array_data_mut.elements[i].clone();
|
||||
}
|
||||
|
||||
for i in replace_len..insert_len {
|
||||
array_data_mut.elements[start + i] = params[i + 2].clone();
|
||||
}
|
||||
array_data_mut.elements[(replace_len + start)..(insert_len + start)]
|
||||
.clone_from_slice(¶ms[(replace_len + 2)..(insert_len + 2)]);
|
||||
} else {
|
||||
for i in 0..insert_len {
|
||||
array_data_mut.elements[start + i] = params[i + 2].clone();
|
||||
}
|
||||
array_data_mut.elements[start..(insert_len + start)]
|
||||
.clone_from_slice(¶ms[2..(insert_len + 2)]);
|
||||
|
||||
let gap = delete_count - insert_len;
|
||||
|
||||
@@ -547,11 +544,8 @@ static UNSHIFT: NativeFunction = native_fn(|mut this, params| {
|
||||
Val::Array(array_data) => {
|
||||
let array_data_mut = Rc::make_mut(array_data);
|
||||
|
||||
let mut i = 0;
|
||||
|
||||
for p in params {
|
||||
for (i, p) in params.into_iter().enumerate() {
|
||||
array_data_mut.elements.insert(i, p);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
Val::Number(array_data_mut.elements.len() as f64)
|
||||
|
||||
@@ -9,7 +9,8 @@ use crate::{
|
||||
};
|
||||
|
||||
use super::{
|
||||
builtin_object::BuiltinObject, range_error_builtin::ToRangeError, type_error_builtin::ToTypeError,
|
||||
builtin_object::BuiltinObject, internal_error_builtin::ToInternalError,
|
||||
range_error_builtin::ToRangeError, type_error_builtin::ToTypeError,
|
||||
};
|
||||
|
||||
pub struct ArrayBuiltin {}
|
||||
@@ -24,7 +25,7 @@ impl BuiltinObject for ArrayBuiltin {
|
||||
"isArray" => IS_ARRAY.to_val(),
|
||||
"from" => FROM.to_val(),
|
||||
"of" => OF.to_val(),
|
||||
_ => return Val::Undefined,
|
||||
_ => Val::Undefined,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +61,7 @@ static FROM: NativeFunction = native_fn(|_this, params| {
|
||||
};
|
||||
|
||||
if params.len() > 1 {
|
||||
return Err(format!("TODO: Using Array.from with a map function").to_val());
|
||||
return Err("TODO: Using Array.from with a map function".to_internal_error());
|
||||
}
|
||||
|
||||
Ok(match first_param {
|
||||
@@ -69,7 +70,9 @@ static FROM: NativeFunction = native_fn(|_this, params| {
|
||||
Val::Void | Val::Undefined | Val::Null | Val::CopyCounter(..) => {
|
||||
return Err("items is not iterable".to_type_error())
|
||||
}
|
||||
Val::Bool(..) | Val::Number(..) | Val::BigInt(..) | Val::Symbol(..) => VsArray::new().to_val(),
|
||||
Val::Bool(..) | Val::Number(..) | Val::BigInt(..) | Val::Symbol(..) => {
|
||||
VsArray::default().to_val()
|
||||
}
|
||||
Val::Object(..) | Val::Function(..) | Val::Class(..) | Val::Static(..) | Val::Dynamic(..) => {
|
||||
let len = first_param
|
||||
.sub(&"length".to_val())
|
||||
@@ -78,7 +81,7 @@ static FROM: NativeFunction = native_fn(|_this, params| {
|
||||
.to_number();
|
||||
|
||||
if len.is_sign_negative() || len.is_nan() {
|
||||
return Ok(VsArray::new().to_val());
|
||||
return Ok(VsArray::default().to_val());
|
||||
}
|
||||
|
||||
if len.is_infinite() {
|
||||
|
||||
@@ -127,15 +127,15 @@ pub static PARSE_INT: NativeFunction = native_fn(|_this, params| {
|
||||
return Ok(Val::Number(f64::NAN));
|
||||
}
|
||||
|
||||
let (is_negative, string_value) = if string_value.starts_with('-') {
|
||||
(true, &string_value[1..])
|
||||
let (is_negative, string_value) = if let Some(stripped) = string_value.strip_prefix('-') {
|
||||
(true, stripped)
|
||||
} else {
|
||||
(false, string_value.as_str())
|
||||
};
|
||||
|
||||
let string_value = match string_value.find(|c: char| !c.is_digit(radix as u32)) {
|
||||
Some(pos) => &string_value[..pos],
|
||||
None => &string_value,
|
||||
None => string_value,
|
||||
};
|
||||
|
||||
match i64::from_str_radix(string_value, radix as u32) {
|
||||
|
||||
@@ -51,7 +51,7 @@ impl BytecodeType {
|
||||
fn from_byte(byte: u8) -> BytecodeType {
|
||||
use BytecodeType::*;
|
||||
|
||||
return match byte {
|
||||
match byte {
|
||||
0x00 => End,
|
||||
0x01 => Void,
|
||||
0x02 => Undefined,
|
||||
@@ -74,7 +74,7 @@ impl BytecodeType {
|
||||
0x14 => GeneratorFunction,
|
||||
|
||||
_ => Unrecognized,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,19 +82,19 @@ impl BytecodeDecoder {
|
||||
pub fn decode_byte(&mut self) -> u8 {
|
||||
let byte = self.bytecode[self.pos];
|
||||
self.pos += 1;
|
||||
return byte;
|
||||
byte
|
||||
}
|
||||
|
||||
pub fn peek_byte(&self) -> u8 {
|
||||
return self.bytecode[self.pos];
|
||||
self.bytecode[self.pos]
|
||||
}
|
||||
|
||||
pub fn decode_type(&mut self) -> BytecodeType {
|
||||
return BytecodeType::from_byte(self.decode_byte());
|
||||
BytecodeType::from_byte(self.decode_byte())
|
||||
}
|
||||
|
||||
pub fn peek_type(&self) -> BytecodeType {
|
||||
return BytecodeType::from_byte(self.peek_byte());
|
||||
BytecodeType::from_byte(self.peek_byte())
|
||||
}
|
||||
|
||||
pub fn decode_val(&mut self, registers: &mut Vec<Val>) -> Val {
|
||||
@@ -171,7 +171,7 @@ impl BytecodeDecoder {
|
||||
pub fn decode_signed_byte(&mut self) -> i8 {
|
||||
let res = self.bytecode[self.pos] as i8;
|
||||
self.pos += 1;
|
||||
return res;
|
||||
res
|
||||
}
|
||||
|
||||
pub fn decode_number(&mut self) -> f64 {
|
||||
@@ -179,7 +179,7 @@ impl BytecodeDecoder {
|
||||
let next_pos = self.pos + 8;
|
||||
buf.clone_from_slice(&self.bytecode[self.pos..next_pos]);
|
||||
self.pos = next_pos;
|
||||
return f64::from_le_bytes(buf);
|
||||
f64::from_le_bytes(buf)
|
||||
}
|
||||
|
||||
pub fn decode_bigint(&mut self) -> BigInt {
|
||||
@@ -195,7 +195,7 @@ impl BytecodeDecoder {
|
||||
let bytes = &self.bytecode[self.pos..self.pos + len];
|
||||
self.pos += len;
|
||||
|
||||
return BigInt::from_bytes_le(sign, bytes);
|
||||
BigInt::from_bytes_le(sign, bytes)
|
||||
}
|
||||
|
||||
pub fn decode_string(&mut self) -> String {
|
||||
@@ -205,7 +205,7 @@ impl BytecodeDecoder {
|
||||
let res = String::from_utf8_lossy(&self.bytecode[start..end]).into_owned();
|
||||
self.pos = end;
|
||||
|
||||
return res;
|
||||
res
|
||||
}
|
||||
|
||||
pub fn decode_varsize_uint(&mut self) -> usize {
|
||||
@@ -227,7 +227,7 @@ impl BytecodeDecoder {
|
||||
pub fn decode_pos(&mut self) -> usize {
|
||||
// TODO: the number of bytes to represent a position should be based on the
|
||||
// size of the bytecode
|
||||
return self.decode_byte() as usize + 256 * self.decode_byte() as usize;
|
||||
self.decode_byte() as usize + 256 * self.decode_byte() as usize
|
||||
}
|
||||
|
||||
pub fn decode_register_index(&mut self) -> Option<usize> {
|
||||
@@ -238,14 +238,14 @@ impl BytecodeDecoder {
|
||||
return None;
|
||||
}
|
||||
|
||||
return Some(byte as usize);
|
||||
Some(byte as usize)
|
||||
}
|
||||
|
||||
pub fn clone_at(&self, pos: usize) -> BytecodeDecoder {
|
||||
return BytecodeDecoder {
|
||||
BytecodeDecoder {
|
||||
bytecode: self.bytecode.clone(),
|
||||
pos,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_pointer(&mut self, registers: &mut Vec<Val>) -> Val {
|
||||
@@ -267,12 +267,7 @@ impl BytecodeDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
let cached_val = self
|
||||
.bytecode
|
||||
.cache
|
||||
.borrow()
|
||||
.get(&pos)
|
||||
.map(|val| val.clone());
|
||||
let cached_val = self.bytecode.cache.borrow().get(&pos).cloned();
|
||||
|
||||
match cached_val {
|
||||
Some(val) => val,
|
||||
@@ -290,7 +285,7 @@ impl BytecodeDecoder {
|
||||
let register_count = self.decode_byte() as usize;
|
||||
let parameter_count = self.decode_byte() as usize;
|
||||
|
||||
return VsFunction {
|
||||
VsFunction {
|
||||
bytecode: self.bytecode.clone(),
|
||||
is_generator,
|
||||
register_count,
|
||||
@@ -298,10 +293,10 @@ impl BytecodeDecoder {
|
||||
start: self.pos,
|
||||
binds: Vec::new(),
|
||||
}
|
||||
.to_val();
|
||||
.to_val()
|
||||
}
|
||||
|
||||
pub fn decode_instruction(&mut self) -> InstructionByte {
|
||||
return InstructionByte::from_byte(self.decode_byte());
|
||||
InstructionByte::from_byte(self.decode_byte())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,10 +38,8 @@ impl BytecodeStackFrame {
|
||||
pub fn apply_unary_op(&mut self, op: fn(input: &Val) -> Val) {
|
||||
let input = self.decoder.decode_val(&mut self.registers);
|
||||
|
||||
let register_index = self.decoder.decode_register_index();
|
||||
|
||||
if register_index.is_some() {
|
||||
self.registers[register_index.unwrap()] = op(&input);
|
||||
if let Some(register_index) = self.decoder.decode_register_index() {
|
||||
self.registers[register_index] = op(&input);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,10 +140,9 @@ impl StackFrameTrait for BytecodeStackFrame {
|
||||
|
||||
Mov => {
|
||||
let val = self.decoder.decode_val(&mut self.registers);
|
||||
let register_index = self.decoder.decode_register_index();
|
||||
|
||||
if register_index.is_some() {
|
||||
self.registers[register_index.unwrap()] = val;
|
||||
if let Some(register_index) = self.decoder.decode_register_index() {
|
||||
self.registers[register_index] = val;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,11 +232,8 @@ impl StackFrameTrait for BytecodeStackFrame {
|
||||
self.decode_parameters(),
|
||||
)?;
|
||||
|
||||
match self.decoder.decode_register_index() {
|
||||
Some(return_target) => {
|
||||
self.registers[return_target] = res;
|
||||
}
|
||||
None => {}
|
||||
if let Some(return_target) = self.decoder.decode_register_index() {
|
||||
self.registers[return_target] = res;
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -277,24 +271,24 @@ impl StackFrameTrait for BytecodeStackFrame {
|
||||
let params = self.decoder.decode_val(&mut self.registers);
|
||||
let register_index = self.decoder.decode_register_index();
|
||||
|
||||
let params_array = params.as_array_data();
|
||||
let params_array = match params.as_array_data() {
|
||||
Some(params_array) => params_array,
|
||||
|
||||
if params_array.is_none() {
|
||||
// Not sure this needs to be an exception in future since compiled
|
||||
// code should never violate this
|
||||
return Err("bind params should always be array".to_internal_error());
|
||||
}
|
||||
None => return Err("bind params should always be array".to_internal_error()),
|
||||
};
|
||||
|
||||
let bound_fn = fn_val.bind((*params_array.unwrap()).elements.clone());
|
||||
let bound_fn = match fn_val.bind(params_array.elements.clone()) {
|
||||
Some(bound_fn) => bound_fn,
|
||||
|
||||
if bound_fn.is_none() {
|
||||
// Not sure this needs to be an exception in future since compiled
|
||||
// code should never violate this
|
||||
return Err("fn parameter of bind should always be bindable".to_internal_error());
|
||||
}
|
||||
None => return Err("fn parameter of bind should always be bindable".to_internal_error()),
|
||||
};
|
||||
|
||||
if register_index.is_some() {
|
||||
self.registers[register_index.unwrap()] = bound_fn.unwrap();
|
||||
if let Some(register_index) = register_index {
|
||||
self.registers[register_index] = bound_fn;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,11 +342,8 @@ impl StackFrameTrait for BytecodeStackFrame {
|
||||
|
||||
let res = native_fn(ThisWrapper::new(true, &mut obj), params)?;
|
||||
|
||||
match self.decoder.decode_register_index() {
|
||||
Some(return_target) => {
|
||||
self.registers[return_target] = res;
|
||||
}
|
||||
None => {}
|
||||
if let Some(return_target) = self.decoder.decode_register_index() {
|
||||
self.registers[return_target] = res;
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -388,11 +379,8 @@ impl StackFrameTrait for BytecodeStackFrame {
|
||||
params,
|
||||
)?;
|
||||
|
||||
match self.decoder.decode_register_index() {
|
||||
Some(return_target) => {
|
||||
self.registers[return_target] = res;
|
||||
}
|
||||
None => {}
|
||||
if let Some(return_target) = self.decoder.decode_register_index() {
|
||||
self.registers[return_target] = res;
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -471,11 +459,8 @@ impl StackFrameTrait for BytecodeStackFrame {
|
||||
self.decode_parameters(),
|
||||
)?;
|
||||
|
||||
match self.decoder.decode_register_index() {
|
||||
Some(target) => {
|
||||
self.registers[target] = instance;
|
||||
}
|
||||
None => {}
|
||||
if let Some(target) = self.decoder.decode_register_index() {
|
||||
self.registers[target] = instance;
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
@@ -10,12 +10,12 @@ pub struct FirstStackFrame {
|
||||
|
||||
impl FirstStackFrame {
|
||||
pub fn new() -> FirstStackFrame {
|
||||
return FirstStackFrame {
|
||||
FirstStackFrame {
|
||||
call_result: CallResult {
|
||||
return_: Val::Void,
|
||||
this: Val::Void,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,8 @@ impl StackFrameTrait for FirstStackFrame {
|
||||
}
|
||||
|
||||
fn get_call_result(&mut self) -> CallResult {
|
||||
return self.call_result.clone();
|
||||
// TODO: get_call_result(self) version? (Move memory variation)
|
||||
self.call_result.clone()
|
||||
}
|
||||
|
||||
fn catch_exception(&mut self, _exception: &mut Val) {
|
||||
|
||||
@@ -27,10 +27,10 @@ pub struct Generator {
|
||||
|
||||
impl Generator {
|
||||
pub fn new(frame: StackFrame) -> Generator {
|
||||
return Generator {
|
||||
Generator {
|
||||
frame,
|
||||
stack: vec![],
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ impl fmt::Display for Generator {
|
||||
// needing to copy.
|
||||
//
|
||||
static NEXT: NativeFrameFunction = NativeFrameFunction {
|
||||
make_frame: || Box::new(GeneratorFrame::default()),
|
||||
make_frame: || Box::<GeneratorFrame>::default(),
|
||||
};
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
@@ -151,12 +151,12 @@ impl StackFrameTrait for GeneratorFrame {
|
||||
return Err("Cannot call Generator.next on a const generator".to_type_error());
|
||||
}
|
||||
|
||||
let mut generator = dynamic_make_mut(&mut dynamic)
|
||||
let generator = dynamic_make_mut(&mut dynamic)
|
||||
.as_any_mut()
|
||||
.downcast_mut::<Generator>()
|
||||
.ok_or_else(|| "Generator.next called on different object".to_type_error())?;
|
||||
|
||||
self.generator = take(&mut generator);
|
||||
self.generator = take(generator);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -217,7 +217,7 @@ impl StackFrameTrait for GeneratorFrame {
|
||||
swap(&mut frame, &mut self.generator.frame);
|
||||
self.generator.stack.push(frame);
|
||||
|
||||
return Ok(FrameStepOk::Continue);
|
||||
Ok(FrameStepOk::Continue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ pub fn to_wrapping_index(index: Option<&Val>, len: usize) -> Option<usize> {
|
||||
return None;
|
||||
}
|
||||
|
||||
return Some(unchecked as usize);
|
||||
Some(unchecked as usize)
|
||||
}
|
||||
|
||||
pub fn to_wrapping_index_clamped(index: &Val, len: usize) -> isize {
|
||||
@@ -28,7 +28,7 @@ pub fn to_wrapping_index_clamped(index: &Val, len: usize) -> isize {
|
||||
return len as isize;
|
||||
}
|
||||
|
||||
return wrapping_index;
|
||||
wrapping_index
|
||||
}
|
||||
|
||||
pub fn to_unchecked_wrapping_index(index: &Val, len: usize) -> isize {
|
||||
@@ -43,5 +43,5 @@ pub fn to_unchecked_wrapping_index(index: &Val, len: usize) -> isize {
|
||||
|
||||
// TODO: Investigate potential pitfalls for arrays with length exceeding max
|
||||
// isize.
|
||||
return floored_index as isize;
|
||||
floored_index as isize
|
||||
}
|
||||
|
||||
@@ -70,10 +70,7 @@ impl ValTrait for IterationResult {
|
||||
}
|
||||
|
||||
fn has(&self, key: &Val) -> Option<bool> {
|
||||
Some(match key.to_string().as_str() {
|
||||
"value" | "done" => true,
|
||||
_ => false,
|
||||
})
|
||||
Some(matches!(key.to_string().as_str(), "value" | "done"))
|
||||
}
|
||||
|
||||
fn submov(&mut self, _key: &Val, _value: Val) -> Result<(), Val> {
|
||||
|
||||
@@ -60,7 +60,7 @@ impl StringIterator {
|
||||
value = (value << 6) | (next_byte & 0x3F) as u32;
|
||||
}
|
||||
|
||||
Some(std::char::from_u32(value as u32).expect("Invalid code point"))
|
||||
Some(std::char::from_u32(value).expect("Invalid code point"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ pub struct MakeGeneratorFrame {
|
||||
|
||||
impl MakeGeneratorFrame {
|
||||
pub fn new(frame: BytecodeStackFrame) -> MakeGeneratorFrame {
|
||||
return MakeGeneratorFrame { frame: Some(frame) };
|
||||
MakeGeneratorFrame { frame: Some(frame) }
|
||||
}
|
||||
|
||||
fn frame_mut(&mut self) -> &mut BytecodeStackFrame {
|
||||
|
||||
@@ -48,7 +48,7 @@ static TO_FIXED: NativeFunction = native_fn(|this, params| {
|
||||
|
||||
format!("{:.*}", precision as usize, number).to_val()
|
||||
}
|
||||
_ => return Err(format!("TODO: number indirection").to_val()),
|
||||
_ => return Err("TODO: number indirection".to_internal_error()),
|
||||
})
|
||||
});
|
||||
|
||||
@@ -72,8 +72,8 @@ static TO_EXPONENTIAL: NativeFunction = native_fn(|this, params| {
|
||||
});
|
||||
|
||||
static TODO_LOCALE: NativeFunction = native_fn(|this, _params| match this.get() {
|
||||
Val::Number(_number) => return Err("TODO: locale".to_internal_error()),
|
||||
_ => return Err("number indirection".to_internal_error()),
|
||||
Val::Number(_number) => Err("TODO: locale".to_internal_error()),
|
||||
_ => Err("number indirection".to_internal_error()),
|
||||
});
|
||||
|
||||
static TO_STRING: NativeFunction = native_fn(|this, params| {
|
||||
|
||||
@@ -45,7 +45,7 @@ pub fn op_plus(left: &Val, right: &Val) -> Result<Val, Val> {
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(Val::Number(left_prim.to_number() + right_prim.to_number()));
|
||||
Ok(Val::Number(left_prim.to_number() + right_prim.to_number()))
|
||||
}
|
||||
|
||||
pub fn op_unary_plus(input: &Val) -> Val {
|
||||
@@ -58,9 +58,7 @@ pub fn op_unary_plus(input: &Val) -> Val {
|
||||
pub fn op_minus(left: &Val, right: &Val) -> Result<Val, Val> {
|
||||
match (left.as_bigint_data(), right.as_bigint_data()) {
|
||||
(Some(left_bigint), Some(right_bigint)) => Ok(Val::BigInt(left_bigint - right_bigint)),
|
||||
(Some(_), None) | (None, Some(_)) => {
|
||||
return Err("Cannot mix BigInt with other types".to_type_error())
|
||||
}
|
||||
(Some(_), None) | (None, Some(_)) => Err("Cannot mix BigInt with other types".to_type_error()),
|
||||
_ => Ok(Val::Number(left.to_number() - right.to_number())),
|
||||
}
|
||||
}
|
||||
@@ -117,10 +115,7 @@ pub fn op_exp(left: &Val, right: &Val) -> Result<Val, Val> {
|
||||
|
||||
pub fn op_eq_impl(left: &Val, right: &Val) -> Result<bool, Val> {
|
||||
Ok(match (left, right) {
|
||||
(left, Val::Undefined | Val::Null) => match left {
|
||||
Val::Undefined | Val::Null => true,
|
||||
_ => false,
|
||||
},
|
||||
(left, Val::Undefined | Val::Null) => matches!(left, Val::Undefined | Val::Null),
|
||||
(Val::Bool(left_bool), Val::Bool(right_bool)) => left_bool == right_bool,
|
||||
(Val::Number(left_number), Val::Number(right_number)) => left_number == right_number,
|
||||
(Val::String(left_string), Val::String(right_string)) => left_string == right_string,
|
||||
@@ -132,7 +127,7 @@ pub fn op_eq_impl(left: &Val, right: &Val) -> Result<bool, Val> {
|
||||
}
|
||||
(Val::BigInt(left_bigint), Val::BigInt(right_bigint)) => left_bigint == right_bigint,
|
||||
(Val::Array(left_array), Val::Array(right_array)) => 'b: {
|
||||
if &**left_array as *const _ == &**right_array as *const _ {
|
||||
if std::ptr::eq(&**left_array, &**right_array) {
|
||||
break 'b true;
|
||||
}
|
||||
|
||||
@@ -155,7 +150,7 @@ pub fn op_eq_impl(left: &Val, right: &Val) -> Result<bool, Val> {
|
||||
return Err("TODO: class instance comparison".to_internal_error());
|
||||
}
|
||||
|
||||
if &**left_object as *const _ == &**right_object as *const _ {
|
||||
if std::ptr::eq(&**left_object, &**right_object) {
|
||||
break 'b true;
|
||||
}
|
||||
|
||||
@@ -234,7 +229,7 @@ pub fn op_triple_eq_impl(left: &Val, right: &Val) -> Result<bool, Val> {
|
||||
(Val::String(left_string), Val::String(right_string)) => left_string == right_string,
|
||||
(Val::BigInt(left_bigint), Val::BigInt(right_bigint)) => left_bigint == right_bigint,
|
||||
(Val::Array(left_array), Val::Array(right_array)) => 'b: {
|
||||
if &**left_array as *const _ == &**right_array as *const _ {
|
||||
if std::ptr::eq(&**left_array, &**right_array) {
|
||||
break 'b true;
|
||||
}
|
||||
|
||||
@@ -257,7 +252,7 @@ pub fn op_triple_eq_impl(left: &Val, right: &Val) -> Result<bool, Val> {
|
||||
return Err("TODO: class instance comparison".to_internal_error());
|
||||
}
|
||||
|
||||
if &**left_object as *const _ == &**right_object as *const _ {
|
||||
if std::ptr::eq(&**left_object, &**right_object) {
|
||||
break 'b true;
|
||||
}
|
||||
|
||||
@@ -319,7 +314,7 @@ pub fn op_or(left: &Val, right: &Val) -> Result<Val, Val> {
|
||||
}
|
||||
|
||||
pub fn op_not(input: &Val) -> Val {
|
||||
return Val::Bool(!input.is_truthy());
|
||||
Val::Bool(!input.is_truthy())
|
||||
}
|
||||
|
||||
pub fn op_less(left: &Val, right: &Val) -> Result<Val, Val> {
|
||||
@@ -330,10 +325,7 @@ pub fn op_less(left: &Val, right: &Val) -> Result<Val, Val> {
|
||||
(Val::Number(left_number), Val::Number(right_number)) => left_number < right_number,
|
||||
(Val::String(left_string), Val::String(right_string)) => left_string < right_string,
|
||||
(Val::BigInt(left_bigint), Val::BigInt(right_bigint)) => left_bigint < right_bigint,
|
||||
_ => match ecma_is_less_than(left, right) {
|
||||
None => false,
|
||||
Some(x) => x,
|
||||
},
|
||||
_ => ecma_is_less_than(left, right).unwrap_or(false),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -360,10 +352,7 @@ pub fn op_greater(left: &Val, right: &Val) -> Result<Val, Val> {
|
||||
(Val::Number(left_number), Val::Number(right_number)) => left_number > right_number,
|
||||
(Val::String(left_string), Val::String(right_string)) => left_string > right_string,
|
||||
(Val::BigInt(left_bigint), Val::BigInt(right_bigint)) => left_bigint > right_bigint,
|
||||
_ => match ecma_is_less_than(right, left) {
|
||||
None => false,
|
||||
Some(x) => x,
|
||||
},
|
||||
_ => ecma_is_less_than(right, left).unwrap_or(false),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -389,11 +378,11 @@ pub fn op_nullish_coalesce(left: &Val, right: &Val) -> Result<Val, Val> {
|
||||
}
|
||||
|
||||
pub fn op_optional_chain(left: &mut Val, right: &Val) -> Result<Val, Val> {
|
||||
return match left {
|
||||
match left {
|
||||
Val::Undefined | Val::Null => Ok(Val::Undefined),
|
||||
|
||||
_ => op_sub(left, right),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_i32(x: f64) -> i32 {
|
||||
@@ -403,7 +392,7 @@ pub fn to_i32(x: f64) -> i32 {
|
||||
|
||||
let int1 = (x.trunc() as i64) & 0xffffffff;
|
||||
|
||||
return int1 as i32;
|
||||
int1 as i32
|
||||
}
|
||||
|
||||
pub fn to_u32(x: f64) -> u32 {
|
||||
@@ -413,7 +402,7 @@ pub fn to_u32(x: f64) -> u32 {
|
||||
|
||||
let int1 = (x.trunc() as i64) & 0xffffffff;
|
||||
|
||||
return int1 as u32;
|
||||
int1 as u32
|
||||
}
|
||||
|
||||
pub fn op_bit_and(left: &Val, right: &Val) -> Result<Val, Val> {
|
||||
|
||||
@@ -282,20 +282,16 @@ static LAST_INDEX_OF: NativeFunction = native_fn(|this, params| {
|
||||
static TODO_LOCALE: NativeFunction = native_fn(|this, _params| {
|
||||
// TODO: Ok(...)
|
||||
match this.get() {
|
||||
Val::String(_string_data) => {
|
||||
return Err("TODO: locale".to_internal_error());
|
||||
}
|
||||
_ => return Err("string indirection".to_internal_error()),
|
||||
Val::String(_string_data) => Err("TODO: locale".to_internal_error()),
|
||||
_ => Err("string indirection".to_internal_error()),
|
||||
}
|
||||
});
|
||||
|
||||
static TODO_REGEXES: NativeFunction = native_fn(|this, _params| {
|
||||
// TODO: Ok(...)
|
||||
match this.get() {
|
||||
Val::String(_string_data) => {
|
||||
return Err("TODO: regexes".to_internal_error());
|
||||
}
|
||||
_ => return Err("string indirection".to_internal_error()),
|
||||
Val::String(_string_data) => Err("TODO: regexes".to_internal_error()),
|
||||
_ => Err("string indirection".to_internal_error()),
|
||||
}
|
||||
});
|
||||
|
||||
@@ -304,9 +300,9 @@ static NORMALIZE: NativeFunction = native_fn(|this, _params| {
|
||||
match this.get() {
|
||||
Val::String(_string_data) => {
|
||||
// Consider https://docs.rs/unicode-normalization/latest/unicode_normalization/
|
||||
return Err("TODO: normalize".to_internal_error());
|
||||
Err("TODO: normalize".to_internal_error())
|
||||
}
|
||||
_ => return Err("string indirection".to_internal_error()),
|
||||
_ => Err("string indirection".to_internal_error()),
|
||||
}
|
||||
});
|
||||
|
||||
@@ -459,9 +455,8 @@ static SLICE: NativeFunction = native_fn(|this, params| {
|
||||
// FIXME: This is a slow way of doing it. Part of the reason is that we're using rust's
|
||||
// string type, so we can't just find the relevant byte range and copy it in one go.
|
||||
for i in start..end {
|
||||
match unicode_at(string_bytes, end as usize, i as usize) {
|
||||
Some(c) => new_string.push(c),
|
||||
None => {}
|
||||
if let Some(c) = unicode_at(string_bytes, end as usize, i as usize) {
|
||||
new_string.push(c)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -603,9 +598,8 @@ static SUBSTRING: NativeFunction = native_fn(|this, params| {
|
||||
// FIXME: This is a slow way of doing it. Part of the reason is that we're using rust's
|
||||
// string type, so we can't just find the relevant byte range and copy it in one go.
|
||||
for i in substring_start..substring_end {
|
||||
match unicode_at(string_bytes, substring_end, i) {
|
||||
Some(c) => new_string.push(c),
|
||||
None => {}
|
||||
if let Some(c) = unicode_at(string_bytes, substring_end, i) {
|
||||
new_string.push(c)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -674,7 +668,7 @@ static VALUES: NativeFunction = native_fn(|this, _params| match this.get() {
|
||||
* - Successful match: Advances str_chars_param and returns true.
|
||||
* - Unsuccessful match: Does not advance str_chars_param and returns false.
|
||||
*/
|
||||
fn match_chars(str_chars_param: &mut Chars, matcher: &String) -> bool {
|
||||
fn match_chars(str_chars_param: &mut Chars, matcher: &str) -> bool {
|
||||
let mut str_chars = str_chars_param.clone();
|
||||
let mut matcher_chars = matcher.chars();
|
||||
|
||||
@@ -749,12 +743,8 @@ fn last_index_of(string_bytes: &[u8], search_bytes: &[u8], at_least_pos: usize)
|
||||
}
|
||||
|
||||
pub fn unicode_at(bytes: &[u8], len: usize, index: usize) -> Option<char> {
|
||||
match code_point_at(bytes, len, index) {
|
||||
Some(code_point) => Some(
|
||||
std::char::from_u32(code_point).expect("Invalid code point"), // TODO: Find out if this is reachable and what to do about it
|
||||
),
|
||||
None => None,
|
||||
}
|
||||
code_point_at(bytes, len, index)
|
||||
.map(|code_point| std::char::from_u32(code_point).expect("Invalid code point"))
|
||||
}
|
||||
|
||||
fn code_point_at(bytes: &[u8], len: usize, index: usize) -> Option<u32> {
|
||||
|
||||
@@ -13,6 +13,15 @@ pub struct VirtualMachine {
|
||||
pub stack: Vec<StackFrame>,
|
||||
}
|
||||
|
||||
impl Default for VirtualMachine {
|
||||
fn default() -> Self {
|
||||
VirtualMachine {
|
||||
frame: Box::new(FirstStackFrame::new()),
|
||||
stack: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtualMachine {
|
||||
pub fn run(
|
||||
&mut self,
|
||||
@@ -43,7 +52,7 @@ impl VirtualMachine {
|
||||
self.step()?;
|
||||
step_count += 1;
|
||||
|
||||
if self.stack.len() == 0 {
|
||||
if self.stack.is_empty() {
|
||||
return Ok(self.frame.get_call_result().return_);
|
||||
}
|
||||
}
|
||||
@@ -51,7 +60,7 @@ impl VirtualMachine {
|
||||
Err("step limit reached".to_internal_error())
|
||||
}
|
||||
None => {
|
||||
while self.stack.len() > 0 {
|
||||
while !self.stack.is_empty() {
|
||||
self.step()?;
|
||||
}
|
||||
|
||||
@@ -60,17 +69,6 @@ impl VirtualMachine {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new() -> VirtualMachine {
|
||||
let mut registers: Vec<Val> = Vec::with_capacity(2);
|
||||
registers.push(Val::Undefined);
|
||||
registers.push(Val::Undefined);
|
||||
|
||||
return VirtualMachine {
|
||||
frame: Box::new(FirstStackFrame::new()),
|
||||
stack: Default::default(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn step(&mut self) -> Result<(), Val> {
|
||||
let step_ok = match self.frame.step() {
|
||||
Ok(step_ok) => step_ok,
|
||||
|
||||
@@ -2,18 +2,14 @@ use std::rc::Rc;
|
||||
|
||||
use crate::vs_value::{ToVal, Val};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct VsArray {
|
||||
pub elements: Vec<Val>,
|
||||
pub elements: Vec<Val>, // TODO: VsArray(Vec<Val>)?
|
||||
}
|
||||
|
||||
impl VsArray {
|
||||
pub fn from(vals: Vec<Val>) -> VsArray {
|
||||
return VsArray { elements: vals };
|
||||
}
|
||||
|
||||
pub fn new() -> VsArray {
|
||||
return VsArray { elements: vec![] };
|
||||
VsArray { elements: vals }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,14 +27,14 @@ impl VsFunction {
|
||||
new_binds.push(p);
|
||||
}
|
||||
|
||||
return VsFunction {
|
||||
VsFunction {
|
||||
bytecode: self.bytecode.clone(),
|
||||
is_generator: self.is_generator,
|
||||
register_count: self.register_count,
|
||||
parameter_count: self.parameter_count,
|
||||
start: self.start,
|
||||
binds: new_binds,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_bytecode_frame(&self) -> BytecodeStackFrame {
|
||||
@@ -51,7 +51,7 @@ impl VsFunction {
|
||||
registers.push(Val::Void);
|
||||
}
|
||||
|
||||
return BytecodeStackFrame {
|
||||
BytecodeStackFrame {
|
||||
decoder: BytecodeDecoder {
|
||||
bytecode: self.bytecode.clone(),
|
||||
pos: self.start,
|
||||
@@ -63,7 +63,7 @@ impl VsFunction {
|
||||
this_target: None,
|
||||
return_target: None,
|
||||
catch_setting: None,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_frame(&self) -> StackFrame {
|
||||
|
||||
@@ -174,7 +174,7 @@ impl ValTrait for Val {
|
||||
fn typeof_(&self) -> VsType {
|
||||
use Val::*;
|
||||
|
||||
return match self {
|
||||
match self {
|
||||
Void => VsType::Undefined,
|
||||
Undefined => VsType::Undefined,
|
||||
Null => VsType::Null,
|
||||
@@ -190,13 +190,13 @@ impl ValTrait for Val {
|
||||
Static(val) => val.typeof_(),
|
||||
Dynamic(val) => val.typeof_(),
|
||||
CopyCounter(_) => VsType::Object,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn to_number(&self) -> f64 {
|
||||
use Val::*;
|
||||
|
||||
return match self {
|
||||
match self {
|
||||
Void => f64::NAN,
|
||||
Undefined => f64::NAN,
|
||||
Null => 0_f64,
|
||||
@@ -216,7 +216,7 @@ impl ValTrait for Val {
|
||||
Static(val) => val.to_number(),
|
||||
Dynamic(val) => val.to_number(),
|
||||
CopyCounter(_) => f64::NAN,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn to_index(&self) -> Option<usize> {
|
||||
@@ -247,7 +247,7 @@ impl ValTrait for Val {
|
||||
fn is_primitive(&self) -> bool {
|
||||
use Val::*;
|
||||
|
||||
return match self {
|
||||
match self {
|
||||
Void => true,
|
||||
Undefined => true,
|
||||
Null => true,
|
||||
@@ -263,13 +263,13 @@ impl ValTrait for Val {
|
||||
Static(val) => val.is_primitive(), // TODO: false?
|
||||
Dynamic(val) => val.is_primitive(),
|
||||
CopyCounter(_) => false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn is_truthy(&self) -> bool {
|
||||
use Val::*;
|
||||
|
||||
return match self {
|
||||
match self {
|
||||
Void => false,
|
||||
Undefined => false,
|
||||
Null => false,
|
||||
@@ -285,7 +285,7 @@ impl ValTrait for Val {
|
||||
Static(val) => val.is_truthy(), // TODO: true?
|
||||
Dynamic(val) => val.is_truthy(),
|
||||
CopyCounter(_) => true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn is_nullish(&self) -> bool {
|
||||
@@ -313,49 +313,49 @@ impl ValTrait for Val {
|
||||
fn bind(&self, params: Vec<Val>) -> Option<Val> {
|
||||
use Val::*;
|
||||
|
||||
return match self {
|
||||
match self {
|
||||
Function(f) => Some(f.bind(params).to_val()),
|
||||
Static(val) => val.bind(params),
|
||||
Dynamic(val) => val.bind(params),
|
||||
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: &BigInt ?
|
||||
fn as_bigint_data(&self) -> Option<BigInt> {
|
||||
use Val::*;
|
||||
|
||||
return match self {
|
||||
match self {
|
||||
BigInt(b) => Some(b.clone()),
|
||||
// TODO: Static? Others too?
|
||||
Dynamic(val) => val.as_bigint_data(),
|
||||
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn as_array_data(&self) -> Option<Rc<VsArray>> {
|
||||
use Val::*;
|
||||
|
||||
return match self {
|
||||
match self {
|
||||
Array(a) => Some(a.clone()),
|
||||
Dynamic(val) => val.as_array_data(),
|
||||
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn as_class_data(&self) -> Option<Rc<VsClass>> {
|
||||
use Val::*;
|
||||
|
||||
return match self {
|
||||
match self {
|
||||
Class(class) => Some(class.clone()),
|
||||
Static(s) => s.as_class_data(),
|
||||
Dynamic(val) => val.as_class_data(),
|
||||
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn load_function(&self) -> LoadFunctionResult {
|
||||
@@ -389,47 +389,46 @@ impl ValTrait for Val {
|
||||
Val::Array(array) => {
|
||||
let index = match key.to_index() {
|
||||
None => {
|
||||
return Some(match key.to_string().as_str() {
|
||||
"at" => true,
|
||||
"concat" => true,
|
||||
"copyWithin" => true,
|
||||
"entries" => true,
|
||||
"every" => true,
|
||||
"fill" => true,
|
||||
"filter" => true,
|
||||
"find" => true,
|
||||
"findIndex" => true,
|
||||
"flat" => true,
|
||||
"flatMap" => true,
|
||||
"includes" => true,
|
||||
"indexOf" => true,
|
||||
"join" => true,
|
||||
"keys" => true,
|
||||
"lastIndexOf" => true,
|
||||
"length" => true,
|
||||
"map" => true,
|
||||
"pop" => true,
|
||||
"push" => true,
|
||||
"reduce" => true,
|
||||
"reduceRight" => true,
|
||||
"reverse" => true,
|
||||
"shift" => true,
|
||||
"slice" => true,
|
||||
"some" => true,
|
||||
"sort" => true,
|
||||
"splice" => true,
|
||||
"toLocaleString" => true,
|
||||
"toString" => true,
|
||||
"unshift" => true,
|
||||
"values" => true,
|
||||
|
||||
_ => false,
|
||||
});
|
||||
return Some(matches!(
|
||||
key.to_string().as_str(),
|
||||
"at"
|
||||
| "concat"
|
||||
| "copyWithin"
|
||||
| "entries"
|
||||
| "every"
|
||||
| "fill"
|
||||
| "filter"
|
||||
| "find"
|
||||
| "findIndex"
|
||||
| "flat"
|
||||
| "flatMap"
|
||||
| "includes"
|
||||
| "indexOf"
|
||||
| "join"
|
||||
| "keys"
|
||||
| "lastIndexOf"
|
||||
| "length"
|
||||
| "map"
|
||||
| "pop"
|
||||
| "push"
|
||||
| "reduce"
|
||||
| "reduceRight"
|
||||
| "reverse"
|
||||
| "shift"
|
||||
| "slice"
|
||||
| "some"
|
||||
| "sort"
|
||||
| "splice"
|
||||
| "toLocaleString"
|
||||
| "toString"
|
||||
| "unshift"
|
||||
| "values"
|
||||
));
|
||||
}
|
||||
Some(i) => i,
|
||||
};
|
||||
|
||||
return Some(index < array.elements.len());
|
||||
Some(index < array.elements.len())
|
||||
}
|
||||
Val::Object(object) => match key {
|
||||
Val::Symbol(symbol) => {
|
||||
@@ -441,7 +440,7 @@ impl ValTrait for Val {
|
||||
return proto.has(key);
|
||||
}
|
||||
|
||||
return Some(false);
|
||||
Some(false)
|
||||
}
|
||||
_ => {
|
||||
if object.string_map.contains_key(&key.to_string()) {
|
||||
@@ -452,17 +451,14 @@ impl ValTrait for Val {
|
||||
return proto.has(key);
|
||||
}
|
||||
|
||||
return Some(false);
|
||||
Some(false)
|
||||
}
|
||||
},
|
||||
Val::Function(_) => Some(false),
|
||||
Val::Class(class) => class.static_.has(key),
|
||||
Val::Static(static_) => static_.has(key),
|
||||
Val::Dynamic(dynamic) => dynamic.has(key),
|
||||
Val::CopyCounter(_) => Some(match key.to_string().as_str() {
|
||||
"tag" | "count" => true,
|
||||
_ => false,
|
||||
}),
|
||||
Val::CopyCounter(_) => Some(matches!(key.to_string().as_str(), "tag" | "count")),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,7 +481,7 @@ impl ValTrait for Val {
|
||||
Val::Symbol(s) => format!("Symbol.{}", symbol_to_name(s.clone())),
|
||||
Val::String(str) => stringify_string(str),
|
||||
Val::Array(vals) => {
|
||||
if vals.elements.len() == 0 {
|
||||
if vals.elements.is_empty() {
|
||||
"[]".to_string()
|
||||
} else if vals.elements.len() == 1 {
|
||||
"[".to_string() + vals.elements[0].codify().as_str() + "]"
|
||||
@@ -508,17 +504,14 @@ impl ValTrait for Val {
|
||||
let mut res = String::new();
|
||||
|
||||
if let Some(proto) = &object.prototype {
|
||||
match proto.sub(&"name".to_val()) {
|
||||
Ok(name) => {
|
||||
if name.typeof_() == VsType::String {
|
||||
res += &name.to_string();
|
||||
}
|
||||
if let Ok(name) = proto.sub(&"name".to_val()) {
|
||||
if name.typeof_() == VsType::String {
|
||||
res += &name.to_string();
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
if object.string_map.len() == 0 {
|
||||
if object.string_map.is_empty() {
|
||||
res += "{}";
|
||||
return res;
|
||||
}
|
||||
@@ -580,7 +573,7 @@ impl fmt::Display for Val {
|
||||
Symbol(s) => write!(f, "Symbol(Symbol.{})", symbol_to_name(s.clone())),
|
||||
String(s) => s.fmt(f),
|
||||
Array(vals) => {
|
||||
if vals.elements.len() == 0 {
|
||||
if vals.elements.is_empty() {
|
||||
Ok(())
|
||||
} else if vals.elements.len() == 1 {
|
||||
vals.elements[0].fmt(f)
|
||||
@@ -716,7 +709,7 @@ impl<'a> std::fmt::Display for PrettyVal<'a> {
|
||||
Val::Symbol(_) => write!(f, "\x1b[32m{}\x1b[39m", self.val.codify()),
|
||||
Val::String(_) => write!(f, "\x1b[32m{}\x1b[39m", self.val.codify()),
|
||||
Val::Array(array) => {
|
||||
if array.elements.len() == 0 {
|
||||
if array.elements.is_empty() {
|
||||
return write!(f, "[]");
|
||||
}
|
||||
|
||||
@@ -738,17 +731,14 @@ impl<'a> std::fmt::Display for PrettyVal<'a> {
|
||||
}
|
||||
Val::Object(object) => {
|
||||
if let Some(proto) = &object.prototype {
|
||||
match proto.sub(&"name".to_val()) {
|
||||
Ok(name) => {
|
||||
if name.typeof_() == VsType::String {
|
||||
write!(f, "{} ", name)?;
|
||||
}
|
||||
if let Ok(name) = proto.sub(&"name".to_val()) {
|
||||
if name.typeof_() == VsType::String {
|
||||
write!(f, "{} ", name)?;
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
if object.string_map.len() == 0 {
|
||||
if object.string_map.is_empty() {
|
||||
return f.write_str("{}");
|
||||
}
|
||||
|
||||
@@ -795,7 +785,7 @@ pub fn number_to_index(x: f64) -> Option<usize> {
|
||||
return None;
|
||||
}
|
||||
|
||||
return Some(x as usize);
|
||||
Some(x as usize)
|
||||
}
|
||||
|
||||
fn stringify_string(str: &str) -> String {
|
||||
|
||||
@@ -82,8 +82,8 @@ fn run_to_result(entry_point: &str, read_file: &js_sys::Function, args: &str) ->
|
||||
|
||||
let diagnostic_len = compile_result
|
||||
.diagnostics
|
||||
.iter()
|
||||
.map(|(_, v)| v.len())
|
||||
.values()
|
||||
.map(|v| v.len())
|
||||
.sum::<usize>();
|
||||
|
||||
if diagnostic_len > 0 {
|
||||
@@ -109,17 +109,16 @@ fn run_to_result(entry_point: &str, read_file: &js_sys::Function, args: &str) ->
|
||||
|
||||
let bytecode = Rc::new(Bytecode::new(assemble(&module)));
|
||||
|
||||
match VirtualMachine::read_default_export(bytecode.clone()).load_function() {
|
||||
LoadFunctionResult::NotAFunction => {
|
||||
return RunResult {
|
||||
diagnostics: HashMap::default(),
|
||||
output: Ok("(Default export is not a function)".into()),
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
if let LoadFunctionResult::NotAFunction =
|
||||
VirtualMachine::read_default_export(bytecode.clone()).load_function()
|
||||
{
|
||||
return RunResult {
|
||||
diagnostics: HashMap::default(),
|
||||
output: Ok("(Default export is not a function)".into()),
|
||||
};
|
||||
};
|
||||
|
||||
let mut vm = VirtualMachine::new();
|
||||
let mut vm = VirtualMachine::default();
|
||||
|
||||
let val_args: Vec<Val> = match parse_args(args) {
|
||||
Ok(args) => args,
|
||||
|
||||
@@ -24,10 +24,10 @@ pub fn compile_command(args: &Vec<String>) {
|
||||
let mut file = File::create("out.vsm").expect("Couldn't create out.vsm");
|
||||
|
||||
file
|
||||
.write(module.to_string().as_bytes())
|
||||
.write_all(module.to_string().as_bytes())
|
||||
.expect("Failed to write out.vsm");
|
||||
|
||||
file.write(b"\n").expect("Failed to write out.vsm");
|
||||
file.write_all(b"\n").expect("Failed to write out.vsm");
|
||||
}
|
||||
|
||||
for (path, diagnostics) in compile_result.diagnostics.iter() {
|
||||
|
||||
@@ -85,7 +85,7 @@ pub fn handle_diagnostics_cli(file_path: &String, diagnostics: &Vec<Diagnostic>)
|
||||
}
|
||||
}
|
||||
|
||||
fn pos_to_line_col(text: &String, pos: u32) -> (u32, u32) {
|
||||
fn pos_to_line_col(text: &str, pos: u32) -> (u32, u32) {
|
||||
let mut line = 1u32;
|
||||
let mut col = 1u32;
|
||||
|
||||
|
||||
@@ -13,7 +13,5 @@ pub fn resolve_entry_path(entry_path: &String) -> ResolvedPath {
|
||||
.to_string(),
|
||||
};
|
||||
|
||||
let resolved_entry_path = resolve_path(&cwd_file, entry_path);
|
||||
|
||||
resolved_entry_path
|
||||
resolve_path(&cwd_file, entry_path)
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ pub fn run_command(args: &Vec<String>) {
|
||||
|
||||
let bytecode = Rc::new(to_bytecode(format, file_path));
|
||||
|
||||
let mut vm = VirtualMachine::new();
|
||||
let mut vm = VirtualMachine::default();
|
||||
|
||||
let val_args: Vec<Val> = args[argpos..]
|
||||
.iter()
|
||||
|
||||
@@ -30,8 +30,7 @@ mod tests {
|
||||
|
||||
let mut failed_paths = HashSet::<PathBuf>::new();
|
||||
|
||||
let mut files =
|
||||
get_files_recursively(&input_dir_path.to_path_buf()).expect("Failed to get files");
|
||||
let mut files = get_files_recursively(&input_dir_path).expect("Failed to get files");
|
||||
|
||||
files.sort();
|
||||
|
||||
@@ -113,7 +112,7 @@ mod tests {
|
||||
failed_paths.insert(rel_file_path.clone());
|
||||
}
|
||||
|
||||
let mut vm = VirtualMachine::new();
|
||||
let mut vm = VirtualMachine::default();
|
||||
|
||||
let result = vm.run(bytecode, Some(2_000_000), &[]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user