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