refactor process to use visit
method everywhere
This commit is contained in:
parent
ecc7b26b66
commit
229470fee3
|
@ -182,9 +182,10 @@ pub fn run(src: &'static str) {
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let src = "
|
let src = "
|
||||||
when {
|
let guard = :nil
|
||||||
false -> :false
|
match :foo with {
|
||||||
true -> :true
|
:foo if guard -> :guarded
|
||||||
|
_ -> :unguarded
|
||||||
}
|
}
|
||||||
";
|
";
|
||||||
run(src);
|
run(src);
|
||||||
|
|
|
@ -60,12 +60,6 @@ impl<'src> Process<'src> {
|
||||||
self.locals.push((word, value.clone()));
|
self.locals.push((word, value.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop_to(&mut self, n: usize) {
|
|
||||||
while self.locals.len() > n {
|
|
||||||
self.locals.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn match_eq<T>(&self, x: T, y: T) -> Option<&Process<'src>>
|
pub fn match_eq<T>(&self, x: T, y: T) -> Option<&Process<'src>>
|
||||||
where
|
where
|
||||||
T: PartialEq,
|
T: PartialEq,
|
||||||
|
@ -134,7 +128,7 @@ impl<'src> Process<'src> {
|
||||||
let list = Value::List(list);
|
let list = Value::List(list);
|
||||||
self.match_pattern(&patt.0, &list);
|
self.match_pattern(&patt.0, &list);
|
||||||
} else if self.match_pattern(&x[i].0, &y[i]).is_none() {
|
} else if self.match_pattern(&x[i].0, &y[i]).is_none() {
|
||||||
self.pop_to(to);
|
self.locals.truncate(to);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +145,7 @@ impl<'src> Process<'src> {
|
||||||
let list = Value::List(y.skip(i));
|
let list = Value::List(y.skip(i));
|
||||||
self.match_pattern(&patt.0, &list);
|
self.match_pattern(&patt.0, &list);
|
||||||
} else if self.match_pattern(patt, y.get(i).unwrap()).is_none() {
|
} else if self.match_pattern(patt, y.get(i).unwrap()).is_none() {
|
||||||
self.pop_to(to);
|
self.locals.truncate(to);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,7 +166,7 @@ impl<'src> Process<'src> {
|
||||||
PairPattern(key, patt) => {
|
PairPattern(key, patt) => {
|
||||||
if let Some(val) = y.get(key) {
|
if let Some(val) = y.get(key) {
|
||||||
if self.match_pattern(&patt.0, val).is_none() {
|
if self.match_pattern(&patt.0, val).is_none() {
|
||||||
self.pop_to(to);
|
self.locals.truncate(to);
|
||||||
return None;
|
return None;
|
||||||
} else {
|
} else {
|
||||||
matched.push(key);
|
matched.push(key);
|
||||||
|
@ -210,31 +204,23 @@ impl<'src> Process<'src> {
|
||||||
clauses: &'src [Spanned<Ast>],
|
clauses: &'src [Spanned<Ast>],
|
||||||
) -> LResult<'src> {
|
) -> LResult<'src> {
|
||||||
{
|
{
|
||||||
let parent = self.ast;
|
let root = self.ast;
|
||||||
let to = self.locals.len();
|
let to = self.locals.len();
|
||||||
let mut clauses = clauses.iter();
|
let mut clauses = clauses.iter();
|
||||||
while let Some((Ast::MatchClause(patt, guard, body), _)) = clauses.next() {
|
while let Some((Ast::MatchClause(patt, guard, body), _)) = clauses.next() {
|
||||||
if self.match_pattern(&patt.0, value).is_some() {
|
if self.match_pattern(&patt.0, value).is_some() {
|
||||||
let pass_guard = match guard.as_ref() {
|
let pass_guard = match guard.as_ref() {
|
||||||
None => true,
|
None => true,
|
||||||
Some((ast, _)) => {
|
Some(guard_expr) => self.visit(guard_expr)?.bool(),
|
||||||
self.ast = ast;
|
|
||||||
let guard_res = self.eval();
|
|
||||||
match &guard_res {
|
|
||||||
Err(_) => return guard_res,
|
|
||||||
Ok(val) => val.bool(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if !pass_guard {
|
if !pass_guard {
|
||||||
self.pop_to(to);
|
self.locals.truncate(to);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
self.ast = &body.0;
|
let result = self.visit(body);
|
||||||
let res = self.eval();
|
self.locals.truncate(to);
|
||||||
self.pop_to(to);
|
self.ast = root;
|
||||||
self.ast = parent;
|
return result;
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(LErr::new("no match".to_string()))
|
Err(LErr::new("no match".to_string()))
|
||||||
|
@ -467,9 +453,6 @@ impl<'src> Process<'src> {
|
||||||
Fn(name, clauses, doc) => {
|
Fn(name, clauses, doc) => {
|
||||||
let doc = doc.map(|s| s.to_string());
|
let doc = doc.map(|s| s.to_string());
|
||||||
let ptr: *const Ast = root_node;
|
let ptr: *const Ast = root_node;
|
||||||
// dbg!(&root);
|
|
||||||
// dbg!(&ptr);
|
|
||||||
// dbg!(&self.fn_info);
|
|
||||||
let info = self.fn_info.get(&ptr).unwrap();
|
let info = self.fn_info.get(&ptr).unwrap();
|
||||||
let FnInfo::Defined(_, _, enclosing) = info else {
|
let FnInfo::Defined(_, _, enclosing) = info else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user