Compare commits

...

2 Commits

Author SHA1 Message Date
Scott Richmond
b8f040c6ce get right with clippy 2024-11-21 20:00:49 -05:00
Scott Richmond
72846ccd5c follow clippy 2024-11-21 19:54:50 -05:00
4 changed files with 59 additions and 85 deletions

View File

@ -15,7 +15,7 @@ pub enum Token<'src> {
Punctuation(&'src str), Punctuation(&'src str),
} }
impl<'src> fmt::Display for Token<'src> { impl fmt::Display for Token<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
Token::Number(n) => write!(f, "[Number {}]", n), Token::Number(n) => write!(f, "[Number {}]", n),
@ -60,7 +60,7 @@ pub fn lexer<'src>(
_ => Token::Word(word), _ => Token::Word(word),
}); });
let keyword = just(':').ignore_then(word.clone()).map(Token::Keyword); let keyword = just(':').ignore_then(word).map(Token::Keyword);
let string = just('"') let string = just('"')
.ignore_then(none_of("\"").repeated().to_slice()) .ignore_then(none_of("\"").repeated().to_slice())

View File

@ -65,7 +65,7 @@ pub enum Ast<'src> {
Recur(Vec<Spanned<Self>>), Recur(Vec<Spanned<Self>>),
} }
impl<'src> fmt::Display for Ast<'src> { impl fmt::Display for Ast<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
Ast::Error => write!(f, "Error"), Ast::Error => write!(f, "Error"),
@ -96,7 +96,7 @@ impl<'src> fmt::Display for Ast<'src> {
"#{{{}}}", "#{{{}}}",
entries entries
.iter() .iter()
.map(|pair| (*pair).0.to_string()) .map(|pair| pair.0.to_string())
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", ") .join(", ")
), ),
@ -179,13 +179,13 @@ impl<'src> fmt::Display for Ast<'src> {
write!(f, "splat: {}", word) write!(f, "splat: {}", word)
} }
Ast::Pair(k, v) => { Ast::Pair(k, v) => {
write!(f, "pair: {} {}", k, (*v).0.to_string()) write!(f, "pair: {} {}", k, v.0)
} }
Ast::Loop(init, body) => { Ast::Loop(init, body) => {
write!( write!(
f, f,
"loop: {} with {}", "loop: {} with {}",
(*init).0.to_string(), init.0,
body.iter() body.iter()
.map(|clause| clause.to_string()) .map(|clause| clause.to_string())
.collect::<Vec<_>>() .collect::<Vec<_>>()
@ -235,7 +235,7 @@ pub enum Pattern<'src> {
Dict(Vec<Spanned<Self>>), Dict(Vec<Spanned<Self>>),
} }
impl<'src> fmt::Display for Pattern<'src> { impl fmt::Display for Pattern<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
Pattern::Nil => write!(f, "nil"), Pattern::Nil => write!(f, "nil"),
@ -245,7 +245,7 @@ impl<'src> fmt::Display for Pattern<'src> {
Pattern::Keyword(k) => write!(f, ":{}", k), Pattern::Keyword(k) => write!(f, ":{}", k),
Pattern::Word(w) => write!(f, "{}", w), Pattern::Word(w) => write!(f, "{}", w),
Pattern::As(w, t) => write!(f, "{} as {}", w, t), Pattern::As(w, t) => write!(f, "{} as {}", w, t),
Pattern::Splattern(p) => write!(f, "...{}", (*p).0.to_string()), Pattern::Splattern(p) => write!(f, "...{}", p.0),
Pattern::Placeholder => write!(f, "_"), Pattern::Placeholder => write!(f, "_"),
Pattern::Tuple(t) => write!( Pattern::Tuple(t) => write!(
f, f,
@ -325,7 +325,7 @@ where
) )
}); });
let splattable = word_pattern.clone().or(placeholder_pattern.clone()); let splattable = word_pattern.or(placeholder_pattern);
let patt_splat = just(Token::Punctuation("...")) let patt_splat = just(Token::Punctuation("..."))
.ignore_then(splattable) .ignore_then(splattable)
@ -430,9 +430,9 @@ where
.delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")"))) .delimited_by(just(Token::Punctuation("(")), just(Token::Punctuation(")")))
.map_with(|args, e| (Ast::Arguments(args), e.span())); .map_with(|args, e| (Ast::Arguments(args), e.span()));
let synth_root = word.clone().or(keyword.clone()); let synth_root = word.or(keyword);
let synth_term = keyword.clone().or(args); let synth_term = keyword.or(args);
let synthetic = synth_root let synthetic = synth_root
.then(synth_term.clone()) .then(synth_term.clone())
@ -445,7 +445,7 @@ where
}); });
let splat = just(Token::Punctuation("...")) let splat = just(Token::Punctuation("..."))
.ignore_then(word.clone()) .ignore_then(word)
.map_with(|(w, _), e| { .map_with(|(w, _), e| {
( (
Ast::Splat(if let Ast::Word(w) = w { Ast::Splat(if let Ast::Word(w) = w {
@ -693,7 +693,7 @@ where
}); });
let box_ = just(Token::Reserved("box")) let box_ = just(Token::Reserved("box"))
.ignore_then(word.clone()) .ignore_then(word)
.then_ignore(just(Token::Punctuation("="))) .then_ignore(just(Token::Punctuation("=")))
.then(nonbinding.clone()) .then(nonbinding.clone())
.map_with(|(word, expr), e| { .map_with(|(word, expr), e| {
@ -706,7 +706,7 @@ where
}); });
let fn_decl = just(Token::Reserved("fn")) let fn_decl = just(Token::Reserved("fn"))
.ignore_then(word.clone()) .ignore_then(word)
.map_with(|(word, _), e| { .map_with(|(word, _), e| {
let name = if let Ast::Word(w) = word { let name = if let Ast::Word(w) = word {
w w
@ -717,7 +717,7 @@ where
}); });
let fn_named = just(Token::Reserved("fn")) let fn_named = just(Token::Reserved("fn"))
.ignore_then(word.clone()) .ignore_then(word)
.then(fn_unguarded.clone()) .then(fn_unguarded.clone())
.map_with(|(word, clause), e| { .map_with(|(word, clause), e| {
let name = if let Ast::Word(word) = word.0 { let name = if let Ast::Word(word) = word.0 {
@ -729,7 +729,7 @@ where
}); });
let fn_compound = just(Token::Reserved("fn")) let fn_compound = just(Token::Reserved("fn"))
.ignore_then(word.clone()) .ignore_then(word)
.then(fn_multiclause.clone()) .then(fn_multiclause.clone())
.map_with(|(word, clauses), e| { .map_with(|(word, clauses), e| {
let name = if let Ast::Word(word) = word.0 { let name = if let Ast::Word(word) = word.0 {

View File

@ -48,10 +48,10 @@ impl<'src> Clone for Value<'src> {
fn clone(&self) -> Value<'src> { fn clone(&self) -> Value<'src> {
match self { match self {
Value::Nil => Value::Nil, Value::Nil => Value::Nil,
Value::Boolean(b) => Value::Boolean(b.clone()), Value::Boolean(b) => Value::Boolean(*b),
Value::String(s) => Value::String(s), Value::String(s) => Value::String(s),
Value::Keyword(s) => Value::Keyword(s), Value::Keyword(s) => Value::Keyword(s),
Value::Number(n) => Value::Number(n.clone()), Value::Number(n) => Value::Number(*n),
Value::Tuple(t) => Value::Tuple(t.clone()), Value::Tuple(t) => Value::Tuple(t.clone()),
Value::Args(a) => Value::Args(a.clone()), Value::Args(a) => Value::Args(a.clone()),
Value::Fn(f) => Value::Fn(f.clone()), Value::Fn(f) => Value::Fn(f.clone()),
@ -65,7 +65,7 @@ impl<'src> Clone for Value<'src> {
} }
} }
impl<'src> fmt::Display for Value<'src> { impl fmt::Display for Value<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
Value::Nil => write!(f, "nil"), Value::Nil => write!(f, "nil"),
@ -120,12 +120,9 @@ impl<'src> fmt::Display for Value<'src> {
} }
} }
impl<'src> Value<'src> { impl Value<'_> {
pub fn bool(&self) -> bool { pub fn bool(&self) -> bool {
match self { matches!(self, Value::Nil | Value::Boolean(false))
Value::Nil | Value::Boolean(false) => false,
_ => true,
}
} }
pub fn ludus_type(&self) -> Value { pub fn ludus_type(&self) -> Value {
@ -170,4 +167,4 @@ impl<'src> PartialEq for Value<'src> {
} }
} }
impl<'src> Eq for Value<'src> {} impl Eq for Value<'_> {}

View File

@ -79,13 +79,9 @@ pub fn match_pattern<'src, 'a>(
} }
// todo: add splats to these match clauses // todo: add splats to these match clauses
(Pattern::Tuple(x), Value::Tuple(y)) => { (Pattern::Tuple(x), Value::Tuple(y)) => {
let has_splat = x.iter().any(|patt| { let has_splat = x
if let (Pattern::Splattern(_), _) = patt { .iter()
true .any(|patt| matches!(patt, (Pattern::Splattern(_), _)));
} else {
false
}
});
if x.len() > y.len() || (!has_splat && x.len() != y.len()) { if x.len() > y.len() || (!has_splat && x.len() != y.len()) {
return None; return None;
}; };
@ -97,41 +93,33 @@ pub fn match_pattern<'src, 'a>(
list.push_back(y[i].clone()) list.push_back(y[i].clone())
} }
let list = Value::List(list); let list = Value::List(list);
match_pattern(&(*patt).0, &list, ctx); match_pattern(&patt.0, &list, ctx);
} else { } else if match_pattern(&x[i].0, &y[i], ctx).is_none() {
if let None = match_pattern(&x[i].0, &y[i], ctx) { while ctx.len() > to {
while ctx.len() > to { ctx.pop();
ctx.pop();
}
return None;
} }
return None;
} }
} }
Some(ctx) Some(ctx)
} }
(Pattern::List(x), Value::List(y)) => { (Pattern::List(x), Value::List(y)) => {
let has_splat = x.iter().any(|patt| { let has_splat = x
if let (Pattern::Splattern(_), _) = patt { .iter()
true .any(|patt| matches!(patt, (Pattern::Splattern(_), _)));
} else {
false
}
});
if x.len() > y.len() || (!has_splat && x.len() != y.len()) { if x.len() > y.len() || (!has_splat && x.len() != y.len()) {
return None; return None;
}; };
let to = ctx.len(); let to = ctx.len();
for i in 0..x.len() { for (i, (patt, _)) in x.iter().enumerate() {
if let Pattern::Splattern(patt) = &x[i].0 { if let Pattern::Splattern(patt) = &patt {
let list = Value::List(y.skip(i)); let list = Value::List(y.skip(i));
match_pattern(&(*patt).0, &list, ctx); match_pattern(&patt.0, &list, ctx);
} else { } else if match_pattern(patt, y.get(i).unwrap(), ctx).is_none() {
if let None = match_pattern(&x[i].0, &y.get(i).unwrap(), ctx) { while ctx.len() > to {
while ctx.len() > to { ctx.pop();
ctx.pop();
}
return None;
} }
return None;
} }
} }
Some(ctx) Some(ctx)
@ -140,28 +128,23 @@ pub fn match_pattern<'src, 'a>(
// - [ ] opportunistic mutation // - [ ] opportunistic mutation
// - [ ] get rid of all the pointer indirection in word splats // - [ ] get rid of all the pointer indirection in word splats
(Pattern::Dict(x), Value::Dict(y)) => { (Pattern::Dict(x), Value::Dict(y)) => {
let has_splat = x.iter().any(|patt| { let has_splat = x
if let (Pattern::Splattern(_), _) = patt { .iter()
true .any(|patt| matches!(patt, (Pattern::Splattern(_), _)));
} else {
false
}
});
if x.len() > y.len() || (!has_splat && x.len() != y.len()) { if x.len() > y.len() || (!has_splat && x.len() != y.len()) {
return None; return None;
}; };
let to = ctx.len(); let to = ctx.len();
let mut matched = vec![]; let mut matched = vec![];
for i in 0..x.len() { for (pattern, _) in x {
let (pattern, _) = &x[i];
match pattern { match pattern {
Pattern::Pair(key, patt) => { Pattern::Pair(key, patt) => {
if let Some(val) = y.get(key) { if let Some(val) = y.get(key) {
if let None = match_pattern(&patt.0, val, ctx) { if match_pattern(&patt.0, val, ctx).is_none() {
while ctx.len() > to { while ctx.len() > to {
ctx.pop(); ctx.pop();
return None;
} }
return None;
} else { } else {
matched.push(key); matched.push(key);
} }
@ -169,7 +152,7 @@ pub fn match_pattern<'src, 'a>(
return None; return None;
}; };
} }
Pattern::Splattern(pattern) => match &(*pattern).0 { Pattern::Splattern(pattern) => match pattern.0 {
Pattern::Word(w) => { Pattern::Word(w) => {
// TODO: find a way to take ownership // TODO: find a way to take ownership
// this will ALWAYS make structural changes, because of this clone // this will ALWAYS make structural changes, because of this clone
@ -178,7 +161,7 @@ pub fn match_pattern<'src, 'a>(
for key in matched.iter() { for key in matched.iter() {
unmatched.remove(*key); unmatched.remove(*key);
} }
ctx.push((*w, Value::Dict(unmatched))); ctx.push((w, Value::Dict(unmatched)));
} }
Pattern::Placeholder => (), Pattern::Placeholder => (),
_ => unreachable!(), _ => unreachable!(),
@ -192,10 +175,10 @@ pub fn match_pattern<'src, 'a>(
} }
} }
pub fn match_clauses<'src, 'a>( pub fn match_clauses<'src>(
value: &Value<'src>, value: &Value<'src>,
clauses: &'src Vec<MatchClause<'src>>, clauses: &'src Vec<MatchClause<'src>>,
ctx: &'a mut Vec<(&'src str, Value<'src>)>, ctx: &mut Vec<(&'src str, Value<'src>)>,
) -> Result<Value<'src>, LudusError> { ) -> Result<Value<'src>, LudusError> {
let to = ctx.len(); let to = ctx.len();
for MatchClause { patt, body, guard } in clauses.iter() { for MatchClause { patt, body, guard } in clauses.iter() {
@ -203,7 +186,7 @@ pub fn match_clauses<'src, 'a>(
let pass_guard = match guard { let pass_guard = match guard {
None => true, None => true,
Some((ast, _)) => { Some((ast, _)) => {
let guard_res = eval(&ast, ctx); let guard_res = eval(ast, ctx);
match &guard_res { match &guard_res {
Err(_) => return guard_res, Err(_) => return guard_res,
Ok(val) => val.bool(), Ok(val) => val.bool(),
@ -228,10 +211,10 @@ pub fn match_clauses<'src, 'a>(
}) })
} }
pub fn apply<'src, 'a>( pub fn apply<'src>(
callee: Value<'src>, callee: Value<'src>,
caller: Value<'src>, caller: Value<'src>,
ctx: &'a mut Vec<(&'src str, Value<'src>)>, ctx: &mut Vec<(&'src str, Value<'src>)>,
) -> Result<Value<'src>, LudusError> { ) -> Result<Value<'src>, LudusError> {
match (callee, caller) { match (callee, caller) {
(Value::Keyword(kw), Value::Dict(dict)) => { (Value::Keyword(kw), Value::Dict(dict)) => {
@ -368,16 +351,10 @@ pub fn eval<'src, 'a>(
Ast::Arguments(a) => { Ast::Arguments(a) => {
let mut args = vec![]; let mut args = vec![];
for (arg, _) in a.iter() { for (arg, _) in a.iter() {
let arg = eval(&arg, ctx)?; let arg = eval(arg, ctx)?;
args.push(arg); args.push(arg);
} }
if args.iter().any(|arg| { if args.iter().any(|arg| matches!(arg, Value::Placeholder)) {
if let Value::Placeholder = arg {
true
} else {
false
}
}) {
Ok(Value::Args(Rc::new(args))) Ok(Value::Args(Rc::new(args)))
} else { } else {
Ok(Value::Tuple(Rc::new(args))) Ok(Value::Tuple(Rc::new(args)))
@ -429,9 +406,9 @@ pub fn eval<'src, 'a>(
return eval(&body.0, ctx); return eval(&body.0, ctx);
}; };
} }
return Err(LudusError { Err(LudusError {
msg: "no match".to_string(), msg: "no match".to_string(),
}); })
} }
Ast::Match(value, clauses) => { Ast::Match(value, clauses) => {
let value = eval(&value.0, ctx)?; let value = eval(&value.0, ctx)?;
@ -468,8 +445,8 @@ pub fn eval<'src, 'a>(
} }
Ast::Do(terms) => { Ast::Do(terms) => {
let mut result = eval(&terms[0].0, ctx)?; let mut result = eval(&terms[0].0, ctx)?;
for i in 1..terms.len() { for (term, _) in terms.iter().skip(1) {
let next = eval(&terms[i].0, ctx)?; let next = eval(term, ctx)?;
let arg = Value::Tuple(Rc::new(vec![result])); let arg = Value::Tuple(Rc::new(vec![result]));
result = apply(next, arg, ctx)?; result = apply(next, arg, ctx)?;
} }