aboutsummaryrefslogtreecommitdiff
path: root/src/eval.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval.rs')
-rw-r--r--src/eval.rs106
1 files changed, 102 insertions, 4 deletions
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}