diff --git a/src/ast/stmt.rs b/src/ast/stmt.rs index 6a5eac4..5f7fe92 100644 --- a/src/ast/stmt.rs +++ b/src/ast/stmt.rs @@ -99,7 +99,7 @@ impl Stmt { let last_span = otherwise .as_ref() - .map(|s| s.span()) + .map(Spanned::span) .unwrap_or_else(|| then.span()); let span = if_token.span.join(&last_span); @@ -169,7 +169,7 @@ impl Stmt { let mut inner_stmts = vec![body]; if let Some((increment, right_paren)) = increment { let increment = Self::expr(increment, &right_paren); - inner_stmts.push(increment) + inner_stmts.push(increment); } let while_body = Self::block(&open_brace, inner_stmts, &close_brace); diff --git a/src/callable/function.rs b/src/callable/function.rs index cae0533..335743a 100644 --- a/src/callable/function.rs +++ b/src/callable/function.rs @@ -37,7 +37,7 @@ impl Callable for LoxFunction { // Define a new env for the call for (param, arg) in self.params.clone().into_iter().zip(args) { - env.define(param, arg) + env.define(param, arg); } // Execute the body diff --git a/src/environment.rs b/src/environment.rs index cd73321..b79ceb5 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -35,12 +35,12 @@ impl Env { } #[must_use = "you should check the assignment was successful"] - pub fn assign_at_depth(&self, name: String, value: Value, depth: usize) -> bool { + pub fn assign_at_depth(&self, name: &str, value: Value, depth: usize) -> bool { self.0.borrow_mut().assign_at_depth(name, value, depth) } #[must_use = "you should check the assignment was successful"] - pub fn assign_global(&self, name: String, value: Value) -> bool { + pub fn assign_global(&self, name: &str, value: Value) -> bool { self.0.borrow_mut().assign_global(name, value) } @@ -86,14 +86,14 @@ impl Inner { self.values.insert(name, value); } - fn assign(&mut self, name: String, value: Value) -> bool { + fn assign(&mut self, name: &str, value: Value) -> bool { self.values - .get_mut(&name) + .get_mut(name) .map(|entry| *entry = value) .is_some() } - fn assign_at_depth(&mut self, name: String, value: Value, depth: usize) -> bool { + fn assign_at_depth(&mut self, name: &str, value: Value, depth: usize) -> bool { if depth == 0 { self.assign(name, value) } else { @@ -104,10 +104,10 @@ impl Inner { } } - fn assign_global(&mut self, name: String, value: Value) -> bool { + fn assign_global(&mut self, name: &str, value: Value) -> bool { self.parent .as_ref() - .map(|parent| parent.assign_global(name.clone(), value.clone())) + .map(|parent| parent.assign_global(name, value.clone())) .unwrap_or_else(|| self.assign(name, value)) } @@ -166,12 +166,8 @@ mod tests { let child = parent.new_child(); parent.define("foo".to_string(), Value::String("definition".to_string())); - assert!(child.assign_at_depth( - "foo".to_string(), - Value::String("assignment".to_string()), - 1 - )); - assert!(!child.assign_at_depth("foo".to_string(), Value::String("invalid".to_string()), 0)); + assert!(child.assign_at_depth("foo", Value::String("assignment".to_string()), 1)); + assert!(!child.assign_at_depth("foo", Value::String("invalid".to_string()), 0)); assert_some_eq!(parent.get("foo"), Value::String("assignment".to_string())); } @@ -189,7 +185,7 @@ mod tests { Value::String("child definition".to_string()), ); - assert!(child.assign_global("foo".to_string(), Value::String("assignment".to_string()))); + assert!(child.assign_global("foo", Value::String("assignment".to_string()))); assert_some_eq!(global.get("foo"), Value::String("assignment".to_string())); } diff --git a/src/interpreter.rs b/src/interpreter.rs index cc3cc35..ca69ad8 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -159,10 +159,8 @@ impl<'a> Interpreter<'a> { let value = self.interpret_expr(value, env)?; name.depth() - .map(|depth| { - env.assign_at_depth(name.as_ref().to_string(), value.clone(), depth) - }) - .unwrap_or_else(|| env.assign_global(name.as_ref().to_string(), value.clone())) + .map(|depth| env.assign_at_depth(name.as_ref(), value.clone(), depth)) + .unwrap_or_else(|| env.assign_global(name.as_ref(), value.clone())) .then_some(value) .ok_or_else(|| { RuntimeError::undefined_var(&Spanned::new( @@ -549,7 +547,7 @@ mod test { assert_eq!( output.lines().collect::>(), ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] - ) + ); } #[test] @@ -580,7 +578,7 @@ mod test { #[test] fn closures_close() { let (_, out) = execute_stmts( - r#" + " fun makeCounter() { var i = 0; fun count() { @@ -592,7 +590,7 @@ mod test { var counter = makeCounter(); counter(); counter(); - "#, + ", ); assert_eq!(out, "1\n2"); } @@ -633,7 +631,7 @@ mod test { ("nil or true", Value::Bool(true)), ] { let value = interpret_expr_to_value(input); - assert_eq!(value, expected_value, "input: `{input}`") + assert_eq!(value, expected_value, "input: `{input}`"); } } @@ -684,11 +682,12 @@ mod test { ("nil", "nil", true), ("nil", "1", false), ] { - let input_eq = format!("{l} == {r}"); - assert_eq!(interpret_expr_to_value(&input_eq), Value::Bool(expected_eq)); - let input_neq = format!("{l} != {r}"); assert_eq!( - interpret_expr_to_value(&input_neq), + interpret_expr_to_value(&format!("{l} == {r}")), + Value::Bool(expected_eq) + ); + assert_eq!( + interpret_expr_to_value(&format!("{l} != {r}")), Value::Bool(!expected_eq) ); } diff --git a/src/parser.rs b/src/parser.rs index 912bb93..e96f3f9 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -64,13 +64,13 @@ impl Parser { #[tracing::instrument(name = "decl", skip_all)] fn parse_var_decl_or_pass(&mut self) -> Result> { match self.pop_if_matches(MatchToken::Var) { - Some(var) => self.finish_var_decl(var), + Some(var) => self.finish_var_decl(&var), None => self.parse_fun_decl_or_pass(), } } /// Parse everything after `var` in a `VarDecl` statement - fn finish_var_decl(&mut self, var_token: Token) -> Result> { + fn finish_var_decl(&mut self, var_token: &Token) -> Result> { debug_assert_eq!(var_token.kind, TokenKind::Var); let name = self.expect_identifier()?; @@ -83,7 +83,7 @@ impl Parser { let semi = self .pop_if_matches(MatchToken::Semicolon) .ok_or_else(|| ParserError::missing_semicolon(self.previous()))?; - Ok(Stmt::var_decl(&var_token, name, initializer, &semi)) + Ok(Stmt::var_decl(var_token, name, initializer, &semi)) } #[tracing::instrument(skip_all)] @@ -101,7 +101,7 @@ impl Parser { // Parse the params list let params = - self.parse_comma_separated_list(MatchToken::RightParen, |p| p.expect_identifier())?; + self.parse_comma_separated_list(MatchToken::RightParen, Self::expect_identifier)?; // Consume the closing `)` self.pop_if_matches(MatchToken::RightParen).ok_or_else(|| { @@ -206,7 +206,7 @@ impl Parser { None } else if let Some(var) = self.pop_if_matches(MatchToken::Var) { // requires and consumes a semicolon - Some(self.finish_var_decl(var)?) + Some(self.finish_var_decl(&var)?) } else { let expr = self.parse_expr()?; let semi = self @@ -277,18 +277,16 @@ impl Parser { return self.parse_print_or_expr_stmt(); }; - let (value, semicolon) = match self.pop_if_matches(MatchToken::Semicolon) { - Some(semicolon) => (None, semicolon), - None => { - let value = self.parse_expr()?; - let semicolon = self - .pop_if_matches(MatchToken::Semicolon) - .ok_or_else(|| ParserError::missing_semicolon(self.previous()))?; - (Some(value), semicolon) - } + if let Some(semicolon) = self.pop_if_matches(MatchToken::Semicolon) { + return Ok(Stmt::return_stmt(&return_token, None, &semicolon)); }; - Ok(Stmt::return_stmt(&return_token, value, &semicolon)) + let value = self.parse_expr()?; + let semicolon = self + .pop_if_matches(MatchToken::Semicolon) + .ok_or_else(|| ParserError::missing_semicolon(self.previous()))?; + + Ok(Stmt::return_stmt(&return_token, Some(value), &semicolon)) } #[tracing::instrument(name = "stmt", skip_all)] @@ -486,8 +484,7 @@ impl Parser { }; // Parse the arguments as expressions - let args = - self.parse_comma_separated_list(MatchToken::RightParen, |p| p.parse_expr())?; + let args = self.parse_comma_separated_list(MatchToken::RightParen, Self::parse_expr)?; // Ensure we have a closing `)` let right_paren = self.pop_if_matches(MatchToken::RightParen).ok_or_else(|| { diff --git a/src/resolver.rs b/src/resolver.rs index 59ab62e..25eec12 100644 --- a/src/resolver.rs +++ b/src/resolver.rs @@ -20,7 +20,7 @@ impl Resolver { } fn begin_scope(&mut self) { - self.scopes.push(Scope::default()) + self.scopes.push(Scope::default()); } fn end_scope(&mut self) { @@ -29,15 +29,14 @@ impl Resolver { fn declare(&mut self, name: String) { if let Some(scope) = self.scopes.last_mut() { - scope.declare(name) + scope.declare(name); } } fn last_scope_has_var(&self, name: &str) -> bool { self.scopes .last() - .map(|scope| scope.is_declared(name)) - .unwrap_or_default() + .is_some_and(|scope| scope.is_declared(name)) } fn is_declared(&self, name: &str) -> bool { @@ -109,9 +108,9 @@ impl Resolver { self.declare(name.clone()); if let Some(initializer) = initializer { - self.resolve_expr(initializer)? + self.resolve_expr(initializer)?; } - self.define(name.clone()) + self.define(name.clone()); } Stmt::Expr(expr) => self.resolve_expr(expr)?, @@ -164,7 +163,7 @@ impl Resolver { match target.as_mut() { Lval::Ident { name } => { if let Some(distance) = self.resolution_distance(name.as_ref().as_ref()) { - name.resolve(distance) + name.resolve(distance); } } } @@ -245,10 +244,8 @@ impl MaybeResolved { fn resolve(&mut self, distance: usize) { self.state = ResolutionState::Resolved(distance); } -} -impl AsRef for MaybeResolved { - fn as_ref(&self) -> &T { + pub fn as_ref(&self) -> &T { &self.inner } } diff --git a/src/scanner.rs b/src/scanner.rs index 25ac21c..20cebee 100644 --- a/src/scanner.rs +++ b/src/scanner.rs @@ -89,9 +89,9 @@ impl Scanner { self.pop_until_matches('\n'); tracing::debug!("discarding comment"); return Ok(None); - } else { - Slash } + + Slash } '"' => { let span = tracing::trace_span!("scan_string_literal", %current_token_start); @@ -448,7 +448,7 @@ mod test { assert_input_scans_to( "9999999999.9999999999", &[NumberLit { - value: 9999999999.9999999999, + value: 9_999_999_999.999_999_999_9, }], ); assert_input_scans_to(&PI.to_string(), &[NumberLit { value: PI }]);