follow clippy
This commit is contained in:
parent
e4954678f0
commit
72846ccd5c
|
@ -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 {
|
||||||
|
|
85
src/vm.rs
85
src/vm.rs
|
@ -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,71 +93,58 @@ 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)
|
||||||
}
|
}
|
||||||
// TODO: optimize this on several levels
|
// TODO: optimize this on several levels
|
||||||
// - [ ] 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)?;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user