tree-based source processing language
at main 973 lines 30 kB view raw
1//! tree walking interpreter for tbsp 2 3use crate::{ast, Wrap}; 4use std::{collections::HashMap, fmt}; 5 6#[derive(Debug, PartialEq, Eq, Clone)] 7pub struct Variable { 8 pub ty: ast::Type, 9 pub name: ast::Identifier, 10 pub value: Value, 11} 12 13impl Variable { 14 fn value(&self) -> &Value { 15 &self.value 16 } 17 18 pub(crate) fn ty(&self) -> &ast::Type { 19 &self.ty 20 } 21 22 fn assign(&mut self, value: Value) -> Result { 23 if self.ty() == &value.ty() { 24 self.value = value; 25 Ok(self.value.clone()) 26 } else { 27 Err(Error::TypeMismatch { 28 expected: self.ty().clone(), 29 got: value.ty(), 30 }) 31 } 32 } 33 34 pub(crate) fn mutate(&mut self, f: impl FnOnce(&mut Self) -> Result) -> Result { 35 f(self) 36 } 37} 38 39#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] 40pub enum Value { 41 Unit, 42 Integer(i128), 43 String(String), 44 Boolean(bool), 45 Node(NodeId), 46 List(Vec<Value>), 47} 48 49type NodeId = usize; 50 51impl Value { 52 pub(crate) fn ty(&self) -> ast::Type { 53 match self { 54 Self::Unit => ast::Type::Unit, 55 Self::Integer(_) => ast::Type::Integer, 56 Self::String(_) => ast::Type::String, 57 Self::Boolean(_) => ast::Type::Boolean, 58 Self::Node(_) => ast::Type::Node, 59 Self::List(_) => ast::Type::List, 60 } 61 } 62 63 fn default(ty: ast::Type) -> Self { 64 match ty { 65 ast::Type::Unit => Self::Unit, 66 ast::Type::Integer => Self::default_int(), 67 ast::Type::String => Self::default_string(), 68 ast::Type::Boolean => Self::default_bool(), 69 ast::Type::Node => unreachable!(), 70 ast::Type::List => Self::default_list(), 71 } 72 } 73 74 fn default_int() -> Self { 75 Self::Integer(0) 76 } 77 78 fn default_bool() -> Self { 79 Self::Boolean(false) 80 } 81 82 fn default_string() -> Self { 83 Self::String(String::default()) 84 } 85 86 fn default_list() -> Self { 87 Self::List(Vec::new()) 88 } 89 90 fn as_boolean(&self) -> std::result::Result<bool, Error> { 91 match self { 92 Self::Boolean(b) => Ok(*b), 93 v => Err(Error::TypeMismatch { 94 expected: ast::Type::Boolean, 95 got: v.ty(), 96 }), 97 } 98 } 99 100 pub(crate) fn as_str(&self) -> std::result::Result<&str, Error> { 101 match self { 102 Self::String(s) => Ok(s.as_str()), 103 v => Err(Error::TypeMismatch { 104 expected: ast::Type::String, 105 got: v.ty(), 106 }), 107 } 108 } 109 110 pub(crate) fn as_int(&self) -> std::result::Result<i128, Error> { 111 match self { 112 Self::Integer(i) => Ok(*i), 113 v => Err(Error::TypeMismatch { 114 expected: ast::Type::Integer, 115 got: v.ty(), 116 }), 117 } 118 } 119 120 pub(crate) fn as_node(&self) -> std::result::Result<NodeId, Error> { 121 match self { 122 Self::Node(id) => Ok(*id), 123 v => Err(Error::TypeMismatch { 124 expected: ast::Type::Node, 125 got: v.ty(), 126 }), 127 } 128 } 129 130 pub(crate) fn as_list(&self) -> std::result::Result<Vec<Value>, Error> { 131 match self { 132 Self::List(values) => Ok(values.clone()), 133 v => Err(Error::TypeMismatch { 134 expected: ast::Type::List, 135 got: v.ty(), 136 }), 137 } 138 } 139 140 fn add(&self, other: &Self) -> Result { 141 match (self, other) { 142 (Self::Integer(s), Self::Integer(o)) => Ok(Self::Integer(*s + *o)), 143 (Self::String(s), Self::String(o)) => Ok(Self::String(format!("{s}{o}"))), 144 (Self::List(l), o) => Ok(Self::List(l.iter().cloned().chain([o.clone()]).collect())), 145 _ => Err(Error::UndefinedBinOp( 146 ast::BinOp::Arith(ast::ArithOp::Add), 147 self.ty(), 148 other.ty(), 149 )), 150 } 151 } 152 153 fn sub(&self, other: &Self) -> Result { 154 match (self, other) { 155 (Self::Integer(s), Self::Integer(o)) => Ok(Self::Integer(*s - *o)), 156 (Self::String(s), Self::String(o)) => { 157 Ok(Self::String(s.strip_suffix(o).unwrap_or(s).to_owned())) 158 } 159 _ => Err(Error::UndefinedBinOp( 160 ast::BinOp::Arith(ast::ArithOp::Sub), 161 self.ty(), 162 other.ty(), 163 )), 164 } 165 } 166 167 fn mul(&self, other: &Self) -> Result { 168 match (self, other) { 169 (Self::Integer(s), Self::Integer(o)) => Ok(Self::Integer(*s * *o)), 170 (Self::Integer(s), Self::String(o)) => Ok(Self::String(o.repeat(*s as usize))), 171 (Self::String(_), Self::Integer(_)) => other.mul(self), 172 _ => Err(Error::UndefinedBinOp( 173 ast::BinOp::Arith(ast::ArithOp::Mul), 174 self.ty(), 175 other.ty(), 176 )), 177 } 178 } 179 180 fn div(&self, other: &Self) -> Result { 181 match (self, other) { 182 (Self::Integer(s), Self::Integer(o)) => Ok(Self::Integer(*s / *o)), 183 _ => Err(Error::UndefinedBinOp( 184 ast::BinOp::Arith(ast::ArithOp::Div), 185 self.ty(), 186 other.ty(), 187 )), 188 } 189 } 190 191 fn mod_(&self, other: &Self) -> Result { 192 match (self, other) { 193 (Self::Integer(s), Self::Integer(o)) => Ok(Self::Integer(*s % *o)), 194 _ => Err(Error::UndefinedBinOp( 195 ast::BinOp::Arith(ast::ArithOp::Mod), 196 self.ty(), 197 other.ty(), 198 )), 199 } 200 } 201 202 fn equals(&self, other: &Self) -> Result { 203 match (self, other) { 204 (Self::Integer(s), Self::Integer(o)) => Ok(Self::Boolean(s == o)), 205 (Self::String(s), Self::String(o)) => Ok(Self::Boolean(s == o)), 206 (Self::Boolean(s), Self::Boolean(o)) => Ok(Self::Boolean(s == o)), 207 _ => Err(Error::UndefinedBinOp( 208 ast::BinOp::Cmp(ast::CmpOp::Eq), 209 self.ty(), 210 other.ty(), 211 )), 212 } 213 } 214 215 fn greater_than(&self, other: &Self) -> Result { 216 match (self, other) { 217 (Self::Integer(s), Self::Integer(o)) => Ok(Self::Boolean(s > o)), 218 (Self::String(s), Self::String(o)) => Ok(Self::Boolean(s.cmp(o).is_gt())), 219 _ => Err(Error::UndefinedBinOp( 220 ast::BinOp::Cmp(ast::CmpOp::Gt), 221 self.ty(), 222 other.ty(), 223 )), 224 } 225 } 226 227 fn less_than(&self, other: &Self) -> Result { 228 match (self, other) { 229 (Self::Integer(s), Self::Integer(o)) => Ok(Self::Boolean(s < o)), 230 (Self::String(s), Self::String(o)) => Ok(Self::Boolean(s.cmp(o).is_lt())), 231 _ => Err(Error::UndefinedBinOp( 232 ast::BinOp::Cmp(ast::CmpOp::Lt), 233 self.ty(), 234 other.ty(), 235 )), 236 } 237 } 238 239 fn greater_than_equals(&self, other: &Self) -> Result { 240 match (self, other) { 241 (Self::Integer(s), Self::Integer(o)) => Ok(Self::Boolean(s >= o)), 242 (Self::String(s), Self::String(o)) => Ok(Self::Boolean(s.cmp(o).is_ge())), 243 (Self::Boolean(s), Self::Boolean(o)) => Ok(Self::Boolean(s == o)), 244 _ => Err(Error::UndefinedBinOp( 245 ast::BinOp::Cmp(ast::CmpOp::Gte), 246 self.ty(), 247 other.ty(), 248 )), 249 } 250 } 251 252 fn less_than_equals(&self, other: &Self) -> Result { 253 match (self, other) { 254 (Self::Integer(s), Self::Integer(o)) => Ok(Self::Boolean(s <= o)), 255 (Self::String(s), Self::String(o)) => Ok(Self::Boolean(s.cmp(o).is_le())), 256 (Self::Boolean(s), Self::Boolean(o)) => Ok(Self::Boolean(s == o)), 257 _ => Err(Error::UndefinedBinOp( 258 ast::BinOp::Cmp(ast::CmpOp::Lte), 259 self.ty(), 260 other.ty(), 261 )), 262 } 263 } 264 265 fn not(&self) -> Result { 266 match self { 267 Self::Boolean(s) => Ok(Self::Boolean(!s)), 268 _ => Err(Error::UndefinedUnaryOp(ast::UnaryOp::Not, self.ty())), 269 } 270 } 271 272 fn and(&self, other: &Self) -> Result { 273 match (self, other) { 274 (Self::Boolean(s), Self::Boolean(o)) => Ok(Self::Boolean(*s && *o)), 275 _ => Err(Error::UndefinedBinOp( 276 ast::BinOp::Logic(ast::LogicOp::And), 277 self.ty(), 278 other.ty(), 279 )), 280 } 281 } 282 283 fn or(&self, other: &Self) -> Result { 284 match (self, other) { 285 (Self::Boolean(s), Self::Boolean(o)) => Ok(Self::Boolean(*s || *o)), 286 _ => Err(Error::UndefinedBinOp( 287 ast::BinOp::Logic(ast::LogicOp::Or), 288 self.ty(), 289 other.ty(), 290 )), 291 } 292 } 293} 294 295impl fmt::Display for Value { 296 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 297 match self { 298 Self::Unit => write!(f, "()"), 299 Self::Integer(i) => write!(f, "{i}"), 300 Self::String(s) => write!(f, "{s}"), 301 Self::Boolean(b) => write!(f, "{b}"), 302 Self::Node(id) => write!(f, "<node #{id}>"), 303 Self::List(items) => { 304 write!(f, "[")?; 305 let mut iterable = items.iter().peekable(); 306 while let Some(item) = iterable.next() { 307 if iterable.peek().is_none() { 308 write!(f, "{item}")?; 309 } else { 310 write!(f, "{item}, ")?; 311 } 312 } 313 write!(f, "]") 314 } 315 } 316 } 317} 318 319impl From<bool> for Value { 320 fn from(value: bool) -> Self { 321 Self::Boolean(value) 322 } 323} 324 325impl From<i128> for Value { 326 fn from(value: i128) -> Self { 327 Self::Integer(value) 328 } 329} 330 331impl From<usize> for Value { 332 fn from(value: usize) -> Self { 333 (value as i128).into() 334 } 335} 336 337impl From<&str> for Value { 338 fn from(value: &str) -> Self { 339 Self::String(value.to_owned()) 340 } 341} 342 343impl From<Vec<Value>> for Value { 344 fn from(value: Vec<Value>) -> Self { 345 Self::List(value) 346 } 347} 348 349#[derive(Debug, PartialEq, Eq)] 350pub enum Error { 351 FailedLookup(ast::Identifier), 352 TypeMismatch { 353 expected: ast::Type, 354 got: ast::Type, 355 }, 356 UndefinedBinOp(ast::BinOp, ast::Type, ast::Type), 357 UndefinedUnaryOp(ast::UnaryOp, ast::Type), 358 AlreadyBound(ast::Identifier), 359 MalformedExpr(String), 360 InvalidNodeKind(String), 361 NoParentNode(tree_sitter::Node<'static>), 362 IncorrectArgFormat { 363 wanted: usize, 364 got: usize, 365 }, 366 InvalidStringSlice { 367 length: usize, 368 start: i128, 369 end: i128, 370 }, 371 ArrayOutOfBounds { 372 idx: i128, 373 len: usize, 374 }, 375 // current node is only set in visitors, not in BEGIN or END blocks 376 CurrentNodeNotPresent, 377} 378 379pub type Result = std::result::Result<Value, Error>; 380 381pub struct Context { 382 variables: HashMap<ast::Identifier, Variable>, 383 language: tree_sitter::Language, 384 program: ast::Program, 385 pub(crate) input_src: Option<String>, 386 cursor: Option<tree_sitter::TreeCursor<'static>>, 387 tree: Option<&'static tree_sitter::Tree>, 388 cache: HashMap<NodeId, tree_sitter::Node<'static>>, 389} 390 391impl fmt::Debug for Context { 392 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 393 f.debug_struct("Context") 394 .field("variables", &self.variables) 395 .field("language", &self.language) 396 .field("input_src", &self.input_src) 397 .field( 398 "cursor", 399 if self.cursor.is_some() { 400 &"Some(<cursor>)" 401 } else { 402 &"None" 403 }, 404 ) 405 .finish() 406 } 407} 408 409impl Context { 410 pub fn new(language: tree_sitter::Language) -> Self { 411 Self { 412 program: Default::default(), 413 variables: Default::default(), 414 language, 415 input_src: None, 416 cursor: None, 417 tree: None, 418 cache: HashMap::default(), 419 } 420 } 421 422 pub fn cache_node(&mut self, node: tree_sitter::Node<'static>) { 423 self.cache.entry(node.id()).or_insert(node); 424 } 425 426 pub fn get_node_by_id(&mut self, id: usize) -> Option<tree_sitter::Node<'static>> { 427 let root_node = self.tree.as_ref().map(|t| t.root_node())?; 428 self.get_node_by_id_helper(root_node, id) 429 } 430 431 fn get_node_by_id_helper( 432 &mut self, 433 start: tree_sitter::Node<'static>, 434 id: usize, 435 ) -> Option<tree_sitter::Node<'static>> { 436 self.cache_node(start); 437 438 if let Some(found) = self.cache.get(&id) { 439 return Some(*found); 440 } 441 442 if start.id() == id { 443 return Some(start); 444 } else { 445 for child in start.children(&mut start.walk()) { 446 if let Some(n) = self.get_node_by_id_helper(child, id) { 447 return Some(n); 448 }; 449 } 450 } 451 452 None 453 } 454 455 pub fn with_program(mut self, program: ast::Program) -> Self { 456 self.program = program; 457 self 458 } 459 460 pub fn with_input(mut self, src: String) -> Self { 461 self.input_src = Some(src); 462 self 463 } 464 465 pub fn with_tree(mut self, tree: tree_sitter::Tree) -> Self { 466 let tree = Box::leak(Box::new(tree)); 467 self.cursor = Some(tree.walk()); 468 self.tree = Some(tree); 469 self 470 } 471 472 pub(crate) fn eval_expr(&mut self, expr: &ast::Expr) -> Result { 473 match expr { 474 ast::Expr::Unit => Ok(Value::Unit), 475 ast::Expr::Lit(lit) => self.eval_lit(lit), 476 ast::Expr::Ident(ident) => self.lookup(ident).map(Variable::value).cloned(), 477 ast::Expr::Bin(lhs, op, rhs) => self.eval_bin(&*lhs, *op, &*rhs), 478 ast::Expr::Unary(expr, op) => self.eval_unary(&*expr, *op), 479 ast::Expr::Call(call) => self.eval_call(&*call), 480 ast::Expr::List(list) => self.eval_list(&*list), 481 ast::Expr::Index(target, idx) => self.eval_index(&*target, &*idx), 482 ast::Expr::If(if_expr) => self.eval_if(if_expr), 483 ast::Expr::Block(block) => self.eval_block(block), 484 ast::Expr::Node => self.eval_node(), 485 ast::Expr::FieldAccess(expr, items) => self.eval_field_access(expr, items), 486 } 487 } 488 489 fn eval_lit(&mut self, lit: &ast::Literal) -> Result { 490 match lit { 491 ast::Literal::Str(s) => Ok(Value::String(s.to_owned())), 492 ast::Literal::Int(i) => Ok(Value::Integer(*i)), 493 ast::Literal::Bool(b) => Ok(Value::Boolean(*b)), 494 } 495 } 496 497 fn eval_node(&mut self) -> Result { 498 self.cursor 499 .as_ref() 500 .ok_or(Error::CurrentNodeNotPresent)? 501 .node() 502 .id() 503 .wrap(Value::Node) 504 .wrap_ok() 505 } 506 507 pub(crate) fn lookup( 508 &mut self, 509 ident: &ast::Identifier, 510 ) -> std::result::Result<&Variable, Error> { 511 self.variables 512 .get(ident) 513 .ok_or_else(|| Error::FailedLookup(ident.to_owned())) 514 } 515 516 pub(crate) fn lookup_mut( 517 &mut self, 518 ident: &ast::Identifier, 519 ) -> std::result::Result<&mut Variable, Error> { 520 self.variables 521 .get_mut(ident) 522 .ok_or_else(|| Error::FailedLookup(ident.to_owned())) 523 } 524 525 fn bind( 526 &mut self, 527 ident: &ast::Identifier, 528 ty: ast::Type, 529 ) -> std::result::Result<&mut Variable, Error> { 530 if self.lookup(ident).is_err() { 531 self.variables 532 .entry(ident.to_owned()) 533 .or_insert_with(|| Variable { 534 name: ident.to_owned(), 535 value: Value::default(ty), 536 ty, 537 }) 538 .wrap_ok() 539 } else { 540 Err(Error::AlreadyBound(ident.to_owned())) 541 } 542 } 543 544 fn eval_bin(&mut self, lhs: &ast::Expr, op: ast::BinOp, rhs: &ast::Expr) -> Result { 545 match op { 546 ast::BinOp::Assign(op) => self.eval_assign(lhs, op, rhs), 547 ast::BinOp::Arith(op) => self.eval_arith(lhs, op, rhs), 548 ast::BinOp::Cmp(op) => self.eval_cmp(lhs, op, rhs), 549 ast::BinOp::Logic(op) => self.eval_logic(lhs, op, rhs), 550 } 551 } 552 553 fn eval_assign( 554 &mut self, 555 lhs: &ast::Expr, 556 ast::AssignOp { op }: ast::AssignOp, 557 rhs: &ast::Expr, 558 ) -> Result { 559 let ast::Expr::Ident(ident) = lhs else { 560 return Err(Error::MalformedExpr(format!( 561 "malformed assigment, lhs: {:?}", 562 lhs 563 ))); 564 }; 565 let value = self.eval_expr(rhs)?; 566 let variable = self.lookup_mut(ident)?; 567 match op { 568 None => variable.assign(value), 569 Some(ast::ArithOp::Add) => variable.assign(variable.value().add(&value)?), 570 Some(ast::ArithOp::Sub) => variable.assign(variable.value().sub(&value)?), 571 Some(ast::ArithOp::Mul) => variable.assign(variable.value().mul(&value)?), 572 Some(ast::ArithOp::Div) => variable.assign(variable.value().div(&value)?), 573 Some(ast::ArithOp::Mod) => variable.assign(variable.value().mod_(&value)?), 574 } 575 } 576 577 fn eval_arith(&mut self, lhs: &ast::Expr, op: ast::ArithOp, rhs: &ast::Expr) -> Result { 578 let l = self.eval_expr(lhs)?; 579 let r = self.eval_expr(rhs)?; 580 match op { 581 ast::ArithOp::Add => l.add(&r), 582 ast::ArithOp::Sub => l.sub(&r), 583 ast::ArithOp::Mul => l.mul(&r), 584 ast::ArithOp::Div => l.div(&r), 585 ast::ArithOp::Mod => l.mod_(&r), 586 } 587 } 588 589 fn eval_cmp(&mut self, lhs: &ast::Expr, op: ast::CmpOp, rhs: &ast::Expr) -> Result { 590 let l = self.eval_expr(lhs)?; 591 let r = self.eval_expr(rhs)?; 592 593 match op { 594 ast::CmpOp::Eq => l.equals(&r), 595 ast::CmpOp::Gt => l.greater_than(&r), 596 ast::CmpOp::Lt => l.less_than(&r), 597 ast::CmpOp::Neq => l.equals(&r).and_then(|v| v.not()), 598 ast::CmpOp::Gte => l.greater_than_equals(&r), 599 ast::CmpOp::Lte => l.less_than_equals(&r), 600 } 601 } 602 603 fn eval_logic(&mut self, lhs: &ast::Expr, op: ast::LogicOp, rhs: &ast::Expr) -> Result { 604 let l = self.eval_expr(lhs)?; 605 606 // short-circuit 607 let l_value = l.as_boolean()?; 608 609 match op { 610 ast::LogicOp::Or => { 611 if l_value { 612 return Ok(l); 613 } else { 614 let r = self.eval_expr(rhs)?; 615 l.or(&r) 616 } 617 } 618 ast::LogicOp::And => { 619 if !l_value { 620 return Ok(l); 621 } else { 622 let r = self.eval_expr(rhs)?; 623 l.and(&r) 624 } 625 } 626 } 627 } 628 629 fn eval_unary(&mut self, expr: &ast::Expr, op: ast::UnaryOp) -> Result { 630 let val = self.eval_expr(expr)?; 631 match op { 632 ast::UnaryOp::Not => val.not(), 633 } 634 } 635 636 fn eval_if(&mut self, if_expr: &ast::IfExpr) -> Result { 637 let cond = self.eval_expr(&if_expr.condition)?; 638 639 if cond.as_boolean()? { 640 self.eval_block(&if_expr.then) 641 } else { 642 self.eval_block(&if_expr.else_) 643 } 644 } 645 646 fn eval_call(&mut self, call: &ast::Call) -> Result { 647 ((&*crate::builtins::BUILTINS) 648 .get(call.function.as_str()) 649 .ok_or_else(|| Error::FailedLookup(call.function.to_owned()))?)( 650 self, 651 call.parameters.as_slice(), 652 ) 653 } 654 655 fn eval_list(&mut self, list: &ast::List) -> Result { 656 let mut vals = vec![]; 657 for i in &list.items { 658 vals.push(self.eval_expr(i)?); 659 } 660 Ok(vals.into()) 661 } 662 663 fn eval_index(&mut self, target: &ast::Expr, idx: &ast::Expr) -> Result { 664 let mut target = self.eval_expr(target)?.as_list()?; 665 let idx = self.eval_expr(idx)?.as_int()?; 666 if idx < 0 || idx >= target.len() as i128 { 667 Err(Error::ArrayOutOfBounds { 668 idx, 669 len: target.len(), 670 }) 671 } else { 672 Ok(target.remove(idx as usize)) 673 } 674 } 675 676 fn eval_declaration(&mut self, decl: &ast::Declaration) -> Result { 677 let initial_value = match decl.init.as_ref() { 678 Some(init) => Some(self.eval_expr(&*init)?), 679 None => None, 680 }; 681 let variable = self.bind(&decl.name, decl.ty)?; 682 683 if let Some(init) = initial_value { 684 variable.assign(init)?; 685 } 686 687 Ok(Value::Unit) 688 } 689 690 fn eval_statement(&mut self, stmt: &ast::Statement) -> Result { 691 match stmt { 692 ast::Statement::Bare(expr) => self.eval_expr(expr), 693 ast::Statement::Declaration(decl) => self.eval_declaration(decl), 694 } 695 } 696 697 fn eval_block(&mut self, block: &ast::Block) -> Result { 698 for stmt in block.body.iter() { 699 self.eval_statement(stmt)?; 700 } 701 Ok(Value::Unit) 702 } 703 704 fn eval_field_access(&mut self, expr: &ast::Expr, field: &ast::Identifier) -> Result { 705 let v = self.eval_expr(expr)?; 706 let base = v.as_node()?; 707 let base_node = self.get_node_by_id(base).unwrap(); 708 base_node 709 .child_by_field_name(field) 710 .ok_or(Error::InvalidNodeKind(field.clone())) 711 .map(|n| n.id()) 712 .map(Value::Node) 713 } 714 715 fn goto_first_child(&mut self) -> bool { 716 self.cursor 717 .as_mut() 718 .map(|c| c.goto_first_child()) 719 .unwrap_or_default() 720 } 721 722 pub fn eval(&mut self) -> Result { 723 let program = std::mem::take(&mut self.program); 724 let mut has_next = true; 725 let mut postorder = Vec::new(); 726 727 // BEGIN block 728 if let Some(block) = program.begin() { 729 self.eval_block(block)?; 730 } 731 732 while has_next { 733 let current_node = self.cursor.as_ref().unwrap().node(); 734 postorder.push(current_node); 735 736 if let Some(block) = program.stanza_by_node(current_node, ast::Modifier::Enter) { 737 self.eval_block(block)?; 738 } 739 740 has_next = self.goto_first_child(); 741 742 if !has_next { 743 has_next = self.cursor.as_mut().unwrap().goto_next_sibling(); 744 if let Some(block) = postorder 745 .pop() 746 .and_then(|n| program.stanza_by_node(n, ast::Modifier::Leave)) 747 { 748 self.eval_block(block)?; 749 }; 750 } 751 752 while !has_next && self.cursor.as_mut().unwrap().goto_parent() { 753 has_next = self.cursor.as_mut().unwrap().goto_next_sibling(); 754 if let Some(block) = postorder 755 .pop() 756 .and_then(|n| program.stanza_by_node(n, ast::Modifier::Leave)) 757 { 758 self.eval_block(block)?; 759 }; 760 } 761 } 762 763 // END block 764 if let Some(block) = program.end() { 765 self.eval_block(block)?; 766 } 767 768 Ok(Value::Unit) 769 } 770} 771 772pub fn evaluate(file: &str, program: &str, language: tree_sitter::Language) -> Result { 773 let mut parser = tree_sitter::Parser::new(); 774 let _ = parser.set_language(&language); 775 776 let tree = parser.parse(file, None).unwrap(); 777 778 let program = ast::Program::new().from_str(program).unwrap(); 779 let mut ctx = Context::new(language) 780 .with_input(file.to_owned()) 781 .with_tree(tree) 782 .with_program(program); 783 784 ctx.eval() 785} 786 787#[cfg(test)] 788mod test { 789 use super::*; 790 use crate::ast::*; 791 792 #[test] 793 fn bin() { 794 let language = tree_sitter_python::language(); 795 let mut ctx = Context::new(language).with_program(Program::new()); 796 assert_eq!( 797 ctx.eval_expr(&Expr::bin(Expr::int(5), "+", Expr::int(10),)), 798 Ok(Value::Integer(15)) 799 ); 800 assert_eq!( 801 ctx.eval_expr(&Expr::bin(Expr::int(5), "==", Expr::int(10),)), 802 Ok(Value::Boolean(false)) 803 ); 804 assert_eq!( 805 ctx.eval_expr(&Expr::bin(Expr::int(5), "<", Expr::int(10),)), 806 Ok(Value::Boolean(true)) 807 ); 808 assert_eq!( 809 ctx.eval_expr(&Expr::bin( 810 Expr::bin(Expr::int(5), "<", Expr::int(10),), 811 "&&", 812 Expr::false_(), 813 )), 814 Ok(Value::Boolean(false)) 815 ); 816 } 817 818 #[test] 819 fn test_evaluate_blocks() { 820 let language = tree_sitter_python::language(); 821 let mut ctx = Context::new(language).with_program(Program::new()); 822 assert_eq!( 823 ctx.eval_block(&Block { 824 body: vec![ 825 Statement::Declaration(Declaration { 826 ty: Type::Integer, 827 name: "a".to_owned(), 828 init: None, 829 }), 830 Statement::Bare(Expr::bin(Expr::ident("a"), "+=", Expr::int(5),)), 831 ] 832 }), 833 Ok(Value::Unit) 834 ); 835 assert_eq!( 836 ctx.lookup(&String::from("a")).unwrap().clone(), 837 Variable { 838 ty: Type::Integer, 839 name: "a".to_owned(), 840 value: Value::Integer(5) 841 } 842 ); 843 } 844 845 #[test] 846 fn test_evaluate_if() { 847 let language = tree_sitter_python::language(); 848 let mut ctx = Context::new(language).with_program(Program::new()); 849 assert_eq!( 850 ctx.eval_block(&Block { 851 body: vec![ 852 Statement::Declaration(Declaration { 853 ty: Type::Integer, 854 name: "a".to_owned(), 855 init: Some(Expr::int(1).boxed()), 856 }), 857 Statement::Bare(Expr::If(IfExpr { 858 condition: Expr::true_().boxed(), 859 then: Block { 860 body: vec![Statement::Bare(Expr::bin( 861 Expr::Ident("a".to_owned()), 862 "+=", 863 Expr::int(5), 864 ))] 865 }, 866 else_: Block { 867 body: vec![Statement::Bare(Expr::bin( 868 Expr::ident("a"), 869 "+=", 870 Expr::int(10), 871 ))] 872 } 873 })) 874 ] 875 }), 876 Ok(Value::Unit) 877 ); 878 assert_eq!( 879 ctx.lookup(&String::from("a")).unwrap().clone(), 880 Variable { 881 ty: Type::Integer, 882 name: "a".to_owned(), 883 value: Value::Integer(6) 884 } 885 ); 886 } 887 888 #[test] 889 fn test_substring() { 890 let language = tree_sitter_python::language(); 891 let mut ctx = Context::new(language).with_program(Program::new()); 892 assert_eq!( 893 ctx.eval_block(&Block { 894 body: vec![ 895 Statement::Declaration(Declaration { 896 ty: Type::String, 897 name: "a".to_owned(), 898 init: Some(Expr::str("foobar").boxed()), 899 }), 900 Statement::Declaration(Declaration { 901 ty: Type::String, 902 name: "b".to_owned(), 903 init: Some( 904 Expr::call( 905 "substr", 906 [Expr::Ident("a".to_owned()), Expr::int(0), Expr::int(3),] 907 ) 908 .boxed() 909 ), 910 }), 911 ] 912 }), 913 Ok(Value::Unit) 914 ); 915 assert_eq!( 916 ctx.lookup(&String::from("b")).unwrap().clone(), 917 Variable { 918 ty: Type::String, 919 name: "b".to_owned(), 920 value: "foo".into() 921 } 922 ); 923 } 924 925 #[test] 926 fn test_list() { 927 let language = tree_sitter_python::language(); 928 let mut ctx = Context::new(language).with_program(Program::new()); 929 assert_eq!( 930 ctx.eval_block(&Block { 931 body: vec![Statement::Declaration(Declaration { 932 ty: Type::List, 933 name: "a".to_owned(), 934 init: Some( 935 Expr::List(List { 936 items: vec![Expr::int(5)] 937 }) 938 .boxed() 939 ), 940 }),] 941 }), 942 Ok(Value::Unit) 943 ); 944 assert_eq!( 945 ctx.lookup(&String::from("a")).unwrap().clone(), 946 Variable { 947 ty: Type::List, 948 name: "a".to_owned(), 949 value: vec![5usize.into()].into(), 950 } 951 ); 952 } 953 954 #[test] 955 fn test_ts_builtins() { 956 let language = tree_sitter_python::language(); 957 let mut ctx = Context::new(language).with_program(Program::new()); 958 assert_eq!( 959 ctx.eval_block(&Block { 960 body: vec![Statement::decl(Type::List, "a", Expr::list([Expr::int(5)]),)] 961 }), 962 Ok(Value::Unit) 963 ); 964 assert_eq!( 965 ctx.lookup(&String::from("a")).unwrap().clone(), 966 Variable { 967 ty: Type::List, 968 name: "a".to_owned(), 969 value: vec![5usize.into()].into(), 970 } 971 ); 972 } 973}