aboutsummaryrefslogtreecommitdiff
path: root/src/eval.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval.rs')
-rw-r--r--src/eval.rs55
1 files changed, 48 insertions, 7 deletions
diff --git a/src/eval.rs b/src/eval.rs
index 859979d..e13cec3 100644
--- a/src/eval.rs
+++ b/src/eval.rs
@@ -39,6 +39,7 @@ pub enum Value {
39 String(String), 39 String(String),
40 Boolean(bool), 40 Boolean(bool),
41 Node, 41 Node,
42 FieldAccess(Vec<String>),
42} 43}
43 44
44impl Value { 45impl Value {
@@ -49,6 +50,7 @@ impl Value {
49 Self::String(_) => ast::Type::String, 50 Self::String(_) => ast::Type::String,
50 Self::Boolean(_) => ast::Type::Boolean, 51 Self::Boolean(_) => ast::Type::Boolean,
51 Self::Node => ast::Type::Node, 52 Self::Node => ast::Type::Node,
53 Self::FieldAccess(_) => ast::Type::Node,
52 } 54 }
53 } 55 }
54 56
@@ -241,6 +243,7 @@ impl fmt::Display for Value {
241 Self::String(s) => write!(f, "{s}"), 243 Self::String(s) => write!(f, "{s}"),
242 Self::Boolean(b) => write!(f, "{b}"), 244 Self::Boolean(b) => write!(f, "{b}"),
243 Self::Node => write!(f, "<node>"), 245 Self::Node => write!(f, "<node>"),
246 Self::FieldAccess(items) => write!(f, "<node>.{}", items.join(".")),
244 } 247 }
245 } 248 }
246} 249}
@@ -317,7 +320,7 @@ pub enum Error {
317 CurrentNodeNotPresent, 320 CurrentNodeNotPresent,
318} 321}
319 322
320type Result = std::result::Result<Value, Error>; 323pub type Result = std::result::Result<Value, Error>;
321 324
322pub struct Context<'a> { 325pub struct Context<'a> {
323 variables: HashMap<ast::Identifier, Variable>, 326 variables: HashMap<ast::Identifier, Variable>,
@@ -385,6 +388,7 @@ impl<'a> Context<'a> {
385 ast::Expr::IfExpr(if_expr) => self.eval_if(if_expr), 388 ast::Expr::IfExpr(if_expr) => self.eval_if(if_expr),
386 ast::Expr::Block(block) => self.eval_block(block), 389 ast::Expr::Block(block) => self.eval_block(block),
387 ast::Expr::Node => Ok(Value::Node), 390 ast::Expr::Node => Ok(Value::Node),
391 ast::Expr::FieldAccess(items) => Ok(Value::FieldAccess(items.to_owned())),
388 } 392 }
389 } 393 }
390 394
@@ -544,12 +548,33 @@ impl<'a> Context<'a> {
544 } 548 }
545 Ok(Value::Unit) 549 Ok(Value::Unit)
546 } 550 }
547 ("text", [arg]) if self.eval_expr(arg)? == Value::Node => { 551 ("text", [arg]) => {
548 let node = self 552 let node = match self.eval_expr(arg)? {
549 .cursor 553 Value::Node => self
550 .as_ref() 554 .cursor
551 .ok_or(Error::CurrentNodeNotPresent)? 555 .as_ref()
552 .node(); 556 .ok_or(Error::CurrentNodeNotPresent)?
557 .node(),
558 Value::FieldAccess(fields) => {
559 let mut node = self
560 .cursor
561 .as_ref()
562 .ok_or(Error::CurrentNodeNotPresent)?
563 .node();
564 for field in &fields {
565 node = node
566 .child_by_field_name(field.as_bytes())
567 .ok_or_else(|| Error::FailedLookup(field.to_owned()))?;
568 }
569 node
570 }
571 v => {
572 return Err(Error::TypeMismatch {
573 expected: ast::Type::Node,
574 got: v.ty(),
575 })
576 }
577 };
553 let text = node 578 let text = node
554 .utf8_text(self.input_src.as_ref().unwrap().as_bytes()) 579 .utf8_text(self.input_src.as_ref().unwrap().as_bytes())
555 .unwrap(); 580 .unwrap();
@@ -629,6 +654,22 @@ impl<'a> Context<'a> {
629 } 654 }
630} 655}
631 656
657pub fn evaluate(file: &str, program: &str, language: tree_sitter::Language) -> Result {
658 let mut parser = tree_sitter::Parser::new();
659 let _ = parser.set_language(language);
660
661 let tree = parser.parse(file, None).unwrap();
662 let cursor = tree.walk();
663
664 let program = ast::Program::new().from_str(program).unwrap();
665 let mut ctx = Context::new(tree_sitter_md::language())
666 .with_input(file.to_owned())
667 .with_cursor(cursor)
668 .with_program(program)?;
669
670 ctx.eval()
671}
672
632#[cfg(test)] 673#[cfg(test)]
633mod test { 674mod test {
634 use super::*; 675 use super::*;