1use xee_xpath_ast::{ast::Span, span::Spanned};
2
3use crate::{ir, Variables};
4
5#[derive(Debug, Clone)]
7pub struct Binding {
8 name: ir::Name,
9 expr: ir::Expr,
10 span: Span,
11}
12
13impl Binding {
14 #[inline]
15 pub fn new(name: ir::Name, expr: ir::Expr, span: Span) -> Self {
16 Self { name, expr, span }
17 }
18}
19
20#[derive(Debug, Clone)]
21pub struct Bindings {
22 bindings: Vec<Binding>,
23}
24
25impl Bindings {
26 pub fn new(binding: Binding) -> Self {
27 Self {
28 bindings: vec![binding],
29 }
30 }
31
32 pub fn empty() -> Self {
33 Self {
34 bindings: Vec::new(),
35 }
36 }
37
38 pub fn atom(&mut self) -> ir::AtomS {
44 let last = self.bindings.last().unwrap();
45 let (want_pop, atom) = match &last.expr {
46 ir::Expr::Atom(atom) => (true, atom.clone()),
47 _ => (
48 false,
49 Spanned::new(ir::Atom::Variable(last.name.clone()), last.span),
50 ),
51 };
52 if want_pop {
53 self.bindings.pop();
54 }
55 atom
56 }
57
58 pub fn expr(&self) -> ir::ExprS {
61 let last_binding = self.bindings.last().unwrap();
62 let bindings = &self.bindings[..self.bindings.len() - 1];
63 let expr = last_binding.expr.clone();
64 Spanned::new(
65 bindings.iter().rev().fold(expr, |expr, binding| {
66 ir::Expr::Let(ir::Let {
67 name: binding.name.clone(),
68 var_expr: Box::new(Spanned::new(binding.expr.clone(), binding.span)),
69 return_expr: Box::new(Spanned::new(expr, last_binding.span)),
70 })
71 }),
72 last_binding.span,
73 )
74 }
75
76 pub fn atom_bindings(mut self) -> (ir::AtomS, Self) {
77 let atom = self.atom();
78 (atom, self)
79 }
80
81 pub fn bind_expr(&self, variables: &mut Variables, expr: ir::ExprS) -> Self {
82 let binding = variables.new_binding(expr.value, expr.span);
83 self.bind(binding)
84 }
85
86 pub fn bind_expr_no_span(&self, variables: &mut Variables, expr: ir::Expr) -> Self {
87 let binding = variables.new_binding(expr, (0..0).into());
88 self.bind(binding)
89 }
90
91 pub fn bind(&self, binding: Binding) -> Self {
93 let mut bindings = self.clone();
94 bindings.bindings.push(binding);
95 bindings
96 }
97
98 pub fn concat(&self, bindings: Bindings) -> Self {
100 let mut result = self.clone();
101 result.bindings.extend(bindings.bindings);
102 result
103 }
104}