diff --git a/mica-cli/src/main.rs b/mica-cli/src/main.rs index 638050a..8433ab4 100644 --- a/mica-cli/src/main.rs +++ b/mica-cli/src/main.rs @@ -88,7 +88,10 @@ fn interpret<'e>( fn engine(options: &EngineOptions) -> Engine { Engine::with_debug_options( mica::corelib::Lib, - mica::DebugOptions { dump_ast: options.dump_ast, dump_bytecode: options.dump_bytecode }, + mica::DebugOptions { + dump_ast: options.dump_ast, + dump_bytecode: options.dump_bytecode, + }, ) } diff --git a/rustfmt.toml b/rustfmt.toml deleted file mode 100644 index 7bbe299..0000000 --- a/rustfmt.toml +++ /dev/null @@ -1,8 +0,0 @@ -use_small_heuristics = "Max" - -wrap_comments = true -comment_width = 100 -imports_granularity = "Crate" -group_imports = "StdExternalCrate" -format_macro_matchers = true -format_macro_bodies = true diff --git a/src/corelib/builtins/list.rs b/src/corelib/builtins/list.rs index 7b137d2..859ca21 100644 --- a/src/corelib/builtins/list.rs +++ b/src/corelib/builtins/list.rs @@ -16,20 +16,29 @@ pub(crate) fn define(builder: TypeBuilder>) -> TypeBuilder().as_slice() + arguments + .raw_self() + .downcast_user_data_unchecked::() + .as_slice() }; let index = arguments.nth(0).unwrap().ensure_number()? as usize; Ok(v.get(index).copied().unwrap_or(RawValue::from(()))) })), ) - .add_function("set", |v: &mut Vec, index: usize, value: RawValue| { - if index < v.len() { - v[index] = value; - Ok(value) - } else { - Err(OutOfBounds { index, len: v.len() }) - } - }) + .add_function( + "set", + |v: &mut Vec, index: usize, value: RawValue| { + if index < v.len() { + v[index] = value; + Ok(value) + } else { + Err(OutOfBounds { + index, + len: v.len(), + }) + } + }, + ) .add_function("first", |v: &Vec| v.first().copied()) .add_function("last", |v: &Vec| v.last().copied()) .add_function("contains", |v: &Vec, x: RawValue| v.contains(&x)) @@ -44,9 +53,15 @@ pub(crate) fn define(builder: TypeBuilder>) -> TypeBuilder, n: usize| v.repeat(n)) .add_function("reverse", |v: &mut Vec| v.reverse()) - .add_function("rotate_left", |v: &mut Vec, n: usize| v.rotate_left(n)) - .add_function("rotate_right", |v: &mut Vec, n: usize| v.rotate_right(n)) - .add_function("swap", |v: &mut Vec, a: usize, b: usize| v.swap(a, b)) + .add_function("rotate_left", |v: &mut Vec, n: usize| { + v.rotate_left(n) + }) + .add_function("rotate_right", |v: &mut Vec, n: usize| { + v.rotate_right(n) + }) + .add_function("swap", |v: &mut Vec, a: usize, b: usize| { + v.swap(a, b) + }) .add_function("clone", |v: &Vec| v.clone()) // TODO: It should be possible to implement this without raw functions in the future. .add_raw_function( diff --git a/src/corelib/builtins/string.rs b/src/corelib/builtins/string.rs index f28b50b..f8e5b61 100644 --- a/src/corelib/builtins/string.rs +++ b/src/corelib/builtins/string.rs @@ -14,7 +14,9 @@ pub(crate) fn define(builder: TypeBuilder) -> TypeBuilder { builder .add_static("debug", |x: Value| format!("{x:?}")) .add_function("cat", |s: &String, t: Gc| format!("{s}{t}")) - .add_function("contains", |s: &String, sub: Gc| s.contains(sub.deref().deref())) + .add_function("contains", |s: &String, sub: Gc| { + s.contains(sub.deref().deref()) + }) .add_function("starts_with", |s: &String, prefix: Gc| { s.starts_with(prefix.deref().deref()) }) @@ -27,11 +29,19 @@ pub(crate) fn define(builder: TypeBuilder) -> TypeBuilder { .add_function("strip_suffix", |s: &String, suffix: Gc| { s.strip_suffix(suffix.deref().deref()).map(|x| x.to_owned()) }) - .add_function("find", |s: &String, substr: Gc| s.find(substr.deref().deref())) - .add_function("rfind", |s: &String, substr: Gc| s.rfind(substr.deref().deref())) - .add_function("byte_at", |s: &String, position: usize| s.as_bytes().get(position).copied()) + .add_function("find", |s: &String, substr: Gc| { + s.find(substr.deref().deref()) + }) + .add_function("rfind", |s: &String, substr: Gc| { + s.rfind(substr.deref().deref()) + }) + .add_function("byte_at", |s: &String, position: usize| { + s.as_bytes().get(position).copied() + }) .add_function("byte_len", |s: &String| s.len()) - .add_function("nth_char", |s: &String, position: usize| s.chars().nth(position)) + .add_function("nth_char", |s: &String, position: usize| { + s.chars().nth(position) + }) .add_function("nth_code_point", |s: &String, position: usize| { s.chars().nth(position).map(u32::from) }) @@ -40,12 +50,16 @@ pub(crate) fn define(builder: TypeBuilder) -> TypeBuilder { .add_function("to_lowercase", |s: &String| s.to_lowercase()) .add_function("to_uppercase", |s: &String| s.to_uppercase()) .add_function("repeat", |s: &String, n: usize| s.repeat(n)) - .add_function("replace", |s: &String, pat: Gc, with: Gc| { - s.replace(pat.deref().deref(), &with) - }) - .add_function("replace", |s: &String, pat: Gc, with: Gc, n: usize| { - s.replacen(pat.deref().deref(), &with, n) - }) + .add_function( + "replace", + |s: &String, pat: Gc, with: Gc| s.replace(pat.deref().deref(), &with), + ) + .add_function( + "replace", + |s: &String, pat: Gc, with: Gc, n: usize| { + s.replacen(pat.deref().deref(), &with, n) + }, + ) .add_function("trim", |s: &String| s.trim().to_owned()) // TODO: It should be possible to implement these without raw functions in the future. .add_raw_function( diff --git a/src/corelib/core.rs b/src/corelib/core.rs index 603bdf7..66b4ac0 100644 --- a/src/corelib/core.rs +++ b/src/corelib/core.rs @@ -49,8 +49,9 @@ fn error(arguments: Arguments) -> Result<(), UserError> { fn assert(condition: Value, message: Option) -> Result { if condition.is_falsy() { - let message = - message.map(|value| value.to_string()).unwrap_or_else(|| "assertion failed".to_owned()); + let message = message + .map(|value| value.to_string()) + .unwrap_or_else(|| "assertion failed".to_owned()); Err(message).mica() } else { Ok(condition) diff --git a/src/corelib/iterators/counters.rs b/src/corelib/iterators/counters.rs index 577c399..3321d1a 100644 --- a/src/corelib/iterators/counters.rs +++ b/src/corelib/iterators/counters.rs @@ -10,7 +10,11 @@ struct CountUp { impl CountUp { fn with_step(min: i64, max: i64, step: i64) -> Self { - Self { current: min, max, step } + Self { + current: min, + max, + step, + } } fn new(min: i64, max: i64) -> Self { @@ -38,7 +42,11 @@ struct CountDown { impl CountDown { fn with_step(max: i64, min: i64, step: i64) -> Self { - Self { current: max, min, step } + Self { + current: max, + min, + step, + } } fn new(max: i64, min: i64) -> Self { diff --git a/src/corelib/iterators/dict.rs b/src/corelib/iterators/dict.rs index 085d177..f4c0998 100644 --- a/src/corelib/iterators/dict.rs +++ b/src/corelib/iterators/dict.rs @@ -17,7 +17,11 @@ pub(crate) struct DictIter { impl DictIter { pub(crate) unsafe fn new(value: RawValue) -> Self { let dict = value.downcast_user_data_unchecked::(); - Self { dict: value, iter: dict.raw_iter(), len: dict.len() } + Self { + dict: value, + iter: dict.raw_iter(), + len: dict.len(), + } } fn checked_next( @@ -29,7 +33,10 @@ impl DictIter { // otherwise the iterator becomes invalid. let current_len = unsafe { dict.downcast_user_data_unchecked::().len() }; if len != current_len { - return Err(LenChangedDuringIteration { was: len, became: current_len }); + return Err(LenChangedDuringIteration { + was: len, + became: current_len, + }); } Ok(iter.next()) } @@ -63,7 +70,11 @@ struct LenChangedDuringIteration { impl std::fmt::Display for LenChangedDuringIteration { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "dict length changed during iteration (was {}, became {})", self.was, self.became) + write!( + f, + "dict length changed during iteration (was {}, became {})", + self.was, self.became + ) } } diff --git a/src/corelib/iterators/list.rs b/src/corelib/iterators/list.rs index 0704462..6e58f96 100644 --- a/src/corelib/iterators/list.rs +++ b/src/corelib/iterators/list.rs @@ -13,7 +13,11 @@ pub(crate) struct ListIter { impl ListIter { pub(crate) unsafe fn new(list: RawValue) -> Self { let slice = unsafe { list.downcast_user_data_unchecked::().as_slice() }; - ListIter { list, i: 0, len: slice.len() } + ListIter { + list, + i: 0, + len: slice.len(), + } } fn has_next(&self) -> bool { @@ -25,7 +29,10 @@ impl ListIter { let list = self.list.downcast_user_data_unchecked::(); let slice = list.as_slice(); if slice.len() != self.len { - return Err(LenChangedDuringIteration { was: self.len, became: slice.len() }); + return Err(LenChangedDuringIteration { + was: self.len, + became: slice.len(), + }); } if let Some(v) = slice.get(self.i) { self.i += 1; @@ -51,7 +58,11 @@ struct LenChangedDuringIteration { impl std::fmt::Display for LenChangedDuringIteration { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "list length changed during iteration (was {}, became {})", self.was, self.became) + write!( + f, + "list length changed during iteration (was {}, became {})", + self.was, self.became + ) } } diff --git a/src/corelib/iterators/string/bytes.rs b/src/corelib/iterators/string/bytes.rs index 037456f..6d09108 100644 --- a/src/corelib/iterators/string/bytes.rs +++ b/src/corelib/iterators/string/bytes.rs @@ -7,7 +7,10 @@ pub(crate) struct StringBytes { impl StringBytes { pub unsafe fn new(s: RawValue) -> Self { - Self { string: s, index: 0 } + Self { + string: s, + index: 0, + } } fn has_next(&self) -> bool { diff --git a/src/corelib/iterators/string/chars.rs b/src/corelib/iterators/string/chars.rs index da9e388..0cd30c1 100644 --- a/src/corelib/iterators/string/chars.rs +++ b/src/corelib/iterators/string/chars.rs @@ -7,7 +7,10 @@ pub(crate) struct StringChars { impl StringChars { pub unsafe fn new(s: RawValue) -> Self { - Self { string: s, index: 0 } + Self { + string: s, + index: 0, + } } fn has_next(&self) -> bool { diff --git a/src/corelib/iterators/string/code_points.rs b/src/corelib/iterators/string/code_points.rs index 9f24e78..dc6eb6f 100644 --- a/src/corelib/iterators/string/code_points.rs +++ b/src/corelib/iterators/string/code_points.rs @@ -7,7 +7,10 @@ pub(crate) struct StringCodePoints { impl StringCodePoints { pub unsafe fn new(s: RawValue) -> Self { - Self { string: s, index: 0 } + Self { + string: s, + index: 0, + } } fn has_next(&self) -> bool { diff --git a/src/corelib/iterators/string/lines.rs b/src/corelib/iterators/string/lines.rs index 01e3859..8366860 100644 --- a/src/corelib/iterators/string/lines.rs +++ b/src/corelib/iterators/string/lines.rs @@ -7,7 +7,10 @@ pub(crate) struct StringLines { impl StringLines { pub unsafe fn new(s: RawValue) -> Self { - Self { string: s, index: 0 } + Self { + string: s, + index: 0, + } } fn has_next(&self) -> bool { diff --git a/src/corelib/iterators/string/rsplit.rs b/src/corelib/iterators/string/rsplit.rs index e65cc27..abe2cd2 100644 --- a/src/corelib/iterators/string/rsplit.rs +++ b/src/corelib/iterators/string/rsplit.rs @@ -10,7 +10,11 @@ pub(crate) struct StringRSplit { impl StringRSplit { pub unsafe fn new(s: RawValue, separator: Gc) -> Self { - Self { string: s, separator, index: unsafe { s.get_raw_string_unchecked().get().len() } } + Self { + string: s, + separator, + index: unsafe { s.get_raw_string_unchecked().get().len() }, + } } fn has_next(&self) -> bool { diff --git a/src/corelib/iterators/string/split.rs b/src/corelib/iterators/string/split.rs index 67251bc..56031a7 100644 --- a/src/corelib/iterators/string/split.rs +++ b/src/corelib/iterators/string/split.rs @@ -10,7 +10,11 @@ pub(crate) struct StringSplit { impl StringSplit { pub unsafe fn new(s: RawValue, separator: Gc) -> Self { - Self { string: s, separator, index: 0 } + Self { + string: s, + separator, + index: 0, + } } fn has_next(&self) -> bool { diff --git a/src/hl/engine.rs b/src/hl/engine.rs index e28e62a..4a504f5 100644 --- a/src/hl/engine.rs +++ b/src/hl/engine.rs @@ -136,7 +136,10 @@ impl Engine { builtin_traits: &BuiltinTraits, identifier: &str, ) -> Gc { - let fields = identifier.split('+').enumerate().map(|(index, name)| (name, index)); + let fields = identifier + .split('+') + .enumerate() + .map(|(index, name)| (name, index)); let type_name = if identifier.is_empty() { String::from("Record{}") } else { @@ -182,7 +185,9 @@ impl Engine { records: vec![], records_by_identifier: HashMap::new(), }, - Box::new(DtableGenerator { corelib: corelib.clone() }), + Box::new(DtableGenerator { + corelib: corelib.clone(), + }), builtin_traits, ); @@ -195,7 +200,13 @@ impl Engine { let iterator = create_trait_value(&mut env, &mut gc, library.builtin_traits.iterator); - let mut engine = Self { env, library, globals: Globals::new(), gc, debug_options }; + let mut engine = Self { + env, + library, + globals: Globals::new(), + gc, + debug_options, + }; // Unwrapping here is fine because at this point we haven't got quite that many globals // registered to overflow an Opr24. engine.set_built_type(&nil).unwrap(); @@ -205,7 +216,9 @@ impl Engine { engine.set_built_type(&list).unwrap(); engine.set("Iterator", iterator).unwrap(); - corelib.load(&mut engine).expect("corelib failed to load (in CoreLibrary::load)"); + corelib + .load(&mut engine) + .expect("corelib failed to load (in CoreLibrary::load)"); engine } @@ -247,7 +260,10 @@ impl Engine { eprintln!("{main_chunk:#?}"); } - Ok(Script { engine: self, main_chunk }) + Ok(Script { + engine: self, + main_chunk, + }) } /// Compiles and starts executing a script in a fiber. @@ -298,8 +314,11 @@ impl Engine { where T: TryFromValue, { - let stack: Vec<_> = - Some(function).into_iter().chain(arguments).map(|x| x.to_raw(&mut self.gc)).collect(); + let stack: Vec<_> = Some(function) + .into_iter() + .chain(arguments) + .map(|x| x.to_raw(&mut self.gc)) + .collect(); // Having to construct a chunk here isn't the most clean, but it's the simplest way of // making the VM perform a function call. It reuses sanity checks such as ensuring // `function` can actually be called. @@ -312,7 +331,10 @@ impl Engine { )); chunk.emit(Opcode::Halt); let chunk = Rc::new(chunk); - let fiber = Fiber { engine: self, inner: vm::Fiber::new(chunk, stack) }; + let fiber = Fiber { + engine: self, + inner: vm::Fiber::new(chunk, stack), + }; fiber.trampoline() } @@ -381,8 +403,11 @@ impl Engine { // Unwrapping here is fine because `to_method_id` ensures that a method with a given ID // exists. let signature = self.env.get_method_signature(method_id.0).unwrap(); - let stack: Vec<_> = - Some(receiver).into_iter().chain(arguments).map(|x| x.to_raw(&mut self.gc)).collect(); + let stack: Vec<_> = Some(receiver) + .into_iter() + .chain(arguments) + .map(|x| x.to_raw(&mut self.gc)) + .collect(); let argument_count = MethodParameterCount::from_count_with_self( u8::try_from(stack.len()).map_err(|_| Error::TooManyArguments)?, ); @@ -399,7 +424,10 @@ impl Engine { )); chunk.emit(Opcode::Halt); let chunk = Rc::new(chunk); - let fiber = Fiber { engine: self, inner: vm::Fiber::new(chunk, stack) }; + let fiber = Fiber { + engine: self, + inner: vm::Fiber::new(chunk, stack), + }; fiber.trampoline() } @@ -502,7 +530,9 @@ impl Engine { let id = id.to_global_id(&mut self.env)?; self.globals.set( id.0, - value.into_value_with_engine_state(&self.library, &mut self.gc).to_raw(&mut self.gc), + value + .into_value_with_engine_state(&self.library, &mut self.gc) + .to_raw(&mut self.gc), ); Ok(()) } @@ -585,8 +615,11 @@ impl Engine { hidden_in_stack_traces: false, }) .map_err(|_| Error::TooManyFunctions)?; - let function = - RawValue::from(self.gc.allocate(Closure { name, function_id, captures: Vec::new() })); + let function = RawValue::from(self.gc.allocate(Closure { + name, + function_id, + captures: Vec::new(), + })); self.globals.set(global_id.0, function); Ok(()) } @@ -684,7 +717,9 @@ impl<'e> Script<'e> { impl<'e> fmt::Debug for Script<'e> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Script").field("main_chunk", &self.main_chunk).finish_non_exhaustive() + f.debug_struct("Script") + .field("main_chunk", &self.main_chunk) + .finish_non_exhaustive() } } @@ -720,7 +755,9 @@ impl GlobalName for &str { Ok(if let Some(slot) = env.get_global(self) { GlobalId(slot) } else { - env.create_global(self).map(GlobalId).map_err(|_| Error::TooManyGlobals)? + env.create_global(self) + .map(GlobalId) + .map_err(|_| Error::TooManyGlobals)? }) } } diff --git a/src/hl/error.rs b/src/hl/error.rs index 03090e9..0d6bb47 100644 --- a/src/hl/error.rs +++ b/src/hl/error.rs @@ -82,7 +82,11 @@ impl fmt::Display for Error { Self::ArgumentCount { expected, got } => { write!(f, "{expected} arguments expected but got {got}") } - Self::ArgumentTypeMismatch { index, expected, got } => { + Self::ArgumentTypeMismatch { + index, + expected, + got, + } => { write!( f, "type mismatch at argument {}, expected {expected} but got {got}", diff --git a/src/hl/fiber.rs b/src/hl/fiber.rs index 57c1091..a79b982 100644 --- a/src/hl/fiber.rs +++ b/src/hl/fiber.rs @@ -17,9 +17,18 @@ impl<'e> Fiber<'e> { if self.inner.halted() { Ok(None) } else { - let Engine { env, library, globals, gc, .. } = &mut self.engine; + let Engine { + env, + library, + globals, + gc, + .. + } = &mut self.engine; let result = self.inner.interpret(env, library, globals, gc)?; - Ok(Some(T::try_from_value(&Value::from_raw(result), &self.engine.library)?)) + Ok(Some(T::try_from_value( + &Value::from_raw(result), + &self.engine.library, + )?)) } } diff --git a/src/hl/function.rs b/src/hl/function.rs index a2547a1..ff1968c 100644 --- a/src/hl/function.rs +++ b/src/hl/function.rs @@ -19,7 +19,11 @@ impl<'a> Arguments<'a> { /// [raw function][RawForeignFunction]. pub fn new(raw_arguments: &'a [RawValue], library: &'a Library) -> Self { // Skip the first argument, which is `self` (or the currently called function). - Self { this: raw_arguments[0], inner: &raw_arguments[1..], library } + Self { + this: raw_arguments[0], + inner: &raw_arguments[1..], + library, + } } /// Returns the number of arguments passed to the function. @@ -30,7 +34,10 @@ impl<'a> Arguments<'a> { /// Raises an error if there weren't exactly `n` arguments passed to the function. pub fn expect_exactly(&self, n: usize) -> Result<(), Error> { if self.count() != n { - Err(Error::ArgumentCount { expected: n, got: self.count() }) + Err(Error::ArgumentCount { + expected: n, + got: self.count(), + }) } else { Ok(()) } @@ -39,7 +46,10 @@ impl<'a> Arguments<'a> { /// Raises an error if there weren't at least `n` arguments passed to the function. pub fn expect_at_least(&self, n: usize) -> Result<(), Error> { if self.count() < n { - Err(Error::ArgumentCount { expected: n, got: self.count() }) + Err(Error::ArgumentCount { + expected: n, + got: self.count(), + }) } else { Ok(()) } @@ -64,7 +74,11 @@ impl<'a> Arguments<'a> { let value = self.inner.get(n).cloned().unwrap_or(RawValue::from(())); T::try_from_value(&Value::from_raw(value), self.library).map_err(|error| { if let Error::TypeMismatch { expected, got } = error { - Error::ArgumentTypeMismatch { index: n, expected, got } + Error::ArgumentTypeMismatch { + index: n, + expected, + got, + } } else { error } diff --git a/src/hl/generated/function_variants.rs b/src/hl/generated/function_variants.rs index ab7d0de..7e46224 100644 --- a/src/hl/generated/function_variants.rs +++ b/src/hl/generated/function_variants.rs @@ -2103,7 +2103,9 @@ where let arg_6 = wrap_in_language_error(arguments.get(6))?; let arg_7 = wrap_in_language_error(arguments.get(7))?; - let result = self(arg_self, arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7); + let result = self( + arg_self, arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7, + ); Ok(result.into_value_with_engine_state(library, gc).to_raw(gc)) }) @@ -2141,7 +2143,9 @@ where let arg_6 = wrap_in_language_error(arguments.get(6))?; let arg_7 = wrap_in_language_error(arguments.get(7))?; - let result = self(arg_self, arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7); + let result = self( + arg_self, arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7, + ); wrap_in_language_error( result.map(|v| v.into_value_with_engine_state(library, gc).to_raw(gc)), @@ -2188,7 +2192,9 @@ where let arg_6 = wrap_in_language_error(arguments.get(6))?; let arg_7 = wrap_in_language_error(arguments.get(7))?; - let result = self(arg_self, arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7); + let result = self( + arg_self, arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7, + ); Ok(result.into_value_with_engine_state(library, gc).to_raw(gc)) }) @@ -2233,7 +2239,9 @@ where let arg_6 = wrap_in_language_error(arguments.get(6))?; let arg_7 = wrap_in_language_error(arguments.get(7))?; - let result = self(arg_self, arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7); + let result = self( + arg_self, arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7, + ); Ok(result.into_value_with_engine_state(library, gc).to_raw(gc)) }) @@ -2276,7 +2284,9 @@ where let arg_6 = wrap_in_language_error(arguments.get(6))?; let arg_7 = wrap_in_language_error(arguments.get(7))?; - let result = self(arg_self, arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7); + let result = self( + arg_self, arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7, + ); wrap_in_language_error( result.map(|v| v.into_value_with_engine_state(library, gc).to_raw(gc)), @@ -2324,7 +2334,9 @@ where let arg_6 = wrap_in_language_error(arguments.get(6))?; let arg_7 = wrap_in_language_error(arguments.get(7))?; - let result = self(arg_self, arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7); + let result = self( + arg_self, arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6, arg_7, + ); wrap_in_language_error( result.map(|v| v.into_value_with_engine_state(library, gc).to_raw(gc)), diff --git a/src/hl/traits.rs b/src/hl/traits.rs index d7e6720..2fd4e10 100644 --- a/src/hl/traits.rs +++ b/src/hl/traits.rs @@ -76,13 +76,16 @@ impl<'e> TraitBuilder<'e> { pub fn add_function(&mut self, name: &str, arity: u8) -> Result { let arity = MethodParameterCount::from_count_without_self(arity) .map_err(|_| Error::TooManyParametersInTraitMethod)?; - self.inner.add_method(Rc::from(name), arity).map(MethodId).map_err(|e| match e { - LanguageErrorKind::TooManyTraits => Error::TooManyTraits, - LanguageErrorKind::TooManyFunctions => Error::TooManyFunctions, - LanguageErrorKind::TooManyMethods => Error::TooManyMethods, - LanguageErrorKind::TooManyParameters => Error::TooManyParametersInTraitMethod, - _ => unreachable!(), - }) + self.inner + .add_method(Rc::from(name), arity) + .map(MethodId) + .map_err(|e| match e { + LanguageErrorKind::TooManyTraits => Error::TooManyTraits, + LanguageErrorKind::TooManyFunctions => Error::TooManyFunctions, + LanguageErrorKind::TooManyMethods => Error::TooManyMethods, + LanguageErrorKind::TooManyParameters => Error::TooManyParametersInTraitMethod, + _ => unreachable!(), + }) } /// Finishes building the trait and wraps it into a value. diff --git a/src/hl/types.rs b/src/hl/types.rs index 4243be4..be95f42 100644 --- a/src/hl/types.rs +++ b/src/hl/types.rs @@ -62,9 +62,17 @@ impl DispatchTableDescriptor { }) .map_err(|_| Error::TooManyFunctions)?; let signature = signature.resolve(builtin_traits); - let index = - env.get_or_create_method_index(&signature).map_err(|_| Error::TooManyMethods)?; - dtable.set_method(index, gc.allocate(Closure { name, function_id, captures: Vec::new() })); + let index = env + .get_or_create_method_index(&signature) + .map_err(|_| Error::TooManyMethods)?; + dtable.set_method( + index, + gc.allocate(Closure { + name, + function_id, + captures: Vec::new(), + }), + ); Ok(()) } @@ -149,9 +157,12 @@ where /// Internal converter for use with `BareExactArgs` parameter counts. fn function_to_method_parameter_count(count: FunctionParameterCount) -> MethodParameterCount { MethodParameterCount::from_count_without_self( - count.to_fixed().expect("BareExactArgs functions are never varargs"), + count + .to_fixed() + .expect("BareExactArgs functions are never varargs"), ) - .expect("generated ForeignFunction variants only support up to 8 arguments") // Thus, overflow is impossible. + .expect("generated ForeignFunction variants only support up to 8 arguments") + // Thus, overflow is impossible. } /// Adds a static function to the struct. diff --git a/src/hl/userdata.rs b/src/hl/userdata.rs index 9624eaf..3f08c19 100644 --- a/src/hl/userdata.rs +++ b/src/hl/userdata.rs @@ -63,7 +63,10 @@ pub(crate) struct Type { impl Type { pub(crate) fn new(dtable: Gc) -> Self { - Self { dtable, _data: PhantomData } + Self { + dtable, + _data: PhantomData, + } } } @@ -144,7 +147,12 @@ impl Object { } self.shared_borrows.set(self.shared_borrows.get() + 1); let reference = &*self.data.get(); - Ok((reference, UnsafeRefGuard { object: self as *const _ })) + Ok(( + reference, + UnsafeRefGuard { + object: self as *const _, + }, + )) } /// Borrows the object mutably using an unsafe guard. @@ -159,7 +167,12 @@ impl Object { } self.borrowed_mutably.set(true); let reference = &mut *self.data.get(); - Ok((reference, UnsafeMutGuard { object: self as *const _ })) + Ok(( + reference, + UnsafeMutGuard { + object: self as *const _, + }, + )) } } diff --git a/src/hl/value.rs b/src/hl/value.rs index c2c07f1..d6b926e 100644 --- a/src/hl/value.rs +++ b/src/hl/value.rs @@ -344,10 +344,13 @@ where type EngineUse = UsesEngine; fn into_value(self, (library, _): (&Library, &mut Memory)) -> Value { - let dtable = library.get_user_dtable::().map(Gc::clone).unwrap_or_else(|| { - let ad_hoc_dtable = DispatchTable::new_for_instance(type_name::()); - Gc::new(ad_hoc_dtable) - }); + let dtable = library + .get_user_dtable::() + .map(Gc::clone) + .unwrap_or_else(|| { + let ad_hoc_dtable = DispatchTable::new_for_instance(type_name::()); + Gc::new(ad_hoc_dtable) + }); let object = Object::new(Gc::as_raw(&dtable), self); Value::UserData(Gc::new(Box::new(object))) } @@ -363,7 +366,10 @@ where } fn type_mismatch(expected: impl Into>, got: &Value) -> Error { - Error::TypeMismatch { expected: expected.into(), got: got.type_name().to_string().into() } + Error::TypeMismatch { + expected: expected.into(), + got: got.type_name().to_string().into(), + } } impl TryFromValue for Value { @@ -454,13 +460,18 @@ where fn try_from_value(value: &Value, library: &Library) -> Result { match value { Value::Nil => Ok(None), - _ => Ok(Some(T::try_from_value(value, library).map_err(|error| { - if let Error::TypeMismatch { expected, got } = error { - Error::TypeMismatch { expected: format!("{expected} or Nil").into(), got } - } else { - unreachable!() - } - })?)), + _ => Ok(Some(T::try_from_value(value, library).map_err( + |error| { + if let Error::TypeMismatch { expected, got } = error { + Error::TypeMismatch { + expected: format!("{expected} or Nil").into(), + got, + } + } else { + unreachable!() + } + }, + )?)), } } } diff --git a/src/ll/ast.rs b/src/ll/ast.rs index ecd2a5a..d5ddac4 100644 --- a/src/ll/ast.rs +++ b/src/ll/ast.rs @@ -37,8 +37,12 @@ enum NodeData { impl Ast { /// Creates a new, empty syntax tree. The module name is used for error messages. pub fn new(module_name: Rc) -> Self { - let mut ast = - Self { module_name, nodes: Vec::new(), locations: Vec::new(), data: Vec::new() }; + let mut ast = Self { + module_name, + nodes: Vec::new(), + locations: Vec::new(), + data: Vec::new(), + }; let _empty = ast.create_node(NodeKind::Empty, ()); ast } @@ -357,7 +361,11 @@ impl fmt::Debug for DumpAst<'_> { if let Some(s) = ast.string(node) { write!(f, "{s:?}")?; } - if ast.children(node).map(|children| children.is_empty()).unwrap_or(false) { + if ast + .children(node) + .map(|children| children.is_empty()) + .unwrap_or(false) + { write!(f, " (children empty)")?; } writeln!(f)?; diff --git a/src/ll/bytecode/chunk.rs b/src/ll/bytecode/chunk.rs index 85c88ff..b3b9583 100644 --- a/src/ll/bytecode/chunk.rs +++ b/src/ll/bytecode/chunk.rs @@ -34,7 +34,8 @@ impl Chunk { /// Pushes an encodable piece of data into the chunk. Returns where it's located. pub fn emit(&mut self, instruction: impl EncodeInstruction) -> usize { let position = self.bytes.len(); - self.bytes.extend_from_slice(&instruction.encode_instruction()); + self.bytes + .extend_from_slice(&instruction.encode_instruction()); // Only push one location, since all encoded instructions are 4 bytes long. self.locations.push(self.codegen_location); position @@ -95,7 +96,9 @@ impl Chunk { let mut bytes = <[u8; Opcode::INSTRUCTION_SIZE]>::try_from(bytes).unwrap(); let opcode: Opcode = std::mem::transmute(bytes[0]); bytes[0] = 0; - let operand = Opr24 { bytes: [bytes[1], bytes[2], bytes[3]] }; + let operand = Opr24 { + bytes: [bytes[1], bytes[2], bytes[3]], + }; *pc += Opcode::INSTRUCTION_SIZE; (opcode, operand) } @@ -154,7 +157,10 @@ impl Chunk { /// Returns the location (in file) of the program counter. pub fn location(&self, pc: usize) -> Location { let index = pc >> 2; - self.locations.get(index).copied().unwrap_or(Location::UNINIT) + self.locations + .get(index) + .copied() + .unwrap_or(Location::UNINIT) } /// Returns whether the given program counter is at the end of the chunk. diff --git a/src/ll/bytecode/dispatch_table.rs b/src/ll/bytecode/dispatch_table.rs index 9757f45..695eaf3 100644 --- a/src/ll/bytecode/dispatch_table.rs +++ b/src/ll/bytecode/dispatch_table.rs @@ -40,7 +40,12 @@ impl DispatchTable { /// Returns a reference to the method at the given index. pub fn get_method(&self, index: MethodIndex) -> Option> { - self.methods.get(index.to_usize()).into_iter().flatten().copied().next() + self.methods + .get(index.to_usize()) + .into_iter() + .flatten() + .copied() + .next() } /// Adds a method into the dispatch table. diff --git a/src/ll/bytecode/environment.rs b/src/ll/bytecode/environment.rs index 013c98c..03571d0 100644 --- a/src/ll/bytecode/environment.rs +++ b/src/ll/bytecode/environment.rs @@ -59,7 +59,11 @@ pub struct MethodSignature { impl MethodSignature { /// Creates a new method signature for a method that does not belong to a trait. pub fn new(name: Rc, parameter_count: MethodParameterCount) -> Self { - Self { name, parameter_count, trait_id: None } + Self { + name, + parameter_count, + trait_id: None, + } } /// Renders this signature into one that can be formatted. @@ -240,7 +244,11 @@ impl Environment { /// `unsafe`. pub(crate) unsafe fn get_prototype_unchecked(&self, id: PrototypeIndex) -> &Prototype { let PrototypeIndex(id) = id; - let proto = self.prototypes.get_unchecked(usize::from(id)).as_ref().unwrap_unchecked(); + let proto = self + .prototypes + .get_unchecked(usize::from(id)) + .as_ref() + .unwrap_unchecked(); proto } @@ -249,7 +257,11 @@ impl Environment { let slot_index = self.traits.len(); let slot = Opr24::try_from(slot_index).map_err(|_| LanguageErrorKind::TooManyTraits)?; let slot = TraitIndex(slot); - self.traits.push(TraitPrototype { name, required: HashSet::new(), shims: vec![] }); + self.traits.push(TraitPrototype { + name, + required: HashSet::new(), + shims: vec![], + }); Ok(slot) } diff --git a/src/ll/bytecode/function.rs b/src/ll/bytecode/function.rs index 654a53f..a33890a 100644 --- a/src/ll/bytecode/function.rs +++ b/src/ll/bytecode/function.rs @@ -31,7 +31,10 @@ pub enum Control { /// The kind of the function (bytecode or FFI). pub enum FunctionKind { - Bytecode { chunk: Rc, captured_locals: Vec }, + Bytecode { + chunk: Rc, + captured_locals: Vec, + }, Foreign(ForeignFunction), Control(Control), } @@ -39,7 +42,10 @@ pub enum FunctionKind { impl std::fmt::Debug for FunctionKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::Bytecode { chunk, captured_locals } => f + Self::Bytecode { + chunk, + captured_locals, + } => f .debug_struct("Bytecode") .field("chunk", chunk) .field("captured_locals", captured_locals) diff --git a/src/ll/bytecode/library.rs b/src/ll/bytecode/library.rs index 84442af..2820073 100644 --- a/src/ll/bytecode/library.rs +++ b/src/ll/bytecode/library.rs @@ -65,7 +65,10 @@ impl Library { self.builtin_dtables.tuples.resize(size + 1, None); } self.builtin_dtables.tuples[size] = - Some(self.builtin_dtable_generator.generate_tuple(env, gc, &self.builtin_traits, size)); + Some( + self.builtin_dtable_generator + .generate_tuple(env, gc, &self.builtin_traits, size), + ); } /// Returns the record type index of the record with the given identifier, generating it if it's @@ -101,7 +104,9 @@ impl Library { }, index, })); - self.builtin_dtables.records_by_identifier.insert(Rc::clone(identifier), index); + self.builtin_dtables + .records_by_identifier + .insert(Rc::clone(identifier), index); Ok(index) } } @@ -197,13 +202,21 @@ impl BuiltinTraits { /// Tries to register built-in traits in the given environment. fn try_register_in(env: &mut Environment) -> Result { let mut builder = TraitBuilder::new(env, None, Rc::from("Iterator"))?; - let iterator_has_next = builder - .add_method(Rc::from("has_next"), MethodParameterCount::from_count_with_self(1))?; - let iterator_next = - builder.add_method(Rc::from("next"), MethodParameterCount::from_count_with_self(1))?; + let iterator_has_next = builder.add_method( + Rc::from("has_next"), + MethodParameterCount::from_count_with_self(1), + )?; + let iterator_next = builder.add_method( + Rc::from("next"), + MethodParameterCount::from_count_with_self(1), + )?; let (iterator, _) = builder.build(); - Ok(Self { iterator, iterator_has_next, iterator_next }) + Ok(Self { + iterator, + iterator_has_next, + iterator_next, + }) } /// Registers built-in traits in the given environment. diff --git a/src/ll/bytecode/opcode.rs b/src/ll/bytecode/opcode.rs index 570ffc7..0197c55 100644 --- a/src/ll/bytecode/opcode.rs +++ b/src/ll/bytecode/opcode.rs @@ -209,7 +209,12 @@ pub trait EncodeInstruction { impl EncodeInstruction for (Opcode, Opr24) { fn encode_instruction(&self) -> [u8; Opcode::INSTRUCTION_SIZE] { - [self.0 as u8, self.1.bytes[0], self.1.bytes[1], self.1.bytes[2]] + [ + self.0 as u8, + self.1.bytes[0], + self.1.bytes[1], + self.1.bytes[2], + ] } } diff --git a/src/ll/bytecode/opr24.rs b/src/ll/bytecode/opr24.rs index e199d04..0be0e15 100644 --- a/src/ll/bytecode/opr24.rs +++ b/src/ll/bytecode/opr24.rs @@ -17,7 +17,11 @@ impl Opr24 { pub fn new(x: u32) -> Result { if x < Self::MAX { Ok(Self { - bytes: [(x & 0xFF) as u8, ((x >> 8) & 0xFF) as u8, ((x >> 16) & 0xFF) as u8], + bytes: [ + (x & 0xFF) as u8, + ((x >> 8) & 0xFF) as u8, + ((x >> 16) & 0xFF) as u8, + ], }) } else { Err(Opr24OutOfRange(())) @@ -43,7 +47,9 @@ impl Opr24 { impl From for Opr24 { fn from(value: u8) -> Self { - Self { bytes: [value, 0, 0] } + Self { + bytes: [value, 0, 0], + } } } diff --git a/src/ll/codegen.rs b/src/ll/codegen.rs index 4e30145..8fc40a8 100644 --- a/src/ll/codegen.rs +++ b/src/ll/codegen.rs @@ -62,7 +62,11 @@ impl<'e> CodeGenerator<'e> { self.generate_node( ast, node, - if i != nodes.len() - 1 { Expression::Discarded } else { Expression::Used }, + if i != nodes.len() - 1 { + Expression::Discarded + } else { + Expression::Used + }, )?; } } diff --git a/src/ll/codegen/assignment.rs b/src/ll/codegen/assignment.rs index 85415c4..9c6f1fc 100644 --- a/src/ll/codegen/assignment.rs +++ b/src/ll/codegen/assignment.rs @@ -93,14 +93,16 @@ impl<'e> CodeGenerator<'e> { match ast.kind(target) { NodeKind::Identifier => { let name = ast.string(target).unwrap(); - let variable = if let Some(slot) = - self.lookup_variable(name).map_err(|kind| ast.error(target, kind))? + let variable = if let Some(slot) = self + .lookup_variable(name) + .map_err(|kind| ast.error(target, kind))? { slot } else { - return Err( - ast.error(target, LanguageErrorKind::VariableDoesNotExist(Rc::clone(name))) - ); + return Err(ast.error( + target, + LanguageErrorKind::VariableDoesNotExist(Rc::clone(name)), + )); }; match result { Expression::Used => self.generate_variable_assign(variable), @@ -117,7 +119,10 @@ impl<'e> CodeGenerator<'e> { .map_err(|kind| ast.error(node, kind))? } else { struct_data.get_field(name).ok_or_else(|| { - ast.error(target, LanguageErrorKind::FieldDoesNotExist(Rc::clone(name))) + ast.error( + target, + LanguageErrorKind::FieldDoesNotExist(Rc::clone(name)), + ) })? }; // Unwrapping is OK here because `receiver` is assigned at the start of each diff --git a/src/ll/codegen/calls.rs b/src/ll/codegen/calls.rs index 47e98a1..f224e72 100644 --- a/src/ll/codegen/calls.rs +++ b/src/ll/codegen/calls.rs @@ -86,7 +86,8 @@ impl<'e> CodeGenerator<'e> { .env .get_or_create_method_index(&signature) .map_err(|kind| ast.error(node, kind))?; - self.chunk.emit((Opcode::CallMethod, Opr24::pack((method_index.to_u16(), 1)))); + self.chunk + .emit((Opcode::CallMethod, Opr24::pack((method_index.to_u16(), 1)))); Ok(ExpressionResult::Present) } diff --git a/src/ll/codegen/control_flow.rs b/src/ll/codegen/control_flow.rs index a719da0..73df397 100644 --- a/src/ll/codegen/control_flow.rs +++ b/src/ll/codegen/control_flow.rs @@ -18,7 +18,10 @@ impl<'e> CodeGenerator<'e> { /// Pushes a new breakable block. pub(super) fn push_breakable_block(&mut self) { let start = self.chunk.emit(Opcode::Nop); - self.breakable_blocks.push(BreakableBlock { breaks: Vec::new(), start }); + self.breakable_blocks.push(BreakableBlock { + breaks: Vec::new(), + start, + }); } /// Pops the topmost breakable block. @@ -29,7 +32,8 @@ impl<'e> CodeGenerator<'e> { for jump in block.breaks { // Unwrapping is safe here because if the loop is too large the error was caught // already before `pop_breakable_block` was called. - self.chunk.patch(jump, Opcode::jump_forward(jump, self.chunk.len()).unwrap()); + self.chunk + .patch(jump, Opcode::jump_forward(jump, self.chunk.len()).unwrap()); } self.chunk.emit((Opcode::ExitBreakableBlock, 1)); } @@ -244,7 +248,10 @@ impl<'e> CodeGenerator<'e> { generator.generate_variable_load(iterator_var); generator.chunk.emit(( Opcode::CallMethod, - Opr24::pack((generator.library.builtin_traits.iterator_has_next.to_u16(), 1)), + Opr24::pack(( + generator.library.builtin_traits.iterator_has_next.to_u16(), + 1, + )), )); Ok(()) }, diff --git a/src/ll/codegen/functions.rs b/src/ll/codegen/functions.rs index 1514e6d..fab04e5 100644 --- a/src/ll/codegen/functions.rs +++ b/src/ll/codegen/functions.rs @@ -42,7 +42,12 @@ impl FunctionCallConv { } fn allow_new_fields(&self) -> bool { - matches!(self, Self::Constructor { allow_new_fields: true }) + matches!( + self, + Self::Constructor { + allow_new_fields: true + } + ) } } @@ -72,8 +77,12 @@ impl<'e> CodeGenerator<'e> { let (_, parameters) = ast.node_pair(head); let parameter_list = ast.children(parameters).unwrap(); - let mut generator = - CodeGenerator::new(Rc::clone(&self.chunk.module_name), self.env, self.library, self.gc); + let mut generator = CodeGenerator::new( + Rc::clone(&self.chunk.module_name), + self.env, + self.library, + self.gc, + ); // NOTE: Hopefully the allocation from this mem::take gets optimized out. generator.locals.parent = Some(mem::take(&mut self.locals)); if call_conv.has_field_access() { @@ -87,13 +96,17 @@ impl<'e> CodeGenerator<'e> { // Create local variables for all the parameters. // Note that in bare functions, the function itself acts as the `self` parameter. let receiver = if call_conv.has_visible_self() { - let receiver = generator.create_variable("self", VariableAllocation::Inherit).unwrap(); + let receiver = generator + .create_variable("self", VariableAllocation::Inherit) + .unwrap(); if let Some(struct_data) = generator.struct_data.as_deref_mut() { struct_data.receiver = Some(receiver); } receiver } else { - generator.create_variable("", VariableAllocation::Inherit).unwrap() + generator + .create_variable("", VariableAllocation::Inherit) + .unwrap() }; for ¶meter in parameter_list { let parameter_name = ast.string(parameter).unwrap(); @@ -126,9 +139,14 @@ impl<'e> CodeGenerator<'e> { if let Some(create_struct) = create_struct { let field_count = generator.struct_data.as_ref().unwrap().fields.len(); let field_count = Opr24::try_from(field_count).map_err(|_| { - ast.error(ast.node_pair(parameters).0, LanguageErrorKind::TooManyFields) + ast.error( + ast.node_pair(parameters).0, + LanguageErrorKind::TooManyFields, + ) })?; - generator.chunk.patch(create_struct, (Opcode::CreateStruct, field_count)); + generator + .chunk + .patch(create_struct, (Opcode::CreateStruct, field_count)); // We also have to discard whatever was at the top of the stack at the moment (ie. the // result of the function's body) and instead return the struct. generator.chunk.emit(Opcode::Discard); @@ -171,10 +189,15 @@ impl<'e> CodeGenerator<'e> { }, hidden_in_stack_traces: false, }; - let function_id = - self.env.create_function(function).map_err(|kind| ast.error(node, kind))?; + let function_id = self + .env + .create_function(function) + .map_err(|kind| ast.error(node, kind))?; - Ok(GeneratedFunction { id: function_id, parameter_count }) + Ok(GeneratedFunction { + id: function_id, + parameter_count, + }) } /// Ensures that a `Func` node is a valid bare function - without a kind, and with a body. @@ -212,10 +235,14 @@ impl<'e> CodeGenerator<'e> { let function = self.generate_function( ast, node, - GenerateFunctionOptions { name: Rc::clone(name), call_conv: FunctionCallConv::Bare }, + GenerateFunctionOptions { + name: Rc::clone(name), + call_conv: FunctionCallConv::Bare, + }, )?; - self.chunk.emit((Opcode::CreateClosure, function.id.to_opr24())); + self.chunk + .emit((Opcode::CreateClosure, function.id.to_opr24())); self.generate_variable_sink(variable); Ok(ExpressionResult::Absent) @@ -238,7 +265,8 @@ impl<'e> CodeGenerator<'e> { }, )?; - self.chunk.emit((Opcode::CreateClosure, function.id.to_opr24())); + self.chunk + .emit((Opcode::CreateClosure, function.id.to_opr24())); Ok(ExpressionResult::Present) } } diff --git a/src/ll/codegen/impls.rs b/src/ll/codegen/impls.rs index 571e536..46136fe 100644 --- a/src/ll/codegen/impls.rs +++ b/src/ll/codegen/impls.rs @@ -47,7 +47,10 @@ impl<'e> CodeGenerator<'e> { self.generate_impl_item(ast, node, &mut state, true)?; } - let proto_id = self.env.create_prototype(proto).map_err(|kind| ast.error(node, kind))?; + let proto_id = self + .env + .create_prototype(proto) + .map_err(|kind| ast.error(node, kind))?; self.chunk.emit((Opcode::Implement, proto_id.to_opr24())); self.struct_data = None; @@ -86,7 +89,10 @@ impl<'e> CodeGenerator<'e> { let function = self.generate_function( ast, node, - GenerateFunctionOptions { name: Rc::clone(&name), call_conv }, + GenerateFunctionOptions { + name: Rc::clone(&name), + call_conv, + }, )?; let parameter_count = @@ -95,7 +101,12 @@ impl<'e> CodeGenerator<'e> { if let Some(trait_index) = state.implemented_trait_index { // For trait instance methods, method ID resolution is performed at runtime. let key = (Rc::clone(&name), parameter_count, trait_index); - if state.proto.trait_instance.insert(key, function.id).is_some() { + if state + .proto + .trait_instance + .insert(key, function.id) + .is_some() + { return Err(ast.error( name_node, LanguageErrorKind::MethodAlreadyImplemented(RenderedSignature { @@ -141,8 +152,10 @@ impl<'e> CodeGenerator<'e> { let (trait_expr, _) = ast.node_pair(node); let as_items = ast.children(node).unwrap(); self.generate_node(ast, trait_expr, Expression::Used)?; - let trait_index = - state.proto.implement_next_trait().map_err(|e| ast.error(node, e))?; + let trait_index = state + .proto + .implement_next_trait() + .map_err(|e| ast.error(node, e))?; let mut state = ImplGenerationState { proto: state.proto, implemented_trait_index: Some(trait_index), diff --git a/src/ll/codegen/traits.rs b/src/ll/codegen/traits.rs index 4648524..89358a8 100644 --- a/src/ll/codegen/traits.rs +++ b/src/ll/codegen/traits.rs @@ -30,7 +30,13 @@ impl<'b> TraitBuilder<'b> { name: Rc, ) -> Result { let trait_id = env.create_trait(name)?; - Ok(Self { env, parent_chunk, trait_id, required_methods: HashSet::new(), shims: vec![] }) + Ok(Self { + env, + parent_chunk, + trait_id, + required_methods: HashSet::new(), + shims: vec![], + }) } /// Generates the *shim* for a trait method. The shim is responsible for calling the actual @@ -44,24 +50,36 @@ impl<'b> TraitBuilder<'b> { let parameter_count = method_signature.parameter_count.to_count_with_self(); let (module_name, codegen_location) = if let Some(parent_chunk) = self.parent_chunk { - (Rc::clone(&parent_chunk.module_name), parent_chunk.codegen_location) + ( + Rc::clone(&parent_chunk.module_name), + parent_chunk.codegen_location, + ) } else { (Rc::from("FFI"), Location::UNINIT) }; let mut chunk = Chunk::new(module_name); chunk.codegen_location = codegen_location; - chunk.emit((Opcode::CallMethod, Opr24::pack((method_id.to_u16(), parameter_count)))); + chunk.emit(( + Opcode::CallMethod, + Opr24::pack((method_id.to_u16(), parameter_count)), + )); chunk.emit(Opcode::Return); - let shim_name = Rc::from(format!("trait {trait_name}.{} ", method_signature.name)); + let shim_name = Rc::from(format!( + "trait {trait_name}.{} ", + method_signature.name + )); let chunk = Rc::new(chunk); let function_id = self.env.create_function(Function { name: shim_name, parameter_count: FunctionParameterCount::Fixed( method_signature.parameter_count.to_count_without_self() as u16, ), - kind: FunctionKind::Bytecode { chunk, captured_locals: vec![] }, + kind: FunctionKind::Bytecode { + chunk, + captured_locals: vec![], + }, hidden_in_stack_traces: true, })?; @@ -77,7 +95,11 @@ impl<'b> TraitBuilder<'b> { parameter_count: MethodParameterCount, ) -> Result { let trait_name = Rc::clone(&self.env.get_trait(self.trait_id).unwrap().name); - let signature = MethodSignature { name, parameter_count, trait_id: Some(self.trait_id) }; + let signature = MethodSignature { + name, + parameter_count, + trait_id: Some(self.trait_id), + }; let method_id = self.env.get_or_create_method_index(&signature)?; let parameter_count_with_receiving_trait = MethodParameterCount::from_count_with_self( @@ -96,12 +118,14 @@ impl<'b> TraitBuilder<'b> { self.shims.push((shim_method_id, shim_function_id)); if !self.required_methods.insert(method_id) { - return Err(LanguageErrorKind::TraitAlreadyHasMethod(RenderedSignature { - name: signature.name, - parameter_count: signature.parameter_count.to_count_without_self(), - // Do not duplicate the trait name in the error message. - trait_name: None, - })); + return Err(LanguageErrorKind::TraitAlreadyHasMethod( + RenderedSignature { + name: signature.name, + parameter_count: signature.parameter_count.to_count_without_self(), + // Do not duplicate the trait name in the error message. + trait_name: None, + }, + )); } Ok(method_id) diff --git a/src/ll/codegen/tuples.rs b/src/ll/codegen/tuples.rs index 93af6e6..d0996a7 100644 --- a/src/ll/codegen/tuples.rs +++ b/src/ll/codegen/tuples.rs @@ -28,7 +28,8 @@ impl<'e> CodeGenerator<'e> { Opr24::try_from(elements.len()) .map_err(|_| ast.error(node, LanguageErrorKind::TupleHasTooManyElements))?, )); - self.library.generate_tuple(self.env, self.gc, elements.len()); + self.library + .generate_tuple(self.env, self.gc, elements.len()); Ok(ExpressionResult::Present) } @@ -45,8 +46,10 @@ impl<'e> CodeGenerator<'e> { return Err(ast.error(node, LanguageErrorKind::RecordHasTooManyFields)); } - let mut fields: Vec<_> = - pairs.iter().map(|&pair| ast.string(ast.node_pair(pair).0).unwrap()).collect(); + let mut fields: Vec<_> = pairs + .iter() + .map(|&pair| ast.string(ast.node_pair(pair).0).unwrap()) + .collect(); fields.sort(); let mut field_order = vec![]; @@ -69,7 +72,8 @@ impl<'e> CodeGenerator<'e> { .get_or_generate_record(self.env, self.gc, &identifier) .map_err(|_| ast.error(node, LanguageErrorKind::TooManyRecords))?; - self.chunk.emit((Opcode::CreateRecord, record_type_index.to_opr24())); + self.chunk + .emit((Opcode::CreateRecord, record_type_index.to_opr24())); for field_index in field_order { self.chunk.emit_u32(field_index); } @@ -109,7 +113,8 @@ impl<'e> CodeGenerator<'e> { // doing things without complicating the implementation too much. // We can swap it out for something more performant if it becomes too slow. self.chunk.emit(Opcode::Duplicate); - self.chunk.emit((Opcode::CallMethod, Opr24::pack((method_index.to_u16(), 1)))); + self.chunk + .emit((Opcode::CallMethod, Opr24::pack((method_index.to_u16(), 1)))); let pattern = if value == NodeId::EMPTY { key } else { value }; self.generate_pattern_destructuring(ast, pattern, Expression::Discarded)?; @@ -118,7 +123,9 @@ impl<'e> CodeGenerator<'e> { let mut fields: Vec<_> = pairs.iter().map(|&pair| ast.node_pair(pair)).collect(); fields.sort_by_key(|&(key, _)| ast.string(key)); let identifier = make_record_identifier( - fields.iter().map(|&(key, _)| ast.string(key).unwrap().deref()), + fields + .iter() + .map(|&(key, _)| ast.string(key).unwrap().deref()), ); let record_type_index = self .library @@ -129,7 +136,8 @@ impl<'e> CodeGenerator<'e> { if result == Expression::Used { self.chunk.emit(Opcode::Duplicate); } - self.chunk.emit((Opcode::DestructureRecord, record_type_index.to_opr24())); + self.chunk + .emit((Opcode::DestructureRecord, record_type_index.to_opr24())); for &(key, value) in fields.iter().rev() { let pattern = if value == NodeId::EMPTY { key } else { value }; self.generate_pattern_destructuring(ast, pattern, Expression::Discarded)?; diff --git a/src/ll/codegen/variables.rs b/src/ll/codegen/variables.rs index f41cf84..ec7ffde 100644 --- a/src/ll/codegen/variables.rs +++ b/src/ll/codegen/variables.rs @@ -89,9 +89,13 @@ impl Locals { let slot = Opr24::new(self.local_count).map_err(|_| LanguageErrorKind::TooManyLocals)?; let slot = LocalIndex(slot); let scope = self.scopes.last_mut().unwrap(); - scope - .variables_by_name - .insert(name.to_owned(), Variable { stack_slot: slot, is_captured: false }); + scope.variables_by_name.insert( + name.to_owned(), + Variable { + stack_slot: slot, + is_captured: false, + }, + ); self.local_count += 1; if allocation == VariableAllocation::Allocate { self.allocated_local_count += 1; @@ -101,10 +105,12 @@ impl Locals { } fn variables_in_scope_mut(&mut self) -> impl Iterator { - self.scopes - .iter_mut() - .rev() - .flat_map(|scope| scope.variables_by_name.iter_mut().map(|(s, v)| (s.as_str(), v))) + self.scopes.iter_mut().rev().flat_map(|scope| { + scope + .variables_by_name + .iter_mut() + .map(|(s, v)| (s.as_str(), v)) + }) } /// Returns the index of the given capture. @@ -112,12 +118,18 @@ impl Locals { // Iterating over captures maybe isn't most efficient here but it's not like we have // thousands of them anyways. Unless somebody absolutely crazy starts writing Mica code. // Then all I can say is: I hate you. - let index = self.captures.iter().rposition(|c| c.eq(&capture)).unwrap_or_else(|| { - let index = self.captures.len(); - self.captures.push(capture); - index - }); - Ok(UpvalueIndex(Opr24::try_from(index).map_err(|_| LanguageErrorKind::TooManyCaptures)?)) + let index = self + .captures + .iter() + .rposition(|c| c.eq(&capture)) + .unwrap_or_else(|| { + let index = self.captures.len(); + self.captures.push(capture); + index + }); + Ok(UpvalueIndex( + Opr24::try_from(index).map_err(|_| LanguageErrorKind::TooManyCaptures)?, + )) } /// Performs a local variable lookup. This may modify parent Locals and capture upvalues. @@ -178,8 +190,10 @@ impl<'e> CodeGenerator<'e> { ) -> Result { if !self.locals.scopes.is_empty() { let place = self.locals.create_local(name, allocation)?; - self.chunk.preallocate_stack_slots = - self.chunk.preallocate_stack_slots.max(self.locals.allocated_local_count); + self.chunk.preallocate_stack_slots = self + .chunk + .preallocate_stack_slots + .max(self.locals.allocated_local_count); Ok(place) } else { let slot = self.env.create_global(name)?; @@ -252,11 +266,17 @@ impl<'e> CodeGenerator<'e> { node: NodeId, ) -> Result { let name = ast.string(node).unwrap(); - if let Some(variable) = self.lookup_variable(name).map_err(|kind| ast.error(node, kind))? { + if let Some(variable) = self + .lookup_variable(name) + .map_err(|kind| ast.error(node, kind))? + { self.generate_variable_load(variable); Ok(ExpressionResult::Present) } else { - Err(ast.error(node, LanguageErrorKind::VariableDoesNotExist(name.to_owned()))) + Err(ast.error( + node, + LanguageErrorKind::VariableDoesNotExist(name.to_owned()), + )) } } } diff --git a/src/ll/error.rs b/src/ll/error.rs index d3a850d..38ba779 100644 --- a/src/ll/error.rs +++ b/src/ll/error.rs @@ -13,7 +13,11 @@ pub struct Location { impl Location { /// The "uninitialized" location, used as a placeholder for proper locations in case there's a /// bug in codegen. - pub const UNINIT: Self = Self { byte: 0, line: 0, column: 0 }; + pub const UNINIT: Self = Self { + byte: 0, + line: 0, + column: 0, + }; /// Returns whether this location is the uninitialized location. pub fn is_uninit(&self) -> bool { @@ -24,7 +28,11 @@ impl Location { /// The default location points to the first column on the first line. impl Default for Location { fn default() -> Self { - Self { byte: 0, line: 1, column: 1 } + Self { + byte: 0, + line: 1, + column: 1, + } } } @@ -53,7 +61,11 @@ impl RenderedSignature { pub const INVALID_NAME: &'static str = ""; pub fn invalid() -> Self { - Self { name: Rc::from(Self::INVALID_NAME), parameter_count: 0, trait_name: None } + Self { + name: Rc::from(Self::INVALID_NAME), + parameter_count: 0, + trait_name: None, + } } pub fn is_invalid(&self) -> bool { @@ -167,12 +179,24 @@ pub enum LanguageErrorKind { CannotAccessDiscardPattern, // Runtime - TypeError { expected: Cow<'static, str>, got: Cow<'static, str> }, - MethodDoesNotExist { type_name: Rc, signature: RenderedSignature }, + TypeError { + expected: Cow<'static, str>, + got: Cow<'static, str>, + }, + MethodDoesNotExist { + type_name: Rc, + signature: RenderedSignature, + }, StructAlreadyImplemented, UserDataAlreadyBorrowed, - DoubleMethodImplementation { type_name: Rc, signature: RenderedSignature }, - MethodsUnimplemented { type_name: Rc, methods: Vec }, + DoubleMethodImplementation { + type_name: Rc, + signature: RenderedSignature, + }, + MethodsUnimplemented { + type_name: Rc, + methods: Vec, + }, User(Box), } @@ -322,9 +346,16 @@ pub struct StackTraceEntry { #[derive(Debug)] pub enum LanguageError { /// A compile-time error. - Compile { kind: LanguageErrorKind, module_name: Rc, location: Location }, + Compile { + kind: LanguageErrorKind, + module_name: Rc, + location: Location, + }, /// A runtime error. - Runtime { kind: LanguageErrorKind, call_stack: Vec }, + Runtime { + kind: LanguageErrorKind, + call_stack: Vec, + }, } impl std::fmt::Display for LanguageError { @@ -343,7 +374,11 @@ impl std::fmt::Display for LanguageError { } match self { - LanguageError::Compile { kind, module_name, location } => { + LanguageError::Compile { + kind, + module_name, + location, + } => { write!(f, "{module_name}:{location}: error: {kind}") } LanguageError::Runtime { kind, call_stack } => { @@ -351,7 +386,11 @@ impl std::fmt::Display for LanguageError { write!(f, "stack traceback (most recent call first):")?; let file_location_width = call_stack .iter() - .map(|entry| FileLocation(&entry.module_name, entry.location).to_string().len()) + .map(|entry| { + FileLocation(&entry.module_name, entry.location) + .to_string() + .len() + }) .max() .unwrap_or(20); for entry in call_stack.iter().rev() { diff --git a/src/ll/gc.rs b/src/ll/gc.rs index 48838fe..eec4e98 100644 --- a/src/ll/gc.rs +++ b/src/ll/gc.rs @@ -23,7 +23,10 @@ pub enum AutoStrategy { AlwaysRun, /// Run the GC if its `allocated_bytes` exceeds `next_run`, and grow `next_run` to /// `allocated_bytes * growth_factor / 256` after collection. - Ceiling { next_run: usize, growth_factor: usize }, + Ceiling { + next_run: usize, + growth_factor: usize, + }, } impl AutoStrategy { @@ -39,7 +42,10 @@ impl AutoStrategy { /// Returns an updated version of the strategy after a successful collection. fn update(self, gc: &Memory) -> Self { if let Self::Ceiling { growth_factor, .. } = self { - Self::Ceiling { next_run: gc.allocated_bytes * growth_factor / 256, growth_factor } + Self::Ceiling { + next_run: gc.allocated_bytes * growth_factor / 256, + growth_factor, + } } else { self } @@ -211,7 +217,10 @@ impl Memory { pub(crate) unsafe fn auto_collect(&mut self, roots: impl Iterator) { #[cfg(feature = "trace-gc")] { - println!("gc | auto_collect called with strategy {:?}", self.auto_strategy); + println!( + "gc | auto_collect called with strategy {:?}", + self.auto_strategy + ); } if self.auto_strategy.satisfied(self) { #[cfg(feature = "trace-gc")] @@ -337,7 +346,11 @@ impl GcMem { unsafe { ptr::write(allocation, mem) } #[cfg(feature = "trace-gc")] { - println!("gcmem | allocated {:p}, T: {}", allocation, std::any::type_name::()); + println!( + "gcmem | allocated {:p}, T: {}", + allocation, + std::any::type_name::() + ); } GcRaw(allocation as *const _) } diff --git a/src/ll/lexer.rs b/src/ll/lexer.rs index 767e98d..68a8899 100644 --- a/src/ll/lexer.rs +++ b/src/ll/lexer.rs @@ -92,7 +92,12 @@ impl Lexer { /// Creates a new lexer. pub fn new(module_name: Rc, input: String) -> Self { - Self { module_name, input, location: Default::default(), token_start: Default::default() } + Self { + module_name, + input, + location: Default::default(), + token_start: Default::default(), + } } /// Emits an error. @@ -102,17 +107,27 @@ impl Lexer { /// Emits an error at a specific location. fn error_at(&self, location: Location, kind: LanguageErrorKind) -> LanguageError { - LanguageError::Compile { module_name: Rc::clone(&self.module_name), kind, location } + LanguageError::Compile { + module_name: Rc::clone(&self.module_name), + kind, + location, + } } /// Emits a token at the `token_start` location. fn token(&self, kind: TokenKind) -> Token { - Token { kind, location: self.token_start } + Token { + kind, + location: self.token_start, + } } /// Returns the character at the current position. fn get(&self) -> char { - self.input[self.location.byte..].chars().next().unwrap_or(Self::EOF) + self.input[self.location.byte..] + .chars() + .next() + .unwrap_or(Self::EOF) } /// Advances the current position by a character. diff --git a/src/ll/parser.rs b/src/ll/parser.rs index 7c933b1..c665a6b 100644 --- a/src/ll/parser.rs +++ b/src/ll/parser.rs @@ -17,7 +17,10 @@ pub struct Parser { impl Parser { /// Constructs a new parser from a lexer. pub fn new(lexer: Lexer) -> Self { - Self { ast: Ast::new(Rc::clone(&lexer.module_name)), lexer } + Self { + ast: Ast::new(Rc::clone(&lexer.module_name)), + lexer, + } } /// Constructs a compilation error located at the given token. @@ -47,7 +50,11 @@ impl Parser { /// token. Otherwise returns `None`. fn try_next(&mut self, kind: TokenKind) -> Result, LanguageError> { let next_token = self.lexer.peek_token()?; - Ok(if next_token.kind == kind { Some(self.lexer.next_token()?) } else { None }) + Ok(if next_token.kind == kind { + Some(self.lexer.next_token()?) + } else { + None + }) } /// Returns the precedence level of the given token kind. @@ -80,7 +87,10 @@ impl Parser { /// Parses a "unit literal". This is used for all literals that are uniquely identified by a /// single token's kind (such as `nil`.) fn parse_unit(&mut self, token: Token, kind: NodeKind) -> NodeId { - self.ast.build_node(kind, ()).with_location(token.location).done() + self.ast + .build_node(kind, ()) + .with_location(token.location) + .done() } /// Parses a number literal. @@ -150,7 +160,11 @@ impl Parser { /// Parses a unary operator. fn unary_operator(&mut self, token: Token, kind: NodeKind) -> Result { let right = self.parse_expression(Self::precedence(&TokenKind::Star))?; - Ok(self.ast.build_node(kind, right).with_location(token.location).done()) + Ok(self + .ast + .build_node(kind, right) + .with_location(token.location) + .done()) } /// Parses a terminated block. Typically blocks are terminated with `end`. @@ -187,7 +201,10 @@ impl Parser { } dest.push(next(self)?); match self.lexer.next_token()? { - Token { kind: TokenKind::Comma, .. } => (), + Token { + kind: TokenKind::Comma, + .. + } => (), t if is_end(&t.kind) => return Ok(t), token => return Err(self.error(&token, LanguageErrorKind::CommaExpected)), } @@ -219,7 +236,11 @@ impl Parser { match self.lexer.next_token()?.kind { TokenKind::RightParen => { let location = self.ast.location(inner); - Ok(self.ast.build_node(NodeKind::Paren, inner).with_location(location).done()) + Ok(self + .ast + .build_node(NodeKind::Paren, inner) + .with_location(location) + .done()) } TokenKind::Comma => { let mut elements = vec![inner]; @@ -315,12 +336,18 @@ impl Parser { NodeId::EMPTY }; let location = p.ast.location(key); - Ok(p.ast.build_node(NodeKind::Pair, (key, value)).with_location(location).done()) + Ok(p.ast + .build_node(NodeKind::Pair, (key, value)) + .with_location(location) + .done()) }, )?; if let TokenKind::DotDot = &end_token.kind { fields.push( - self.ast.build_node(NodeKind::Rest, ()).with_location(end_token.location).done(), + self.ast + .build_node(NodeKind::Rest, ()) + .with_location(end_token.location) + .done(), ); let _right_brace = self.expect(TokenKind::RightBrace, |_| { LanguageErrorKind::RestMustBeFollowedByRightBrace @@ -336,7 +363,11 @@ impl Parser { fn parse_let_expression(&mut self, token: Token) -> Result { let right = self.parse_expression(0)?; - Ok(self.ast.build_node(NodeKind::Let, right).with_location(token.location).done()) + Ok(self + .ast + .build_node(NodeKind::Let, right) + .with_location(token.location) + .done()) } /// Parses a `do` block. @@ -371,9 +402,13 @@ impl Parser { })?; branches.push( if let Some(condition) = condition { - self.ast.build_node(NodeKind::IfBranch, condition).with_children(branch) + self.ast + .build_node(NodeKind::IfBranch, condition) + .with_children(branch) } else { - self.ast.build_node(NodeKind::ElseBranch, ()).with_children(branch) + self.ast + .build_node(NodeKind::ElseBranch, ()) + .with_children(branch) } .with_location(do_token.location) .done(), @@ -421,8 +456,9 @@ impl Parser { /// Parses a `for` expression. fn parse_for_expression(&mut self, token: Token) -> Result { let binding = self.parse_expression(0)?; - let _in_token = - self.expect(TokenKind::In, |_| LanguageErrorKind::InExpectedAfterForBinding)?; + let _in_token = self.expect(TokenKind::In, |_| { + LanguageErrorKind::InExpectedAfterForBinding + })?; let iterator = self.parse_expression(0)?; let do_token = self.expect(TokenKind::Do, |_| LanguageErrorKind::MissingDo)?; let mut body = Vec::new(); @@ -449,8 +485,9 @@ impl Parser { NodeId::EMPTY }; - let left_paren = - self.expect(TokenKind::LeftParen, |_| LanguageErrorKind::LeftParenExpected)?; + let left_paren = self.expect(TokenKind::LeftParen, |_| { + LanguageErrorKind::LeftParenExpected + })?; let mut parameters = Vec::new(); self.parse_comma_separated(&mut parameters, TokenKind::RightParen, |p| { let name = p.lexer.next_token()?; @@ -459,9 +496,15 @@ impl Parser { // We allow either `constructor` or `static`, but not both. let kind = if let Some(token) = self.try_next(TokenKind::Constructor)? { - self.ast.build_node(NodeKind::Constructor, ()).with_location(token.location).done() + self.ast + .build_node(NodeKind::Constructor, ()) + .with_location(token.location) + .done() } else if let Some(token) = self.try_next(TokenKind::Static)? { - self.ast.build_node(NodeKind::Static, ()).with_location(token.location).done() + self.ast + .build_node(NodeKind::Static, ()) + .with_location(token.location) + .done() } else { NodeId::EMPTY }; @@ -506,14 +549,22 @@ impl Parser { } else { self.parse_expression(0)? }; - Ok(self.ast.build_node(kind, result).with_location(token.location).done()) + Ok(self + .ast + .build_node(kind, result) + .with_location(token.location) + .done()) } /// Parses a struct declaration. fn parse_struct(&mut self, struct_token: Token) -> Result { let name = self.lexer.next_token()?; let name = self.parse_identifier(name)?; - Ok(self.ast.build_node(NodeKind::Struct, name).with_location(struct_token.location).done()) + Ok(self + .ast + .build_node(NodeKind::Struct, name) + .with_location(struct_token.location) + .done()) } /// Parses an `as` block. @@ -567,7 +618,11 @@ impl Parser { TokenKind::At => { let name = self.lexer.next_token()?; let name = self.parse_identifier(name)?; - Ok(self.ast.build_node(NodeKind::Field, name).with_location(token.location).done()) + Ok(self + .ast + .build_node(NodeKind::Field, name) + .with_location(token.location) + .done()) } TokenKind::LeftParen => self.parse_paren_or_tuple(token), @@ -602,7 +657,11 @@ impl Parser { let precedence = Self::precedence(&token.kind) - (Self::associativity(&token.kind) == Associativity::Right) as i8; let right = self.parse_expression(precedence)?; - Ok(self.ast.build_node(kind, (left, right)).with_location(token.location).done()) + Ok(self + .ast + .build_node(kind, (left, right)) + .with_location(token.location) + .done()) } /// Parses a function call. diff --git a/src/ll/value.rs b/src/ll/value.rs index a141cd7..195a555 100644 --- a/src/ll/value.rs +++ b/src/ll/value.rs @@ -107,7 +107,10 @@ impl RawValue { } fn type_error(&self, expected: impl Into>) -> LanguageErrorKind { - LanguageErrorKind::TypeError { expected: expected.into(), got: self.type_name() } + LanguageErrorKind::TypeError { + expected: expected.into(), + got: self.type_name(), + } } /// Returns a boolean value without performing any checks. @@ -174,7 +177,12 @@ impl RawValue { where T: UserData, { - if let Some(value) = self.get_raw_user_data_unchecked().get().as_any().downcast_ref::() { + if let Some(value) = self + .get_raw_user_data_unchecked() + .get() + .as_any() + .downcast_ref::() + { value } else { unreachable_unchecked() @@ -285,7 +293,10 @@ impl RawValue { /// Returns an error if the types of the two values are not the same. pub fn try_partial_cmp(&self, other: &Self) -> Result, LanguageErrorKind> { if self.0.kind() != other.0.kind() { - Err(LanguageErrorKind::TypeError { expected: self.type_name(), got: other.type_name() }) + Err(LanguageErrorKind::TypeError { + expected: self.type_name(), + got: other.type_name(), + }) } else { match self.0.kind() { ValueKind::Nil => Ok(Some(Ordering::Equal)), @@ -387,7 +398,11 @@ impl fmt::Debug for RawValue { write!(f, "{:?}", self.0.get_raw_string_unchecked().get().deref()) } ValueKind::Function => { - write!(f, "", self.0.get_raw_function_unchecked().get_raw()) + write!( + f, + "", + self.0.get_raw_function_unchecked().get_raw() + ) } ValueKind::Struct => dtable(f, self.0.get_raw_struct_unchecked().get().dtable()), ValueKind::Trait => dtable(f, self.0.get_raw_trait_unchecked().get().dtable()), diff --git a/src/ll/value/dicts.rs b/src/ll/value/dicts.rs index 5830259..d9c6cf7 100644 --- a/src/ll/value/dicts.rs +++ b/src/ll/value/dicts.rs @@ -73,10 +73,10 @@ impl Dict { /// Removes the value at the given key and returns it (or `nil` if there was no value). pub fn remove(&self, key: RawValue) -> RawValue { let inner = unsafe { &mut *self.inner.get() }; - match inner - .table - .remove_entry(key.hash(&mut inner.state.build_hasher()), equivalent_key(key)) - { + match inner.table.remove_entry( + key.hash(&mut inner.state.build_hasher()), + equivalent_key(key), + ) { Some((_, v)) => v, None => RawValue::from(()), } @@ -89,7 +89,10 @@ impl Dict { None } else { let hash = key.hash(&mut inner.state.build_hasher()); - inner.table.get(hash, equivalent_key(key)).map(|&(_key, value)| value) + inner + .table + .get(hash, equivalent_key(key)) + .map(|&(_key, value)| value) } } @@ -121,7 +124,9 @@ impl Dict { impl Clone for Dict { fn clone(&self) -> Self { - Self { inner: UnsafeCell::new((unsafe { &*self.inner.get() }).clone()) } + Self { + inner: UnsafeCell::new((unsafe { &*self.inner.get() }).clone()), + } } } diff --git a/src/ll/value/lists.rs b/src/ll/value/lists.rs index 8f91d61..420ccce 100644 --- a/src/ll/value/lists.rs +++ b/src/ll/value/lists.rs @@ -25,7 +25,9 @@ pub struct List { impl List { /// Creates a new, empty list. pub fn new(elements: Vec) -> List { - List { elements: UnsafeCell::new(elements) } + List { + elements: UnsafeCell::new(elements), + } } /// Returns a mutable reference to the vector inside. diff --git a/src/ll/value/structs.rs b/src/ll/value/structs.rs index c607c37..4fb0021 100644 --- a/src/ll/value/structs.rs +++ b/src/ll/value/structs.rs @@ -33,7 +33,9 @@ impl Struct { dtable: UnsafeCell::new(self.dtable().instance.unwrap_unchecked()), sealed: Cell::new(true), fields: UnsafeCell::new( - std::iter::repeat(RawValue::from(())).take(field_count).collect(), + std::iter::repeat(RawValue::from(())) + .take(field_count) + .collect(), ), } } diff --git a/src/ll/value/traits.rs b/src/ll/value/traits.rs index 26e3da9..dbf2ead 100644 --- a/src/ll/value/traits.rs +++ b/src/ll/value/traits.rs @@ -22,16 +22,24 @@ impl Trait { /// Creates a new instance of a trait inside the given GC memory. pub fn create_trait(env: &Environment, gc: &mut Memory, trait_id: TraitIndex) -> GcRaw { - let prototype = env.get_trait(trait_id).expect("trait with given ID does not exist"); + let prototype = env + .get_trait(trait_id) + .expect("trait with given ID does not exist"); let name = &prototype.name; let mut dispatch_table = DispatchTable::new_for_type(Rc::clone(name)); dispatch_table.pretty_name = Rc::from(format!("trait {name}")); for &(method_id, function_id) in &prototype.shims { let function = unsafe { env.get_function_unchecked(function_id) }; - let closure = - gc.allocate(Closure { name: Rc::clone(&function.name), function_id, captures: vec![] }); + let closure = gc.allocate(Closure { + name: Rc::clone(&function.name), + function_id, + captures: vec![], + }); dispatch_table.set_method(method_id, closure); } let dispatch_table = gc.allocate(dispatch_table); - gc.allocate(Trait { id: trait_id, dtable: dispatch_table }) + gc.allocate(Trait { + id: trait_id, + dtable: dispatch_table, + }) } diff --git a/src/ll/vm.rs b/src/ll/vm.rs index f8d1e1d..41b6a90 100644 --- a/src/ll/vm.rs +++ b/src/ll/vm.rs @@ -238,8 +238,11 @@ impl Fiber { /// Returns an upvalue for the local at the given stack slot. fn get_upvalue_for_local(&mut self, stack_slot: u32) -> Pin> { - if let Some((_, upvalue)) = - self.open_upvalues.iter().rev().find(|(slot, _)| *slot == stack_slot) + if let Some((_, upvalue)) = self + .open_upvalues + .iter() + .rev() + .find(|(slot, _)| *slot == stack_slot) { Pin::clone(upvalue) } else { @@ -254,7 +257,8 @@ impl Fiber { /// Allocates `n` storage slots for local variables. fn allocate_chunk_storage_slots(&mut self, n: usize) { - self.stack.extend(std::iter::repeat_with(|| RawValue::from(())).take(n)); + self.stack + .extend(std::iter::repeat_with(|| RawValue::from(())).take(n)); } /// Calls a function. For bytecode functions this saves the stack and begins executing the @@ -279,8 +283,10 @@ impl Fiber { self.allocate_chunk_storage_slots(chunk.preallocate_stack_slots as usize); } FunctionKind::Foreign(f) => { - let arguments = - unsafe { self.stack.get_unchecked(self.stack.len() - argument_count..) }; + let arguments = unsafe { + self.stack + .get_unchecked(self.stack.len() - argument_count..) + }; let result = match f(library, gc, arguments) { Ok(value) => value, Err(kind) => { @@ -359,7 +365,10 @@ impl Fiber { ) -> GcRaw { let function = unsafe { env.get_function_unchecked(function_id) }; let mut captures = Vec::new(); - if let FunctionKind::Bytecode { captured_locals, .. } = &function.kind { + if let FunctionKind::Bytecode { + captured_locals, .. + } = &function.kind + { for capture in captured_locals { captures.push(match capture { CaptureKind::Local(slot) => { @@ -373,7 +382,11 @@ impl Fiber { }); } } - gc.allocate(Closure { name, function_id, captures }) + gc.allocate(Closure { + name, + function_id, + captures, + }) } /// Returns the dispatch table of the given value. @@ -387,9 +400,10 @@ impl Fiber { ValueKind::Function => &library.builtin_dtables.function, ValueKind::Struct => value.get_raw_struct_unchecked().get().dtable(), ValueKind::Trait => value.get_raw_trait_unchecked().get().dtable(), - ValueKind::UserData => { - value.get_raw_user_data_unchecked().get().dtable(Some(library)) - } + ValueKind::UserData => value + .get_raw_user_data_unchecked() + .get() + .dtable(Some(library)), } } } @@ -414,7 +428,12 @@ impl Fiber { fn initialize_dtable_with_trait_methods( &mut self, methods: impl Iterator< - Item = (Rc, MethodParameterCount, ImplementedTraitIndex, FunctionIndex), + Item = ( + Rc, + MethodParameterCount, + ImplementedTraitIndex, + FunctionIndex, + ), >, traits: &[GcRaw], env: &Environment, @@ -475,7 +494,10 @@ impl Fiber { /// Returns an iterator over all GC roots. fn roots<'a>(&'a self, globals: &'a mut Globals) -> impl Iterator + 'a { - globals.iter().chain(self.stack.iter().copied()).chain(self.closure.map(RawValue::from)) + globals + .iter() + .chain(self.stack.iter().copied()) + .chain(self.closure.map(RawValue::from)) } /// Interprets bytecode in the chunk, with the provided user state. @@ -612,8 +634,10 @@ impl Fiber { } let _sentinel = unsafe { self.chunk.read_u32(&mut self.pc) }; - let record: Box = - Box::new(Record { record_type: Rc::clone(record_type), fields }); + let record: Box = Box::new(Record { + record_type: Rc::clone(record_type), + fields, + }); let record = gc.allocate(record); self.push(RawValue::from(record)); } @@ -954,7 +978,10 @@ impl Fiber { } } - let result = self.stack.pop().expect("no result found on the top of the stack"); + let result = self + .stack + .pop() + .expect("no result found on the top of the stack"); self.stack.resize( self.stack.len() - self.chunk.preallocate_stack_slots as usize, diff --git a/tests/api/functions.rs b/tests/api/functions.rs index ff51f71..c1997d5 100644 --- a/tests/api/functions.rs +++ b/tests/api/functions.rs @@ -29,11 +29,16 @@ fn user_data_parameters_can_be_passed_into_functions() { .add_type(TypeBuilder::::new("Vec2").add_static("new", |x, y| Vec2 { x, y })) .reveal(); engine - .add_function("same_vec2", |v: Vec2, x: f32, y: f32| assert_eq!(v, Vec2 { x, y })) + .add_function("same_vec2", |v: Vec2, x: f32, y: f32| { + assert_eq!(v, Vec2 { x, y }) + }) .reveal(); - let _: Value = - engine.start("test.mi", "same_vec2(Vec2.new(1, 2), 1, 2)").reveal().trampoline().reveal(); + let _: Value = engine + .start("test.mi", "same_vec2(Vec2.new(1, 2), 1, 2)") + .reveal() + .trampoline() + .reveal(); } #[test] diff --git a/tests/api/stress.rs b/tests/api/stress.rs index 6d131d5..485973e 100644 --- a/tests/api/stress.rs +++ b/tests/api/stress.rs @@ -7,5 +7,9 @@ fn gc_collect_should_not_cause_use_after_free() { let mut engine = Engine::new(); let _: Value = engine.start("test.mi", "[]").reveal().trampoline().reveal(); let _: Value = engine.start("test.mi", "[]").reveal().trampoline().reveal(); - let _: Value = engine.start("test.mi", "Gc.collect").reveal().trampoline().reveal(); + let _: Value = engine + .start("test.mi", "Gc.collect") + .reveal() + .trampoline() + .reveal(); } diff --git a/tests/api/traits.rs b/tests/api/traits.rs index ba6762a..2c0715e 100644 --- a/tests/api/traits.rs +++ b/tests/api/traits.rs @@ -13,15 +13,22 @@ fn exposing_traits_from_rust() { engine.set("GameLoop", game_loop_trait).reveal(); let game: Value = engine - .start("test.mi", include_str!("traits/exposing_traits_from_rust.mi")) + .start( + "test.mi", + include_str!("traits/exposing_traits_from_rust.mi"), + ) .reveal() .trampoline() .reveal(); - let _: Value = engine.call_method(game.clone(), m_draw, [Value::new(0.1666)]).reveal(); + let _: Value = engine + .call_method(game.clone(), m_draw, [Value::new(0.1666)]) + .reveal(); let _: Value = engine.call_method(game.clone(), m_update, []).reveal(); - let did_draw: bool = engine.call_method(game.clone(), ("did_draw", 0), []).reveal(); + let did_draw: bool = engine + .call_method(game.clone(), ("did_draw", 0), []) + .reveal(); let did_update: bool = engine.call_method(game, ("did_update", 0), []).reveal(); assert!(did_draw); @@ -39,7 +46,10 @@ fn binding_type_that_implements_builtin_traits() { impl CountUp { fn new(from: usize, to: usize) -> Self { - Self { current: from, max: to } + Self { + current: from, + max: to, + } } fn has_next(&self) -> bool { @@ -65,7 +75,10 @@ fn binding_type_that_implements_builtin_traits() { .reveal(); let result: usize = engine - .start("test.mi", include_str!("traits/binding_type_that_implements_builtin_traits.mi")) + .start( + "test.mi", + include_str!("traits/binding_type_that_implements_builtin_traits.mi"), + ) .reveal() .trampoline() .reveal(); diff --git a/tests/api/value.rs b/tests/api/value.rs index 9e859e5..b6a2c1e 100644 --- a/tests/api/value.rs +++ b/tests/api/value.rs @@ -7,15 +7,21 @@ fn passing_tuples_to_mica() { let mut engine = Engine::new(); engine.set("coords", (1, 2, 3)).reveal(); - let _: Value = - engine.start("test.mi", "assert(coords == (1, 2, 3))").reveal().trampoline().reveal(); + let _: Value = engine + .start("test.mi", "assert(coords == (1, 2, 3))") + .reveal() + .trampoline() + .reveal(); } #[test] fn receiving_tuples_from_mica() { let mut engine = Engine::new(); - let coords: (i32, i32, i32) = - engine.start("test.mi", "(1, 2, 3)").reveal().trampoline().reveal(); + let coords: (i32, i32, i32) = engine + .start("test.mi", "(1, 2, 3)") + .reveal() + .trampoline() + .reveal(); assert_eq!(coords, (1, 2, 3)); } diff --git a/tests/runner.rs b/tests/runner.rs index b4d1e43..bad18ca 100644 --- a/tests/runner.rs +++ b/tests/runner.rs @@ -56,7 +56,10 @@ struct TestSpec { impl TestSpec { fn parse(file_name: &str, code: &str) -> Self { let mut parser = SpecParser { - spec: TestSpec { file_name: file_name.to_string(), ..Default::default() }, + spec: TestSpec { + file_name: file_name.to_string(), + ..Default::default() + }, error_lines: vec![], current_line: 1, }; @@ -112,7 +115,9 @@ impl SpecParser { match directive { "error" => self.error_lines.push(argument.to_string()), "line" => { - self.spec.line_markers.insert(argument.to_string(), self.current_line); + self.spec + .line_markers + .insert(argument.to_string(), self.current_line); } _ => return false, } @@ -150,11 +155,17 @@ struct ErrorMatcher<'s> { impl<'s> ErrorMatcher<'s> { fn error_char(&self) -> u8 { - self.error.get(self.position_in_error).copied().unwrap_or(b'\0') + self.error + .get(self.position_in_error) + .copied() + .unwrap_or(b'\0') } fn pattern_char(&self) -> u8 { - self.pattern.get(self.position_in_pattern).copied().unwrap_or(b'\0') + self.pattern + .get(self.position_in_pattern) + .copied() + .unwrap_or(b'\0') } fn match_string(&mut self, s: &str) -> bool { @@ -268,8 +279,13 @@ impl Outcome { fn match_error_against_pattern(error: &str, pattern: &str, spec: &TestSpec) -> bool { let (error, pattern) = (error.as_bytes(), pattern.as_bytes()); - let mut matcher = - ErrorMatcher { spec, error, pattern, position_in_error: 0, position_in_pattern: 0 }; + let mut matcher = ErrorMatcher { + spec, + error, + pattern, + position_in_error: 0, + position_in_pattern: 0, + }; matcher.check() } @@ -419,8 +435,11 @@ fn collect_all_tests(base_path: impl AsRef) -> Vec { let entry = entry.expect("cannot read directory entry"); let file_type = entry.file_type().expect("cannot stat directory entry"); let path = entry.path(); - let file_name = - path.file_name().unwrap().to_str().expect("invalid UTF-8 found in path"); + let file_name = path + .file_name() + .unwrap() + .to_str() + .expect("invalid UTF-8 found in path"); if file_type.is_dir() { let suite = if suite.is_empty() { @@ -431,7 +450,11 @@ fn collect_all_tests(base_path: impl AsRef) -> Vec { let suite = Arc::from(suite); visit(tests, suite, &entry.path()); } else if let Some(test_name) = file_name.strip_suffix(".test.mi") { - tests.push(Test { suite: Arc::clone(&suite), name: test_name.to_owned(), path }); + tests.push(Test { + suite: Arc::clone(&suite), + name: test_name.to_owned(), + path, + }); } } } @@ -460,16 +483,31 @@ fn main() -> ExitCode { let tests = collect_all_tests("tests"); let start_time = Instant::now(); let outcomes: Vec<_> = if args.single_threaded { - tests.iter().map(|test| (test.run(args.include_ignored), test)).collect() + tests + .iter() + .map(|test| (test.run(args.include_ignored), test)) + .collect() } else { - tests.par_iter().map(|test| (test.run(args.include_ignored), test)).collect() + tests + .par_iter() + .map(|test| (test.run(args.include_ignored), test)) + .collect() }; let end_time = Instant::now(); let total = outcomes.len(); - let successful = outcomes.iter().filter(|(outcome, _)| outcome.is_success()).count(); - let failures: Vec<_> = outcomes.iter().filter(|(outcome, _)| outcome.is_failure()).collect(); - let ignored = outcomes.iter().filter(|(outcome, _)| outcome.is_ignored()).count(); + let successful = outcomes + .iter() + .filter(|(outcome, _)| outcome.is_success()) + .count(); + let failures: Vec<_> = outcomes + .iter() + .filter(|(outcome, _)| outcome.is_failure()) + .collect(); + let ignored = outcomes + .iter() + .filter(|(outcome, _)| outcome.is_ignored()) + .count(); if !failures.is_empty() { for (outcome, test) in &failures { diff --git a/xtask/src/codegen/function_variants.rs b/xtask/src/codegen/function_variants.rs index 53d42d6..a5e41c4 100644 --- a/xtask/src/codegen/function_variants.rs +++ b/xtask/src/codegen/function_variants.rs @@ -108,7 +108,9 @@ fn generate_for_params( variant: "InfallibleRawSelf", function_param_user_types: &["RawSelf<'_>"], parameter_count_definition: METHOD_PARAMETER_COUNT, - self_mode: SelfMode::Enabled { setup_code: SETUP_RAW_SELF }, + self_mode: SelfMode::Enabled { + setup_code: SETUP_RAW_SELF, + }, ..infallible_options }, )?; @@ -118,7 +120,9 @@ fn generate_for_params( variant: "FallibleRawSelf", function_param_user_types: &["RawSelf<'_>"], parameter_count_definition: METHOD_PARAMETER_COUNT, - self_mode: SelfMode::Enabled { setup_code: SETUP_RAW_SELF }, + self_mode: SelfMode::Enabled { + setup_code: SETUP_RAW_SELF, + }, ..fallible_options }, )?; @@ -145,7 +149,9 @@ fn generate_for_params( parameter_count_definition: METHOD_PARAMETER_COUNT, user_generic_params: &["Ret", "Recv"], user_generic_bounds: &[BOUND_RET, BOUND_SELF], - self_mode: SelfMode::Enabled { setup_code: SETUP_SELF }, + self_mode: SelfMode::Enabled { + setup_code: SETUP_SELF, + }, ..infallible_options }, )?; @@ -158,7 +164,9 @@ fn generate_for_params( parameter_count_definition: METHOD_PARAMETER_COUNT, user_generic_params: &["Ret", "Recv"], user_generic_bounds: &[BOUND_RET, BOUND_MUT_SELF], - self_mode: SelfMode::Enabled { setup_code: SETUP_MUT_SELF }, + self_mode: SelfMode::Enabled { + setup_code: SETUP_MUT_SELF, + }, ..infallible_options }, )?; @@ -171,7 +179,9 @@ fn generate_for_params( parameter_count_definition: METHOD_PARAMETER_COUNT, user_generic_params: &["Ret", "Err", "Recv"], user_generic_bounds: &[BOUND_RET, BOUND_ERR, BOUND_SELF], - self_mode: SelfMode::Enabled { setup_code: SETUP_SELF }, + self_mode: SelfMode::Enabled { + setup_code: SETUP_SELF, + }, ..fallible_options }, )?; @@ -184,7 +194,9 @@ fn generate_for_params( parameter_count_definition: METHOD_PARAMETER_COUNT, user_generic_params: &["Ret", "Err", "Recv"], user_generic_bounds: &[BOUND_RET, BOUND_ERR, BOUND_MUT_SELF], - self_mode: SelfMode::Enabled { setup_code: SETUP_MUT_SELF }, + self_mode: SelfMode::Enabled { + setup_code: SETUP_MUT_SELF, + }, ..fallible_options }, )?; @@ -243,7 +255,11 @@ fn generate_variant( user_generic_bounds .iter() .map(|str| str.to_string()) - .chain(function_param_value_types.iter().map(|p| format!("{p}: TryFromValue"))) + .chain( + function_param_value_types + .iter() + .map(|p| format!("{p}: TryFromValue")), + ) .map(|bound| format!("{bound} + 'static")), ); @@ -254,8 +270,11 @@ fn generate_variant( into_raw_foreign_function.push_str(setup_code); } - let variable_list: Vec<_> = - function_param_value_types.iter().enumerate().map(|(i, _)| format!("arg_{i}")).collect(); + let variable_list: Vec<_> = function_param_value_types + .iter() + .enumerate() + .map(|(i, _)| format!("arg_{i}")) + .collect(); for (i, variable) in variable_list.iter().enumerate() { writeln!( into_raw_foreign_function, diff --git a/xtask/src/main.rs b/xtask/src/main.rs index a37b70e..97834a9 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -19,7 +19,9 @@ enum Command { fn main() { let subscriber = tracing_subscriber::registry() .with( - EnvFilter::builder().with_default_directive(LevelFilter::DEBUG.into()).from_env_lossy(), + EnvFilter::builder() + .with_default_directive(LevelFilter::DEBUG.into()) + .from_env_lossy(), ) .with(tracing_subscriber::fmt::layer().without_time()); tracing::subscriber::set_global_default(subscriber)