This commit is contained in:
adamnemecek 2024-05-14 20:07:41 -07:00 committed by GitHub
parent c796a253af
commit b85540007e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 171 additions and 181 deletions

View File

@ -14,7 +14,7 @@ impl<'src> Analyzer<'src> {
asts: &HashMap<PathBuf, Ast<'src>>,
root: &Path,
) -> CompileResult<'src, Justfile<'src>> {
Analyzer::default().justfile(loaded, paths, asts, root)
Self::default().justfile(loaded, paths, asts, root)
}
fn justfile(

View File

@ -34,21 +34,21 @@ impl Color {
pub(crate) fn auto() -> Self {
Self {
use_color: UseColor::Auto,
..Color::default()
..Self::default()
}
}
pub(crate) fn always() -> Self {
Self {
use_color: UseColor::Always,
..Color::default()
..Self::default()
}
}
pub(crate) fn never() -> Self {
Self {
use_color: UseColor::Never,
..Color::default()
..Self::default()
}
}

View File

@ -14,7 +14,7 @@ impl<'src> CompileError<'src> {
pub(crate) fn new(token: Token<'src>, kind: CompileErrorKind<'src>) -> CompileError<'src> {
Self {
token,
kind: Box::new(kind),
kind: kind.into(),
}
}
}

View File

@ -8,9 +8,9 @@ impl Compiler {
loader: &'src Loader,
root: &Path,
) -> RunResult<'src, Compilation<'src>> {
let mut asts: HashMap<PathBuf, Ast> = HashMap::new();
let mut paths: HashMap<PathBuf, PathBuf> = HashMap::new();
let mut srcs: HashMap<PathBuf, &str> = HashMap::new();
let mut asts = HashMap::<PathBuf, Ast>::new();
let mut paths = HashMap::<PathBuf, PathBuf>::new();
let mut srcs = HashMap::<PathBuf, &str>::new();
let mut loaded = Vec::new();
let mut stack = Vec::new();

View File

@ -1290,7 +1290,7 @@ mod tests {
test! {
name: shell_args_clear,
args: ["--clear-shell-args"],
shell_args: Some(vec![]),
shell_args: Some(Vec::new()),
}
@ -1304,14 +1304,14 @@ mod tests {
test! {
name: shell_args_set_and_clear,
args: ["--shell-arg", "bar", "--clear-shell-args"],
shell_args: Some(vec![]),
shell_args: Some(Vec::new()),
}
test! {
name: shell_args_set_multiple_and_clear,
args: ["--shell-arg", "bar", "--shell-arg", "baz", "--clear-shell-args"],
shell_args: Some(vec![]),
shell_args: Some(Vec::new()),
}

View File

@ -53,23 +53,23 @@ impl<'src> Expression<'src> {
impl<'src> Display for Expression<'src> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
match self {
Expression::Assert { condition, error } => write!(f, "assert({condition}, {error})"),
Expression::Backtick { token, .. } => write!(f, "{}", token.lexeme()),
Expression::Join { lhs: None, rhs } => write!(f, "/ {rhs}"),
Expression::Join {
Self::Assert { condition, error } => write!(f, "assert({condition}, {error})"),
Self::Backtick { token, .. } => write!(f, "{}", token.lexeme()),
Self::Join { lhs: None, rhs } => write!(f, "/ {rhs}"),
Self::Join {
lhs: Some(lhs),
rhs,
} => write!(f, "{lhs} / {rhs}"),
Expression::Concatenation { lhs, rhs } => write!(f, "{lhs} + {rhs}"),
Expression::Conditional {
Self::Concatenation { lhs, rhs } => write!(f, "{lhs} + {rhs}"),
Self::Conditional {
condition,
then,
otherwise,
} => write!(f, "if {condition} {{ {then} }} else {{ {otherwise} }}"),
Expression::StringLiteral { string_literal } => write!(f, "{string_literal}"),
Expression::Variable { name } => write!(f, "{}", name.lexeme()),
Expression::Call { thunk } => write!(f, "{thunk}"),
Expression::Group { contents } => write!(f, "({contents})"),
Self::StringLiteral { string_literal } => write!(f, "{string_literal}"),
Self::Variable { name } => write!(f, "{}", name.lexeme()),
Self::Call { thunk } => write!(f, "{thunk}"),
Self::Group { contents } => write!(f, "({contents})"),
}
}
}

View File

@ -25,10 +25,10 @@ pub(crate) enum Item<'src> {
impl<'src> Display for Item<'src> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Item::Alias(alias) => write!(f, "{alias}"),
Item::Assignment(assignment) => write!(f, "{assignment}"),
Item::Comment(comment) => write!(f, "{comment}"),
Item::Import {
Self::Alias(alias) => write!(f, "{alias}"),
Self::Assignment(assignment) => write!(f, "{assignment}"),
Self::Comment(comment) => write!(f, "{comment}"),
Self::Import {
relative, optional, ..
} => {
write!(f, "import")?;
@ -39,7 +39,7 @@ impl<'src> Display for Item<'src> {
write!(f, " {relative}")
}
Item::Module {
Self::Module {
name,
relative,
optional,
@ -59,8 +59,8 @@ impl<'src> Display for Item<'src> {
Ok(())
}
Item::Recipe(recipe) => write!(f, "{}", recipe.color_display(Color::never())),
Item::Set(set) => write!(f, "{set}"),
Self::Recipe(recipe) => write!(f, "{}", recipe.color_display(Color::never())),
Self::Set(set) => write!(f, "{set}"),
}
}
}

View File

@ -38,16 +38,16 @@ pub(crate) struct Lexer<'src> {
impl<'src> Lexer<'src> {
/// Lex `src`
pub(crate) fn lex(path: &'src Path, src: &'src str) -> CompileResult<'src, Vec<Token<'src>>> {
Lexer::new(path, src).tokenize()
Self::new(path, src).tokenize()
}
#[cfg(test)]
pub(crate) fn test_lex(src: &'src str) -> CompileResult<'src, Vec<Token<'src>>> {
Lexer::new("justfile".as_ref(), src).tokenize()
Self::new("justfile".as_ref(), src).tokenize()
}
/// Create a new Lexer to lex `src`
fn new(path: &'src Path, src: &'src str) -> Lexer<'src> {
fn new(path: &'src Path, src: &'src str) -> Self {
let mut chars = src.chars();
let next = chars.next();
@ -57,7 +57,7 @@ impl<'src> Lexer<'src> {
line: 0,
};
Lexer {
Self {
indentation: vec![""],
tokens: Vec::new(),
token_start: start,
@ -282,11 +282,7 @@ impl<'src> Lexer<'src> {
/// True if `c` can be a continuation character of an identifier
fn is_identifier_continue(c: char) -> bool {
if Self::is_identifier_start(c) {
return true;
}
matches!(c, '0'..='9' | '-')
Self::is_identifier_start(c) || matches!(c, '0'..='9' | '-')
}
/// Consume the text and produce a series of tokens
@ -1028,7 +1024,7 @@ mod tests {
length,
path: "justfile".as_ref(),
},
kind: Box::new(kind),
kind: kind.into(),
};
assert_eq!(have, want);
}

View File

@ -6,15 +6,15 @@ pub struct List<T: Display, I: Iterator<Item = T> + Clone> {
}
impl<T: Display, I: Iterator<Item = T> + Clone> List<T, I> {
pub fn or<II: IntoIterator<Item = T, IntoIter = I>>(values: II) -> List<T, I> {
List {
pub fn or<II: IntoIterator<Item = T, IntoIter = I>>(values: II) -> Self {
Self {
conjunction: "or",
values: values.into_iter(),
}
}
pub fn and<II: IntoIterator<Item = T, IntoIter = I>>(values: II) -> List<T, I> {
List {
pub fn and<II: IntoIterator<Item = T, IntoIter = I>>(values: II) -> Self {
Self {
conjunction: "and",
values: values.into_iter(),
}

View File

@ -7,7 +7,7 @@ pub(crate) struct Loader {
impl Loader {
pub(crate) fn new() -> Self {
Loader {
Self {
srcs: Arena::new(),
paths: Arena::new(),
}

View File

@ -18,10 +18,10 @@ impl<'src> Node<'src> for Ast<'src> {
impl<'src> Node<'src> for Item<'src> {
fn tree(&self) -> Tree<'src> {
match self {
Item::Alias(alias) => alias.tree(),
Item::Assignment(assignment) => assignment.tree(),
Item::Comment(comment) => comment.tree(),
Item::Import {
Self::Alias(alias) => alias.tree(),
Self::Assignment(assignment) => assignment.tree(),
Self::Comment(comment) => comment.tree(),
Self::Import {
relative, optional, ..
} => {
let mut tree = Tree::atom("import");
@ -32,7 +32,7 @@ impl<'src> Node<'src> for Item<'src> {
tree.push(format!("{relative}"))
}
Item::Module {
Self::Module {
name,
optional,
relative,
@ -52,8 +52,8 @@ impl<'src> Node<'src> for Item<'src> {
tree
}
Item::Recipe(recipe) => recipe.tree(),
Item::Set(set) => set.tree(),
Self::Recipe(recipe) => recipe.tree(),
Self::Set(set) => set.tree(),
}
}
}
@ -83,7 +83,7 @@ impl<'src> Node<'src> for Assignment<'src> {
impl<'src> Node<'src> for Expression<'src> {
fn tree(&self) -> Tree<'src> {
match self {
Expression::Assert {
Self::Assert {
condition: Condition { lhs, rhs, operator },
error,
} => Tree::atom(Keyword::Assert.lexeme())
@ -91,8 +91,8 @@ impl<'src> Node<'src> for Expression<'src> {
.push(operator.to_string())
.push(rhs.tree())
.push(error.tree()),
Expression::Concatenation { lhs, rhs } => Tree::atom("+").push(lhs.tree()).push(rhs.tree()),
Expression::Conditional {
Self::Concatenation { lhs, rhs } => Tree::atom("+").push(lhs.tree()).push(rhs.tree()),
Self::Conditional {
condition: Condition { lhs, rhs, operator },
then,
otherwise,
@ -105,7 +105,7 @@ impl<'src> Node<'src> for Expression<'src> {
tree.push_mut(otherwise.tree());
tree
}
Expression::Call { thunk } => {
Self::Call { thunk } => {
use Thunk::*;
let mut tree = Tree::atom("call");
@ -158,14 +158,14 @@ impl<'src> Node<'src> for Expression<'src> {
tree
}
Expression::Variable { name } => Tree::atom(name.lexeme()),
Expression::StringLiteral {
Self::Variable { name } => Tree::atom(name.lexeme()),
Self::StringLiteral {
string_literal: StringLiteral { cooked, .. },
} => Tree::string(cooked),
Expression::Backtick { contents, .. } => Tree::atom("backtick").push(Tree::string(contents)),
Expression::Group { contents } => Tree::List(vec![contents.tree()]),
Expression::Join { lhs: None, rhs } => Tree::atom("/").push(rhs.tree()),
Expression::Join {
Self::Backtick { contents, .. } => Tree::atom("backtick").push(Tree::string(contents)),
Self::Group { contents } => Tree::List(vec![contents.tree()]),
Self::Join { lhs: None, rhs } => Tree::atom("/").push(rhs.tree()),
Self::Join {
lhs: Some(lhs),
rhs,
} => Tree::atom("/").push(lhs.tree()).push(rhs.tree()),
@ -258,8 +258,8 @@ impl<'src> Node<'src> for Line<'src> {
impl<'src> Node<'src> for Fragment<'src> {
fn tree(&self) -> Tree<'src> {
match self {
Fragment::Text { token } => Tree::string(token.lexeme()),
Fragment::Interpolation { expression } => Tree::List(vec![expression.tree()]),
Self::Text { token } => Tree::string(token.lexeme()),
Self::Interpolation { expression } => Tree::List(vec![expression.tree()]),
}
}
}

View File

@ -479,18 +479,18 @@ impl<'run, 'src> Parser<'run, 'src> {
self.parse_conditional()?
} else if self.accepted(Slash)? {
let lhs = None;
let rhs = Box::new(self.parse_expression()?);
let rhs = self.parse_expression()?.into();
Expression::Join { lhs, rhs }
} else {
let value = self.parse_value()?;
if self.accepted(Slash)? {
let lhs = Some(Box::new(value));
let rhs = Box::new(self.parse_expression()?);
let rhs = self.parse_expression()?.into();
Expression::Join { lhs, rhs }
} else if self.accepted(Plus)? {
let lhs = Box::new(value);
let rhs = Box::new(self.parse_expression()?);
let lhs = value.into();
let rhs = self.parse_expression()?.into();
Expression::Concatenation { lhs, rhs }
} else {
value
@ -525,8 +525,8 @@ impl<'run, 'src> Parser<'run, 'src> {
Ok(Expression::Conditional {
condition,
then: Box::new(then),
otherwise: Box::new(otherwise),
then: then.into(),
otherwise: otherwise.into(),
})
}
@ -542,8 +542,8 @@ impl<'run, 'src> Parser<'run, 'src> {
};
let rhs = self.parse_expression()?;
Ok(Condition {
lhs: Box::new(lhs),
rhs: Box::new(rhs),
lhs: lhs.into(),
rhs: rhs.into(),
operator,
})
}
@ -592,7 +592,7 @@ impl<'run, 'src> Parser<'run, 'src> {
}
} else if self.next_is(ParenL) {
self.presume(ParenL)?;
let contents = Box::new(self.parse_expression()?);
let contents = self.parse_expression()?.into();
self.expect(ParenR)?;
Ok(Expression::Group { contents })
} else {
@ -1055,7 +1055,7 @@ mod tests {
length,
path: "justfile".as_ref(),
},
kind: Box::new(kind),
kind: kind.into(),
};
assert_eq!(have, want);
}

View File

@ -1,7 +1,4 @@
use {
super::*,
std::process::{ExitStatus, Stdio},
};
use super::*;
/// Return a `Error::Signal` if the process was terminated by a signal,
/// otherwise return an `Error::UnknownFailure`
@ -303,7 +300,7 @@ impl<'src, D> Recipe<'src, D> {
config: &Config,
mut evaluator: Evaluator<'src, 'run>,
) -> RunResult<'src, ()> {
let mut evaluated_lines = vec![];
let mut evaluated_lines = Vec::new();
for line in &self.body {
evaluated_lines.push(evaluator.evaluate_line(line, false)?);
}

View File

@ -2,19 +2,19 @@ use super::*;
#[derive(Debug)]
pub(crate) struct Scope<'src: 'run, 'run> {
parent: Option<&'run Scope<'src, 'run>>,
parent: Option<&'run Self>,
bindings: Table<'src, Binding<'src, String>>,
}
impl<'src, 'run> Scope<'src, 'run> {
pub(crate) fn child(&'run self) -> Scope<'src, 'run> {
pub(crate) fn child(&'run self) -> Self {
Self {
parent: Some(self),
bindings: Table::new(),
}
}
pub(crate) fn new() -> Scope<'src, 'run> {
pub(crate) fn new() -> Self {
Self {
parent: None,
bindings: Table::new(),
@ -50,7 +50,7 @@ impl<'src, 'run> Scope<'src, 'run> {
self.bindings.keys().copied()
}
pub(crate) fn parent(&self) -> Option<&'run Scope<'src, 'run>> {
pub(crate) fn parent(&self) -> Option<&'run Self> {
self.parent
}
}

View File

@ -21,17 +21,17 @@ pub(crate) enum Setting<'src> {
impl<'src> Display for Setting<'src> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
match self {
Setting::AllowDuplicateRecipes(value)
| Setting::AllowDuplicateVariables(value)
| Setting::DotenvLoad(value)
| Setting::Export(value)
| Setting::Fallback(value)
| Setting::IgnoreComments(value)
| Setting::PositionalArguments(value)
| Setting::Quiet(value)
| Setting::WindowsPowerShell(value) => write!(f, "{value}"),
Setting::Shell(shell) | Setting::WindowsShell(shell) => write!(f, "{shell}"),
Setting::DotenvFilename(value) | Setting::DotenvPath(value) | Setting::Tempdir(value) => {
Self::AllowDuplicateRecipes(value)
| Self::AllowDuplicateVariables(value)
| Self::DotenvLoad(value)
| Self::Export(value)
| Self::Fallback(value)
| Self::IgnoreComments(value)
| Self::PositionalArguments(value)
| Self::Quiet(value)
| Self::WindowsPowerShell(value) => write!(f, "{value}"),
Self::Shell(shell) | Self::WindowsShell(shell) => write!(f, "{shell}"),
Self::DotenvFilename(value) | Self::DotenvPath(value) | Self::Tempdir(value) => {
write!(f, "{value:?}")
}
}

View File

@ -5,7 +5,7 @@ pub(crate) struct Shebang<'line> {
}
impl<'line> Shebang<'line> {
pub(crate) fn new(line: &'line str) -> Option<Shebang<'line>> {
pub(crate) fn new(line: &'line str) -> Option<Self> {
if !line.starts_with("#!") {
return None;
}
@ -24,7 +24,7 @@ impl<'line> Shebang<'line> {
return None;
}
Some(Shebang {
Some(Self {
interpreter,
argument,
})

View File

@ -45,7 +45,7 @@ pub struct Summary {
}
impl Summary {
fn new(justfile: &full::Justfile) -> Summary {
fn new(justfile: &full::Justfile) -> Self {
let mut aliases = BTreeMap::new();
for alias in justfile.aliases.values() {
@ -55,7 +55,7 @@ impl Summary {
.push(alias.name.to_string());
}
Summary {
Self {
recipes: justfile
.recipes
.iter()
@ -87,8 +87,8 @@ pub struct Recipe {
}
impl Recipe {
fn new(recipe: &full::Recipe, aliases: Vec<String>) -> Recipe {
Recipe {
fn new(recipe: &full::Recipe, aliases: Vec<String>) -> Self {
Self {
private: recipe.private,
shebang: recipe.shebang,
quiet: recipe.quiet,
@ -108,8 +108,8 @@ pub struct Parameter {
}
impl Parameter {
fn new(parameter: &full::Parameter) -> Parameter {
Parameter {
fn new(parameter: &full::Parameter) -> Self {
Self {
kind: ParameterKind::new(parameter.kind),
name: parameter.name.lexeme().to_owned(),
default: parameter.default.as_ref().map(Expression::new),
@ -140,8 +140,8 @@ pub struct Line {
}
impl Line {
fn new(line: &full::Line) -> Line {
Line {
fn new(line: &full::Line) -> Self {
Self {
fragments: line.fragments.iter().map(Fragment::new).collect(),
}
}
@ -154,12 +154,12 @@ pub enum Fragment {
}
impl Fragment {
fn new(fragment: &full::Fragment) -> Fragment {
fn new(fragment: &full::Fragment) -> Self {
match fragment {
full::Fragment::Text { token } => Fragment::Text {
full::Fragment::Text { token } => Self::Text {
text: token.lexeme().to_owned(),
},
full::Fragment::Interpolation { expression } => Fragment::Expression {
full::Fragment::Interpolation { expression } => Self::Expression {
expression: Expression::new(expression),
},
}
@ -173,8 +173,8 @@ pub struct Assignment {
}
impl Assignment {
fn new(assignment: &full::Assignment) -> Assignment {
Assignment {
fn new(assignment: &full::Assignment) -> Self {
Self {
exported: assignment.export,
expression: Expression::new(&assignment.value),
}
@ -218,7 +218,7 @@ pub enum Expression {
}
impl Expression {
fn new(expression: &full::Expression) -> Expression {
fn new(expression: &full::Expression) -> Self {
use full::Expression::*;
match expression {
Assert {
@ -232,51 +232,51 @@ impl Expression {
},
error: Box::new(Expression::new(error)),
},
Backtick { contents, .. } => Expression::Backtick {
Backtick { contents, .. } => Self::Backtick {
command: (*contents).clone(),
},
Call { thunk } => match thunk {
full::Thunk::Nullary { name, .. } => Expression::Call {
full::Thunk::Nullary { name, .. } => Self::Call {
name: name.lexeme().to_owned(),
arguments: Vec::new(),
},
full::Thunk::Unary { name, arg, .. } => Expression::Call {
full::Thunk::Unary { name, arg, .. } => Self::Call {
name: name.lexeme().to_owned(),
arguments: vec![Expression::new(arg)],
arguments: vec![Self::new(arg)],
},
full::Thunk::UnaryOpt {
name,
args: (a, opt_b),
..
} => {
let mut arguments = vec![];
let mut arguments = Vec::new();
if let Some(b) = opt_b.as_ref() {
arguments.push(Expression::new(b));
arguments.push(Self::new(b));
}
arguments.push(Expression::new(a));
Expression::Call {
arguments.push(Self::new(a));
Self::Call {
name: name.lexeme().to_owned(),
arguments,
}
}
full::Thunk::Binary {
name, args: [a, b], ..
} => Expression::Call {
} => Self::Call {
name: name.lexeme().to_owned(),
arguments: vec![Expression::new(a), Expression::new(b)],
arguments: vec![Self::new(a), Self::new(b)],
},
full::Thunk::BinaryPlus {
name,
args: ([a, b], rest),
..
} => {
let mut arguments = vec![Expression::new(a), Expression::new(b)];
let mut arguments = vec![Self::new(a), Self::new(b)];
for arg in rest {
arguments.push(Expression::new(arg));
arguments.push(Self::new(arg));
}
Expression::Call {
Self::Call {
name: name.lexeme().to_owned(),
arguments,
}
@ -285,37 +285,37 @@ impl Expression {
name,
args: [a, b, c],
..
} => Expression::Call {
} => Self::Call {
name: name.lexeme().to_owned(),
arguments: vec![Expression::new(a), Expression::new(b), Expression::new(c)],
arguments: vec![Self::new(a), Self::new(b), Self::new(c)],
},
},
Concatenation { lhs, rhs } => Expression::Concatenation {
lhs: Box::new(Expression::new(lhs)),
rhs: Box::new(Expression::new(rhs)),
Concatenation { lhs, rhs } => Self::Concatenation {
lhs: Self::new(lhs).into(),
rhs: Self::new(rhs).into(),
},
Join { lhs, rhs } => Expression::Join {
lhs: lhs.as_ref().map(|lhs| Box::new(Expression::new(lhs))),
rhs: Box::new(Expression::new(rhs)),
Join { lhs, rhs } => Self::Join {
lhs: lhs.as_ref().map(|lhs| Self::new(lhs).into()),
rhs: Self::new(rhs).into(),
},
Conditional {
condition: full::Condition { lhs, rhs, operator },
otherwise,
then,
} => Expression::Conditional {
lhs: Box::new(Expression::new(lhs)),
} => Self::Conditional {
lhs: Self::new(lhs).into(),
operator: ConditionalOperator::new(*operator),
otherwise: Box::new(Expression::new(otherwise)),
rhs: Box::new(Expression::new(rhs)),
then: Box::new(Expression::new(then)),
otherwise: Self::new(otherwise).into(),
rhs: Self::new(rhs).into(),
then: Self::new(then).into(),
},
StringLiteral { string_literal } => Expression::String {
StringLiteral { string_literal } => Self::String {
text: string_literal.cooked.clone(),
},
Variable { name, .. } => Expression::Variable {
Variable { name, .. } => Self::Variable {
name: name.lexeme().to_owned(),
},
Group { contents } => Expression::new(contents),
Group { contents } => Self::new(contents),
}
}
}

View File

@ -7,8 +7,8 @@ pub(crate) struct Table<'key, V: Keyed<'key>> {
}
impl<'key, V: Keyed<'key>> Table<'key, V> {
pub(crate) fn new() -> Table<'key, V> {
Table {
pub(crate) fn new() -> Self {
Self {
map: BTreeMap::new(),
}
}
@ -63,7 +63,7 @@ impl<'key, V: Keyed<'key>> Default for Table<'key, V> {
impl<'key, V: Keyed<'key>> FromIterator<V> for Table<'key, V> {
fn from_iter<I: IntoIterator<Item = V>>(iter: I) -> Self {
Table {
Self {
map: iter.into_iter().map(|value| (value.key(), value)).collect(),
}
}

View File

@ -88,7 +88,7 @@ pub(crate) fn analysis_error(
length,
path: "justfile".as_ref(),
},
kind: Box::new(kind),
kind: kind.into(),
};
assert_eq!(have, want);
}

View File

@ -64,14 +64,14 @@ impl<'src> Thunk<'src> {
(Function::Nullary(function), 0) => Ok(Thunk::Nullary { function, name }),
(Function::Unary(function), 1) => Ok(Thunk::Unary {
function,
arg: Box::new(arguments.pop().unwrap()),
arg: arguments.pop().unwrap().into(),
name,
}),
(Function::UnaryOpt(function), 1..=2) => {
let a = Box::new(arguments.remove(0));
let a = arguments.remove(0).into();
let b = match arguments.pop() {
Some(value) => Box::new(Some(value)),
None => Box::new(None),
Some(value) => Some(value).into(),
None => None.into(),
};
Ok(Thunk::UnaryOpt {
function,
@ -80,8 +80,8 @@ impl<'src> Thunk<'src> {
})
}
(Function::Binary(function), 2) => {
let b = Box::new(arguments.pop().unwrap());
let a = Box::new(arguments.pop().unwrap());
let b = arguments.pop().unwrap().into();
let a = arguments.pop().unwrap().into();
Ok(Thunk::Binary {
function,
args: [a, b],
@ -90,8 +90,8 @@ impl<'src> Thunk<'src> {
}
(Function::BinaryPlus(function), 2..=usize::MAX) => {
let rest = arguments.drain(2..).collect();
let b = Box::new(arguments.pop().unwrap());
let a = Box::new(arguments.pop().unwrap());
let b = arguments.pop().unwrap().into();
let a = arguments.pop().unwrap().into();
Ok(Thunk::BinaryPlus {
function,
args: ([a, b], rest),
@ -99,9 +99,9 @@ impl<'src> Thunk<'src> {
})
}
(Function::Ternary(function), 3) => {
let c = Box::new(arguments.pop().unwrap());
let b = Box::new(arguments.pop().unwrap());
let a = Box::new(arguments.pop().unwrap());
let c = arguments.pop().unwrap().into();
let b = arguments.pop().unwrap().into();
let a = arguments.pop().unwrap().into();
Ok(Thunk::Ternary {
function,
args: [a, b, c],

View File

@ -1,7 +1,4 @@
use {
super::*,
std::{borrow::Cow, mem},
};
use {super::*, std::borrow::Cow};
/// Construct a `Tree` from a symbolic expression literal. This macro, and the
/// Tree type, are only used in the Parser unit tests, providing a concise
@ -54,66 +51,66 @@ pub(crate) enum Tree<'text> {
/// …an atom containing text, or…
Atom(Cow<'text, str>),
/// …a list containing zero or more `Tree`s.
List(Vec<Tree<'text>>),
List(Vec<Self>),
}
impl<'text> Tree<'text> {
/// Construct an Atom from a text scalar
pub(crate) fn atom(text: impl Into<Cow<'text, str>>) -> Tree<'text> {
Tree::Atom(text.into())
pub(crate) fn atom(text: impl Into<Cow<'text, str>>) -> Self {
Self::Atom(text.into())
}
/// Construct a List from an iterable of trees
pub(crate) fn list(children: impl IntoIterator<Item = Tree<'text>>) -> Tree<'text> {
Tree::List(children.into_iter().collect())
pub(crate) fn list(children: impl IntoIterator<Item = Self>) -> Self {
Self::List(children.into_iter().collect())
}
/// Convenience function to create an atom containing quoted text
pub(crate) fn string(contents: impl AsRef<str>) -> Tree<'text> {
Tree::atom(format!("\"{}\"", contents.as_ref()))
pub(crate) fn string(contents: impl AsRef<str>) -> Self {
Self::atom(format!("\"{}\"", contents.as_ref()))
}
/// Push a child node into self, turning it into a List if it was an Atom
pub(crate) fn push(self, tree: impl Into<Tree<'text>>) -> Tree<'text> {
pub(crate) fn push(self, tree: impl Into<Self>) -> Self {
match self {
Tree::List(mut children) => {
Self::List(mut children) => {
children.push(tree.into());
Tree::List(children)
Self::List(children)
}
Tree::Atom(text) => Tree::List(vec![Tree::Atom(text), tree.into()]),
Self::Atom(text) => Self::List(vec![Self::Atom(text), tree.into()]),
}
}
/// Extend a self with a tail of Trees, turning self into a List if it was an
/// Atom
pub(crate) fn extend<I, T>(self, tail: I) -> Tree<'text>
pub(crate) fn extend<I, T>(self, tail: I) -> Self
where
I: IntoIterator<Item = T>,
T: Into<Tree<'text>>,
T: Into<Self>,
{
// Tree::List(children.into_iter().collect())
let mut head = match self {
Tree::List(children) => children,
Tree::Atom(text) => vec![Tree::Atom(text)],
Self::List(children) => children,
Self::Atom(text) => vec![Self::Atom(text)],
};
for child in tail {
head.push(child.into());
}
Tree::List(head)
Self::List(head)
}
/// Like `push`, but modify self in-place
pub(crate) fn push_mut(&mut self, tree: impl Into<Tree<'text>>) {
*self = mem::replace(self, Tree::List(Vec::new())).push(tree.into());
pub(crate) fn push_mut(&mut self, tree: impl Into<Self>) {
*self = mem::replace(self, Self::List(Vec::new())).push(tree.into());
}
}
impl Display for Tree<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Tree::List(children) => {
Self::List(children) => {
write!(f, "(")?;
for (i, child) in children.iter().enumerate() {
@ -125,7 +122,7 @@ impl Display for Tree<'_> {
write!(f, ")")
}
Tree::Atom(text) => write!(f, "{text}"),
Self::Atom(text) => write!(f, "{text}"),
}
}
}
@ -134,7 +131,7 @@ impl<'text, T> From<T> for Tree<'text>
where
T: Into<Cow<'text, str>>,
{
fn from(text: T) -> Tree<'text> {
Tree::Atom(text.into())
fn from(text: T) -> Self {
Self::Atom(text.into())
}
}

View File

@ -5,8 +5,8 @@ pub(crate) struct Variables<'expression, 'src> {
}
impl<'expression, 'src> Variables<'expression, 'src> {
pub(crate) fn new(root: &'expression Expression<'src>) -> Variables<'expression, 'src> {
Variables { stack: vec![root] }
pub(crate) fn new(root: &'expression Expression<'src>) -> Self {
Self { stack: vec![root] }
}
}

View File

@ -2,7 +2,7 @@ use super::*;
#[test]
fn readme() {
let mut justfiles = vec![];
let mut justfiles = Vec::new();
let mut current = None;
for line in fs::read_to_string("README.md").unwrap().lines() {