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 = a.precedes(
283                        &b,
284                        self.runnable
285                            .documents()
286                            .borrow()
287                            .document_order_access(self.xot()),
288                    )?;
289                    self.state.push(result);
290                }
291                EncodedInstruction::Follows => {
292                    let b = self.state.pop()?;
293                    let a = self.state.pop()?;
294                    if a.is_empty() || b.is_empty() {
295                        self.state.push(sequence::Sequence::default());
296                        continue;
297                    }
298                    let result = a.follows(
299                        &b,
300                        self.runnable
301                            .documents()
302                            .borrow()
303                            .document_order_access(self.xot()),
304                    )?;
305                    self.state.push(result);
306                }
307                EncodedInstruction::Union => {
308                    let b = self.state.pop()?;
309                    let a = self.state.pop()?;
310                    let combined = a.union(
311                        b,
312                        self.runnable
313                            .documents()
314                            .borrow()
315                            .document_order_access(self.xot()),
316                    )?;
317                    self.state.push(combined);
318                }
319                EncodedInstruction::Intersect => {
320                    let b = self.state.pop()?;
321                    let a = self.state.pop()?;
322                    let combined = a.intersect(
323                        b,
324                        self.runnable
325                            .documents()
326                            .borrow()
327                            .document_order_access(self.xot()),
328                    )?;
329                    self.state.push(combined);
330                }
331                EncodedInstruction::Except => {
332                    let b = self.state.pop()?;
333                    let a = self.state.pop()?;
334                    let combined = a.except(
335                        b,
336                        self.runnable
337                            .documents()
338                            .borrow()
339                            .document_order_access(self.xot()),
340                    )?;
341                    self.state.push(combined);
342                }
343                EncodedInstruction::Dup => {
344                    let value = self.state.pop()?;
345                    self.state.push(value.clone());
346                    self.state.push(value);
347                }
348                EncodedInstruction::Pop => {
349                    self.state.pop()?;
350                }
351                EncodedInstruction::Call => {
352                    let arity = self.read_u8();
353                    self.call(arity)?;
354                }
355                EncodedInstruction::Lookup => {
356                    self.lookup()?;
357                }
358                EncodedInstruction::WildcardLookup => {
359                    self.wildcard_lookup()?;
360                }
361                EncodedInstruction::Step => {
362                    let step_id = self.read_u16();
363                    let node: xot::Node = self.state.pop()?.try_into()?;
364                    let step = &(self.current_inline_function().steps[step_id as usize]);
365                    let value = xml::resolve_step(step, node, self.state.xot());
366                    self.state.push(value);
367                }
368                EncodedInstruction::Deduplicate => {
369                    let value = self.state.pop()?;
370                    let value = value.deduplicate(
371                        self.runnable
372                            .documents()
373                            .borrow()
374                            .document_order_access(self.xot()),
375                    )?;
376                    self.state.push(value);
377                }
378                EncodedInstruction::Return => {
379                    if self.state.inline_return(start_base) {
380                        break;
381                    }
382                }
383                EncodedInstruction::ReturnConvert => {
384                    let sequence_type_id = self.read_u16();
385                    let sequence = self.state.pop()?;
386                    let sequence_type =
387                        &(self.current_inline_function().sequence_types[sequence_type_id as usize]);
388
389                    let sequence = sequence.sequence_type_matching_function_conversion(
390                        sequence_type,
391                        self.runnable.static_context(),
392                        self.state.xot(),
393                        &|function| self.runnable.function_info(function).signature(),
394                    )?;
395                    self.state.push(sequence);
396                }
397                EncodedInstruction::LetDone => {
398                    let return_value = self.state.pop()?;
399                    // pop the variable assignment
400                    let _ = self.state.pop();
401                    self.state.push(return_value);
402                }
403                EncodedInstruction::Cast => {
404                    let type_id = self.read_u16();
405                    let value = self.pop_atomic_option()?;
406                    let cast_type = &(self.current_inline_function().cast_types[type_id as usize]);
407                    if let Some(value) = value {
408                        let cast_value = value
409                            .cast_to_schema_type(cast_type.xs, self.runnable.static_context())?;
410                        self.state.push(cast_value);
411                    } else if cast_type.empty_sequence_allowed {
412                        self.state.push(sequence::Sequence::default());
413                    } else {
414                        Err(error::Error::XPTY0004)?;
415                    }
416                }
417                EncodedInstruction::Castable => {
418                    let type_id = self.read_u16();
419                    let value = self.pop_atomic_option()?;
420                    let cast_type = &(self.current_inline_function().cast_types[type_id as usize]);
421                    if let Some(value) = value {
422                        let cast_value =
423                            value.cast_to_schema_type(cast_type.xs, self.runnable.static_context());
424                        self.state.push(cast_value.is_ok());
425                    } else if cast_type.empty_sequence_allowed {
426                        self.state.push(true)
427                    } else {
428                        self.state.push(false);
429                    }
430                }
431                EncodedInstruction::InstanceOf => {
432                    let sequence_type_id = self.read_u16();
433                    let sequence = self.state.pop()?;
434                    let sequence_type =
435                        &(self.current_inline_function().sequence_types[sequence_type_id as usize]);
436                    let matches = sequence.sequence_type_matching(
437                        sequence_type,
438                        self.state.xot(),
439                        &|function| self.runnable.function_info(function).signature(),
440                    );
441                    if matches.is_ok() {
442                        self.state.push(true);
443                    } else {
444                        self.state.push(false);
445                    }
446                }
447                EncodedInstruction::Treat => {
448                    let sequence_type_id = self.read_u16();
449                    let sequence = self.state.top()?;
450                    let sequence_type =
451                        &(self.current_inline_function().sequence_types[sequence_type_id as usize]);
452                    let matches = sequence.sequence_type_matching(
453                        sequence_type,
454                        self.state.xot(),
455                        &|function| self.runnable.function_info(function).signature(),
456                    );
457                    if matches.is_err() {
458                        Err(error::Error::XPDY0050)?;
459                    }
460                }
461                EncodedInstruction::Range => {
462                    let b = self.state.pop()?;
463                    let a = self.state.pop()?;
464                    let a = a.atomized_option(self.state.xot())?;
465                    let b = b.atomized_option(self.state.xot())?;
466                    let (a, b) = match (a, b) {
467                        (None, None) | (None, _) | (_, None) => {
468                            self.state.push(sequence::Sequence::default());
469                            continue;
470                        }
471                        (Some(a), Some(b)) => (a, b),
472                    };
473                    // we want to ensure we have integers at this point;
474                    // we don't want to be casting strings or anything
475                    a.ensure_base_schema_type(Xs::Integer)?;
476                    b.ensure_base_schema_type(Xs::Integer)?;
477
478                    let a: IBig = a.try_into().unwrap();
479                    let b: IBig = b.try_into().unwrap();
480
481                    match a.cmp(&b) {
482                        Ordering::Greater => self.state.push(sequence::Sequence::default()),
483                        Ordering::Equal => self.state.push(a),
484                        Ordering::Less => {
485                            let sequence: sequence::Sequence =
486                                sequence::Range::new(a, b + 1)?.into();
487                            self.state.push(sequence)
488                        }
489                    }
490                }
491
492                EncodedInstruction::SequenceLen => {
493                    let value = self.state.pop()?;
494                    let l: IBig = value.len().into();
495                    self.state.push(l);
496                }
497                EncodedInstruction::SequenceGet => {
498                    let value = self.state.pop()?;
499                    let index = self.pop_atomic()?;
500                    let index = index.cast_to_integer_value::<i64>()? as usize;
501                    // substract 1 as Xpath is 1-indexed
502                    let item = value.get(index - 1).ok_or(error::Error::XPTY0004)?;
503                    let sequence: sequence::Sequence = item.into();
504                    self.state.push(sequence)
505                }
506                EncodedInstruction::BuildNew => {
507                    self.state.build_new();
508                }
509                EncodedInstruction::BuildPush => {
510                    self.state.build_push()?;
511                }
512                EncodedInstruction::BuildComplete => {
513                    self.state.build_complete();
514                }
515                EncodedInstruction::IsNumeric => {
516                    let is_numeric = self.pop_is_numeric()?;
517                    self.state.push(is_numeric);
518                }
519                EncodedInstruction::XmlName => {
520                    let local_name_value = self.pop_atomic()?;
521                    let namespace_value = self.pop_atomic()?;
522                    let namespace = namespace_value.to_str()?;
523                    let local_name = local_name_value.to_string()?;
524                    let name =
525                        xee_name::Name::new(local_name, namespace.to_string(), String::new());
526                    self.state.push(name);
527                }
528                EncodedInstruction::XmlDocument => {
529                    let root_node = self.state.xot.new_document();
530                    let item = sequence::Item::Node(root_node);
531                    self.state.push(item);
532                }
533                EncodedInstruction::XmlElement => {
534                    let name_id = self.pop_xot_name()?;
535                    let element_node = self.state.xot.new_element(name_id);
536                    let item = sequence::Item::Node(element_node);
537                    self.state.push(item);
538                }
539                EncodedInstruction::XmlAttribute => {
540                    let value = self.pop_atomic()?;
541                    let name_id = self.pop_xot_name()?;
542                    let attribute_node = self
543                        .state
544                        .xot
545                        .new_attribute_node(name_id, value.string_value());
546                    let item = sequence::Item::Node(attribute_node);
547                    self.state.push(item);
548                }
549                EncodedInstruction::XmlNamespace => {
550                    let uri = self.pop_atomic()?;
551                    let namespace_id = self.state.xot.add_namespace(&uri.string_value());
552                    let prefix = self.pop_atomic()?;
553                    let prefix_id = self.state.xot.add_prefix(&prefix.string_value());
554                    let namespace_node = self.state.xot.new_namespace_node(prefix_id, namespace_id);
555                    let item = sequence::Item::Node(namespace_node);
556                    self.state.push(item);
557                }
558                EncodedInstruction::XmlText => {
559                    let text_atomic = self.pop_atomic()?;
560                    let text = text_atomic.into_canonical();
561                    let text_node = self.state.xot.new_text(&text);
562                    let item = sequence::Item::Node(text_node);
563                    self.state.push(item);
564                }
565                EncodedInstruction::XmlComment => {
566                    let text_atomic = self.pop_atomic()?;
567                    let text = text_atomic.into_canonical();
568                    let comment_node = self.state.xot.new_comment(&text);
569                    let item = sequence::Item::Node(comment_node);
570                    self.state.push(item);
571                }
572                EncodedInstruction::XmlProcessingInstruction => {
573                    let text_atomic = self.pop_atomic()?;
574                    let text = text_atomic.into_canonical();
575                    let text = if !text.is_empty() {
576                        Some(text.as_str())
577                    } else {
578                        None
579                    };
580                    let target_atomic = self.pop_atomic()?;
581                    let target = target_atomic.into_canonical();
582                    let target_id = self.state.xot.add_name(&target);
583                    let pi_node = self.state.xot.new_processing_instruction(target_id, text);
584                    let item = sequence::Item::Node(pi_node);
585                    self.state.push(item);
586                }
587                EncodedInstruction::XmlAppend => {
588                    let child_value = self.state.pop()?;
589                    let parent_node = self.pop_node()?;
590                    self.xml_append(parent_node, child_value)?;
591                    // now we can push back the parent node
592                    let item = sequence::Item::Node(parent_node);
593                    self.state.push(item);
594                }
595                EncodedInstruction::CopyShallow => {
596                    let value = &self.state.pop()?;
597                    if value.is_empty() {
598                        self.state.push(sequence::Sequence::default());
599                        continue;
600                    }
601                    if value.len() > 1 {
602                        Err(error::Error::XTTE3180)?;
603                    }
604                    let item = value.iter().next().unwrap();
605                    let copy = match &item {
606                        sequence::Item::Atomic(_) | sequence::Item::Function(_) => item.clone(),
607                        sequence::Item::Node(node) => {
608                            let copied_node = self.shallow_copy_node(*node);
609                            sequence::Item::Node(copied_node)
610                        }
611                    };
612                    self.state.push(copy);
613                }
614                EncodedInstruction::CopyDeep => {
615                    let value = &self.state.pop()?;
616                    if value.is_empty() {
617                        self.state.push(sequence::Sequence::default());
618                        continue;
619                    }
620                    let mut new_sequence = Vec::with_capacity(value.len());
621                    for item in value.iter() {
622                        let copy = match &item {
623                            sequence::Item::Atomic(_) | sequence::Item::Function(_) => item.clone(),
624                            sequence::Item::Node(node) => {
625                                let copied_node = self.state.xot.clone_node(*node);
626                                sequence::Item::Node(copied_node)
627                            }
628                        };
629                        new_sequence.push(copy);
630                    }
631                    self.state.push(new_sequence);
632                }
633                EncodedInstruction::ApplyTemplates => {
634                    let value = self.state.pop()?;
635                    let mode_id = self.read_u16();
636                    let mode = pattern::ModeId::new(mode_id as usize);
637                    let value = self.apply_templates_sequence(mode, value)?;
638                    self.state.push(value);
639                }
640                EncodedInstruction::PrintTop => {
641                    let top = self.state.top()?;
642                    println!("{:#?}", top);
643                }
644                EncodedInstruction::PrintStack => {
645                    println!("{:#?}", self.state.stack());
646                }
647            }
648        }
649        Ok(())
650    }
651
652    pub(crate) fn create_static_closure_from_stack(
653        &mut self,
654        static_function_id: function::StaticFunctionId,
655    ) -> error::Result<function::Function> {
656        Self::create_static_closure(self.runnable.dynamic_context(), static_function_id, || {
657            Some(self.state.pop_value())
658        })
659    }
660
661    pub(crate) fn create_static_closure_from_context(
662        &mut self,
663        static_function_id: function::StaticFunctionId,
664        arg: Option<xot::Node>,
665    ) -> error::Result<function::Function> {
666        Self::create_static_closure(self.runnable.dynamic_context(), static_function_id, || {
667            arg.map(|n| {
668                let value: stack::Value = n.into();
669                value
670            })
671        })
672    }
673
674    pub(crate) fn create_static_closure<F>(
675        context: &DynamicContext,
676        static_function_id: function::StaticFunctionId,
677        mut get: F,
678    ) -> error::Result<function::Function>
679    where
680        F: FnMut() -> Option<stack::Value>,
681    {
682        let static_function = &context.static_context().function_by_id(static_function_id);
683        // get any context value from the stack if needed
684        let closure_vars = if static_function.needs_context() {
685            let value = get();
686            if let Some(value) = value {
687                vec![value]
688            } else {
689                vec![]
690            }
691        } else {
692            vec![]
693        };
694        Ok(function::StaticFunctionData::new(static_function_id, closure_vars).into())
695    }
696
697    pub(crate) fn current_inline_function(&self) -> &function::InlineFunction {
698        self.runnable
699            .program()
700            .inline_function(self.state.frame().function())
701    }
702
703    pub(crate) fn function_name(&self, function: &function::Function) -> Option<Name> {
704        self.runnable.function_info(function).name()
705    }
706
707    pub(crate) fn function_arity(&self, function: &function::Function) -> usize {
708        self.runnable.function_info(function).arity()
709    }
710
711    fn call(&mut self, arity: u8) -> error::Result<()> {
712        let function = self.state.callable(arity as usize)?;
713        self.call_function(&function, arity)
714    }
715
716    pub(crate) fn call_function_with_arguments(
717        &mut self,
718        function: &function::Function,
719        arguments: &[sequence::Sequence],
720    ) -> error::Result<sequence::Sequence> {
721        // put function onto the stack
722        let item: sequence::Item = function.clone().into();
723        self.state.push(item);
724        // then arguments
725        let arity = arguments.len() as u8;
726        for arg in arguments.iter() {
727            self.state.push(arg.clone());
728        }
729        self.call_function(function, arity)?;
730        if matches!(function, function::Function::Inline(_)) {
731            // run interpreter until we return to the base
732            // we started in
733            self.run_actual(self.state.frame().base())?;
734        }
735        self.state.pop()
736    }
737
738    fn call_function(&mut self, function: &function::Function, arity: u8) -> error::Result<()> {
739        match function {
740            function::Function::Static(data) => {
741                self.call_static(data.id, arity, &data.closure_vars)
742            }
743            function::Function::Inline(data) => self.call_inline(data.id, arity),
744            function::Function::Array(array) => self.call_array(array, arity as usize),
745            function::Function::Map(map) => self.call_map(map, arity as usize),
746        }
747    }
748
749    pub(crate) fn arguments(&self, arity: u8) -> &[stack::Value] {
750        self.state.arguments(arity as usize)
751    }
752
753    fn call_static(
754        &mut self,
755        static_function_id: function::StaticFunctionId,
756        arity: u8,
757        closure_vars: &[stack::Value],
758    ) -> error::Result<()> {
759        let static_function = self.runnable.program().static_function(static_function_id);
760        if arity as usize != static_function.arity() {
761            return Err(error::Error::XPTY0004);
762        }
763        let parameter_types = static_function.signature().parameter_types();
764        let arguments = self.coerce_arguments(parameter_types, arity)?;
765        let result =
766            static_function.invoke(self.runnable.dynamic_context, self, arguments, closure_vars)?;
767        // pop the last item off
768        let _ = self.state.pop();
769        self.state.push(result);
770        Ok(())
771    }
772
773    fn call_inline(
774        &mut self,
775        function_id: function::InlineFunctionId,
776        arity: u8,
777    ) -> error::Result<()> {
778        // look up the function in order to access the parameters information
779        let function = self.runnable.program().inline_function(function_id);
780        let parameter_types = &function.signature.parameter_types();
781        if arity as usize != parameter_types.len() {
782            return Err(error::Error::XPTY0004);
783        }
784
785        let arguments = self.coerce_arguments(parameter_types, arity)?;
786
787        // now we have a list of arguments that we want to push back onto the stack
788        // (they are already reversed)
789        for arg in arguments {
790            self.state.push(arg);
791        }
792
793        self.state.push_frame(function_id, arity as usize)
794    }
795
796    fn coerce_arguments(
797        &mut self,
798        parameter_types: &[Option<ast::SequenceType>],
799        arity: u8,
800    ) -> error::Result<Vec<sequence::Sequence>> {
801        // TODO: fast path if no sequence type declarations exist for
802        // parameters could cache this inside of signature so that it's really
803        // fast to detect.
804
805        // we could also have a secondary fast path where if the types are all
806        // exactly the same, we don't do a clone.
807
808        // get all the stack values out in order
809        let stack_values = self.state.arguments(arity as usize);
810        let mut arguments = Vec::with_capacity(arity as usize);
811        let static_context = self.runnable.static_context();
812        let xot = self.state.xot();
813        for (parameter_type, stack_value) in parameter_types.iter().zip(stack_values) {
814            let sequence: sequence::Sequence = stack_value.try_into()?;
815            if let Some(type_) = parameter_type {
816                // matching also takes care of function conversion rules
817                let sequence = sequence.sequence_type_matching_function_conversion(
818                    type_,
819                    static_context,
820                    xot,
821                    &|function| self.runnable.function_info(function).signature(),
822                )?;
823                arguments.push(sequence);
824            } else {
825                // no need to do any checking or conversion
826                arguments.push(sequence);
827            }
828        }
829        self.state.truncate_arguments(arity as usize);
830        Ok(arguments)
831    }
832
833    fn call_array(&mut self, array: &function::Array, arity: usize) -> error::Result<()> {
834        if arity != 1 {
835            return Err(error::Error::XPTY0004);
836        }
837        // the argument
838        let position = self.pop_atomic()?;
839        let sequence = Self::array_get(array, position)?;
840        // pop the array off the stack
841        self.state.pop()?;
842        // now push the result
843        self.state.push(sequence);
844        Ok(())
845    }
846
847    fn array_get(
848        array: &function::Array,
849        position: atomic::Atomic,
850    ) -> error::Result<sequence::Sequence> {
851        let position = position
852            .cast_to_integer_value::<i64>()
853            .map_err(|_| error::Error::XPTY0004)?;
854        let position = position as usize;
855        if position == 0 {
856            return Err(error::Error::FOAY0001);
857        }
858        let position = position - 1;
859        let sequence = array.index(position);
860        sequence.cloned().ok_or(error::Error::FOAY0001)
861    }
862
863    fn call_map(&mut self, map: &function::Map, arity: usize) -> error::Result<()> {
864        if arity != 1 {
865            return Err(error::Error::XPTY0004);
866        }
867        let key = self.pop_atomic()?;
868        let value = map.get(&key);
869        // pop the map off the stack
870        self.state.pop()?;
871        if let Some(value) = value {
872            self.state.push(value.clone());
873        } else {
874            self.state.push(sequence::Sequence::default());
875        }
876        Ok(())
877    }
878
879    fn lookup(&mut self) -> error::Result<()> {
880        let key_specifier = self.state.pop()?;
881        let value = self.state.pop()?;
882        let function: function::Function = value.try_into()?;
883        let value = self.lookup_value(&function, key_specifier)?;
884        let sequence: sequence::Sequence = value.into();
885        self.state.push(sequence);
886        Ok(())
887    }
888
889    fn lookup_value(
890        &self,
891        function: &function::Function,
892        key_specifier: sequence::Sequence,
893    ) -> error::Result<Vec<sequence::Item>> {
894        match function {
895            function::Function::Map(map) => self.lookup_map(map, key_specifier),
896            function::Function::Array(array) => self.lookup_array(array, key_specifier),
897            _ => Err(error::Error::XPTY0004),
898        }
899    }
900
901    fn lookup_map(
902        &self,
903        map: &function::Map,
904        key_specifier: sequence::Sequence,
905    ) -> error::Result<Vec<sequence::Item>> {
906        self.lookup_helper(key_specifier, map, |map, atomic| {
907            Ok(map.get(&atomic).cloned().unwrap_or_default())
908        })
909    }
910
911    fn lookup_array(
912        &self,
913        array: &function::Array,
914        key_specifier: sequence::Sequence,
915    ) -> error::Result<Vec<sequence::Item>> {
916        self.lookup_helper(key_specifier, array, |array, atomic| match atomic {
917            atomic::Atomic::Integer(..) => Self::array_get(array, atomic),
918            _ => Err(error::Error::XPTY0004),
919        })
920    }
921
922    fn lookup_helper<T>(
923        &self,
924        key_specifier: sequence::Sequence,
925        data: T,
926        get_key: impl Fn(&T, atomic::Atomic) -> error::Result<sequence::Sequence>,
927    ) -> error::Result<Vec<sequence::Item>> {
928        let keys = key_specifier
929            .atomized(self.state.xot())
930            .collect::<error::Result<Vec<_>>>()?;
931        let mut result = Vec::new();
932        for key in keys {
933            for item in get_key(&data, key)?.iter() {
934                result.push(item.clone());
935            }
936        }
937        Ok(result)
938    }
939
940    fn wildcard_lookup(&mut self) -> error::Result<()> {
941        let value = self.state.pop()?;
942        let function: function::Function = value.try_into()?;
943        let value = match function {
944            function::Function::Map(map) => {
945                let mut result = Vec::new();
946                for key in map.keys() {
947                    for value in self.lookup_map(&map, key.clone().into())? {
948                        result.push(value)
949                    }
950                }
951                result
952            }
953            function::Function::Array(array) => {
954                let mut result = Vec::new();
955                for i in 1..(array.len() + 1) {
956                    let i: IBig = i.into();
957                    for value in self.lookup_array(&array, i.into())? {
958                        result.push(value)
959                    }
960                }
961                result
962            }
963            _ => return Err(error::Error::XPTY0004),
964        };
965        let sequence: sequence::Sequence = value.into();
966        self.state.push(sequence);
967        Ok(())
968    }
969
970    fn value_compare<O>(&mut self, op: O) -> error::Result<()>
971    where
972        O: AtomicCompare,
973    {
974        let b = self.state.pop()?;
975        let a = self.state.pop()?;
976        // https://www.w3.org/TR/xpath-31/#id-value-comparisons
977        // If an operand is the empty sequence, the result is the empty sequence
978        if a.is_empty() || b.is_empty() {
979            self.state.push(sequence::Sequence::default());
980            return Ok(());
981        }
982        let v = a.value_compare(
983            &b,
984            op,
985            self.runnable.default_collation()?.as_ref(),
986            self.runnable.implicit_timezone(),
987            self.state.xot(),
988        )?;
989        self.state.push(v);
990        Ok(())
991    }
992
993    fn general_compare<O>(&mut self, op: O) -> error::Result<()>
994    where
995        O: AtomicCompare,
996    {
997        let b = self.state.pop()?;
998        let a = self.state.pop()?;
999        let value =
1000            a.general_comparison(&b, op, self.runnable.dynamic_context(), self.state.xot())?;
1001        self.state.push(value);
1002        Ok(())
1003    }
1004
1005    fn arithmetic<F>(&mut self, op: F) -> error::Result<()>
1006    where
1007        F: Fn(atomic::Atomic, atomic::Atomic) -> error::Result<atomic::Atomic>,
1008    {
1009        self.arithmetic_with_offset(|a, b, _| op(a, b))
1010    }
1011
1012    fn arithmetic_with_offset<F>(&mut self, op: F) -> error::Result<()>
1013    where
1014        F: Fn(atomic::Atomic, atomic::Atomic, chrono::FixedOffset) -> error::Result<atomic::Atomic>,
1015    {
1016        let b = self.state.pop()?;
1017        let a = self.state.pop()?;
1018        // https://www.w3.org/TR/xpath-31/#id-arithmetic
1019        // 2. If an operand is the empty sequence, the result is the empty sequence
1020        if a.is_empty() || b.is_empty() {
1021            self.state.push(sequence::Sequence::default());
1022            return Ok(());
1023        }
1024        let a = a.atomized_one(self.state.xot())?;
1025        let b = b.atomized_one(self.state.xot())?;
1026        let result = op(a, b, self.runnable.implicit_timezone())?;
1027        self.state.push(result);
1028        Ok(())
1029    }
1030
1031    fn unary_arithmetic<F>(&mut self, op: F) -> error::Result<()>
1032    where
1033        F: Fn(atomic::Atomic) -> error::Result<atomic::Atomic>,
1034    {
1035        let a = self.state.pop()?;
1036        if a.is_empty() {
1037            self.state.push(sequence::Sequence::default());
1038            return Ok(());
1039        }
1040        let a = a.atomized_one(self.state.xot())?;
1041        let value = op(a)?;
1042        self.state.push(value);
1043        Ok(())
1044    }
1045
1046    fn pop_is_numeric(&mut self) -> error::Result<bool> {
1047        let value = self.state.pop()?;
1048        let a = value.atomized_option(self.state.xot())?;
1049        if let Some(a) = a {
1050            Ok(a.is_numeric())
1051        } else {
1052            Ok(false)
1053        }
1054    }
1055
1056    fn pop_atomic(&mut self) -> error::Result<atomic::Atomic> {
1057        let value = self.state.pop()?;
1058        value.atomized_one(self.state.xot())
1059    }
1060
1061    fn pop_atomic_option(&mut self) -> error::Result<Option<atomic::Atomic>> {
1062        let value = self.state.pop()?;
1063        value.atomized_option(self.state.xot())
1064    }
1065
1066    fn pop_xot_name(&mut self) -> error::Result<xot::NameId> {
1067        let value = self.pop_atomic()?;
1068        let name: xee_name::Name = value.try_into()?;
1069        let namespace = name.namespace();
1070        let ns = self.state.xot.add_namespace(namespace);
1071        Ok(self.state.xot.add_name_ns(name.local_name(), ns))
1072    }
1073
1074    fn pop_node(&mut self) -> error::Result<xot::Node> {
1075        let value = self.state.pop()?;
1076        let node = value.one()?.to_node()?;
1077        Ok(node)
1078    }
1079
1080    fn pop_atomic2(&mut self) -> error::Result<(atomic::Atomic, atomic::Atomic)> {
1081        let b = self.pop_atomic()?;
1082        let a = self.pop_atomic()?;
1083        Ok((a, b))
1084    }
1085
1086    fn pop_atomic2_option(
1087        &mut self,
1088    ) -> error::Result<(Option<atomic::Atomic>, Option<atomic::Atomic>)> {
1089        let b = self.pop_atomic_option()?;
1090        let a = self.pop_atomic_option()?;
1091        Ok((a, b))
1092    }
1093
1094    fn pop_effective_boolean(&mut self) -> error::Result<bool> {
1095        let a = self.state.pop()?;
1096        a.effective_boolean_value()
1097    }
1098
1099    pub(crate) fn regex(&self, pattern: &str, flags: &str) -> error::Result<Rc<regexml::Regex>> {
1100        self.state.regex(pattern, flags)
1101    }
1102
1103    pub(crate) fn xot(&self) -> &Xot {
1104        self.state.xot()
1105    }
1106
1107    pub(crate) fn xot_mut(&mut self) -> &mut Xot {
1108        self.state.xot_mut()
1109    }
1110
1111    fn xml_append(
1112        &mut self,
1113        parent_node: xot::Node,
1114        value: sequence::Sequence,
1115    ) -> error::Result<()> {
1116        let mut string_values = Vec::new();
1117        for item in value.iter() {
1118            match item {
1119                sequence::Item::Node(node) => {
1120                    // if there were any string values before this node, add them
1121                    // to the node, separated by a space character
1122                    if !string_values.is_empty() {
1123                        self.xml_append_string_values(parent_node, &string_values);
1124                        string_values.clear();
1125                    }
1126                    match self.state.xot.value(node) {
1127                        xot::Value::Document => {
1128                            // TODO: Handle adding all the children instead
1129                            return Err(error::Error::Unsupported);
1130                        }
1131                        xot::Value::Text(text) => {
1132                            // zero length text nodes are skipped
1133                            // Can this even exist, or does Xot not have
1134                            // them anyway?
1135                            if text.get().is_empty() {
1136                                continue;
1137                            }
1138                        }
1139                        _ => {}
1140                    }
1141
1142                    // if we have a parent we're already in another document,
1143                    // in which case we want to make a clone first
1144                    let node = if self.state.xot.parent(node).is_some() {
1145                        self.state.xot.clone_node(node)
1146                    } else {
1147                        node
1148                    };
1149                    // TODO: error out if namespace or attribute node
1150                    // is added once a normal child already exists
1151                    self.state.xot.any_append(parent_node, node).unwrap();
1152                }
1153                sequence::Item::Atomic(atomic) => string_values.push(atomic.string_value()),
1154                sequence::Item::Function(_) => return Err(error::Error::XTDE0450),
1155            }
1156        }
1157        // if there are any string values left in the end
1158        if !string_values.is_empty() {
1159            self.xml_append_string_values(parent_node, &string_values);
1160        }
1161        Ok(())
1162    }
1163
1164    fn xml_append_string_values(&mut self, parent_node: xot::Node, string_values: &[String]) {
1165        let text = string_values.join(" ");
1166        let text_node = self.state.xot.new_text(&text);
1167        self.state.xot.append(parent_node, text_node).unwrap();
1168    }
1169
1170    fn shallow_copy_node(&mut self, node: xot::Node) -> xot::Node {
1171        let xot = &mut self.state.xot;
1172        let value = xot.value(node);
1173        match value {
1174            // root and element are shallow copies
1175            xot::Value::Document => xot.new_document(),
1176            // TODO: work on copying prefixes
1177            xot::Value::Element(element) => xot.new_element(element.name()),
1178            // we can clone (deep-copy) these nodes as it's the same
1179            // operation as shallow copy
1180            _ => xot.clone_node(node),
1181        }
1182    }
1183
1184    fn apply_templates_sequence(
1185        &mut self,
1186        mode: pattern::ModeId,
1187        sequence: sequence::Sequence,
1188    ) -> error::Result<sequence::Sequence> {
1189        let mut r: Vec<sequence::Item> = Vec::new();
1190        let size: IBig = sequence.len().into();
1191
1192        for (i, item) in sequence.iter().enumerate() {
1193            let sequence = self.apply_templates_item(mode, item, i, size.clone())?;
1194            if let Some(sequence) = sequence {
1195                for item in sequence.iter() {
1196                    r.push(item.clone());
1197                }
1198            }
1199        }
1200        Ok(r.into())
1201    }
1202
1203    fn apply_templates_item(
1204        &mut self,
1205        mode: pattern::ModeId,
1206        item: sequence::Item,
1207        position: usize,
1208        size: IBig,
1209    ) -> error::Result<Option<sequence::Sequence>> {
1210        let function_id = self.lookup_pattern(mode, &item);
1211
1212        if let Some(function_id) = function_id {
1213            let position: IBig = (position + 1).into();
1214            let arguments: Vec<sequence::Sequence> = vec![
1215                item.into(),
1216                atomic::Atomic::from(position).into(),
1217                atomic::Atomic::from(size.clone()).into(),
1218            ];
1219            let function = function::InlineFunctionData::new(function_id, Vec::new()).into();
1220            self.call_function_with_arguments(&function, &arguments)
1221                .map(Some)
1222        } else {
1223            Ok(None)
1224        }
1225    }
1226
1227    pub(crate) fn lookup_pattern(
1228        &mut self,
1229        mode: pattern::ModeId,
1230        item: &sequence::Item,
1231    ) -> Option<function::InlineFunctionId> {
1232        self.runnable
1233            .program()
1234            .declarations
1235            .mode_lookup
1236            .lookup(mode, |pattern| self.matches(pattern, item))
1237            .copied()
1238    }
1239
1240    // The interpreter can return an error for any byte code, in any level of
1241    // nesting in the function. When this happens the interpreter stops with
1242    // the error code. We here wrap it in a SpannedError using the current
1243    // span.
1244    pub(crate) fn err(&self, value_error: error::Error) -> error::SpannedError {
1245        error::SpannedError {
1246            error: value_error,
1247            span: Some(self.current_span()),
1248        }
1249    }
1250
1251    // During the compilation process, spans became associated with each
1252    // compiled bytecode instruction. Here we take the current function and the
1253    // instruction in it to determine the span of the code that failed.
1254    fn current_span(&self) -> SourceSpan {
1255        let frame = self.state.frame();
1256        let function = self.runnable.program().inline_function(frame.function());
1257        // we substract 1 to end up in the current instruction - this
1258        // because the ip is already on the next instruction
1259        function.spans[frame.ip - 1]
1260    }
1261
1262    fn read_instruction(&mut self) -> EncodedInstruction {
1263        let frame = self.state.frame_mut();
1264        let function = self.runnable.program().inline_function(frame.function());
1265        let chunk = &function.chunk;
1266        read_instruction(chunk, &mut frame.ip)
1267    }
1268
1269    fn read_u16(&mut self) -> u16 {
1270        let frame = &mut self.state.frame_mut();
1271        let function = self.runnable.program().inline_function(frame.function());
1272        let chunk = &function.chunk;
1273        read_u16(chunk, &mut frame.ip)
1274    }
1275
1276    fn read_i16(&mut self) -> i16 {
1277        let frame = &mut self.state.frame_mut();
1278        let function = self.runnable.program().inline_function(frame.function());
1279        let chunk = &function.chunk;
1280        read_i16(chunk, &mut frame.ip)
1281    }
1282
1283    fn read_u8(&mut self) -> u8 {
1284        let frame = &mut self.state.frame_mut();
1285        let function = self.runnable.program().inline_function(frame.function());
1286        let chunk = &function.chunk;
1287        read_u8(chunk, &mut frame.ip)
1288    }
1289}