1use ibig::{ibig, IBig};
2
3use xee_interpreter::error::Error;
4use xee_interpreter::function::FunctionRule;
5use xee_interpreter::interpreter::instruction::Instruction;
6use xee_interpreter::span::SourceSpan;
7use xee_interpreter::{error, function, sequence};
8
9use crate::declaration_compiler::ModeIds;
10use crate::ir;
11
12use super::builder::{BackwardJumpRef, ForwardJumpRef, FunctionBuilder, JumpCondition};
13use super::scope;
14
15pub(crate) type Scopes = scope::Scopes<ir::Name>;
16
17pub struct FunctionCompiler<'a> {
18 pub(crate) scopes: &'a mut Scopes,
19 pub(crate) mode_ids: &'a ModeIds,
20 pub(crate) builder: FunctionBuilder<'a>,
21}
22
23impl<'a> FunctionCompiler<'a> {
24 pub fn new(
25 builder: FunctionBuilder<'a>,
26 scopes: &'a mut Scopes,
27 mode_ids: &'a ModeIds,
28 ) -> Self {
29 Self {
30 builder,
31 scopes,
32 mode_ids,
33 }
34 }
35
36 pub fn compile_expr(&mut self, expr: &ir::ExprS) -> error::SpannedResult<()> {
37 let span = expr.span.into();
38 match &expr.value {
39 ir::Expr::Atom(atom) => self.compile_atom(atom),
40 ir::Expr::Let(let_) => self.compile_let(let_, span),
41 ir::Expr::Binary(binary) => self.compile_binary(binary, span),
42 ir::Expr::Unary(unary) => self.compile_unary(unary, span),
43 ir::Expr::FunctionDefinition(function_definition) => {
44 self.compile_function_definition(function_definition, span)
45 }
46 ir::Expr::FunctionCall(function_call) => {
47 self.compile_function_call(function_call, span)
48 }
49 ir::Expr::Lookup(lookup) => self.compile_lookup(lookup, span),
50 ir::Expr::WildcardLookup(wildcard_lookup) => {
51 self.compile_wildcard_lookup(wildcard_lookup, span)
52 }
53 ir::Expr::Step(step) => self.compile_step(step, span),
54 ir::Expr::Deduplicate(expr) => self.compile_deduplicate(expr, span),
55 ir::Expr::If(if_) => self.compile_if(if_, span),
56 ir::Expr::Map(map) => self.compile_map(map, span),
57 ir::Expr::Filter(filter) => self.compile_filter(filter, span),
58 ir::Expr::PatternPredicate(pattern_predicate) => {
59 self.compile_pattern_predicate(pattern_predicate, span)
60 }
61 ir::Expr::Quantified(quantified) => self.compile_quantified(quantified, span),
62 ir::Expr::Cast(cast) => self.compile_cast(cast, span),
63 ir::Expr::Castable(castable) => self.compile_castable(castable, span),
64 ir::Expr::InstanceOf(instance_of) => self.compile_instance_of(instance_of, span),
65 ir::Expr::Treat(treat) => self.compile_treat(treat, span),
66 ir::Expr::MapConstructor(map_constructor) => {
67 self.compile_map_constructor(map_constructor, span)
68 }
69 ir::Expr::ArrayConstructor(array_constructor) => {
70 self.compile_array_constructor(array_constructor, span)
71 }
72 ir::Expr::XmlName(xml_name) => self.compile_xml_name(xml_name, span),
73 ir::Expr::XmlDocument(root) => self.compile_xml_document(root, span),
74 ir::Expr::XmlElement(element) => self.compile_xml_element(element, span),
75 ir::Expr::XmlAttribute(attribute) => self.compile_xml_attribute(attribute, span),
76 ir::Expr::XmlNamespace(namespace) => self.compile_xml_namespace(namespace, span),
77 ir::Expr::XmlText(text) => self.compile_xml_text(text, span),
78 ir::Expr::XmlComment(comment) => self.compile_xml_comment(comment, span),
79 ir::Expr::XmlProcessingInstruction(processing_instruction) => {
80 self.compile_xml_processing_instruction(processing_instruction, span)
81 }
82 ir::Expr::XmlAppend(xml_append) => self.compile_xml_append(xml_append, span),
83 ir::Expr::ApplyTemplates(apply_templates) => {
84 self.compile_apply_templates(apply_templates, span)
85 }
86 ir::Expr::CopyShallow(copy_shallow) => self.compile_copy_shallow(copy_shallow, span),
87 ir::Expr::CopyDeep(copy_deep) => self.compile_copy_deep(copy_deep, span),
88 }
89 }
90
91 fn compile_atom(&mut self, atom: &ir::AtomS) -> error::SpannedResult<()> {
92 let span = atom.span.into();
93 match &atom.value {
94 ir::Atom::Const(c) => {
95 match c {
96 ir::Const::Integer(i) => {
97 self.builder.emit_constant((i.clone()).into(), span);
98 }
99 ir::Const::String(s) => {
100 self.builder.emit_constant((s).into(), span);
101 }
102 ir::Const::Double(d) => {
103 self.builder.emit_constant((*d).into(), span);
104 }
105 ir::Const::Decimal(d) => {
106 self.builder.emit_constant((*d).into(), span);
107 }
108 ir::Const::EmptySequence => self
109 .builder
110 .emit_constant(sequence::Sequence::default(), span),
111 ir::Const::StaticFunctionReference(static_function_id, context_names) => {
112 self.compile_static_function_reference(
113 *static_function_id,
114 context_names.as_ref(),
115 span,
116 )?;
117 }
118 };
119 Ok(())
120 }
121 ir::Atom::Variable(name) => self.compile_variable(name, span),
122 }
123 }
124
125 fn compile_variable(&mut self, name: &ir::Name, span: SourceSpan) -> error::SpannedResult<()> {
126 if let Some(index) = self.scopes.get(name) {
127 if index > u16::MAX as usize {
128 return Err(Error::XPDY0130.with_span(span));
129 }
130 self.builder.emit(Instruction::Var(index as u16), span);
131 Ok(())
132 } else {
133 if self.scopes.is_closed_over_name(name) {
135 let index = self.builder.add_closure_name(name);
136 if index > u16::MAX as usize {
137 return Err(Error::XPDY0130.with_span(span));
138 }
139 self.builder
140 .emit(Instruction::ClosureVar(index as u16), span);
141 Ok(())
142 } else {
143 Err(Error::Unsupported.into())
148 }
150 }
151 }
152
153 fn compile_variable_set(
154 &mut self,
155 name: &ir::Name,
156 span: SourceSpan,
157 ) -> error::SpannedResult<()> {
158 if let Some(index) = self.scopes.get(name) {
159 if index > u16::MAX as usize {
160 return Err(Error::XPDY0130.with_span(span));
161 }
162 self.builder.emit(Instruction::Set(index as u16), span);
163 } else {
164 panic!("can only set locals: {:?}", name);
165 }
166 Ok(())
167 }
168
169 fn compile_let(&mut self, let_: &ir::Let, span: SourceSpan) -> error::SpannedResult<()> {
170 self.compile_expr(&let_.var_expr)?;
171 self.scopes.push_name(&let_.name);
172 self.compile_expr(&let_.return_expr)?;
173 self.builder.emit(Instruction::LetDone, span);
174 self.scopes.pop_name();
175 Ok(())
176 }
177
178 fn compile_if(&mut self, if_: &ir::If, span: SourceSpan) -> error::SpannedResult<()> {
179 self.compile_atom(&if_.condition)?;
180 let jump_else = self.builder.emit_jump_forward(JumpCondition::False, span);
181 self.compile_expr(&if_.then)?;
182 let jump_end = self.builder.emit_jump_forward(JumpCondition::Always, span);
183 self.builder.patch_jump(jump_else);
184 self.compile_expr(&if_.else_)?;
185 self.builder.patch_jump(jump_end);
186 Ok(())
187 }
188
189 fn compile_binary(
190 &mut self,
191 binary: &ir::Binary,
192 span: SourceSpan,
193 ) -> error::SpannedResult<()> {
194 self.compile_atom(&binary.left)?;
195 self.compile_atom(&binary.right)?;
196 match &binary.op {
197 ir::BinaryOperator::Add => {
198 self.builder.emit(Instruction::Add, span);
199 }
200 ir::BinaryOperator::Sub => {
201 self.builder.emit(Instruction::Sub, span);
202 }
203 ir::BinaryOperator::Mul => {
204 self.builder.emit(Instruction::Mul, span);
205 }
206 ir::BinaryOperator::Div => {
207 self.builder.emit(Instruction::Div, span);
208 }
209 ir::BinaryOperator::IntDiv => {
210 self.builder.emit(Instruction::IntDiv, span);
211 }
212 ir::BinaryOperator::Mod => {
213 self.builder.emit(Instruction::Mod, span);
214 }
215 ir::BinaryOperator::ValueEq => {
216 self.builder.emit(Instruction::Eq, span);
217 }
218 ir::BinaryOperator::ValueNe => {
219 self.builder.emit(Instruction::Ne, span);
220 }
221 ir::BinaryOperator::ValueLt => {
222 self.builder.emit(Instruction::Lt, span);
223 }
224 ir::BinaryOperator::ValueLe => {
225 self.builder.emit(Instruction::Le, span);
226 }
227 ir::BinaryOperator::ValueGt => {
228 self.builder.emit(Instruction::Gt, span);
229 }
230 ir::BinaryOperator::ValueGe => {
231 self.builder.emit(Instruction::Ge, span);
232 }
233 ir::BinaryOperator::GenEq => {
234 self.builder.emit(Instruction::GenEq, span);
235 }
236 ir::BinaryOperator::GenNe => {
237 self.builder.emit(Instruction::GenNe, span);
238 }
239 ir::BinaryOperator::GenLt => {
240 self.builder.emit(Instruction::GenLt, span);
241 }
242 ir::BinaryOperator::GenLe => {
243 self.builder.emit(Instruction::GenLe, span);
244 }
245 ir::BinaryOperator::GenGt => {
246 self.builder.emit(Instruction::GenGt, span);
247 }
248 ir::BinaryOperator::GenGe => {
249 self.builder.emit(Instruction::GenGe, span);
250 }
251 ir::BinaryOperator::Comma => {
252 self.builder.emit(Instruction::Comma, span);
253 }
254 ir::BinaryOperator::Union => {
255 self.builder.emit(Instruction::Union, span);
256 }
257 ir::BinaryOperator::Intersect => {
258 self.builder.emit(Instruction::Intersect, span);
259 }
260 ir::BinaryOperator::Except => {
261 self.builder.emit(Instruction::Except, span);
262 }
263 ir::BinaryOperator::Range => {
264 self.builder.emit(Instruction::Range, span);
265 }
266 ir::BinaryOperator::Concat => {
267 self.builder.emit(Instruction::Concat, span);
268 }
269 ir::BinaryOperator::And => {
270 let first_false = self.builder.emit_jump_forward(JumpCondition::False, span);
272 let second_false = self.builder.emit_jump_forward(JumpCondition::False, span);
273 self.builder.emit_constant(true.into(), span);
275 let end = self.builder.emit_jump_forward(JumpCondition::Always, span);
276 self.builder.patch_jump(first_false);
277 self.builder.emit(Instruction::Pop, span);
279 self.builder.patch_jump(second_false);
280 self.builder.emit_constant(false.into(), span);
282 self.builder.patch_jump(end);
283 }
284 ir::BinaryOperator::Or => {
285 let first_true = self.builder.emit_jump_forward(JumpCondition::True, span);
287 let second_true = self.builder.emit_jump_forward(JumpCondition::True, span);
288 self.builder.emit_constant(false.into(), span);
290 let end = self.builder.emit_jump_forward(JumpCondition::Always, span);
291 self.builder.patch_jump(first_true);
293 self.builder.emit(Instruction::Pop, span);
295 self.builder.patch_jump(second_true);
296 self.builder.emit_constant(true.into(), span);
298 self.builder.patch_jump(end);
299 }
300 ir::BinaryOperator::Is => {
301 self.builder.emit(Instruction::Is, span);
302 }
303 ir::BinaryOperator::Precedes => {
304 self.builder.emit(Instruction::Precedes, span);
305 }
306 ir::BinaryOperator::Follows => {
307 self.builder.emit(Instruction::Follows, span);
308 }
309 }
310 Ok(())
311 }
312
313 fn compile_unary(&mut self, unary: &ir::Unary, span: SourceSpan) -> error::SpannedResult<()> {
314 self.compile_atom(&unary.atom)?;
315 match unary.op {
316 ir::UnaryOperator::Plus => {
317 self.builder.emit(Instruction::Plus, span);
318 }
319 ir::UnaryOperator::Minus => {
320 self.builder.emit(Instruction::Minus, span);
321 }
322 }
323 Ok(())
324 }
325
326 pub fn compile_function_id(
327 &mut self,
328 function_definition: &ir::FunctionDefinition,
329 span: SourceSpan,
330 ) -> error::SpannedResult<function::InlineFunctionId> {
331 let nested_builder = self.builder.builder();
332 self.scopes.push_scope();
333
334 let mut compiler = FunctionCompiler {
335 builder: nested_builder,
336 scopes: self.scopes,
337 mode_ids: self.mode_ids,
338 };
339
340 for param in &function_definition.params {
341 compiler.scopes.push_name(¶m.name);
342 }
343 compiler.compile_expr(&function_definition.body)?;
344 for _ in &function_definition.params {
345 compiler.scopes.pop_name();
346 }
347
348 compiler.scopes.pop_scope();
349
350 let function = compiler
351 .builder
352 .finish("inline".to_string(), function_definition, span);
353 for name in function.closure_names.iter().rev() {
357 self.compile_variable(name, span)?;
358 }
359 Ok(self.builder.add_function(function))
360 }
361
362 pub(crate) fn compile_function_definition(
363 &mut self,
364 function_definition: &ir::FunctionDefinition,
365 span: SourceSpan,
366 ) -> error::SpannedResult<()> {
367 let function_id = self.compile_function_id(function_definition, span)?;
368 self.builder
369 .emit(Instruction::Closure(function_id.as_u16()), span);
370 Ok(())
371 }
372
373 fn compile_static_function_reference(
374 &mut self,
375 static_function_id: function::StaticFunctionId,
376 context_names: Option<&ir::ContextNames>,
377 span: SourceSpan,
378 ) -> error::SpannedResult<()> {
379 let static_function = self
380 .builder
381 .static_context()
382 .function_by_id(static_function_id);
383 match static_function.function_rule {
384 Some(FunctionRule::ItemFirst) => {
385 let context_names = context_names.ok_or(Error::XPDY0002.with_span(span))?;
386 self.compile_variable(&context_names.item, span)?
387 }
388 Some(FunctionRule::ItemLast) => {
389 let context_names = context_names.ok_or(Error::XPDY0002.with_span(span))?;
390 self.compile_variable(&context_names.item, span)?
391 }
392 Some(FunctionRule::ItemLastOptional) => {
393 if let Some(context_names) = context_names {
394 self.compile_variable(&context_names.item, span)?;
395 } else {
396 self.builder
397 .emit_constant(sequence::Sequence::default(), span);
398 }
399 }
400 Some(FunctionRule::PositionFirst) => self.compile_variable(
401 {
402 let context_names = context_names.ok_or(Error::XPDY0002.with_span(span))?;
403 &context_names.position
404 },
405 span,
406 )?,
407 Some(FunctionRule::SizeFirst) => {
408 let context_names = context_names.ok_or(Error::XPDY0002.with_span(span))?;
409 self.compile_variable(&context_names.last, span)?
410 }
411 Some(FunctionRule::Collation) | Some(FunctionRule::AnonymousClosure) | None => {}
412 }
413 self.builder.emit(
414 Instruction::StaticClosure(static_function_id.as_u16()),
415 span,
416 );
417 Ok(())
418 }
419
420 fn compile_function_call(
421 &mut self,
422 function_call: &ir::FunctionCall,
423 span: SourceSpan,
424 ) -> error::SpannedResult<()> {
425 self.compile_atom(&function_call.atom)?;
426 for arg in &function_call.args {
427 self.compile_atom(arg)?;
428 }
429 self.builder
430 .emit(Instruction::Call(function_call.args.len() as u8), span);
431 Ok(())
432 }
433
434 fn compile_lookup(
435 &mut self,
436 lookup: &ir::Lookup,
437 span: SourceSpan,
438 ) -> error::SpannedResult<()> {
439 self.compile_atom(&lookup.atom)?;
440 self.compile_atom(&lookup.arg_atom)?;
441 self.builder.emit(Instruction::Lookup, span);
442 Ok(())
443 }
444
445 fn compile_wildcard_lookup(
446 &mut self,
447 lookup: &ir::WildcardLookup,
448 span: SourceSpan,
449 ) -> error::SpannedResult<()> {
450 self.compile_atom(&lookup.atom)?;
451 self.builder.emit(Instruction::WildcardLookup, span);
452 Ok(())
453 }
454
455 fn compile_step(&mut self, step: &ir::Step, span: SourceSpan) -> error::SpannedResult<()> {
456 self.compile_atom(&step.context)?;
457 let step_id = self.builder.add_step(step.step.clone());
458 self.builder.emit(Instruction::Step(step_id as u16), span);
459 Ok(())
460 }
461
462 fn compile_deduplicate(
463 &mut self,
464 expr: &ir::ExprS,
465 span: SourceSpan,
466 ) -> error::SpannedResult<()> {
467 self.compile_expr(expr)?;
468 self.builder.emit(Instruction::Deduplicate, span);
469 Ok(())
470 }
471
472 fn compile_cast(&mut self, cast: &ir::Cast, span: SourceSpan) -> error::SpannedResult<()> {
473 self.compile_atom(&cast.atom)?;
474 let cast_type = cast.cast_type();
475 let cast_type_id = self.builder.add_cast_type(cast_type);
476 self.builder
477 .emit(Instruction::Cast(cast_type_id as u16), span);
478 Ok(())
479 }
480
481 fn compile_castable(
482 &mut self,
483 castable: &ir::Castable,
484 span: SourceSpan,
485 ) -> error::SpannedResult<()> {
486 self.compile_atom(&castable.atom)?;
487 let cast_type = castable.cast_type();
488 let cast_type_id = self.builder.add_cast_type(cast_type);
489 self.builder
490 .emit(Instruction::Castable(cast_type_id as u16), span);
491 Ok(())
492 }
493
494 fn compile_instance_of(
495 &mut self,
496 instance_of: &ir::InstanceOf,
497 span: SourceSpan,
498 ) -> error::SpannedResult<()> {
499 self.compile_atom(&instance_of.atom)?;
500 let sequence_type_id = self
501 .builder
502 .add_sequence_type(instance_of.sequence_type.clone());
503 self.builder
504 .emit(Instruction::InstanceOf(sequence_type_id as u16), span);
505 Ok(())
506 }
507
508 fn compile_treat(&mut self, treat: &ir::Treat, span: SourceSpan) -> error::SpannedResult<()> {
509 self.compile_atom(&treat.atom)?;
510 let sequence_type_id = self.builder.add_sequence_type(treat.sequence_type.clone());
511 self.builder
512 .emit(Instruction::Treat(sequence_type_id as u16), span);
513 Ok(())
514 }
515
516 fn compile_map_constructor(
517 &mut self,
518 map_constructor: &ir::MapConstructor,
519 span: SourceSpan,
520 ) -> error::SpannedResult<()> {
521 for (key_atom, value_atom) in map_constructor.members.iter().rev() {
525 self.compile_atom(key_atom)?;
526 self.compile_atom(value_atom)?;
527 }
528 let len: IBig = map_constructor.members.len().into();
530 let len: sequence::Sequence = len.into();
531 self.builder.emit_constant(len, span);
532 self.builder.emit(Instruction::CurlyMap, span);
533 Ok(())
534 }
535
536 fn compile_array_constructor(
537 &mut self,
538 array_constructor: &ir::ArrayConstructor,
539 span: SourceSpan,
540 ) -> error::SpannedResult<()> {
541 match array_constructor {
542 ir::ArrayConstructor::Curly(atom) => {
543 self.compile_curly_array_constructor(atom, span)?;
544 }
545 ir::ArrayConstructor::Square(atoms) => {
546 self.compile_square_array_constructor(atoms, span)?;
547 }
548 }
549 Ok(())
550 }
551
552 fn compile_curly_array_constructor(
553 &mut self,
554 atom: &ir::AtomS,
555 span: SourceSpan,
556 ) -> error::SpannedResult<()> {
557 self.compile_atom(atom)?;
558 self.builder.emit(Instruction::CurlyArray, span);
559 Ok(())
560 }
561
562 fn compile_square_array_constructor(
563 &mut self,
564 atoms: &[ir::AtomS],
565 span: SourceSpan,
566 ) -> error::SpannedResult<()> {
567 for atom in atoms.iter().rev() {
570 self.compile_atom(atom)?;
571 }
572 let len: IBig = atoms.len().into();
574 let len: sequence::Sequence = len.into();
575 self.builder.emit_constant(len, span);
576 self.builder.emit(Instruction::SquareArray, span);
577 Ok(())
578 }
579
580 fn compile_map(&mut self, map: &ir::Map, span: SourceSpan) -> error::SpannedResult<()> {
581 self.builder.emit(Instruction::BuildNew, span);
583
584 let (loop_start, loop_end) =
585 self.compile_sequence_loop_init(&map.var_atom, &map.context_names, span)?;
586
587 self.compile_sequence_get_item(&map.var_atom, &map.context_names, span)?;
588 self.scopes.push_name(&map.context_names.item);
590 self.compile_expr(&map.return_expr)?;
592 self.scopes.pop_name();
593
594 self.builder.emit(Instruction::BuildPush, span);
596
597 self.builder.emit(Instruction::Pop, span);
599
600 self.compile_sequence_loop_iterate(loop_start, &map.context_names, span)?;
601
602 self.builder.patch_jump(loop_end);
603 self.compile_sequence_loop_end(span);
604
605 self.builder.emit(Instruction::BuildComplete, span);
606 self.scopes.pop_name();
608 self.scopes.pop_name();
609 Ok(())
610 }
611
612 fn compile_filter(
613 &mut self,
614 filter: &ir::Filter,
615 span: SourceSpan,
616 ) -> error::SpannedResult<()> {
617 self.builder.emit(Instruction::BuildNew, span);
619
620 let (loop_start, loop_end) =
621 self.compile_sequence_loop_init(&filter.var_atom, &filter.context_names, span)?;
622
623 self.compile_sequence_get_item(&filter.var_atom, &filter.context_names, span)?;
625 self.scopes.push_name(&filter.context_names.item);
627 self.compile_expr(&filter.return_expr)?;
629 self.scopes.pop_name();
630 self.builder.emit(Instruction::Dup, span);
632 self.builder.emit(Instruction::IsNumeric, span);
634 let is_not_numeric = self.builder.emit_jump_forward(JumpCondition::False, span);
637 self.compile_variable(&filter.context_names.position, span)?;
639 self.builder.emit(Instruction::Eq, span);
640 self.builder.patch_jump(is_not_numeric);
645 let is_included = self.builder.emit_jump_forward(JumpCondition::True, span);
646 self.builder.emit(Instruction::Pop, span);
648 let iterate = self.builder.emit_jump_forward(JumpCondition::Always, span);
650
651 self.builder.patch_jump(is_included);
652 self.builder.emit(Instruction::BuildPush, span);
654
655 self.builder.patch_jump(iterate);
656 self.compile_sequence_loop_iterate(loop_start, &filter.context_names, span)?;
658
659 self.builder.patch_jump(loop_end);
660 self.compile_sequence_loop_end(span);
661
662 self.builder.emit(Instruction::BuildComplete, span);
663 self.scopes.pop_name();
665 self.scopes.pop_name();
666 Ok(())
667 }
668
669 fn compile_quantified(
670 &mut self,
671 quantified: &ir::Quantified,
672 span: SourceSpan,
673 ) -> error::SpannedResult<()> {
674 let (loop_start, loop_end) =
675 self.compile_sequence_loop_init(&quantified.var_atom, &quantified.context_names, span)?;
676
677 self.compile_sequence_get_item(&quantified.var_atom, &quantified.context_names, span)?;
678 self.scopes.push_name(&quantified.context_names.item);
680 self.compile_expr(&quantified.satisifies_expr)?;
682 self.scopes.pop_name();
683
684 let jump_out_end = match quantified.quantifier {
685 ir::Quantifier::Some => self.builder.emit_jump_forward(JumpCondition::True, span),
686 ir::Quantifier::Every => self.builder.emit_jump_forward(JumpCondition::False, span),
687 };
688 self.builder.emit(Instruction::Pop, span);
690
691 self.compile_sequence_loop_iterate(loop_start, &quantified.context_names, span)?;
692
693 self.builder.patch_jump(loop_end);
694
695 self.compile_sequence_loop_end(span);
697
698 let reached_end_value = match quantified.quantifier {
699 ir::Quantifier::Some => false.into(),
700 ir::Quantifier::Every => true.into(),
701 };
702 self.builder.emit_constant(reached_end_value, span);
703 let end = self.builder.emit_jump_forward(JumpCondition::Always, span);
704
705 self.builder.patch_jump(jump_out_end);
707 self.builder.emit(Instruction::Pop, span);
709 self.compile_sequence_loop_end(span);
710
711 let jumped_out_value = match quantified.quantifier {
712 ir::Quantifier::Some => true.into(),
713 ir::Quantifier::Every => false.into(),
714 };
715 self.builder.emit_constant(jumped_out_value, span);
717
718 self.builder.patch_jump(end);
719 self.scopes.pop_name();
721 self.scopes.pop_name();
722 Ok(())
723 }
724
725 fn compile_sequence_loop_init(
726 &mut self,
727 atom: &ir::AtomS,
728 context_names: &ir::ContextNames,
729 span: SourceSpan,
730 ) -> error::SpannedResult<(BackwardJumpRef, ForwardJumpRef)> {
731 self.compile_atom(atom)?;
733 self.scopes.push_name(&context_names.last);
734 self.builder.emit(Instruction::SequenceLen, span);
735
736 self.builder.emit_constant(ibig!(1).into(), span);
738 self.scopes.push_name(&context_names.position);
739
740 let loop_start_ref = self.builder.loop_start();
741
742 self.compile_variable(&context_names.position, span)?;
744 self.compile_variable(&context_names.last, span)?;
745 self.builder.emit(Instruction::Gt, span);
746 let loop_end_ref = self.builder.emit_jump_forward(JumpCondition::True, span);
748
749 Ok((loop_start_ref, loop_end_ref))
750 }
751
752 fn compile_sequence_get_item(
753 &mut self,
754 atom: &ir::AtomS,
755 context_names: &ir::ContextNames,
756 span: SourceSpan,
757 ) -> error::SpannedResult<()> {
758 self.compile_variable(&context_names.position, span)?;
760 self.compile_atom(atom)?;
761 self.builder.emit(Instruction::SequenceGet, span);
762 Ok(())
763 }
764
765 fn compile_sequence_loop_iterate(
766 &mut self,
767 loop_start: BackwardJumpRef,
768 context_names: &ir::ContextNames,
769 span: SourceSpan,
770 ) -> error::SpannedResult<()> {
771 self.compile_variable(&context_names.position, span)?;
773 self.builder.emit_constant(ibig!(1).into(), span);
774 self.builder.emit(Instruction::Add, span);
775 self.compile_variable_set(&context_names.position, span)?;
776 self.builder
777 .emit_jump_backward(loop_start, JumpCondition::Always, span);
778 Ok(())
779 }
780
781 fn compile_sequence_loop_end(&mut self, span: SourceSpan) {
782 self.builder.emit(Instruction::Pop, span);
784 self.builder.emit(Instruction::Pop, span);
785 }
786
787 fn compile_xml_name(
788 &mut self,
789 xml_name: &ir::XmlName,
790 span: SourceSpan,
791 ) -> error::SpannedResult<()> {
792 self.compile_atom(&xml_name.namespace)?;
793 self.compile_atom(&xml_name.local_name)?;
794 self.builder.emit(Instruction::XmlName, span);
795 Ok(())
796 }
797
798 fn compile_xml_document(
799 &mut self,
800 _root: &ir::XmlRoot,
801 span: SourceSpan,
802 ) -> error::SpannedResult<()> {
803 self.builder.emit(Instruction::XmlDocument, span);
804 Ok(())
805 }
806
807 fn compile_xml_element(
808 &mut self,
809 element: &ir::XmlElement,
810 span: SourceSpan,
811 ) -> error::SpannedResult<()> {
812 self.compile_atom(&element.name)?;
813 self.builder.emit(Instruction::XmlElement, span);
814 Ok(())
815 }
816
817 fn compile_xml_attribute(
818 &mut self,
819 attribute: &ir::XmlAttribute,
820 span: SourceSpan,
821 ) -> error::SpannedResult<()> {
822 self.compile_atom(&attribute.name)?;
823 self.compile_atom(&attribute.value)?;
824 self.builder.emit(Instruction::XmlAttribute, span);
825 Ok(())
826 }
827
828 fn compile_xml_namespace(
829 &mut self,
830 prefix: &ir::XmlNamespace,
831 span: SourceSpan,
832 ) -> error::SpannedResult<()> {
833 self.compile_atom(&prefix.prefix)?;
834 self.compile_atom(&prefix.namespace)?;
835 self.builder.emit(Instruction::XmlNamespace, span);
836 Ok(())
837 }
838
839 fn compile_xml_text(
840 &mut self,
841 text: &ir::XmlText,
842 span: SourceSpan,
843 ) -> error::SpannedResult<()> {
844 self.compile_atom(&text.value)?;
846 self.builder.emit(Instruction::XmlText, span);
847 Ok(())
848 }
849
850 fn compile_xml_append(
851 &mut self,
852 append: &ir::XmlAppend,
853 span: SourceSpan,
854 ) -> error::SpannedResult<()> {
855 self.compile_atom(&append.parent)?;
856 self.compile_atom(&append.child)?;
857 self.builder.emit(Instruction::XmlAppend, span);
858 Ok(())
859 }
860
861 fn compile_xml_comment(
862 &mut self,
863 comment: &ir::XmlComment,
864 span: SourceSpan,
865 ) -> error::SpannedResult<()> {
866 self.compile_atom(&comment.value)?;
867 self.builder.emit(Instruction::XmlComment, span);
868 Ok(())
869 }
870
871 fn compile_xml_processing_instruction(
872 &mut self,
873 processing_instruction: &ir::XmlProcessingInstruction,
874 span: SourceSpan,
875 ) -> error::SpannedResult<()> {
876 self.compile_atom(&processing_instruction.target)?;
877 self.compile_atom(&processing_instruction.content)?;
878 self.builder
879 .emit(Instruction::XmlProcessingInstruction, span);
880 Ok(())
881 }
882
883 fn compile_apply_templates(
884 &mut self,
885 apply_templates: &ir::ApplyTemplates,
886 span: SourceSpan,
887 ) -> error::SpannedResult<()> {
888 self.compile_atom(&apply_templates.select)?;
889
890 let mode_id = if matches!(
891 apply_templates.mode,
892 ir::ApplyTemplatesModeValue::Named(_) | ir::ApplyTemplatesModeValue::Unnamed
893 ) {
894 self.mode_ids.get(&apply_templates.mode)
895 } else {
896 todo!("#current mode not handled yet")
897 };
898 if let Some(mode_id) = mode_id {
899 self.builder
900 .emit(Instruction::ApplyTemplates(mode_id.get() as u16), span);
901 } else {
902 self.builder
905 .emit_constant(sequence::Sequence::default(), span);
906 }
907 Ok(())
908 }
909
910 fn compile_copy_shallow(
911 &mut self,
912 copy_shallow: &ir::CopyShallow,
913 span: SourceSpan,
914 ) -> error::SpannedResult<()> {
915 self.compile_atom(©_shallow.select)?;
916 self.builder.emit(Instruction::CopyShallow, span);
917 Ok(())
918 }
919
920 fn compile_copy_deep(
921 &mut self,
922 copy_deep: &ir::CopyDeep,
923 span: SourceSpan,
924 ) -> error::SpannedResult<()> {
925 self.compile_atom(©_deep.select)?;
926 self.builder.emit(Instruction::CopyDeep, span);
927 Ok(())
928 }
929
930 fn compile_pattern_predicate(
931 &mut self,
932 predicate: &ir::PatternPredicate,
933 span: SourceSpan,
934 ) -> error::SpannedResult<()> {
935 self.compile_expr(&predicate.expr)?;
937 self.builder.emit(Instruction::Dup, span);
939 self.builder.emit(Instruction::IsNumeric, span);
941 let is_not_numeric = self.builder.emit_jump_forward(JumpCondition::False, span);
944 self.compile_variable(&predicate.context_names.position, span)?;
946 self.builder.emit(Instruction::Eq, span);
947 self.builder.patch_jump(is_not_numeric);
948 Ok(())
949 }
950}