xee_interpreter/interpreter/
interpret.rs

1use std::cmp::Ordering;
2use std::rc::Rc;
3
4use ibig::{ibig, IBig};
5
6use xee_name::Name;
7use xee_schema_type::Xs;
8use xee_xpath_ast::ast;
9use xot::xmlname::NameStrInfo;
10use xot::Xot;
11
12use crate::atomic::{self, AtomicCompare};
13use crate::atomic::{
14    op_add, op_div, op_idiv, op_mod, op_multiply, op_subtract, OpEq, OpGe, OpGt, OpLe, OpLt, OpNe,
15};
16use crate::context::DynamicContext;
17use crate::function;
18use crate::pattern::PredicateMatcher;
19use crate::sequence;
20use crate::span::SourceSpan;
21use crate::stack;
22use crate::xml;
23use crate::{error, pattern};
24
25use super::instruction::{read_i16, read_instruction, read_u16, read_u8, EncodedInstruction};
26use super::runnable::Runnable;
27use super::state::State;
28
29pub struct Interpreter<'a> {
30    runnable: &'a Runnable<'a>,
31    pub(crate) state: State<'a>,
32}
33
34pub struct ContextInfo {
35    pub item: stack::Value,
36    pub position: stack::Value,
37    pub size: stack::Value,
38}
39
40impl From<sequence::Item> for ContextInfo {
41    fn from(item: sequence::Item) -> Self {
42        ContextInfo {
43            item: item.into(),
44            position: ibig!(1).into(),
45            size: ibig!(1).into(),
46        }
47    }
48}
49
50impl<'a> Interpreter<'a> {
51    pub fn new(runnable: &'a Runnable<'a>, xot: &'a mut Xot) -> Self {
52        Interpreter {
53            runnable,
54            state: State::new(xot),
55        }
56    }
57
58    pub fn state(self) -> State<'a> {
59        self.state
60    }
61
62    pub(crate) fn runnable(&self) -> &Runnable {
63        self.runnable
64    }
65
66    pub fn start(&mut self, context_info: ContextInfo, arguments: Vec<sequence::Sequence>) {
67        self.start_function(self.runnable.program().main_id(), context_info, arguments)
68    }
69
70    fn start_function(
71        &mut self,
72        function_id: function::InlineFunctionId,
73        context_info: ContextInfo,
74        arguments: Vec<sequence::Sequence>,
75    ) {
76        self.state.push_start_frame(function_id);
77
78        self.push_context_info(context_info);
79        // and any arguments
80        for arg in arguments {
81            self.state.push(arg);
82        }
83    }
84
85    fn push_context_info(&mut self, context_info: ContextInfo) {
86        self.state.push_value(context_info.item);
87        self.state.push_value(context_info.position);
88        self.state.push_value(context_info.size);
89    }
90
91    pub fn run(&mut self, start_base: usize) -> error::SpannedResult<()> {
92        // annotate run with detailed error information
93        self.run_actual(start_base).map_err(|e| self.err(e))
94    }
95
96    pub(crate) fn run_actual(&mut self, start_base: usize) -> error::Result<()> {
97        // we can make this an infinite loop as all functions end
98        // with the return instruction
99        loop {
100            let instruction = self.read_instruction();
101            match instruction {
102                EncodedInstruction::Add => {
103                    self.arithmetic_with_offset(op_add)?;
104                }
105                EncodedInstruction::Sub => {
106                    self.arithmetic_with_offset(op_subtract)?;
107                }
108                EncodedInstruction::Mul => {
109                    self.arithmetic(op_multiply)?;
110                }
111                EncodedInstruction::Div => {
112                    self.arithmetic(op_div)?;
113                }
114                EncodedInstruction::IntDiv => {
115                    self.arithmetic(op_idiv)?;
116                }
117                EncodedInstruction::Mod => {
118                    self.arithmetic(op_mod)?;
119                }
120                EncodedInstruction::Plus => {
121                    self.unary_arithmetic(|a| a.plus())?;
122                }
123                EncodedInstruction::Minus => {
124                    self.unary_arithmetic(|a| a.minus())?;
125                }
126                EncodedInstruction::Concat => {
127                    let (a, b) = self.pop_atomic2_option()?;
128                    let a = a.unwrap_or("".into());
129                    let b = b.unwrap_or("".into());
130                    let a = a.cast_to_string();
131                    let b = b.cast_to_string();
132                    let a = a.to_str().unwrap();
133                    let b = b.to_str().unwrap();
134                    let result = a.to_string() + b;
135                    let item: sequence::Item = result.into();
136                    self.state.push(item);
137                }
138                EncodedInstruction::Const => {
139                    let index = self.read_u16();
140                    self.state
141                        .push(self.current_inline_function().constants[index as usize].clone());
142                }
143                EncodedInstruction::Closure => {
144                    let function_id = self.read_u16();
145                    let inline_function_id = function::InlineFunctionId(function_id as usize);
146                    let closure_function =
147                        self.runnable.program().inline_function(inline_function_id);
148
149                    let mut closure_vars = Vec::with_capacity(closure_function.closure_names.len());
150                    for _ in 0..closure_function.closure_names.len() {
151                        closure_vars.push(self.state.pop_value());
152                    }
153                    let function: function::Function =
154                        function::InlineFunctionData::new(inline_function_id, closure_vars).into();
155                    let item: sequence::Item = function.into();
156                    self.state.push(item);
157                }
158                EncodedInstruction::StaticClosure => {
159                    let static_function_id = self.read_u16();
160                    let static_function_id =
161                        function::StaticFunctionId(static_function_id as usize);
162                    let static_closure =
163                        self.create_static_closure_from_stack(static_function_id)?;
164                    let item: sequence::Item = static_closure.into();
165                    self.state.push(item);
166                }
167                EncodedInstruction::Var => {
168                    let index = self.read_u16();
169                    self.state.push_var(index as usize);
170                }
171                EncodedInstruction::Set => {
172                    let index = self.read_u16();
173                    self.state.set_var(index as usize);
174                }
175                EncodedInstruction::ClosureVar => {
176                    let index = self.read_u16();
177                    self.state.push_closure_var(index as usize)?;
178                }
179                EncodedInstruction::Comma => {
180                    let b = self.state.pop()?;
181                    let a = self.state.pop()?;
182                    let sequence = a.concat(b)?;
183                    self.state.push(sequence);
184                }
185                EncodedInstruction::CurlyArray => {
186                    let sequence = self.state.pop()?;
187                    let array: function::Array = sequence.into();
188                    self.state.push(array);
189                }
190                EncodedInstruction::SquareArray => {
191                    let length = self.pop_atomic().unwrap();
192                    let length = length.cast_to_integer_value::<i64>()?;
193                    let mut popped: Vec<sequence::Sequence> = Vec::with_capacity(length as usize);
194                    for _ in 0..length {
195                        popped.push(self.state.pop()?);
196                    }
197                    let item: sequence::Item = function::Array::new(popped).into();
198                    self.state.push(item);
199                }
200                EncodedInstruction::CurlyMap => {
201                    let length = self.pop_atomic().unwrap();
202                    let length = length.cast_to_integer_value::<i64>()?;
203                    let mut popped: Vec<(atomic::Atomic, sequence::Sequence)> =
204                        Vec::with_capacity(length as usize);
205                    for _ in 0..length {
206                        let value = self.state.pop()?;
207                        let key = self.pop_atomic()?;
208                        popped.push((key, value));
209                    }
210                    let item: sequence::Item = function::Map::new(popped)?.into();
211                    self.state.push(item);
212                }
213                EncodedInstruction::Jump => {
214                    let displacement = self.read_i16();
215                    self.state.jump(displacement as i32);
216                }
217                EncodedInstruction::JumpIfTrue => {
218                    let displacement = self.read_i16();
219                    let a = self.pop_effective_boolean()?;
220                    if a {
221                        self.state.jump(displacement as i32);
222                    }
223                }
224                EncodedInstruction::JumpIfFalse => {
225                    let displacement = self.read_i16();
226                    let a = self.pop_effective_boolean()?;
227                    if !a {
228                        self.state.jump(displacement as i32);
229                    }
230                }
231                EncodedInstruction::Eq => {
232                    self.value_compare(OpEq)?;
233                }
234                EncodedInstruction::Ne => self.value_compare(OpNe)?,
235                EncodedInstruction::Lt => {
236                    self.value_compare(OpLt)?;
237                }
238                EncodedInstruction::Le => {
239                    self.value_compare(OpLe)?;
240                }
241                EncodedInstruction::Gt => {
242                    self.value_compare(OpGt)?;
243                }
244                EncodedInstruction::Ge => {
245                    self.value_compare(OpGe)?;
246                }
247                EncodedInstruction::GenEq => {
248                    self.general_compare(OpEq)?;
249                }
250                EncodedInstruction::GenNe => {
251                    self.general_compare(OpNe)?;
252                }
253                EncodedInstruction::GenLt => {
254                    self.general_compare(OpLt)?;
255                }
256                EncodedInstruction::GenLe => {
257                    self.general_compare(OpLe)?;
258                }
259                EncodedInstruction::GenGt => {
260                    self.general_compare(OpGt)?;
261                }
262                EncodedInstruction::GenGe => {
263                    self.general_compare(OpGe)?;
264                }
265                EncodedInstruction::Is => {
266                    let b = self.state.pop()?;
267                    let a = self.state.pop()?;
268                    if a.is_empty() || b.is_empty() {
269                        self.state.push(sequence::Sequence::default());
270                        continue;
271                    }
272                    let result = a.is(&b)?;
273                    self.state.push(result);
274                }
275                EncodedInstruction::Precedes => {
276                    let b = self.state.pop()?;
277                    let a = self.state.pop()?;
278                    if a.is_empty() || b.is_empty() {
279                        self.state.push(sequence::Sequence::default());
280                        continue;
281                    }
282                    let result =
283                        a.precedes(&b, self.runnable.documents().borrow().annotations())?;
284                    self.state.push(result);
285                }
286                EncodedInstruction::Follows => {
287                    let b = self.state.pop()?;
288                    let a = self.state.pop()?;
289                    if a.is_empty() || b.is_empty() {
290                        self.state.push(sequence::Sequence::default());
291                        continue;
292                    }
293                    let result = a.follows(&b, self.runnable.documents().borrow().annotations())?;
294                    self.state.push(result);
295                }
296                EncodedInstruction::Union => {
297                    let b = self.state.pop()?;
298                    let a = self.state.pop()?;
299                    let combined = a.union(b, self.runnable.documents().borrow().annotations())?;
300                    self.state.push(combined);
301                }
302                EncodedInstruction::Intersect => {
303                    let b = self.state.pop()?;
304                    let a = self.state.pop()?;
305                    let combined =
306                        a.intersect(b, self.runnable.documents().borrow().annotations())?;
307                    self.state.push(combined);
308                }
309                EncodedInstruction::Except => {
310                    let b = self.state.pop()?;
311                    let a = self.state.pop()?;
312                    let combined = a.except(b, self.runnable.documents().borrow().annotations())?;
313                    self.state.push(combined);
314                }
315                EncodedInstruction::Dup => {
316                    let value = self.state.pop()?;
317                    self.state.push(value.clone());
318                    self.state.push(value);
319                }
320                EncodedInstruction::Pop => {
321                    self.state.pop()?;
322                }
323                EncodedInstruction::Call => {
324                    let arity = self.read_u8();
325                    self.call(arity)?;
326                }
327                EncodedInstruction::Lookup => {
328                    self.lookup()?;
329                }
330                EncodedInstruction::WildcardLookup => {
331                    self.wildcard_lookup()?;
332                }
333                EncodedInstruction::Step => {
334                    let step_id = self.read_u16();
335                    let node: xot::Node = self.state.pop()?.try_into()?;
336                    let step = &(self.current_inline_function().steps[step_id as usize]);
337                    let value = xml::resolve_step(step, node, self.state.xot());
338                    self.state.push(value);
339                }
340                EncodedInstruction::Deduplicate => {
341                    let value = self.state.pop()?;
342                    let value =
343                        value.deduplicate(self.runnable.documents().borrow().annotations())?;
344                    self.state.push(value);
345                }
346                EncodedInstruction::Return => {
347                    if self.state.inline_return(start_base) {
348                        break;
349                    }
350                }
351                EncodedInstruction::ReturnConvert => {
352                    let sequence_type_id = self.read_u16();
353                    let sequence = self.state.pop()?;
354                    let sequence_type =
355                        &(self.current_inline_function().sequence_types[sequence_type_id as usize]);
356
357                    let sequence = sequence.sequence_type_matching_function_conversion(
358                        sequence_type,
359                        self.runnable.static_context(),
360                        self.state.xot(),
361                        &|function| self.runnable.function_info(function).signature(),
362                    )?;
363                    self.state.push(sequence);
364                }
365                EncodedInstruction::LetDone => {
366                    let return_value = self.state.pop()?;
367                    // pop the variable assignment
368                    let _ = self.state.pop();
369                    self.state.push(return_value);
370                }
371                EncodedInstruction::Cast => {
372                    let type_id = self.read_u16();
373                    let value = self.pop_atomic_option()?;
374                    let cast_type = &(self.current_inline_function().cast_types[type_id as usize]);
375                    if let Some(value) = value {
376                        let cast_value = value
377                            .cast_to_schema_type(cast_type.xs, self.runnable.static_context())?;
378                        self.state.push(cast_value);
379                    } else if cast_type.empty_sequence_allowed {
380                        self.state.push(sequence::Sequence::default());
381                    } else {
382                        Err(error::Error::XPTY0004)?;
383                    }
384                }
385                EncodedInstruction::Castable => {
386                    let type_id = self.read_u16();
387                    let value = self.pop_atomic_option()?;
388                    let cast_type = &(self.current_inline_function().cast_types[type_id as usize]);
389                    if let Some(value) = value {
390                        let cast_value =
391                            value.cast_to_schema_type(cast_type.xs, self.runnable.static_context());
392                        self.state.push(cast_value.is_ok());
393                    } else if cast_type.empty_sequence_allowed {
394                        self.state.push(true)
395                    } else {
396                        self.state.push(false);
397                    }
398                }
399                EncodedInstruction::InstanceOf => {
400                    let sequence_type_id = self.read_u16();
401                    let sequence = self.state.pop()?;
402                    let sequence_type =
403                        &(self.current_inline_function().sequence_types[sequence_type_id as usize]);
404                    let matches = sequence.sequence_type_matching(
405                        sequence_type,
406                        self.state.xot(),
407                        &|function| self.runnable.function_info(function).signature(),
408                    );
409                    if matches.is_ok() {
410                        self.state.push(true);
411                    } else {
412                        self.state.push(false);
413                    }
414                }
415                EncodedInstruction::Treat => {
416                    let sequence_type_id = self.read_u16();
417                    let sequence = self.state.top()?;
418                    let sequence_type =
419                        &(self.current_inline_function().sequence_types[sequence_type_id as usize]);
420                    let matches = sequence.sequence_type_matching(
421                        sequence_type,
422                        self.state.xot(),
423                        &|function| self.runnable.function_info(function).signature(),
424                    );
425                    if matches.is_err() {
426                        Err(error::Error::XPDY0050)?;
427                    }
428                }
429                EncodedInstruction::Range => {
430                    let b = self.state.pop()?;
431                    let a = self.state.pop()?;
432                    let a = a.atomized_option(self.state.xot())?;
433                    let b = b.atomized_option(self.state.xot())?;
434                    let (a, b) = match (a, b) {
435                        (None, None) | (None, _) | (_, None) => {
436                            self.state.push(sequence::Sequence::default());
437                            continue;
438                        }
439                        (Some(a), Some(b)) => (a, b),
440                    };
441                    // we want to ensure we have integers at this point;
442                    // we don't want to be casting strings or anything
443                    a.ensure_base_schema_type(Xs::Integer)?;
444                    b.ensure_base_schema_type(Xs::Integer)?;
445
446                    let a: IBig = a.try_into().unwrap();
447                    let b: IBig = b.try_into().unwrap();
448
449                    match a.cmp(&b) {
450                        Ordering::Greater => self.state.push(sequence::Sequence::default()),
451                        Ordering::Equal => self.state.push(a),
452                        Ordering::Less => {
453                            let sequence: sequence::Sequence =
454                                sequence::Range::new(a, b + 1)?.into();
455                            self.state.push(sequence)
456                        }
457                    }
458                }
459
460                EncodedInstruction::SequenceLen => {
461                    let value = self.state.pop()?;
462                    let l: IBig = value.len().into();
463                    self.state.push(l);
464                }
465                EncodedInstruction::SequenceGet => {
466                    let value = self.state.pop()?;
467                    let index = self.pop_atomic()?;
468                    let index = index.cast_to_integer_value::<i64>()? as usize;
469                    // substract 1 as Xpath is 1-indexed
470                    let item = value.get(index - 1).ok_or(error::Error::XPTY0004)?;
471                    let sequence: sequence::Sequence = item.into();
472                    self.state.push(sequence)
473                }
474                EncodedInstruction::BuildNew => {
475                    self.state.build_new();
476                }
477                EncodedInstruction::BuildPush => {
478                    self.state.build_push()?;
479                }
480                EncodedInstruction::BuildComplete => {
481                    self.state.build_complete();
482                }
483                EncodedInstruction::IsNumeric => {
484                    let is_numeric = self.pop_is_numeric()?;
485                    self.state.push(is_numeric);
486                }
487                EncodedInstruction::XmlName => {
488                    let local_name_value = self.pop_atomic()?;
489                    let namespace_value = self.pop_atomic()?;
490                    let namespace = namespace_value.to_str()?;
491                    let local_name = local_name_value.to_string()?;
492                    let name =
493                        xee_name::Name::new(local_name, namespace.to_string(), String::new());
494                    self.state.push(name);
495                }
496                EncodedInstruction::XmlDocument => {
497                    let root_node = self.state.xot.new_document();
498                    let item = sequence::Item::Node(root_node);
499                    self.state.push(item);
500                }
501                EncodedInstruction::XmlElement => {
502                    let name_id = self.pop_xot_name()?;
503                    let element_node = self.state.xot.new_element(name_id);
504                    let item = sequence::Item::Node(element_node);
505                    self.state.push(item);
506                }
507                EncodedInstruction::XmlAttribute => {
508                    let value = self.pop_atomic()?;
509                    let name_id = self.pop_xot_name()?;
510                    let attribute_node = self
511                        .state
512                        .xot
513                        .new_attribute_node(name_id, value.string_value());
514                    let item = sequence::Item::Node(attribute_node);
515                    self.state.push(item);
516                }
517                EncodedInstruction::XmlNamespace => {
518                    let uri = self.pop_atomic()?;
519                    let namespace_id = self.state.xot.add_namespace(&uri.string_value());
520                    let prefix = self.pop_atomic()?;
521                    let prefix_id = self.state.xot.add_prefix(&prefix.string_value());
522                    let namespace_node = self.state.xot.new_namespace_node(prefix_id, namespace_id);
523                    let item = sequence::Item::Node(namespace_node);
524                    self.state.push(item);
525                }
526                EncodedInstruction::XmlText => {
527                    let text_atomic = self.pop_atomic()?;
528                    let text = text_atomic.into_canonical();
529                    let text_node = self.state.xot.new_text(&text);
530                    let item = sequence::Item::Node(text_node);
531                    self.state.push(item);
532                }
533                EncodedInstruction::XmlComment => {
534                    let text_atomic = self.pop_atomic()?;
535                    let text = text_atomic.into_canonical();
536                    let comment_node = self.state.xot.new_comment(&text);
537                    let item = sequence::Item::Node(comment_node);
538                    self.state.push(item);
539                }
540                EncodedInstruction::XmlProcessingInstruction => {
541                    let text_atomic = self.pop_atomic()?;
542                    let text = text_atomic.into_canonical();
543                    let text = if !text.is_empty() {
544                        Some(text.as_str())
545                    } else {
546                        None
547                    };
548                    let target_atomic = self.pop_atomic()?;
549                    let target = target_atomic.into_canonical();
550                    let target_id = self.state.xot.add_name(&target);
551                    let pi_node = self.state.xot.new_processing_instruction(target_id, text);
552                    let item = sequence::Item::Node(pi_node);
553                    self.state.push(item);
554                }
555                EncodedInstruction::XmlAppend => {
556                    let child_value = self.state.pop()?;
557                    let parent_node = self.pop_node()?;
558                    self.xml_append(parent_node, child_value)?;
559                    // now we can push back the parent node
560                    let item = sequence::Item::Node(parent_node);
561                    self.state.push(item);
562                }
563                EncodedInstruction::CopyShallow => {
564                    let value = &self.state.pop()?;
565                    if value.is_empty() {
566                        self.state.push(sequence::Sequence::default());
567                        continue;
568                    }
569                    if value.len() > 1 {
570                        Err(error::Error::XTTE3180)?;
571                    }
572                    let item = value.iter().next().unwrap();
573                    let copy = match &item {
574                        sequence::Item::Atomic(_) | sequence::Item::Function(_) => item.clone(),
575                        sequence::Item::Node(node) => {
576                            let copied_node = self.shallow_copy_node(*node);
577                            sequence::Item::Node(copied_node)
578                        }
579                    };
580                    self.state.push(copy);
581                }
582                EncodedInstruction::CopyDeep => {
583                    let value = &self.state.pop()?;
584                    if value.is_empty() {
585                        self.state.push(sequence::Sequence::default());
586                        continue;
587                    }
588                    let mut new_sequence = Vec::with_capacity(value.len());
589                    for item in value.iter() {
590                        let copy = match &item {
591                            sequence::Item::Atomic(_) | sequence::Item::Function(_) => item.clone(),
592                            sequence::Item::Node(node) => {
593                                let copied_node = self.state.xot.clone_node(*node);
594                                sequence::Item::Node(copied_node)
595                            }
596                        };
597                        new_sequence.push(copy);
598                    }
599                    self.state.push(new_sequence);
600                }
601                EncodedInstruction::ApplyTemplates => {
602                    let value = self.state.pop()?;
603                    let mode_id = self.read_u16();
604                    let mode = pattern::ModeId::new(mode_id as usize);
605                    let value = self.apply_templates_sequence(mode, value)?;
606                    self.state.push(value);
607                }
608                EncodedInstruction::PrintTop => {
609                    let top = self.state.top()?;
610                    println!("{:#?}", top);
611                }
612                EncodedInstruction::PrintStack => {
613                    println!("{:#?}", self.state.stack());
614                }
615            }
616        }
617        Ok(())
618    }
619
620    pub(crate) fn create_static_closure_from_stack(
621        &mut self,
622        static_function_id: function::StaticFunctionId,
623    ) -> error::Result<function::Function> {
624        Self::create_static_closure(self.runnable.dynamic_context(), static_function_id, || {
625            Some(self.state.pop_value())
626        })
627    }
628
629    pub(crate) fn create_static_closure_from_context(
630        &mut self,
631        static_function_id: function::StaticFunctionId,
632        arg: Option<xot::Node>,
633    ) -> error::Result<function::Function> {
634        Self::create_static_closure(self.runnable.dynamic_context(), static_function_id, || {
635            arg.map(|n| {
636                let value: stack::Value = n.into();
637                value
638            })
639        })
640    }
641
642    pub(crate) fn create_static_closure<F>(
643        context: &DynamicContext,
644        static_function_id: function::StaticFunctionId,
645        mut get: F,
646    ) -> error::Result<function::Function>
647    where
648        F: FnMut() -> Option<stack::Value>,
649    {
650        let static_function = &context.static_context().function_by_id(static_function_id);
651        // get any context value from the stack if needed
652        let closure_vars = if static_function.needs_context() {
653            let value = get();
654            if let Some(value) = value {
655                vec![value]
656            } else {
657                vec![]
658            }
659        } else {
660            vec![]
661        };
662        Ok(function::StaticFunctionData::new(static_function_id, closure_vars).into())
663    }
664
665    pub(crate) fn current_inline_function(&self) -> &function::InlineFunction {
666        self.runnable
667            .program()
668            .inline_function(self.state.frame().function())
669    }
670
671    pub(crate) fn function_name(&self, function: &function::Function) -> Option<Name> {
672        self.runnable.function_info(function).name()
673    }
674
675    pub(crate) fn function_arity(&self, function: &function::Function) -> usize {
676        self.runnable.function_info(function).arity()
677    }
678
679    fn call(&mut self, arity: u8) -> error::Result<()> {
680        let function = self.state.callable(arity as usize)?;
681        self.call_function(&function, arity)
682    }
683
684    pub(crate) fn call_function_with_arguments(
685        &mut self,
686        function: &function::Function,
687        arguments: &[sequence::Sequence],
688    ) -> error::Result<sequence::Sequence> {
689        // put function onto the stack
690        let item: sequence::Item = function.clone().into();
691        self.state.push(item);
692        // then arguments
693        let arity = arguments.len() as u8;
694        for arg in arguments.iter() {
695            self.state.push(arg.clone());
696        }
697        self.call_function(function, arity)?;
698        if matches!(function, function::Function::Inline(_)) {
699            // run interpreter until we return to the base
700            // we started in
701            self.run_actual(self.state.frame().base())?;
702        }
703        self.state.pop()
704    }
705
706    fn call_function(&mut self, function: &function::Function, arity: u8) -> error::Result<()> {
707        match function {
708            function::Function::Static(data) => {
709                self.call_static(data.id, arity, &data.closure_vars)
710            }
711            function::Function::Inline(data) => self.call_inline(data.id, arity),
712            function::Function::Array(array) => self.call_array(array, arity as usize),
713            function::Function::Map(map) => self.call_map(map, arity as usize),
714        }
715    }
716
717    pub(crate) fn arguments(&self, arity: u8) -> &[stack::Value] {
718        self.state.arguments(arity as usize)
719    }
720
721    fn call_static(
722        &mut self,
723        static_function_id: function::StaticFunctionId,
724        arity: u8,
725        closure_vars: &[stack::Value],
726    ) -> error::Result<()> {
727        let static_function = self.runnable.program().static_function(static_function_id);
728        if arity as usize != static_function.arity() {
729            return Err(error::Error::XPTY0004);
730        }
731        let parameter_types = static_function.signature().parameter_types();
732        let arguments = self.coerce_arguments(parameter_types, arity)?;
733        let result =
734            static_function.invoke(self.runnable.dynamic_context, self, arguments, closure_vars)?;
735        // pop the last item off
736        let _ = self.state.pop();
737        self.state.push(result);
738        Ok(())
739    }
740
741    fn call_inline(
742        &mut self,
743        function_id: function::InlineFunctionId,
744        arity: u8,
745    ) -> error::Result<()> {
746        // look up the function in order to access the parameters information
747        let function = self.runnable.program().inline_function(function_id);
748        let parameter_types = &function.signature.parameter_types();
749        if arity as usize != parameter_types.len() {
750            return Err(error::Error::XPTY0004);
751        }
752
753        let arguments = self.coerce_arguments(parameter_types, arity)?;
754
755        // now we have a list of arguments that we want to push back onto the stack
756        // (they are already reversed)
757        for arg in arguments {
758            self.state.push(arg);
759        }
760
761        self.state.push_frame(function_id, arity as usize)
762    }
763
764    fn coerce_arguments(
765        &mut self,
766        parameter_types: &[Option<ast::SequenceType>],
767        arity: u8,
768    ) -> error::Result<Vec<sequence::Sequence>> {
769        // TODO: fast path if no sequence type declarations exist for
770        // parameters could cache this inside of signature so that it's really
771        // fast to detect.
772
773        // we could also have a secondary fast path where if the types are all
774        // exactly the same, we don't do a clone.
775
776        // get all the stack values out in order
777        let stack_values = self.state.arguments(arity as usize);
778        let mut arguments = Vec::with_capacity(arity as usize);
779        let static_context = self.runnable.static_context();
780        let xot = self.state.xot();
781        for (parameter_type, stack_value) in parameter_types.iter().zip(stack_values) {
782            let sequence: sequence::Sequence = stack_value.try_into()?;
783            if let Some(type_) = parameter_type {
784                // matching also takes care of function conversion rules
785                let sequence = sequence.sequence_type_matching_function_conversion(
786                    type_,
787                    static_context,
788                    xot,
789                    &|function| self.runnable.function_info(function).signature(),
790                )?;
791                arguments.push(sequence);
792            } else {
793                // no need to do any checking or conversion
794                arguments.push(sequence);
795            }
796        }
797        self.state.truncate_arguments(arity as usize);
798        Ok(arguments)
799    }
800
801    fn call_array(&mut self, array: &function::Array, arity: usize) -> error::Result<()> {
802        if arity != 1 {
803            return Err(error::Error::XPTY0004);
804        }
805        // the argument
806        let position = self.pop_atomic()?;
807        let sequence = Self::array_get(array, position)?;
808        // pop the array off the stack
809        self.state.pop()?;
810        // now push the result
811        self.state.push(sequence);
812        Ok(())
813    }
814
815    fn array_get(
816        array: &function::Array,
817        position: atomic::Atomic,
818    ) -> error::Result<sequence::Sequence> {
819        let position = position
820            .cast_to_integer_value::<i64>()
821            .map_err(|_| error::Error::XPTY0004)?;
822        let position = position as usize;
823        if position == 0 {
824            return Err(error::Error::FOAY0001);
825        }
826        let position = position - 1;
827        let sequence = array.index(position);
828        sequence.cloned().ok_or(error::Error::FOAY0001)
829    }
830
831    fn call_map(&mut self, map: &function::Map, arity: usize) -> error::Result<()> {
832        if arity != 1 {
833            return Err(error::Error::XPTY0004);
834        }
835        let key = self.pop_atomic()?;
836        let value = map.get(&key);
837        // pop the map off the stack
838        self.state.pop()?;
839        if let Some(value) = value {
840            self.state.push(value.clone());
841        } else {
842            self.state.push(sequence::Sequence::default());
843        }
844        Ok(())
845    }
846
847    fn lookup(&mut self) -> error::Result<()> {
848        let key_specifier = self.state.pop()?;
849        let value = self.state.pop()?;
850        let function: function::Function = value.try_into()?;
851        let value = self.lookup_value(&function, key_specifier)?;
852        let sequence: sequence::Sequence = value.into();
853        self.state.push(sequence);
854        Ok(())
855    }
856
857    fn lookup_value(
858        &self,
859        function: &function::Function,
860        key_specifier: sequence::Sequence,
861    ) -> error::Result<Vec<sequence::Item>> {
862        match function {
863            function::Function::Map(map) => self.lookup_map(map, key_specifier),
864            function::Function::Array(array) => self.lookup_array(array, key_specifier),
865            _ => Err(error::Error::XPTY0004),
866        }
867    }
868
869    fn lookup_map(
870        &self,
871        map: &function::Map,
872        key_specifier: sequence::Sequence,
873    ) -> error::Result<Vec<sequence::Item>> {
874        self.lookup_helper(key_specifier, map, |map, atomic| {
875            Ok(map.get(&atomic).cloned().unwrap_or_default())
876        })
877    }
878
879    fn lookup_array(
880        &self,
881        array: &function::Array,
882        key_specifier: sequence::Sequence,
883    ) -> error::Result<Vec<sequence::Item>> {
884        self.lookup_helper(key_specifier, array, |array, atomic| match atomic {
885            atomic::Atomic::Integer(..) => Self::array_get(array, atomic),
886            _ => Err(error::Error::XPTY0004),
887        })
888    }
889
890    fn lookup_helper<T>(
891        &self,
892        key_specifier: sequence::Sequence,
893        data: T,
894        get_key: impl Fn(&T, atomic::Atomic) -> error::Result<sequence::Sequence>,
895    ) -> error::Result<Vec<sequence::Item>> {
896        let keys = key_specifier
897            .atomized(self.state.xot())
898            .collect::<error::Result<Vec<_>>>()?;
899        let mut result = Vec::new();
900        for key in keys {
901            for item in get_key(&data, key)?.iter() {
902                result.push(item.clone());
903            }
904        }
905        Ok(result)
906    }
907
908    fn wildcard_lookup(&mut self) -> error::Result<()> {
909        let value = self.state.pop()?;
910        let function: function::Function = value.try_into()?;
911        let value = match function {
912            function::Function::Map(map) => {
913                let mut result = Vec::new();
914                for key in map.keys() {
915                    for value in self.lookup_map(&map, key.clone().into())? {
916                        result.push(value)
917                    }
918                }
919                result
920            }
921            function::Function::Array(array) => {
922                let mut result = Vec::new();
923                for i in 1..(array.len() + 1) {
924                    let i: IBig = i.into();
925                    for value in self.lookup_array(&array, i.into())? {
926                        result.push(value)
927                    }
928                }
929                result
930            }
931            _ => return Err(error::Error::XPTY0004),
932        };
933        let sequence: sequence::Sequence = value.into();
934        self.state.push(sequence);
935        Ok(())
936    }
937
938    fn value_compare<O>(&mut self, op: O) -> error::Result<()>
939    where
940        O: AtomicCompare,
941    {
942        let b = self.state.pop()?;
943        let a = self.state.pop()?;
944        // https://www.w3.org/TR/xpath-31/#id-value-comparisons
945        // If an operand is the empty sequence, the result is the empty sequence
946        if a.is_empty() || b.is_empty() {
947            self.state.push(sequence::Sequence::default());
948            return Ok(());
949        }
950        let v = a.value_compare(
951            &b,
952            op,
953            self.runnable.default_collation()?.as_ref(),
954            self.runnable.implicit_timezone(),
955            self.state.xot(),
956        )?;
957        self.state.push(v);
958        Ok(())
959    }
960
961    fn general_compare<O>(&mut self, op: O) -> error::Result<()>
962    where
963        O: AtomicCompare,
964    {
965        let b = self.state.pop()?;
966        let a = self.state.pop()?;
967        let value =
968            a.general_comparison(&b, op, self.runnable.dynamic_context(), self.state.xot())?;
969        self.state.push(value);
970        Ok(())
971    }
972
973    fn arithmetic<F>(&mut self, op: F) -> error::Result<()>
974    where
975        F: Fn(atomic::Atomic, atomic::Atomic) -> error::Result<atomic::Atomic>,
976    {
977        self.arithmetic_with_offset(|a, b, _| op(a, b))
978    }
979
980    fn arithmetic_with_offset<F>(&mut self, op: F) -> error::Result<()>
981    where
982        F: Fn(atomic::Atomic, atomic::Atomic, chrono::FixedOffset) -> error::Result<atomic::Atomic>,
983    {
984        let b = self.state.pop()?;
985        let a = self.state.pop()?;
986        // https://www.w3.org/TR/xpath-31/#id-arithmetic
987        // 2. If an operand is the empty sequence, the result is the empty sequence
988        if a.is_empty() || b.is_empty() {
989            self.state.push(sequence::Sequence::default());
990            return Ok(());
991        }
992        let a = a.atomized_one(self.state.xot())?;
993        let b = b.atomized_one(self.state.xot())?;
994        let result = op(a, b, self.runnable.implicit_timezone())?;
995        self.state.push(result);
996        Ok(())
997    }
998
999    fn unary_arithmetic<F>(&mut self, op: F) -> error::Result<()>
1000    where
1001        F: Fn(atomic::Atomic) -> error::Result<atomic::Atomic>,
1002    {
1003        let a = self.state.pop()?;
1004        if a.is_empty() {
1005            self.state.push(sequence::Sequence::default());
1006            return Ok(());
1007        }
1008        let a = a.atomized_one(self.state.xot())?;
1009        let value = op(a)?;
1010        self.state.push(value);
1011        Ok(())
1012    }
1013
1014    fn pop_is_numeric(&mut self) -> error::Result<bool> {
1015        let value = self.state.pop()?;
1016        let a = value.atomized_option(self.state.xot())?;
1017        if let Some(a) = a {
1018            Ok(a.is_numeric())
1019        } else {
1020            Ok(false)
1021        }
1022    }
1023
1024    fn pop_atomic(&mut self) -> error::Result<atomic::Atomic> {
1025        let value = self.state.pop()?;
1026        value.atomized_one(self.state.xot())
1027    }
1028
1029    fn pop_atomic_option(&mut self) -> error::Result<Option<atomic::Atomic>> {
1030        let value = self.state.pop()?;
1031        value.atomized_option(self.state.xot())
1032    }
1033
1034    fn pop_xot_name(&mut self) -> error::Result<xot::NameId> {
1035        let value = self.pop_atomic()?;
1036        let name: xee_name::Name = value.try_into()?;
1037        let namespace = name.namespace();
1038        let ns = self.state.xot.add_namespace(namespace);
1039        Ok(self.state.xot.add_name_ns(name.local_name(), ns))
1040    }
1041
1042    fn pop_node(&mut self) -> error::Result<xot::Node> {
1043        let value = self.state.pop()?;
1044        let node = value.one()?.to_node()?;
1045        Ok(node)
1046    }
1047
1048    fn pop_atomic2(&mut self) -> error::Result<(atomic::Atomic, atomic::Atomic)> {
1049        let b = self.pop_atomic()?;
1050        let a = self.pop_atomic()?;
1051        Ok((a, b))
1052    }
1053
1054    fn pop_atomic2_option(
1055        &mut self,
1056    ) -> error::Result<(Option<atomic::Atomic>, Option<atomic::Atomic>)> {
1057        let b = self.pop_atomic_option()?;
1058        let a = self.pop_atomic_option()?;
1059        Ok((a, b))
1060    }
1061
1062    fn pop_effective_boolean(&mut self) -> error::Result<bool> {
1063        let a = self.state.pop()?;
1064        a.effective_boolean_value()
1065    }
1066
1067    pub(crate) fn regex(&self, pattern: &str, flags: &str) -> error::Result<Rc<regexml::Regex>> {
1068        self.state.regex(pattern, flags)
1069    }
1070
1071    pub(crate) fn xot(&self) -> &Xot {
1072        self.state.xot()
1073    }
1074
1075    pub(crate) fn xot_mut(&mut self) -> &mut Xot {
1076        self.state.xot_mut()
1077    }
1078
1079    fn xml_append(
1080        &mut self,
1081        parent_node: xot::Node,
1082        value: sequence::Sequence,
1083    ) -> error::Result<()> {
1084        let mut string_values = Vec::new();
1085        for item in value.iter() {
1086            match item {
1087                sequence::Item::Node(node) => {
1088                    // if there were any string values before this node, add them
1089                    // to the node, separated by a space character
1090                    if !string_values.is_empty() {
1091                        self.xml_append_string_values(parent_node, &string_values);
1092                        string_values.clear();
1093                    }
1094                    match self.state.xot.value(node) {
1095                        xot::Value::Document => {
1096                            todo!("Handle adding all the children instead");
1097                        }
1098                        xot::Value::Text(text) => {
1099                            // zero length text nodes are skipped
1100                            // Can this even exist, or does Xot not have
1101                            // them anyway?
1102                            if text.get().is_empty() {
1103                                continue;
1104                            }
1105                        }
1106                        _ => {}
1107                    }
1108
1109                    // if we have a parent we're already in another document,
1110                    // in which case we want to make a clone first
1111                    let node = if self.state.xot.parent(node).is_some() {
1112                        self.state.xot.clone_node(node)
1113                    } else {
1114                        node
1115                    };
1116                    // TODO: error out if namespace or attribute node
1117                    // is added once a normal child already exists
1118                    self.state.xot.any_append(parent_node, node).unwrap();
1119                }
1120                sequence::Item::Atomic(atomic) => string_values.push(atomic.string_value()),
1121                sequence::Item::Function(_) => return Err(error::Error::XTDE0450),
1122            }
1123        }
1124        // if there are any string values left in the end
1125        if !string_values.is_empty() {
1126            self.xml_append_string_values(parent_node, &string_values);
1127        }
1128        Ok(())
1129    }
1130
1131    fn xml_append_string_values(&mut self, parent_node: xot::Node, string_values: &[String]) {
1132        let text = string_values.join(" ");
1133        let text_node = self.state.xot.new_text(&text);
1134        self.state.xot.append(parent_node, text_node).unwrap();
1135    }
1136
1137    fn shallow_copy_node(&mut self, node: xot::Node) -> xot::Node {
1138        let xot = &mut self.state.xot;
1139        let value = xot.value(node);
1140        match value {
1141            // root and element are shallow copies
1142            xot::Value::Document => xot.new_document(),
1143            // TODO: work on copying prefixes
1144            xot::Value::Element(element) => xot.new_element(element.name()),
1145            // we can clone (deep-copy) these nodes as it's the same
1146            // operation as shallow copy
1147            _ => xot.clone_node(node),
1148        }
1149    }
1150
1151    fn apply_templates_sequence(
1152        &mut self,
1153        mode: pattern::ModeId,
1154        sequence: sequence::Sequence,
1155    ) -> error::Result<sequence::Sequence> {
1156        let mut r: Vec<sequence::Item> = Vec::new();
1157        let size: IBig = sequence.len().into();
1158
1159        for (i, item) in sequence.iter().enumerate() {
1160            let sequence = self.apply_templates_item(mode, item, i, size.clone())?;
1161            if let Some(sequence) = sequence {
1162                for item in sequence.iter() {
1163                    r.push(item.clone());
1164                }
1165            }
1166        }
1167        Ok(r.into())
1168    }
1169
1170    fn apply_templates_item(
1171        &mut self,
1172        mode: pattern::ModeId,
1173        item: sequence::Item,
1174        position: usize,
1175        size: IBig,
1176    ) -> error::Result<Option<sequence::Sequence>> {
1177        let function_id = self.lookup_pattern(mode, &item);
1178
1179        if let Some(function_id) = function_id {
1180            let position: IBig = (position + 1).into();
1181            let arguments: Vec<sequence::Sequence> = vec![
1182                item.into(),
1183                atomic::Atomic::from(position).into(),
1184                atomic::Atomic::from(size.clone()).into(),
1185            ];
1186            let function = function::InlineFunctionData::new(function_id, Vec::new()).into();
1187            self.call_function_with_arguments(&function, &arguments)
1188                .map(Some)
1189        } else {
1190            Ok(None)
1191        }
1192    }
1193
1194    pub(crate) fn lookup_pattern(
1195        &mut self,
1196        mode: pattern::ModeId,
1197        item: &sequence::Item,
1198    ) -> Option<function::InlineFunctionId> {
1199        self.runnable
1200            .program()
1201            .declarations
1202            .mode_lookup
1203            .lookup(mode, |pattern| self.matches(pattern, item))
1204            .copied()
1205    }
1206
1207    // The interpreter can return an error for any byte code, in any level of
1208    // nesting in the function. When this happens the interpreter stops with
1209    // the error code. We here wrap it in a SpannedError using the current
1210    // span.
1211    pub(crate) fn err(&self, value_error: error::Error) -> error::SpannedError {
1212        error::SpannedError {
1213            error: value_error,
1214            span: Some(self.current_span()),
1215        }
1216    }
1217
1218    // During the compilation process, spans became associated with each
1219    // compiled bytecode instruction. Here we take the current function and the
1220    // instruction in it to determine the span of the code that failed.
1221    fn current_span(&self) -> SourceSpan {
1222        let frame = self.state.frame();
1223        let function = self.runnable.program().inline_function(frame.function());
1224        // we substract 1 to end up in the current instruction - this
1225        // because the ip is already on the next instruction
1226        function.spans[frame.ip - 1]
1227    }
1228
1229    fn read_instruction(&mut self) -> EncodedInstruction {
1230        let frame = self.state.frame_mut();
1231        let function = self.runnable.program().inline_function(frame.function());
1232        let chunk = &function.chunk;
1233        read_instruction(chunk, &mut frame.ip)
1234    }
1235
1236    fn read_u16(&mut self) -> u16 {
1237        let frame = &mut self.state.frame_mut();
1238        let function = self.runnable.program().inline_function(frame.function());
1239        let chunk = &function.chunk;
1240        read_u16(chunk, &mut frame.ip)
1241    }
1242
1243    fn read_i16(&mut self) -> i16 {
1244        let frame = &mut self.state.frame_mut();
1245        let function = self.runnable.program().inline_function(frame.function());
1246        let chunk = &function.chunk;
1247        read_i16(chunk, &mut frame.ip)
1248    }
1249
1250    fn read_u8(&mut self) -> u8 {
1251        let frame = &mut self.state.frame_mut();
1252        let function = self.runnable.program().inline_function(frame.function());
1253        let chunk = &function.chunk;
1254        read_u8(chunk, &mut frame.ip)
1255    }
1256}