Add list comprehension

This commit is contained in:
imaqtkatt 2024-05-03 11:24:47 -03:00
parent cd320af476
commit e13e360118
4 changed files with 30 additions and 4 deletions

View File

@ -29,6 +29,8 @@ pub enum Term {
Lst { els: Vec<Term> },
// "(" ... ")"
Tup { els: Vec<Term> },
// "[" {term} "for" {bind} "in" {iter} ("if" {cond})? "]"
Comprehension { term: Box<Term>, bind: Name, iter: Box<Term>, cond: Option<Box<Term>> },
}
#[derive(Clone, Debug)]

View File

@ -88,6 +88,7 @@ impl Term {
rhs.order_kwargs(ctx);
}
Term::Lst { els } | Term::Tup { els } => els.iter_mut().for_each(|e| e.order_kwargs(ctx)),
Term::Comprehension { .. } => {}
Term::None | Term::Var { .. } | Term::Num { .. } | Term::Str { .. } => {}
}
}

View File

@ -65,10 +65,7 @@ impl<'a> PyParser<'a> {
head
}
}
'[' => {
let els = self.list_like(|p| p.parse_term_py(), "[", "]", ",", true, 0)?;
Term::Lst { els }
}
'[' => self.list_or_comprehension()?,
'\"' => {
let str = self.parse_quoted_string()?;
let val = STRINGS.get(str);
@ -90,6 +87,28 @@ impl<'a> PyParser<'a> {
Ok(res)
}
fn list_or_comprehension(&mut self) -> Result<Term, String> {
self.consume("[")?;
let head = self.parse_term_py()?;
if self.try_consume_keyword("for") {
let bind = self.parse_hvml_name()?;
self.consume("in")?;
let iter = self.parse_term_py()?;
let mut cond = None;
if self.try_consume_keyword("if") {
cond = Some(Box::new(self.parse_term_py()?));
}
self.consume("]")?;
Ok(Term::Comprehension { term: Box::new(head), bind, iter: Box::new(iter), cond })
} else {
let mut head = vec![head];
self.try_consume(",");
let tail = self.list_like(|p| p.parse_term_py(), "", "]", ",", true, 0)?;
head.extend(tail);
Ok(Term::Lst { els: head })
}
}
fn parse_term_py(&mut self) -> Result<Term, String> {
self.skip_trivia();
if self.try_consume_keyword("lambda") {
@ -562,6 +581,9 @@ def inc(n):
n += 1;
return n;
def inc_list(list):
return [x+1 for x in list];
def lam():
return lambda x, y: return x;;

View File

@ -109,6 +109,7 @@ impl Term {
tag: lang::Tag::Static,
els: els.into_iter().map(Self::to_lang).collect(),
},
Term::Comprehension { .. } => todo!(),
}
}
}