aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay <[email protected]>2024-08-23 23:00:52 +0100
committerAkshay <[email protected]>2024-08-23 23:00:52 +0100
commit1702f955a4546828cd535be6cecad57b90128de8 (patch)
tree1fe50f313570839004e52d52cacddcc09a5b4cd7
parent32de8bd5dac80a2c09e7106144cab5a8e16accc4 (diff)
add lists and index exprs
-rw-r--r--src/ast.rs18
-rw-r--r--src/eval.rs106
-rw-r--r--src/parser.rs118
3 files changed, 229 insertions, 13 deletions
diff --git a/src/ast.rs b/src/ast.rs
index 35bf6c3..fe986da 100644
--- a/src/ast.rs
+++ b/src/ast.rs
@@ -59,14 +59,15 @@ pub enum Statement {
59#[derive(Debug, Eq, PartialEq, Clone)] 59#[derive(Debug, Eq, PartialEq, Clone)]
60pub enum Expr { 60pub enum Expr {
61 Node, 61 Node,
62 FieldAccess(Box<Expr>, Identifier),
63 Unit, 62 Unit,
64 Lit(Literal), 63 Lit(Literal),
65 Ident(Identifier), 64 Ident(Identifier),
66 // List(Vec<Expr>), 65 FieldAccess(Box<Expr>, Identifier),
66 Index(Box<Expr>, Box<Expr>),
67 Bin(Box<Expr>, BinOp, Box<Expr>), 67 Bin(Box<Expr>, BinOp, Box<Expr>),
68 Unary(Box<Expr>, UnaryOp), 68 Unary(Box<Expr>, UnaryOp),
69 Call(Call), 69 Call(Call),
70 List(List),
70 If(IfExpr), 71 If(IfExpr),
71 Block(Block), 72 Block(Block),
72} 73}
@@ -154,6 +155,18 @@ impl From<Call> for Expr {
154 } 155 }
155} 156}
156 157
158/// A list construction expression
159#[derive(Debug, Eq, PartialEq, Clone)]
160pub struct List {
161 pub items: Vec<Expr>,
162}
163
164impl From<List> for Expr {
165 fn from(list: List) -> Expr {
166 Expr::List(list)
167 }
168}
169
157#[derive(Debug, PartialEq, Eq, Clone, Copy)] 170#[derive(Debug, PartialEq, Eq, Clone, Copy)]
158pub enum Type { 171pub enum Type {
159 Unit, 172 Unit,
@@ -161,6 +174,7 @@ pub enum Type {
161 String, 174 String,
162 Boolean, 175 Boolean,
163 Node, 176 Node,
177 List,
164} 178}
165 179
166#[derive(Debug, PartialEq, Eq, Clone)] 180#[derive(Debug, PartialEq, Eq, Clone)]
diff --git a/src/eval.rs b/src/eval.rs
index 7822419..104571b 100644
--- a/src/eval.rs
+++ b/src/eval.rs
@@ -15,17 +15,17 @@ impl Variable {
15 &self.value 15 &self.value
16 } 16 }
17 17
18 fn ty(&self) -> ast::Type { 18 fn ty(&self) -> &ast::Type {
19 self.ty 19 &self.ty
20 } 20 }
21 21
22 fn assign(&mut self, value: Value) -> Result { 22 fn assign(&mut self, value: Value) -> Result {
23 if self.ty() == value.ty() { 23 if self.ty() == &value.ty() {
24 self.value = value; 24 self.value = value;
25 Ok(self.value.clone()) 25 Ok(self.value.clone())
26 } else { 26 } else {
27 Err(Error::TypeMismatch { 27 Err(Error::TypeMismatch {
28 expected: self.ty(), 28 expected: self.ty().clone(),
29 got: value.ty(), 29 got: value.ty(),
30 }) 30 })
31 } 31 }
@@ -39,6 +39,7 @@ pub enum Value {
39 String(String), 39 String(String),
40 Boolean(bool), 40 Boolean(bool),
41 Node(NodeId), 41 Node(NodeId),
42 List(Vec<Value>),
42} 43}
43 44
44type NodeId = usize; 45type NodeId = usize;
@@ -51,6 +52,7 @@ impl Value {
51 Self::String(_) => ast::Type::String, 52 Self::String(_) => ast::Type::String,
52 Self::Boolean(_) => ast::Type::Boolean, 53 Self::Boolean(_) => ast::Type::Boolean,
53 Self::Node(_) => ast::Type::Node, 54 Self::Node(_) => ast::Type::Node,
55 Self::List(_) => ast::Type::List,
54 } 56 }
55 } 57 }
56 58
@@ -61,6 +63,7 @@ impl Value {
61 ast::Type::String => Self::default_string(), 63 ast::Type::String => Self::default_string(),
62 ast::Type::Boolean => Self::default_bool(), 64 ast::Type::Boolean => Self::default_bool(),
63 ast::Type::Node => unreachable!(), 65 ast::Type::Node => unreachable!(),
66 ast::Type::List => Self::default_list(),
64 } 67 }
65 } 68 }
66 69
@@ -76,6 +79,10 @@ impl Value {
76 Self::String(String::default()) 79 Self::String(String::default())
77 } 80 }
78 81
82 fn default_list() -> Self {
83 Self::List(Vec::new())
84 }
85
79 fn as_boolean(&self) -> std::result::Result<bool, Error> { 86 fn as_boolean(&self) -> std::result::Result<bool, Error> {
80 match self { 87 match self {
81 Self::Boolean(b) => Ok(*b), 88 Self::Boolean(b) => Ok(*b),
@@ -116,6 +123,16 @@ impl Value {
116 } 123 }
117 } 124 }
118 125
126 fn as_list(&self) -> std::result::Result<Vec<Value>, Error> {
127 match self {
128 Self::List(values) => Ok(values.clone()),
129 v => Err(Error::TypeMismatch {
130 expected: ast::Type::List,
131 got: v.ty(),
132 }),
133 }
134 }
135
119 fn add(&self, other: &Self) -> Result { 136 fn add(&self, other: &Self) -> Result {
120 match (self, other) { 137 match (self, other) {
121 (Self::Integer(s), Self::Integer(o)) => Ok(Self::Integer(*s + *o)), 138 (Self::Integer(s), Self::Integer(o)) => Ok(Self::Integer(*s + *o)),
@@ -278,6 +295,13 @@ impl fmt::Display for Value {
278 Self::String(s) => write!(f, "{s}"), 295 Self::String(s) => write!(f, "{s}"),
279 Self::Boolean(b) => write!(f, "{b}"), 296 Self::Boolean(b) => write!(f, "{b}"),
280 Self::Node(id) => write!(f, "<node #{id}>"), 297 Self::Node(id) => write!(f, "<node #{id}>"),
298 Self::List(items) => {
299 write!(f, "[")?;
300 for i in items {
301 write!(f, "{i}")?;
302 }
303 write!(f, "]")
304 }
281 } 305 }
282 } 306 }
283} 307}
@@ -300,6 +324,12 @@ impl From<&str> for Value {
300 } 324 }
301} 325}
302 326
327impl From<Vec<Value>> for Value {
328 fn from(value: Vec<Value>) -> Self {
329 Self::List(value)
330 }
331}
332
303type NodeKind = u16; 333type NodeKind = u16;
304 334
305#[derive(Debug, Default)] 335#[derive(Debug, Default)]
@@ -371,11 +401,16 @@ pub enum Error {
371 AlreadyBound(ast::Identifier), 401 AlreadyBound(ast::Identifier),
372 MalformedExpr(String), 402 MalformedExpr(String),
373 InvalidNodeKind(String), 403 InvalidNodeKind(String),
404 NoParentNode(tree_sitter::Node<'static>),
374 InvalidStringSlice { 405 InvalidStringSlice {
375 length: usize, 406 length: usize,
376 start: i128, 407 start: i128,
377 end: i128, 408 end: i128,
378 }, 409 },
410 ArrayOutOfBounds {
411 idx: i128,
412 len: usize
413 },
379 // current node is only set in visitors, not in BEGIN or END blocks 414 // current node is only set in visitors, not in BEGIN or END blocks
380 CurrentNodeNotPresent, 415 CurrentNodeNotPresent,
381} 416}
@@ -484,6 +519,8 @@ impl Context {
484 ast::Expr::Bin(lhs, op, rhs) => self.eval_bin(&*lhs, *op, &*rhs), 519 ast::Expr::Bin(lhs, op, rhs) => self.eval_bin(&*lhs, *op, &*rhs),
485 ast::Expr::Unary(expr, op) => self.eval_unary(&*expr, *op), 520 ast::Expr::Unary(expr, op) => self.eval_unary(&*expr, *op),
486 ast::Expr::Call(call) => self.eval_call(&*call), 521 ast::Expr::Call(call) => self.eval_call(&*call),
522 ast::Expr::List(list) => self.eval_list(&*list),
523 ast::Expr::Index(target, idx) => self.eval_index(&*target, &*idx),
487 ast::Expr::If(if_expr) => self.eval_if(if_expr), 524 ast::Expr::If(if_expr) => self.eval_if(if_expr),
488 ast::Expr::Block(block) => self.eval_block(block), 525 ast::Expr::Block(block) => self.eval_block(block),
489 ast::Expr::Node => self.eval_node(), 526 ast::Expr::Node => self.eval_node(),
@@ -704,10 +741,40 @@ impl Context {
704 .unwrap(); 741 .unwrap();
705 Ok(Value::String(text.to_owned())) 742 Ok(Value::String(text.to_owned()))
706 } 743 }
744 ("parent", [arg]) => {
745 let v = self.eval_expr(arg)?;
746 let id = v.as_node()?;
747 let node = self.get_node_by_id(id).unwrap();
748 let parent = node.parent();
749 parent
750 .map(|n| Value::Node(n.id()))
751 .ok_or(Error::NoParentNode(node))
752 }
707 (s, _) => Err(Error::FailedLookup(s.to_owned())), 753 (s, _) => Err(Error::FailedLookup(s.to_owned())),
708 } 754 }
709 } 755 }
710 756
757 fn eval_list(&mut self, list: &ast::List) -> Result {
758 let mut vals = vec![];
759 for i in &list.items {
760 vals.push(self.eval_expr(i)?);
761 }
762 Ok(vals.into())
763 }
764
765 fn eval_index(&mut self, target: &ast::Expr, idx: &ast::Expr) -> Result {
766 let mut target = self.eval_expr(target)?.as_list()?;
767 let idx = self.eval_expr(idx)?.as_int()?;
768 if idx < 0 || idx >= target.len() as i128 {
769 Err(Error::ArrayOutOfBounds {
770 idx,
771 len: target.len()
772 })
773 } else {
774 Ok(target.remove(idx as usize))
775 }
776 }
777
711 fn eval_declaration(&mut self, decl: &ast::Declaration) -> Result { 778 fn eval_declaration(&mut self, decl: &ast::Declaration) -> Result {
712 let initial_value = match decl.init.as_ref() { 779 let initial_value = match decl.init.as_ref() {
713 Some(init) => Some(self.eval_expr(&*init)?), 780 Some(init) => Some(self.eval_expr(&*init)?),
@@ -986,4 +1053,35 @@ mod test {
986 } 1053 }
987 ); 1054 );
988 } 1055 }
1056
1057 #[test]
1058 fn test_list() {
1059 let language = tree_sitter_python::language();
1060 let mut ctx = Context::new(language)
1061 .with_program(ast::Program::new())
1062 .unwrap();
1063 assert_eq!(
1064 ctx.eval_block(&ast::Block {
1065 body: vec![ast::Statement::Declaration(ast::Declaration {
1066 ty: ast::Type::List,
1067 name: "a".to_owned(),
1068 init: Some(
1069 ast::Expr::List(ast::List {
1070 items: vec![ast::Expr::int(5)]
1071 })
1072 .boxed()
1073 ),
1074 }),]
1075 }),
1076 Ok(Value::Unit)
1077 );
1078 assert_eq!(
1079 ctx.lookup(&String::from("a")).unwrap().clone(),
1080 Variable {
1081 ty: ast::Type::List,
1082 name: "a".to_owned(),
1083 value: vec![5.into()].into(),
1084 }
1085 );
1086 }
989} 1087}
diff --git a/src/parser.rs b/src/parser.rs
index 4ec8e57..15d03fe 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -169,28 +169,51 @@ fn parse_mul<'a>(i: &'a str) -> IResult<&'a str, Expr> {
169 let div = parse_op("/", BinOp::Arith(ArithOp::Div)); 169 let div = parse_op("/", BinOp::Arith(ArithOp::Div));
170 let mod_ = parse_op("%", BinOp::Arith(ArithOp::Mod)); 170 let mod_ = parse_op("%", BinOp::Arith(ArithOp::Mod));
171 let op = alt((mul, div, mod_)); 171 let op = alt((mul, div, mod_));
172 let recursive = parse_binary(parse_field_access, op, parse_mul); 172 let recursive = parse_binary(parse_field_or_index, op, parse_mul);
173 let base = parse_field_access; 173 let base = parse_field_or_index;
174 alt((recursive, base)).parse(i) 174 alt((recursive, base)).parse(i)
175} 175}
176 176
177fn parse_field_access<'a>(i: &'a str) -> IResult<&'a str, Expr> { 177fn parse_field_or_index<'a>(i: &'a str) -> IResult<&'a str, Expr> {
178 let trailing = map(tuple((ws(char('.')), ws(parse_ident))), |(_, i)| i); 178 enum FieldOrIndex {
179 Field(String),
180 Index(Expr),
181 }
182
179 let (i, base) = parse_atom(i)?; 183 let (i, base) = parse_atom(i)?;
180 184
185 let field = map(tuple((ws(char('.')), ws(parse_ident))), |(_, i)| {
186 FieldOrIndex::Field(i)
187 });
188 let index = map(
189 tuple((ws(char('[')), parse_expr, ws(char(']')))),
190 |(_, idx, _)| FieldOrIndex::Index(idx),
191 );
192
181 fold_many0( 193 fold_many0(
182 trailing, 194 alt((field, index)),
183 move || base.clone(), 195 move || base.clone(),
184 move |acc, new| Expr::FieldAccess(acc.boxed(), new), 196 move |acc, new| match new {
197 FieldOrIndex::Field(f) => Expr::FieldAccess(acc.boxed(), f),
198 FieldOrIndex::Index(idx) => Expr::Index(acc.boxed(), idx.boxed()),
199 },
185 )(i) 200 )(i)
186} 201}
187 202
203fn parse_list<'a>(i: &'a str) -> IResult<&'a str, List> {
204 let open = ws(char('['));
205 let items = separated_list0(char(','), parse_expr);
206 let close = ws(char(']'));
207 map(tuple((open, items, close)), |(_, items, _)| List { items }).parse(i)
208}
209
188fn parse_atom<'a>(i: &'a str) -> IResult<&'a str, Expr> { 210fn parse_atom<'a>(i: &'a str) -> IResult<&'a str, Expr> {
189 let inner = alt(( 211 let inner = alt((
190 map(tag("node"), |_| Expr::Node), 212 map(tag("node"), |_| Expr::Node),
191 map(parse_block, Expr::Block), 213 map(parse_block, Expr::Block),
192 map(parse_if, Expr::If), 214 map(parse_if, Expr::If),
193 map(parse_call, Expr::Call), 215 map(parse_call, Expr::Call),
216 map(parse_list, Expr::List),
194 map(parse_lit, Expr::Lit), 217 map(parse_lit, Expr::Lit),
195 map(parse_ident, Expr::Ident), 218 map(parse_ident, Expr::Ident),
196 map(parse_unit, |_| Expr::Unit), 219 map(parse_unit, |_| Expr::Unit),
@@ -254,7 +277,8 @@ fn parse_type<'a>(i: &'a str) -> IResult<&'a str, Type> {
254 let int = value(Type::Integer, tag("int")); 277 let int = value(Type::Integer, tag("int"));
255 let string = value(Type::String, tag("string")); 278 let string = value(Type::String, tag("string"));
256 let bool_ = value(Type::Boolean, tag("bool")); 279 let bool_ = value(Type::Boolean, tag("bool"));
257 alt((int, string, bool_)).parse(i) 280 let list = value(Type::List, tag("list"));
281 alt((int, string, bool_, list)).parse(i)
258} 282}
259 283
260fn parse_declaration<'a>(i: &'a str) -> IResult<&'a str, Declaration> { 284fn parse_declaration<'a>(i: &'a str) -> IResult<&'a str, Declaration> {
@@ -510,6 +534,27 @@ mod test {
510 ) 534 )
511 )) 535 ))
512 ); 536 );
537 assert_eq!(
538 parse_expr("a[0]"),
539 Ok((
540 "",
541 Expr::Index(Expr::Ident("a".to_owned()).boxed(), Expr::int(0).boxed())
542 ))
543 );
544 assert_eq!(
545 parse_expr("children(node)[0]"),
546 Ok((
547 "",
548 Expr::Index(
549 Expr::Call(Call {
550 function: "children".to_owned(),
551 parameters: vec![Expr::Node]
552 })
553 .boxed(),
554 Expr::int(0).boxed()
555 )
556 ))
557 );
513 } 558 }
514 559
515 #[test] 560 #[test]
@@ -544,6 +589,22 @@ mod test {
544 }) 589 })
545 )) 590 ))
546 ); 591 );
592 assert_eq!(
593 parse_statement(r#"list a =["a", "b", "c"]; "#),
594 Ok((
595 "",
596 Statement::Declaration(Declaration {
597 ty: Type::List,
598 name: "a".to_owned(),
599 init: Some(
600 Expr::List(List {
601 items: vec![Expr::str("a"), Expr::str("b"), Expr::str("c"),]
602 })
603 .boxed()
604 )
605 })
606 ))
607 );
547 } 608 }
548 609
549 #[test] 610 #[test]
@@ -624,6 +685,49 @@ mod test {
624 ); 685 );
625 } 686 }
626 687
688 #[test]
689 fn test_parse_index() {
690 assert_eq!(
691 parse_expr(
692 r#"
693 a[0]
694 "#
695 ),
696 Ok((
697 "",
698 Expr::Index(Expr::Ident("a".to_owned()).boxed(), Expr::int(0).boxed()),
699 ))
700 );
701 assert_eq!(
702 parse_expr(r#"node.children[idx]"#),
703 Ok((
704 "",
705 Expr::Index(
706 Expr::FieldAccess(Expr::Node.boxed(), Identifier::from("children")).boxed(),
707 Expr::Ident("idx".to_owned()).boxed()
708 )
709 ))
710 );
711 assert_eq!(
712 parse_expr(r#"foo[i].bar[j]"#),
713 Ok((
714 "",
715 Expr::Index(
716 Expr::FieldAccess(
717 Expr::Index(
718 Expr::Ident("foo".to_owned()).boxed(),
719 Expr::Ident("i".to_owned()).boxed()
720 )
721 .boxed(),
722 "bar".to_owned()
723 )
724 .boxed(),
725 Expr::Ident("j".to_owned()).boxed()
726 ),
727 ))
728 );
729 }
730
627 // #[test] 731 // #[test]
628 // fn test_skip_query() { 732 // fn test_skip_query() {
629 // assert_eq!( 733 // assert_eq!(