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        let position = position - 1;
824        let sequence = array.index(position);
825        sequence.cloned().ok_or(error::Error::FOAY0001)
826    }
827
828    fn call_map(&mut self, map: &function::Map, arity: usize) -> error::Result<()> {
829        if arity != 1 {
830            return Err(error::Error::XPTY0004);
831        }
832        let key = self.pop_atomic()?;
833        let value = map.get(&key);
834        // pop the map off the stack
835        self.state.pop()?;
836        if let Some(value) = value {
837            self.state.push(value.clone());
838        } else {
839            self.state.push(sequence::Sequence::default());
840        }
841        Ok(())
842    }
843
844    fn lookup(&mut self) -> error::Result<()> {
845        let key_specifier = self.state.pop()?;
846        let value = self.state.pop()?;
847        let function: function::Function = value.try_into()?;
848        let value = self.lookup_value(&function, key_specifier)?;
849        let sequence: sequence::Sequence = value.into();
850        self.state.push(sequence);
851        Ok(())
852    }
853
854    fn lookup_value(
855        &self,
856        function: &function::Function,
857        key_specifier: sequence::Sequence,
858    ) -> error::Result<Vec<sequence::Item>> {
859        match function {
860            function::Function::Map(map) => self.lookup_map(map, key_specifier),
861            function::Function::Array(array) => self.lookup_array(array, key_specifier),
862            _ => Err(error::Error::XPTY0004),
863        }
864    }
865
866    fn lookup_map(
867        &self,
868        map: &function::Map,
869        key_specifier: sequence::Sequence,
870    ) -> error::Result<Vec<sequence::Item>> {
871        self.lookup_helper(key_specifier, map, |map, atomic| {
872            Ok(map.get(&atomic).cloned().unwrap_or_default())
873        })
874    }
875
876    fn lookup_array(
877        &self,
878        array: &function::Array,
879        key_specifier: sequence::Sequence,
880    ) -> error::Result<Vec<sequence::Item>> {
881        self.lookup_helper(key_specifier, array, |array, atomic| match atomic {
882            atomic::Atomic::Integer(..) => Self::array_get(array, atomic),
883            _ => Err(error::Error::XPTY0004),
884        })
885    }
886
887    fn lookup_helper<T>(
888        &self,
889        key_specifier: sequence::Sequence,
890        data: T,
891        get_key: impl Fn(&T, atomic::Atomic) -> error::Result<sequence::Sequence>,
892    ) -> error::Result<Vec<sequence::Item>> {
893        let keys = key_specifier
894            .atomized(self.state.xot())
895            .collect::<error::Result<Vec<_>>>()?;
896        let mut result = Vec::new();
897        for key in keys {
898            for item in get_key(&data, key)?.iter() {
899                result.push(item.clone());
900            }
901        }
902        Ok(result)
903    }
904
905    fn wildcard_lookup(&mut self) -> error::Result<()> {
906        let value = self.state.pop()?;
907        let function: function::Function = value.try_into()?;
908        let value = match function {
909            function::Function::Map(map) => {
910                let mut result = Vec::new();
911                for key in map.keys() {
912                    for value in self.lookup_map(&map, key.clone().into())? {
913                        result.push(value)
914                    }
915                }
916                result
917            }
918            function::Function::Array(array) => {
919                let mut result = Vec::new();
920                for i in 1..(array.len() + 1) {
921                    let i: IBig = i.into();
922                    for value in self.lookup_array(&array, i.into())? {
923                        result.push(value)
924                    }
925                }
926                result
927            }
928            _ => return Err(error::Error::XPTY0004),
929        };
930        let sequence: sequence::Sequence = value.into();
931        self.state.push(sequence);
932        Ok(())
933    }
934
935    fn value_compare<O>(&mut self, op: O) -> error::Result<()>
936    where
937        O: AtomicCompare,
938    {
939        let b = self.state.pop()?;
940        let a = self.state.pop()?;
941        // https://www.w3.org/TR/xpath-31/#id-value-comparisons
942        // If an operand is the empty sequence, the result is the empty sequence
943        if a.is_empty() || b.is_empty() {
944            self.state.push(sequence::Sequence::default());
945            return Ok(());
946        }
947        let v = a.value_compare(
948            &b,
949            op,
950            self.runnable.default_collation()?.as_ref(),
951            self.runnable.implicit_timezone(),
952            self.state.xot(),
953        )?;
954        self.state.push(v);
955        Ok(())
956    }
957
958    fn general_compare<O>(&mut self, op: O) -> error::Result<()>
959    where
960        O: AtomicCompare,
961    {
962        let b = self.state.pop()?;
963        let a = self.state.pop()?;
964        let value =
965            a.general_comparison(&b, op, self.runnable.dynamic_context(), self.state.xot())?;
966        self.state.push(value);
967        Ok(())
968    }
969
970    fn arithmetic<F>(&mut self, op: F) -> error::Result<()>
971    where
972        F: Fn(atomic::Atomic, atomic::Atomic) -> error::Result<atomic::Atomic>,
973    {
974        self.arithmetic_with_offset(|a, b, _| op(a, b))
975    }
976
977    fn arithmetic_with_offset<F>(&mut self, op: F) -> error::Result<()>
978    where
979        F: Fn(atomic::Atomic, atomic::Atomic, chrono::FixedOffset) -> error::Result<atomic::Atomic>,
980    {
981        let b = self.state.pop()?;
982        let a = self.state.pop()?;
983        // https://www.w3.org/TR/xpath-31/#id-arithmetic
984        // 2. If an operand is the empty sequence, the result is the empty sequence
985        if a.is_empty() || b.is_empty() {
986            self.state.push(sequence::Sequence::default());
987            return Ok(());
988        }
989        let a = a.atomized_one(self.state.xot())?;
990        let b = b.atomized_one(self.state.xot())?;
991        let result = op(a, b, self.runnable.implicit_timezone())?;
992        self.state.push(result);
993        Ok(())
994    }
995
996    fn unary_arithmetic<F>(&mut self, op: F) -> error::Result<()>
997    where
998        F: Fn(atomic::Atomic) -> error::Result<atomic::Atomic>,
999    {
1000        let a = self.state.pop()?;
1001        if a.is_empty() {
1002            self.state.push(sequence::Sequence::default());
1003            return Ok(());
1004        }
1005        let a = a.atomized_one(self.state.xot())?;
1006        let value = op(a)?;
1007        self.state.push(value);
1008        Ok(())
1009    }
1010
1011    fn pop_is_numeric(&mut self) -> error::Result<bool> {
1012        let value = self.state.pop()?;
1013        let a = value.atomized_option(self.state.xot())?;
1014        if let Some(a) = a {
1015            Ok(a.is_numeric())
1016        } else {
1017            Ok(false)
1018        }
1019    }
1020
1021    fn pop_atomic(&mut self) -> error::Result<atomic::Atomic> {
1022        let value = self.state.pop()?;
1023        value.atomized_one(self.state.xot())
1024    }
1025
1026    fn pop_atomic_option(&mut self) -> error::Result<Option<atomic::Atomic>> {
1027        let value = self.state.pop()?;
1028        value.atomized_option(self.state.xot())
1029    }
1030
1031    fn pop_xot_name(&mut self) -> error::Result<xot::NameId> {
1032        let value = self.pop_atomic()?;
1033        let name: xee_name::Name = value.try_into()?;
1034        let namespace = name.namespace();
1035        let ns = self.state.xot.add_namespace(namespace);
1036        Ok(self.state.xot.add_name_ns(name.local_name(), ns))
1037    }
1038
1039    fn pop_node(&mut self) -> error::Result<xot::Node> {
1040        let value = self.state.pop()?;
1041        let node = value.one()?.to_node()?;
1042        Ok(node)
1043    }
1044
1045    fn pop_atomic2(&mut self) -> error::Result<(atomic::Atomic, atomic::Atomic)> {
1046        let b = self.pop_atomic()?;
1047        let a = self.pop_atomic()?;
1048        Ok((a, b))
1049    }
1050
1051    fn pop_atomic2_option(
1052        &mut self,
1053    ) -> error::Result<(Option<atomic::Atomic>, Option<atomic::Atomic>)> {
1054        let b = self.pop_atomic_option()?;
1055        let a = self.pop_atomic_option()?;
1056        Ok((a, b))
1057    }
1058
1059    fn pop_effective_boolean(&mut self) -> error::Result<bool> {
1060        let a = self.state.pop()?;
1061        a.effective_boolean_value()
1062    }
1063
1064    pub(crate) fn regex(&self, pattern: &str, flags: &str) -> error::Result<Rc<regexml::Regex>> {
1065        self.state.regex(pattern, flags)
1066    }
1067
1068    pub(crate) fn xot(&self) -> &Xot {
1069        self.state.xot()
1070    }
1071
1072    pub(crate) fn xot_mut(&mut self) -> &mut Xot {
1073        self.state.xot_mut()
1074    }
1075
1076    fn xml_append(
1077        &mut self,
1078        parent_node: xot::Node,
1079        value: sequence::Sequence,
1080    ) -> error::Result<()> {
1081        let mut string_values = Vec::new();
1082        for item in value.iter() {
1083            match item {
1084                sequence::Item::Node(node) => {
1085                    // if there were any string values before this node, add them
1086                    // to the node, separated by a space character
1087                    if !string_values.is_empty() {
1088                        self.xml_append_string_values(parent_node, &string_values);
1089                        string_values.clear();
1090                    }
1091                    match self.state.xot.value(node) {
1092                        xot::Value::Document => {
1093                            todo!("Handle adding all the children instead");
1094                        }
1095                        xot::Value::Text(text) => {
1096                            // zero length text nodes are skipped
1097                            // Can this even exist, or does Xot not have
1098                            // them anyway?
1099                            if text.get().is_empty() {
1100                                continue;
1101                            }
1102                        }
1103                        _ => {}
1104                    }
1105
1106                    // if we have a parent we're already in another document,
1107                    // in which case we want to make a clone first
1108                    let node = if self.state.xot.parent(node).is_some() {
1109                        self.state.xot.clone_node(node)
1110                    } else {
1111                        node
1112                    };
1113                    // TODO: error out if namespace or attribute node
1114                    // is added once a normal child already exists
1115                    self.state.xot.any_append(parent_node, node).unwrap();
1116                }
1117                sequence::Item::Atomic(atomic) => string_values.push(atomic.string_value()),
1118                sequence::Item::Function(_) => return Err(error::Error::XTDE0450),
1119            }
1120        }
1121        // if there are any string values left in the end
1122        if !string_values.is_empty() {
1123            self.xml_append_string_values(parent_node, &string_values);
1124        }
1125        Ok(())
1126    }
1127
1128    fn xml_append_string_values(&mut self, parent_node: xot::Node, string_values: &[String]) {
1129        let text = string_values.join(" ");
1130        let text_node = self.state.xot.new_text(&text);
1131        self.state.xot.append(parent_node, text_node).unwrap();
1132    }
1133
1134    fn shallow_copy_node(&mut self, node: xot::Node) -> xot::Node {
1135        let xot = &mut self.state.xot;
1136        let value = xot.value(node);
1137        match value {
1138            // root and element are shallow copies
1139            xot::Value::Document => xot.new_document(),
1140            // TODO: work on copying prefixes
1141            xot::Value::Element(element) => xot.new_element(element.name()),
1142            // we can clone (deep-copy) these nodes as it's the same
1143            // operation as shallow copy
1144            _ => xot.clone_node(node),
1145        }
1146    }
1147
1148    fn apply_templates_sequence(
1149        &mut self,
1150        mode: pattern::ModeId,
1151        sequence: sequence::Sequence,
1152    ) -> error::Result<sequence::Sequence> {
1153        let mut r: Vec<sequence::Item> = Vec::new();
1154        let size: IBig = sequence.len().into();
1155
1156        for (i, item) in sequence.iter().enumerate() {
1157            let sequence = self.apply_templates_item(mode, item, i, size.clone())?;
1158            if let Some(sequence) = sequence {
1159                for item in sequence.iter() {
1160                    r.push(item.clone());
1161                }
1162            }
1163        }
1164        Ok(r.into())
1165    }
1166
1167    fn apply_templates_item(
1168        &mut self,
1169        mode: pattern::ModeId,
1170        item: sequence::Item,
1171        position: usize,
1172        size: IBig,
1173    ) -> error::Result<Option<sequence::Sequence>> {
1174        let function_id = self.lookup_pattern(mode, &item);
1175
1176        if let Some(function_id) = function_id {
1177            let position: IBig = (position + 1).into();
1178            let arguments: Vec<sequence::Sequence> = vec![
1179                item.into(),
1180                atomic::Atomic::from(position).into(),
1181                atomic::Atomic::from(size.clone()).into(),
1182            ];
1183            let function = function::InlineFunctionData::new(function_id, Vec::new()).into();
1184            self.call_function_with_arguments(&function, &arguments)
1185                .map(Some)
1186        } else {
1187            Ok(None)
1188        }
1189    }
1190
1191    pub(crate) fn lookup_pattern(
1192        &mut self,
1193        mode: pattern::ModeId,
1194        item: &sequence::Item,
1195    ) -> Option<function::InlineFunctionId> {
1196        self.runnable
1197            .program()
1198            .declarations
1199            .mode_lookup
1200            .lookup(mode, |pattern| self.matches(pattern, item))
1201            .copied()
1202    }
1203
1204    // The interpreter can return an error for any byte code, in any level of
1205    // nesting in the function. When this happens the interpreter stops with
1206    // the error code. We here wrap it in a SpannedError using the current
1207    // span.
1208    pub(crate) fn err(&self, value_error: error::Error) -> error::SpannedError {
1209        error::SpannedError {
1210            error: value_error,
1211            span: Some(self.current_span()),
1212        }
1213    }
1214
1215    // During the compilation process, spans became associated with each
1216    // compiled bytecode instruction. Here we take the current function and the
1217    // instruction in it to determine the span of the code that failed.
1218    fn current_span(&self) -> SourceSpan {
1219        let frame = self.state.frame();
1220        let function = self.runnable.program().inline_function(frame.function());
1221        // we substract 1 to end up in the current instruction - this
1222        // because the ip is already on the next instruction
1223        function.spans[frame.ip - 1]
1224    }
1225
1226    fn read_instruction(&mut self) -> EncodedInstruction {
1227        let frame = self.state.frame_mut();
1228        let function = self.runnable.program().inline_function(frame.function());
1229        let chunk = &function.chunk;
1230        read_instruction(chunk, &mut frame.ip)
1231    }
1232
1233    fn read_u16(&mut self) -> u16 {
1234        let frame = &mut self.state.frame_mut();
1235        let function = self.runnable.program().inline_function(frame.function());
1236        let chunk = &function.chunk;
1237        read_u16(chunk, &mut frame.ip)
1238    }
1239
1240    fn read_i16(&mut self) -> i16 {
1241        let frame = &mut self.state.frame_mut();
1242        let function = self.runnable.program().inline_function(frame.function());
1243        let chunk = &function.chunk;
1244        read_i16(chunk, &mut frame.ip)
1245    }
1246
1247    fn read_u8(&mut self) -> u8 {
1248        let frame = &mut self.state.frame_mut();
1249        let function = self.runnable.program().inline_function(frame.function());
1250        let chunk = &function.chunk;
1251        read_u8(chunk, &mut frame.ip)
1252    }
1253}