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