aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAkshay <[email protected]>2024-08-08 22:19:14 +0100
committerAkshay <[email protected]>2024-08-08 22:19:14 +0100
commit32de8bd5dac80a2c09e7106144cab5a8e16accc4 (patch)
treeee93a3e00be30ec15fe94378353b9178da652629 /src
parent3ad5ba1f6d3f4c5944bbf29a7d761c93cf3740e3 (diff)
store nodes as usize
Diffstat (limited to 'src')
-rw-r--r--src/ast.rs13
-rw-r--r--src/eval.rs174
-rw-r--r--src/lib.rs25
-rw-r--r--src/parser.rs40
4 files changed, 170 insertions, 82 deletions
diff --git a/src/ast.rs b/src/ast.rs
index 96fe8ab..35bf6c3 100644
--- a/src/ast.rs
+++ b/src/ast.rs
@@ -59,7 +59,7 @@ 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(Vec<Identifier>), 62 FieldAccess(Box<Expr>, Identifier),
63 Unit, 63 Unit,
64 Lit(Literal), 64 Lit(Literal),
65 Ident(Identifier), 65 Ident(Identifier),
@@ -67,7 +67,7 @@ pub enum 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 IfExpr(If), 70 If(IfExpr),
71 Block(Block), 71 Block(Block),
72} 72}
73 73
@@ -75,6 +75,13 @@ impl Expr {
75 pub fn boxed(self) -> Box<Expr> { 75 pub fn boxed(self) -> Box<Expr> {
76 Box::new(self) 76 Box::new(self)
77 } 77 }
78
79 pub fn as_ident(self) -> Option<Identifier> {
80 match self {
81 Self::Ident(i) => Some(i),
82 _ => None,
83 }
84 }
78} 85}
79 86
80#[derive(Debug, Eq, PartialEq, Clone, Copy)] 87#[derive(Debug, Eq, PartialEq, Clone, Copy)]
@@ -164,7 +171,7 @@ pub struct Declaration {
164} 171}
165 172
166#[derive(Debug, Eq, PartialEq, Clone)] 173#[derive(Debug, Eq, PartialEq, Clone)]
167pub struct If { 174pub struct IfExpr {
168 pub condition: Box<Expr>, 175 pub condition: Box<Expr>,
169 pub then: Block, 176 pub then: Block,
170 pub else_: Block, 177 pub else_: Block,
diff --git a/src/eval.rs b/src/eval.rs
index 1a3f8a8..7822419 100644
--- a/src/eval.rs
+++ b/src/eval.rs
@@ -1,6 +1,6 @@
1//! tree walking interpreter for tbsp 1//! tree walking interpreter for tbsp
2 2
3use crate::ast; 3use crate::{ast, Wrap};
4use std::{collections::HashMap, fmt}; 4use std::{collections::HashMap, fmt};
5 5
6#[derive(Debug, PartialEq, Eq, Clone)] 6#[derive(Debug, PartialEq, Eq, Clone)]
@@ -38,10 +38,11 @@ pub enum Value {
38 Integer(i128), 38 Integer(i128),
39 String(String), 39 String(String),
40 Boolean(bool), 40 Boolean(bool),
41 Node, 41 Node(NodeId),
42 FieldAccess(Vec<String>),
43} 42}
44 43
44type NodeId = usize;
45
45impl Value { 46impl Value {
46 fn ty(&self) -> ast::Type { 47 fn ty(&self) -> ast::Type {
47 match self { 48 match self {
@@ -49,8 +50,7 @@ impl Value {
49 Self::Integer(_) => ast::Type::Integer, 50 Self::Integer(_) => ast::Type::Integer,
50 Self::String(_) => ast::Type::String, 51 Self::String(_) => ast::Type::String,
51 Self::Boolean(_) => ast::Type::Boolean, 52 Self::Boolean(_) => ast::Type::Boolean,
52 Self::Node => ast::Type::Node, 53 Self::Node(_) => ast::Type::Node,
53 Self::FieldAccess(_) => ast::Type::Node,
54 } 54 }
55 } 55 }
56 56
@@ -106,6 +106,16 @@ impl Value {
106 } 106 }
107 } 107 }
108 108
109 fn as_node(&self) -> std::result::Result<NodeId, Error> {
110 match self {
111 Self::Node(id) => Ok(*id),
112 v => Err(Error::TypeMismatch {
113 expected: ast::Type::Node,
114 got: v.ty(),
115 }),
116 }
117 }
118
109 fn add(&self, other: &Self) -> Result { 119 fn add(&self, other: &Self) -> Result {
110 match (self, other) { 120 match (self, other) {
111 (Self::Integer(s), Self::Integer(o)) => Ok(Self::Integer(*s + *o)), 121 (Self::Integer(s), Self::Integer(o)) => Ok(Self::Integer(*s + *o)),
@@ -267,8 +277,7 @@ impl fmt::Display for Value {
267 Self::Integer(i) => write!(f, "{i}"), 277 Self::Integer(i) => write!(f, "{i}"),
268 Self::String(s) => write!(f, "{s}"), 278 Self::String(s) => write!(f, "{s}"),
269 Self::Boolean(b) => write!(f, "{b}"), 279 Self::Boolean(b) => write!(f, "{b}"),
270 Self::Node => write!(f, "<node>"), 280 Self::Node(id) => write!(f, "<node #{id}>"),
271 Self::FieldAccess(items) => write!(f, "<node>.{}", items.join(".")),
272 } 281 }
273 } 282 }
274} 283}
@@ -373,15 +382,17 @@ pub enum Error {
373 382
374pub type Result = std::result::Result<Value, Error>; 383pub type Result = std::result::Result<Value, Error>;
375 384
376pub struct Context<'a> { 385pub struct Context {
377 variables: HashMap<ast::Identifier, Variable>, 386 variables: HashMap<ast::Identifier, Variable>,
378 language: tree_sitter::Language, 387 language: tree_sitter::Language,
379 visitors: Visitors, 388 visitors: Visitors,
380 input_src: Option<String>, 389 input_src: Option<String>,
381 cursor: Option<tree_sitter::TreeCursor<'a>>, 390 cursor: Option<tree_sitter::TreeCursor<'static>>,
391 tree: Option<&'static tree_sitter::Tree>,
392 cache: HashMap<NodeId, tree_sitter::Node<'static>>,
382} 393}
383 394
384impl<'a> fmt::Debug for Context<'a> { 395impl fmt::Debug for Context {
385 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 396 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
386 f.debug_struct("Context") 397 f.debug_struct("Context")
387 .field("variables", &self.variables) 398 .field("variables", &self.variables)
@@ -400,7 +411,7 @@ impl<'a> fmt::Debug for Context<'a> {
400 } 411 }
401} 412}
402 413
403impl<'a> Context<'a> { 414impl Context {
404 pub fn new(language: tree_sitter::Language) -> Self { 415 pub fn new(language: tree_sitter::Language) -> Self {
405 Self { 416 Self {
406 visitors: Default::default(), 417 visitors: Default::default(),
@@ -408,9 +419,44 @@ impl<'a> Context<'a> {
408 language, 419 language,
409 input_src: None, 420 input_src: None,
410 cursor: None, 421 cursor: None,
422 tree: None,
423 cache: HashMap::default(),
411 } 424 }
412 } 425 }
413 426
427 pub fn cache_node(&mut self, node: tree_sitter::Node<'static>) {
428 self.cache.entry(node.id()).or_insert(node);
429 }
430
431 pub fn get_node_by_id(&mut self, id: usize) -> Option<tree_sitter::Node<'static>> {
432 let root_node = self.tree.as_ref().map(|t| t.root_node())?;
433 self.get_node_by_id_helper(root_node, id)
434 }
435
436 fn get_node_by_id_helper(
437 &mut self,
438 start: tree_sitter::Node<'static>,
439 id: usize,
440 ) -> Option<tree_sitter::Node<'static>> {
441 self.cache_node(start);
442
443 if let Some(found) = self.cache.get(&id) {
444 return Some(*found);
445 }
446
447 if start.id() == id {
448 return Some(start);
449 } else {
450 for child in start.children(&mut start.walk()) {
451 if let Some(n) = self.get_node_by_id_helper(child, id) {
452 return Some(n);
453 };
454 }
455 }
456
457 None
458 }
459
414 pub fn with_program(mut self, program: ast::Program) -> std::result::Result<Self, Error> { 460 pub fn with_program(mut self, program: ast::Program) -> std::result::Result<Self, Error> {
415 for stanza in program.stanzas.into_iter() { 461 for stanza in program.stanzas.into_iter() {
416 self.visitors.insert(stanza, &self.language)?; 462 self.visitors.insert(stanza, &self.language)?;
@@ -423,8 +469,10 @@ impl<'a> Context<'a> {
423 self 469 self
424 } 470 }
425 471
426 pub fn with_cursor(mut self, cursor: tree_sitter::TreeCursor<'a>) -> Self { 472 pub fn with_tree(mut self, tree: tree_sitter::Tree) -> Self {
427 self.cursor = Some(cursor); 473 let tree = Box::leak(Box::new(tree));
474 self.cursor = Some(tree.walk());
475 self.tree = Some(tree);
428 self 476 self
429 } 477 }
430 478
@@ -436,10 +484,10 @@ impl<'a> Context<'a> {
436 ast::Expr::Bin(lhs, op, rhs) => self.eval_bin(&*lhs, *op, &*rhs), 484 ast::Expr::Bin(lhs, op, rhs) => self.eval_bin(&*lhs, *op, &*rhs),
437 ast::Expr::Unary(expr, op) => self.eval_unary(&*expr, *op), 485 ast::Expr::Unary(expr, op) => self.eval_unary(&*expr, *op),
438 ast::Expr::Call(call) => self.eval_call(&*call), 486 ast::Expr::Call(call) => self.eval_call(&*call),
439 ast::Expr::IfExpr(if_expr) => self.eval_if(if_expr), 487 ast::Expr::If(if_expr) => self.eval_if(if_expr),
440 ast::Expr::Block(block) => self.eval_block(block), 488 ast::Expr::Block(block) => self.eval_block(block),
441 ast::Expr::Node => Ok(Value::Node), 489 ast::Expr::Node => self.eval_node(),
442 ast::Expr::FieldAccess(items) => Ok(Value::FieldAccess(items.to_owned())), 490 ast::Expr::FieldAccess(expr, items) => self.eval_field_access(expr, items),
443 } 491 }
444 } 492 }
445 493
@@ -451,6 +499,16 @@ impl<'a> Context<'a> {
451 } 499 }
452 } 500 }
453 501
502 fn eval_node(&mut self) -> Result {
503 self.cursor
504 .as_ref()
505 .ok_or(Error::CurrentNodeNotPresent)?
506 .node()
507 .id()
508 .wrap(Value::Node)
509 .wrap_ok()
510 }
511
454 fn lookup(&mut self, ident: &ast::Identifier) -> std::result::Result<&Variable, Error> { 512 fn lookup(&mut self, ident: &ast::Identifier) -> std::result::Result<&Variable, Error> {
455 self.variables 513 self.variables
456 .get(ident) 514 .get(ident)
@@ -469,14 +527,14 @@ impl<'a> Context<'a> {
469 ty: ast::Type, 527 ty: ast::Type,
470 ) -> std::result::Result<&mut Variable, Error> { 528 ) -> std::result::Result<&mut Variable, Error> {
471 if self.lookup(ident).is_err() { 529 if self.lookup(ident).is_err() {
472 Ok(self 530 self.variables
473 .variables
474 .entry(ident.to_owned()) 531 .entry(ident.to_owned())
475 .or_insert_with(|| Variable { 532 .or_insert_with(|| Variable {
476 name: ident.to_owned(), 533 name: ident.to_owned(),
477 value: Value::default(ty), 534 value: Value::default(ty),
478 ty, 535 ty,
479 })) 536 })
537 .wrap_ok()
480 } else { 538 } else {
481 Err(Error::AlreadyBound(ident.to_owned())) 539 Err(Error::AlreadyBound(ident.to_owned()))
482 } 540 }
@@ -574,7 +632,7 @@ impl<'a> Context<'a> {
574 } 632 }
575 } 633 }
576 634
577 fn eval_if(&mut self, if_expr: &ast::If) -> Result { 635 fn eval_if(&mut self, if_expr: &ast::IfExpr) -> Result {
578 let cond = self.eval_expr(&if_expr.condition)?; 636 let cond = self.eval_expr(&if_expr.condition)?;
579 637
580 if cond.as_boolean()? { 638 if cond.as_boolean()? {
@@ -638,32 +696,9 @@ impl<'a> Context<'a> {
638 } 696 }
639 } 697 }
640 ("text", [arg]) => { 698 ("text", [arg]) => {
641 let node = match self.eval_expr(arg)? { 699 let v = self.eval_expr(arg)?;
642 Value::Node => self 700 let id = v.as_node()?;
643 .cursor 701 let node = self.get_node_by_id(id).unwrap();
644 .as_ref()
645 .ok_or(Error::CurrentNodeNotPresent)?
646 .node(),
647 Value::FieldAccess(fields) => {
648 let mut node = self
649 .cursor
650 .as_ref()
651 .ok_or(Error::CurrentNodeNotPresent)?
652 .node();
653 for field in &fields {
654 node = node
655 .child_by_field_name(field.as_bytes())
656 .ok_or_else(|| Error::FailedLookup(field.to_owned()))?;
657 }
658 node
659 }
660 v => {
661 return Err(Error::TypeMismatch {
662 expected: ast::Type::Node,
663 got: v.ty(),
664 })
665 }
666 };
667 let text = node 702 let text = node
668 .utf8_text(self.input_src.as_ref().unwrap().as_bytes()) 703 .utf8_text(self.input_src.as_ref().unwrap().as_bytes())
669 .unwrap(); 704 .unwrap();
@@ -689,7 +724,7 @@ impl<'a> Context<'a> {
689 724
690 fn eval_statement(&mut self, stmt: &ast::Statement) -> Result { 725 fn eval_statement(&mut self, stmt: &ast::Statement) -> Result {
691 match stmt { 726 match stmt {
692 ast::Statement::Bare(expr) => self.eval_expr(expr).map(|_| Value::Unit), 727 ast::Statement::Bare(expr) => self.eval_expr(expr),
693 ast::Statement::Declaration(decl) => self.eval_declaration(decl), 728 ast::Statement::Declaration(decl) => self.eval_declaration(decl),
694 } 729 }
695 } 730 }
@@ -701,6 +736,24 @@ impl<'a> Context<'a> {
701 Ok(Value::Unit) 736 Ok(Value::Unit)
702 } 737 }
703 738
739 fn eval_field_access(&mut self, expr: &ast::Expr, field: &ast::Identifier) -> Result {
740 let v = self.eval_expr(expr)?;
741 let base = v.as_node()?;
742 let base_node = self.get_node_by_id(base).unwrap();
743 base_node
744 .child_by_field_name(field)
745 .ok_or(Error::InvalidNodeKind(field.clone()))
746 .map(|n| n.id())
747 .map(Value::Node)
748 }
749
750 fn goto_first_child(&mut self) -> bool {
751 self.cursor
752 .as_mut()
753 .map(|c| c.goto_first_child())
754 .unwrap_or_default()
755 }
756
704 pub fn eval(&mut self) -> Result { 757 pub fn eval(&mut self) -> Result {
705 let visitors = std::mem::take(&mut self.visitors); 758 let visitors = std::mem::take(&mut self.visitors);
706 let mut has_next = true; 759 let mut has_next = true;
@@ -710,29 +763,29 @@ impl<'a> Context<'a> {
710 self.eval_block(&visitors.begin)?; 763 self.eval_block(&visitors.begin)?;
711 764
712 while has_next { 765 while has_next {
713 let current_node = self.cursor.as_mut().unwrap().node(); 766 let current_node = self.cursor.as_ref().unwrap().node();
714 postorder.push(current_node); 767 postorder.push(current_node);
715 768
716 let visitor = visitors.get_by_node(current_node); 769 let visitor = visitors.get_by_node(current_node);
717 770
718 visitor.map(|v| self.eval_block(&v.enter)); 771 if let Some(v) = visitor {
772 self.eval_block(&v.enter)?;
773 }
719 774
720 has_next = self.cursor.as_mut().unwrap().goto_first_child(); 775 has_next = self.goto_first_child();
721 776
722 if !has_next { 777 if !has_next {
723 has_next = self.cursor.as_mut().unwrap().goto_next_sibling(); 778 has_next = self.cursor.as_mut().unwrap().goto_next_sibling();
724 postorder 779 if let Some(v) = postorder.pop().and_then(|n| visitors.get_by_node(n)) {
725 .pop() 780 self.eval_block(&v.leave)?;
726 .and_then(|n| visitors.get_by_node(n)) 781 }
727 .map(|v| self.eval_block(&v.leave));
728 } 782 }
729 783
730 while !has_next && self.cursor.as_mut().unwrap().goto_parent() { 784 while !has_next && self.cursor.as_mut().unwrap().goto_parent() {
731 has_next = self.cursor.as_mut().unwrap().goto_next_sibling(); 785 has_next = self.cursor.as_mut().unwrap().goto_next_sibling();
732 postorder 786 if let Some(v) = postorder.pop().and_then(|n| visitors.get_by_node(n)) {
733 .pop() 787 self.eval_block(&v.leave)?;
734 .and_then(|n| visitors.get_by_node(n)) 788 }
735 .map(|v| self.eval_block(&v.leave));
736 } 789 }
737 } 790 }
738 791
@@ -748,12 +801,11 @@ pub fn evaluate(file: &str, program: &str, language: tree_sitter::Language) -> R
748 let _ = parser.set_language(&language); 801 let _ = parser.set_language(&language);
749 802
750 let tree = parser.parse(file, None).unwrap(); 803 let tree = parser.parse(file, None).unwrap();
751 let cursor = tree.walk();
752 804
753 let program = ast::Program::new().from_str(program).unwrap(); 805 let program = ast::Program::new().from_str(program).unwrap();
754 let mut ctx = Context::new(language) 806 let mut ctx = Context::new(language)
755 .with_input(file.to_owned()) 807 .with_input(file.to_owned())
756 .with_cursor(cursor) 808 .with_tree(tree)
757 .with_program(program)?; 809 .with_program(program)?;
758 810
759 ctx.eval() 811 ctx.eval()
@@ -857,7 +909,7 @@ mod test {
857 name: "a".to_owned(), 909 name: "a".to_owned(),
858 init: Some(ast::Expr::int(1).boxed()), 910 init: Some(ast::Expr::int(1).boxed()),
859 }), 911 }),
860 ast::Statement::Bare(ast::Expr::IfExpr(ast::If { 912 ast::Statement::Bare(ast::Expr::If(ast::IfExpr {
861 condition: ast::Expr::true_().boxed(), 913 condition: ast::Expr::true_().boxed(),
862 then: ast::Block { 914 then: ast::Block {
863 body: vec![ast::Statement::Bare(ast::Expr::Bin( 915 body: vec![ast::Statement::Bare(ast::Expr::Bin(
diff --git a/src/lib.rs b/src/lib.rs
index fca5dd5..39f4605 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,29 @@
1mod ast; 1mod ast;
2mod eval; 2mod eval;
3mod parser; 3pub mod parser;
4mod string; 4mod string;
5 5
6pub use eval::evaluate; 6pub use eval::evaluate;
7
8trait Wrap<T> {
9 fn wrap<F, U>(self, f: F) -> U
10 where
11 F: Fn(T) -> U,
12 Self: Sized;
13
14 fn wrap_ok<E>(self) -> Result<Self, E>
15 where
16 Self: Sized,
17 {
18 Ok(self)
19 }
20}
21
22impl<T> Wrap<T> for T {
23 fn wrap<F, U>(self, f: F) -> U
24 where
25 F: Fn(T) -> U,
26 {
27 f(self)
28 }
29}
diff --git a/src/parser.rs b/src/parser.rs
index d705a11..4ec8e57 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -4,7 +4,7 @@ use nom::{
4 character::complete::{alpha1, alphanumeric1, char, multispace0, multispace1, one_of}, 4 character::complete::{alpha1, alphanumeric1, char, multispace0, multispace1, one_of},
5 combinator::{map, opt, recognize, value}, 5 combinator::{map, opt, recognize, value},
6 error::ParseError, 6 error::ParseError,
7 multi::{many0, many0_count, many1, separated_list0, separated_list1}, 7 multi::{fold_many0, many0, many0_count, many1, separated_list0},
8 sequence::{delimited, pair, preceded, terminated, tuple}, 8 sequence::{delimited, pair, preceded, terminated, tuple},
9 IResult, Parser, 9 IResult, Parser,
10}; 10};
@@ -169,24 +169,27 @@ 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_atom, op, parse_mul); 172 let recursive = parse_binary(parse_field_access, op, parse_mul);
173 let base = parse_atom; 173 let base = parse_field_access;
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, Vec<Identifier>> { 177fn parse_field_access<'a>(i: &'a str) -> IResult<&'a str, Expr> {
178 let node = tag("node"); 178 let trailing = map(tuple((ws(char('.')), ws(parse_ident))), |(_, i)| i);
179 let dot = ws(char('.')); 179 let (i, base) = parse_atom(i)?;
180 let fields = separated_list1(ws(char('.')), map(parse_name, str::to_owned)); 180
181 map(tuple((node, dot, fields)), |(_, _, fields)| fields)(i) 181 fold_many0(
182 trailing,
183 move || base.clone(),
184 move |acc, new| Expr::FieldAccess(acc.boxed(), new),
185 )(i)
182} 186}
183 187
184fn parse_atom<'a>(i: &'a str) -> IResult<&'a str, Expr> { 188fn parse_atom<'a>(i: &'a str) -> IResult<&'a str, Expr> {
185 let inner = alt(( 189 let inner = alt((
186 map(parse_field_access, Expr::FieldAccess),
187 map(tag("node"), |_| Expr::Node), 190 map(tag("node"), |_| Expr::Node),
188 map(parse_block, Expr::Block), 191 map(parse_block, Expr::Block),
189 map(parse_if, Expr::IfExpr), 192 map(parse_if, Expr::If),
190 map(parse_call, Expr::Call), 193 map(parse_call, Expr::Call),
191 map(parse_lit, Expr::Lit), 194 map(parse_lit, Expr::Lit),
192 map(parse_ident, Expr::Ident), 195 map(parse_ident, Expr::Ident),
@@ -217,7 +220,7 @@ fn parse_block<'a>(i: &'a str) -> IResult<&'a str, Block> {
217 delimited(open, statements, close).parse(i) 220 delimited(open, statements, close).parse(i)
218} 221}
219 222
220fn parse_if<'a>(i: &'a str) -> IResult<&'a str, If> { 223fn parse_if<'a>(i: &'a str) -> IResult<&'a str, IfExpr> {
221 let if_ = delimited(multispace0, tag("if"), multispace1); 224 let if_ = delimited(multispace0, tag("if"), multispace1);
222 225
223 let open = char('('); 226 let open = char('(');
@@ -231,7 +234,7 @@ fn parse_if<'a>(i: &'a str) -> IResult<&'a str, If> {
231 234
232 map( 235 map(
233 tuple((if_, open, condition, close, then, else_)), 236 tuple((if_, open, condition, close, then, else_)),
234 |(_, _, condition, _, then, else_)| If { 237 |(_, _, condition, _, then, else_)| IfExpr {
235 condition: condition.boxed(), 238 condition: condition.boxed(),
236 then, 239 then,
237 else_: else_.unwrap_or_default(), 240 else_: else_.unwrap_or_default(),
@@ -571,7 +574,7 @@ mod test {
571 assert_eq!(parse_expr(r#" node "#), Ok(("", Expr::Node))); 574 assert_eq!(parse_expr(r#" node "#), Ok(("", Expr::Node)));
572 assert_eq!( 575 assert_eq!(
573 parse_expr(r#" node.foo "#), 576 parse_expr(r#" node.foo "#),
574 Ok(("", Expr::FieldAccess(vec!["foo".to_owned()]))) 577 Ok(("", Expr::FieldAccess(Expr::Node.boxed(), "foo".to_owned())))
575 ); 578 );
576 assert_eq!( 579 assert_eq!(
577 parse_expr( 580 parse_expr(
@@ -581,7 +584,10 @@ mod test {
581 ), 584 ),
582 Ok(( 585 Ok((
583 "", 586 "",
584 Expr::FieldAccess(vec!["foo".to_owned(), "bar".to_owned()]) 587 Expr::FieldAccess(
588 Expr::FieldAccess(Expr::Node.boxed(), "foo".to_owned()).boxed(),
589 "bar".to_owned()
590 )
585 )) 591 ))
586 ); 592 );
587 } 593 }
@@ -600,7 +606,7 @@ mod test {
600 ), 606 ),
601 Ok(( 607 Ok((
602 "", 608 "",
603 Expr::IfExpr(If { 609 Expr::If(IfExpr {
604 condition: Expr::Bin( 610 condition: Expr::Bin(
605 Expr::int(1).boxed(), 611 Expr::int(1).boxed(),
606 BinOp::Cmp(CmpOp::Eq), 612 BinOp::Cmp(CmpOp::Eq),
@@ -713,7 +719,7 @@ mod test {
713 parse_statement("if (true) { true; };"), 719 parse_statement("if (true) { true; };"),
714 Ok(( 720 Ok((
715 "", 721 "",
716 Statement::Bare(Expr::IfExpr(If { 722 Statement::Bare(Expr::If(IfExpr {
717 condition: Expr::true_().boxed(), 723 condition: Expr::true_().boxed(),
718 then: Block { 724 then: Block {
719 body: vec![Statement::Bare(Expr::true_())] 725 body: vec![Statement::Bare(Expr::true_())]
@@ -726,7 +732,7 @@ mod test {
726 parse_expr("if (true) { true; } else { true; }"), 732 parse_expr("if (true) { true; } else { true; }"),
727 Ok(( 733 Ok((
728 "", 734 "",
729 Expr::IfExpr(If { 735 Expr::If(IfExpr {
730 condition: Expr::true_().boxed(), 736 condition: Expr::true_().boxed(),
731 then: Block { 737 then: Block {
732 body: vec![Statement::Bare(Expr::true_())] 738 body: vec![Statement::Bare(Expr::true_())]