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 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 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 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 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 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 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 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 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 let item: sequence::Item = function.clone().into();
723 self.state.push(item);
724 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 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 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 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 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 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 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 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 let position = self.pop_atomic()?;
839 let sequence = Self::array_get(array, position)?;
840 self.state.pop()?;
842 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 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 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 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 !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 return Err(error::Error::Unsupported);
1130 }
1131 xot::Value::Text(text) => {
1132 if text.get().is_empty() {
1136 continue;
1137 }
1138 }
1139 _ => {}
1140 }
1141
1142 let node = if self.state.xot.parent(node).is_some() {
1145 self.state.xot.clone_node(node)
1146 } else {
1147 node
1148 };
1149 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 !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 xot::Value::Document => xot.new_document(),
1176 xot::Value::Element(element) => xot.new_element(element.name()),
1178 _ => 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 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 fn current_span(&self) -> SourceSpan {
1255 let frame = self.state.frame();
1256 let function = self.runnable.program().inline_function(frame.function());
1257 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}