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 unreachable!("variable not found: {:?}", name);
144 }
145 }
146 }
147
148 fn compile_variable_set(
149 &mut self,
150 name: &ir::Name,
151 span: SourceSpan,
152 ) -> error::SpannedResult<()> {
153 if let Some(index) = self.scopes.get(name) {
154 if index > u16::MAX as usize {
155 return Err(Error::XPDY0130.with_span(span));
156 }
157 self.builder.emit(Instruction::Set(index as u16), span);
158 } else {
159 panic!("can only set locals: {:?}", name);
160 }
161 Ok(())
162 }
163
164 fn compile_let(&mut self, let_: &ir::Let, span: SourceSpan) -> error::SpannedResult<()> {
165 self.compile_expr(&let_.var_expr)?;
166 self.scopes.push_name(&let_.name);
167 self.compile_expr(&let_.return_expr)?;
168 self.builder.emit(Instruction::LetDone, span);
169 self.scopes.pop_name();
170 Ok(())
171 }
172
173 fn compile_if(&mut self, if_: &ir::If, span: SourceSpan) -> error::SpannedResult<()> {
174 self.compile_atom(&if_.condition)?;
175 let jump_else = self.builder.emit_jump_forward(JumpCondition::False, span);
176 self.compile_expr(&if_.then)?;
177 let jump_end = self.builder.emit_jump_forward(JumpCondition::Always, span);
178 self.builder.patch_jump(jump_else);
179 self.compile_expr(&if_.else_)?;
180 self.builder.patch_jump(jump_end);
181 Ok(())
182 }
183
184 fn compile_binary(
185 &mut self,
186 binary: &ir::Binary,
187 span: SourceSpan,
188 ) -> error::SpannedResult<()> {
189 self.compile_atom(&binary.left)?;
190 self.compile_atom(&binary.right)?;
191 match &binary.op {
192 ir::BinaryOperator::Add => {
193 self.builder.emit(Instruction::Add, span);
194 }
195 ir::BinaryOperator::Sub => {
196 self.builder.emit(Instruction::Sub, span);
197 }
198 ir::BinaryOperator::Mul => {
199 self.builder.emit(Instruction::Mul, span);
200 }
201 ir::BinaryOperator::Div => {
202 self.builder.emit(Instruction::Div, span);
203 }
204 ir::BinaryOperator::IntDiv => {
205 self.builder.emit(Instruction::IntDiv, span);
206 }
207 ir::BinaryOperator::Mod => {
208 self.builder.emit(Instruction::Mod, span);
209 }
210 ir::BinaryOperator::ValueEq => {
211 self.builder.emit(Instruction::Eq, span);
212 }
213 ir::BinaryOperator::ValueNe => {
214 self.builder.emit(Instruction::Ne, span);
215 }
216 ir::BinaryOperator::ValueLt => {
217 self.builder.emit(Instruction::Lt, span);
218 }
219 ir::BinaryOperator::ValueLe => {
220 self.builder.emit(Instruction::Le, span);
221 }
222 ir::BinaryOperator::ValueGt => {
223 self.builder.emit(Instruction::Gt, span);
224 }
225 ir::BinaryOperator::ValueGe => {
226 self.builder.emit(Instruction::Ge, span);
227 }
228 ir::BinaryOperator::GenEq => {
229 self.builder.emit(Instruction::GenEq, span);
230 }
231 ir::BinaryOperator::GenNe => {
232 self.builder.emit(Instruction::GenNe, span);
233 }
234 ir::BinaryOperator::GenLt => {
235 self.builder.emit(Instruction::GenLt, span);
236 }
237 ir::BinaryOperator::GenLe => {
238 self.builder.emit(Instruction::GenLe, span);
239 }
240 ir::BinaryOperator::GenGt => {
241 self.builder.emit(Instruction::GenGt, span);
242 }
243 ir::BinaryOperator::GenGe => {
244 self.builder.emit(Instruction::GenGe, span);
245 }
246 ir::BinaryOperator::Comma => {
247 self.builder.emit(Instruction::Comma, span);
248 }
249 ir::BinaryOperator::Union => {
250 self.builder.emit(Instruction::Union, span);
251 }
252 ir::BinaryOperator::Intersect => {
253 self.builder.emit(Instruction::Intersect, span);
254 }
255 ir::BinaryOperator::Except => {
256 self.builder.emit(Instruction::Except, span);
257 }
258 ir::BinaryOperator::Range => {
259 self.builder.emit(Instruction::Range, span);
260 }
261 ir::BinaryOperator::Concat => {
262 self.builder.emit(Instruction::Concat, span);
263 }
264 ir::BinaryOperator::And => {
265 let first_false = self.builder.emit_jump_forward(JumpCondition::False, span);
267 let second_false = self.builder.emit_jump_forward(JumpCondition::False, span);
268 self.builder.emit_constant(true.into(), span);
270 let end = self.builder.emit_jump_forward(JumpCondition::Always, span);
271 self.builder.patch_jump(first_false);
272 self.builder.emit(Instruction::Pop, span);
274 self.builder.patch_jump(second_false);
275 self.builder.emit_constant(false.into(), span);
277 self.builder.patch_jump(end);
278 }
279 ir::BinaryOperator::Or => {
280 let first_true = self.builder.emit_jump_forward(JumpCondition::True, span);
282 let second_true = self.builder.emit_jump_forward(JumpCondition::True, span);
283 self.builder.emit_constant(false.into(), span);
285 let end = self.builder.emit_jump_forward(JumpCondition::Always, span);
286 self.builder.patch_jump(first_true);
288 self.builder.emit(Instruction::Pop, span);
290 self.builder.patch_jump(second_true);
291 self.builder.emit_constant(true.into(), span);
293 self.builder.patch_jump(end);
294 }
295 ir::BinaryOperator::Is => {
296 self.builder.emit(Instruction::Is, span);
297 }
298 ir::BinaryOperator::Precedes => {
299 self.builder.emit(Instruction::Precedes, span);
300 }
301 ir::BinaryOperator::Follows => {
302 self.builder.emit(Instruction::Follows, span);
303 }
304 }
305 Ok(())
306 }
307
308 fn compile_unary(&mut self, unary: &ir::Unary, span: SourceSpan) -> error::SpannedResult<()> {
309 self.compile_atom(&unary.atom)?;
310 match unary.op {
311 ir::UnaryOperator::Plus => {
312 self.builder.emit(Instruction::Plus, span);
313 }
314 ir::UnaryOperator::Minus => {
315 self.builder.emit(Instruction::Minus, span);
316 }
317 }
318 Ok(())
319 }
320
321 pub fn compile_function_id(
322 &mut self,
323 function_definition: &ir::FunctionDefinition,
324 span: SourceSpan,
325 ) -> error::SpannedResult<function::InlineFunctionId> {
326 let nested_builder = self.builder.builder();
327 self.scopes.push_scope();
328
329 let mut compiler = FunctionCompiler {
330 builder: nested_builder,
331 scopes: self.scopes,
332 mode_ids: self.mode_ids,
333 };
334
335 for param in &function_definition.params {
336 compiler.scopes.push_name(¶m.name);
337 }
338 compiler.compile_expr(&function_definition.body)?;
339 for _ in &function_definition.params {
340 compiler.scopes.pop_name();
341 }
342
343 compiler.scopes.pop_scope();
344
345 let function = compiler
346 .builder
347 .finish("inline".to_string(), function_definition, span);
348 for name in function.closure_names.iter().rev() {
352 self.compile_variable(name, span)?;
353 }
354 Ok(self.builder.add_function(function))
355 }
356
357 pub(crate) fn compile_function_definition(
358 &mut self,
359 function_definition: &ir::FunctionDefinition,
360 span: SourceSpan,
361 ) -> error::SpannedResult<()> {
362 let function_id = self.compile_function_id(function_definition, span)?;
363 self.builder
364 .emit(Instruction::Closure(function_id.as_u16()), span);
365 Ok(())
366 }
367
368 fn compile_static_function_reference(
369 &mut self,
370 static_function_id: function::StaticFunctionId,
371 context_names: Option<&ir::ContextNames>,
372 span: SourceSpan,
373 ) -> error::SpannedResult<()> {
374 let static_function = self
375 .builder
376 .static_context()
377 .function_by_id(static_function_id);
378 match static_function.function_rule {
379 Some(FunctionRule::ItemFirst) => {
380 let context_names = context_names.ok_or(Error::XPDY0002.with_span(span))?;
381 self.compile_variable(&context_names.item, span)?
382 }
383 Some(FunctionRule::ItemLast) => {
384 let context_names = context_names.ok_or(Error::XPDY0002.with_span(span))?;
385 self.compile_variable(&context_names.item, span)?
386 }
387 Some(FunctionRule::ItemLastOptional) => {
388 if let Some(context_names) = context_names {
389 self.compile_variable(&context_names.item, span)?;
390 } else {
391 self.builder
392 .emit_constant(sequence::Sequence::default(), span);
393 }
394 }
395 Some(FunctionRule::PositionFirst) => self.compile_variable(
396 {
397 let context_names = context_names.ok_or(Error::XPDY0002.with_span(span))?;
398 &context_names.position
399 },
400 span,
401 )?,
402 Some(FunctionRule::SizeFirst) => {
403 let context_names = context_names.ok_or(Error::XPDY0002.with_span(span))?;
404 self.compile_variable(&context_names.last, span)?
405 }
406 Some(FunctionRule::Collation) | None => {}
407 }
408 self.builder.emit(
409 Instruction::StaticClosure(static_function_id.as_u16()),
410 span,
411 );
412 Ok(())
413 }
414
415 fn compile_function_call(
416 &mut self,
417 function_call: &ir::FunctionCall,
418 span: SourceSpan,
419 ) -> error::SpannedResult<()> {
420 self.compile_atom(&function_call.atom)?;
421 for arg in &function_call.args {
422 self.compile_atom(arg)?;
423 }
424 self.builder
425 .emit(Instruction::Call(function_call.args.len() as u8), span);
426 Ok(())
427 }
428
429 fn compile_lookup(
430 &mut self,
431 lookup: &ir::Lookup,
432 span: SourceSpan,
433 ) -> error::SpannedResult<()> {
434 self.compile_atom(&lookup.atom)?;
435 self.compile_atom(&lookup.arg_atom)?;
436 self.builder.emit(Instruction::Lookup, span);
437 Ok(())
438 }
439
440 fn compile_wildcard_lookup(
441 &mut self,
442 lookup: &ir::WildcardLookup,
443 span: SourceSpan,
444 ) -> error::SpannedResult<()> {
445 self.compile_atom(&lookup.atom)?;
446 self.builder.emit(Instruction::WildcardLookup, span);
447 Ok(())
448 }
449
450 fn compile_step(&mut self, step: &ir::Step, span: SourceSpan) -> error::SpannedResult<()> {
451 self.compile_atom(&step.context)?;
452 let step_id = self.builder.add_step(step.step.clone());
453 self.builder.emit(Instruction::Step(step_id as u16), span);
454 Ok(())
455 }
456
457 fn compile_deduplicate(
458 &mut self,
459 expr: &ir::ExprS,
460 span: SourceSpan,
461 ) -> error::SpannedResult<()> {
462 self.compile_expr(expr)?;
463 self.builder.emit(Instruction::Deduplicate, span);
464 Ok(())
465 }
466
467 fn compile_cast(&mut self, cast: &ir::Cast, span: SourceSpan) -> error::SpannedResult<()> {
468 self.compile_atom(&cast.atom)?;
469 let cast_type = cast.cast_type();
470 let cast_type_id = self.builder.add_cast_type(cast_type);
471 self.builder
472 .emit(Instruction::Cast(cast_type_id as u16), span);
473 Ok(())
474 }
475
476 fn compile_castable(
477 &mut self,
478 castable: &ir::Castable,
479 span: SourceSpan,
480 ) -> error::SpannedResult<()> {
481 self.compile_atom(&castable.atom)?;
482 let cast_type = castable.cast_type();
483 let cast_type_id = self.builder.add_cast_type(cast_type);
484 self.builder
485 .emit(Instruction::Castable(cast_type_id as u16), span);
486 Ok(())
487 }
488
489 fn compile_instance_of(
490 &mut self,
491 instance_of: &ir::InstanceOf,
492 span: SourceSpan,
493 ) -> error::SpannedResult<()> {
494 self.compile_atom(&instance_of.atom)?;
495 let sequence_type_id = self
496 .builder
497 .add_sequence_type(instance_of.sequence_type.clone());
498 self.builder
499 .emit(Instruction::InstanceOf(sequence_type_id as u16), span);
500 Ok(())
501 }
502
503 fn compile_treat(&mut self, treat: &ir::Treat, span: SourceSpan) -> error::SpannedResult<()> {
504 self.compile_atom(&treat.atom)?;
505 let sequence_type_id = self.builder.add_sequence_type(treat.sequence_type.clone());
506 self.builder
507 .emit(Instruction::Treat(sequence_type_id as u16), span);
508 Ok(())
509 }
510
511 fn compile_map_constructor(
512 &mut self,
513 map_constructor: &ir::MapConstructor,
514 span: SourceSpan,
515 ) -> error::SpannedResult<()> {
516 for (key_atom, value_atom) in map_constructor.members.iter().rev() {
520 self.compile_atom(key_atom)?;
521 self.compile_atom(value_atom)?;
522 }
523 let len: IBig = map_constructor.members.len().into();
525 let len: sequence::Sequence = len.into();
526 self.builder.emit_constant(len, span);
527 self.builder.emit(Instruction::CurlyMap, span);
528 Ok(())
529 }
530
531 fn compile_array_constructor(
532 &mut self,
533 array_constructor: &ir::ArrayConstructor,
534 span: SourceSpan,
535 ) -> error::SpannedResult<()> {
536 match array_constructor {
537 ir::ArrayConstructor::Curly(atom) => {
538 self.compile_curly_array_constructor(atom, span)?;
539 }
540 ir::ArrayConstructor::Square(atoms) => {
541 self.compile_square_array_constructor(atoms, span)?;
542 }
543 }
544 Ok(())
545 }
546
547 fn compile_curly_array_constructor(
548 &mut self,
549 atom: &ir::AtomS,
550 span: SourceSpan,
551 ) -> error::SpannedResult<()> {
552 self.compile_atom(atom)?;
553 self.builder.emit(Instruction::CurlyArray, span);
554 Ok(())
555 }
556
557 fn compile_square_array_constructor(
558 &mut self,
559 atoms: &[ir::AtomS],
560 span: SourceSpan,
561 ) -> error::SpannedResult<()> {
562 for atom in atoms.iter().rev() {
565 self.compile_atom(atom)?;
566 }
567 let len: IBig = atoms.len().into();
569 let len: sequence::Sequence = len.into();
570 self.builder.emit_constant(len, span);
571 self.builder.emit(Instruction::SquareArray, span);
572 Ok(())
573 }
574
575 fn compile_map(&mut self, map: &ir::Map, span: SourceSpan) -> error::SpannedResult<()> {
576 self.builder.emit(Instruction::BuildNew, span);
578
579 let (loop_start, loop_end) =
580 self.compile_sequence_loop_init(&map.var_atom, &map.context_names, span)?;
581
582 self.compile_sequence_get_item(&map.var_atom, &map.context_names, span)?;
583 self.scopes.push_name(&map.context_names.item);
585 self.compile_expr(&map.return_expr)?;
587 self.scopes.pop_name();
588
589 self.builder.emit(Instruction::BuildPush, span);
591
592 self.builder.emit(Instruction::Pop, span);
594
595 self.compile_sequence_loop_iterate(loop_start, &map.context_names, span)?;
596
597 self.builder.patch_jump(loop_end);
598 self.compile_sequence_loop_end(span);
599
600 self.builder.emit(Instruction::BuildComplete, span);
601 self.scopes.pop_name();
603 self.scopes.pop_name();
604 Ok(())
605 }
606
607 fn compile_filter(
608 &mut self,
609 filter: &ir::Filter,
610 span: SourceSpan,
611 ) -> error::SpannedResult<()> {
612 self.builder.emit(Instruction::BuildNew, span);
614
615 let (loop_start, loop_end) =
616 self.compile_sequence_loop_init(&filter.var_atom, &filter.context_names, span)?;
617
618 self.compile_sequence_get_item(&filter.var_atom, &filter.context_names, span)?;
620 self.scopes.push_name(&filter.context_names.item);
622 self.compile_expr(&filter.return_expr)?;
624 self.scopes.pop_name();
625 self.builder.emit(Instruction::Dup, span);
627 self.builder.emit(Instruction::IsNumeric, span);
629 let is_not_numeric = self.builder.emit_jump_forward(JumpCondition::False, span);
632 self.compile_variable(&filter.context_names.position, span)?;
634 self.builder.emit(Instruction::Eq, span);
635 self.builder.patch_jump(is_not_numeric);
640 let is_included = self.builder.emit_jump_forward(JumpCondition::True, span);
641 self.builder.emit(Instruction::Pop, span);
643 let iterate = self.builder.emit_jump_forward(JumpCondition::Always, span);
645
646 self.builder.patch_jump(is_included);
647 self.builder.emit(Instruction::BuildPush, span);
649
650 self.builder.patch_jump(iterate);
651 self.compile_sequence_loop_iterate(loop_start, &filter.context_names, span)?;
653
654 self.builder.patch_jump(loop_end);
655 self.compile_sequence_loop_end(span);
656
657 self.builder.emit(Instruction::BuildComplete, span);
658 self.scopes.pop_name();
660 self.scopes.pop_name();
661 Ok(())
662 }
663
664 fn compile_quantified(
665 &mut self,
666 quantified: &ir::Quantified,
667 span: SourceSpan,
668 ) -> error::SpannedResult<()> {
669 let (loop_start, loop_end) =
670 self.compile_sequence_loop_init(&quantified.var_atom, &quantified.context_names, span)?;
671
672 self.compile_sequence_get_item(&quantified.var_atom, &quantified.context_names, span)?;
673 self.scopes.push_name(&quantified.context_names.item);
675 self.compile_expr(&quantified.satisifies_expr)?;
677 self.scopes.pop_name();
678
679 let jump_out_end = match quantified.quantifier {
680 ir::Quantifier::Some => self.builder.emit_jump_forward(JumpCondition::True, span),
681 ir::Quantifier::Every => self.builder.emit_jump_forward(JumpCondition::False, span),
682 };
683 self.builder.emit(Instruction::Pop, span);
685
686 self.compile_sequence_loop_iterate(loop_start, &quantified.context_names, span)?;
687
688 self.builder.patch_jump(loop_end);
689
690 self.compile_sequence_loop_end(span);
692
693 let reached_end_value = match quantified.quantifier {
694 ir::Quantifier::Some => false.into(),
695 ir::Quantifier::Every => true.into(),
696 };
697 self.builder.emit_constant(reached_end_value, span);
698 let end = self.builder.emit_jump_forward(JumpCondition::Always, span);
699
700 self.builder.patch_jump(jump_out_end);
702 self.builder.emit(Instruction::Pop, span);
704 self.compile_sequence_loop_end(span);
705
706 let jumped_out_value = match quantified.quantifier {
707 ir::Quantifier::Some => true.into(),
708 ir::Quantifier::Every => false.into(),
709 };
710 self.builder.emit_constant(jumped_out_value, span);
712
713 self.builder.patch_jump(end);
714 self.scopes.pop_name();
716 self.scopes.pop_name();
717 Ok(())
718 }
719
720 fn compile_sequence_loop_init(
721 &mut self,
722 atom: &ir::AtomS,
723 context_names: &ir::ContextNames,
724 span: SourceSpan,
725 ) -> error::SpannedResult<(BackwardJumpRef, ForwardJumpRef)> {
726 self.compile_atom(atom)?;
728 self.scopes.push_name(&context_names.last);
729 self.builder.emit(Instruction::SequenceLen, span);
730
731 self.builder.emit_constant(ibig!(1).into(), span);
733 self.scopes.push_name(&context_names.position);
734
735 let loop_start_ref = self.builder.loop_start();
736
737 self.compile_variable(&context_names.position, span)?;
739 self.compile_variable(&context_names.last, span)?;
740 self.builder.emit(Instruction::Gt, span);
741 let loop_end_ref = self.builder.emit_jump_forward(JumpCondition::True, span);
743
744 Ok((loop_start_ref, loop_end_ref))
745 }
746
747 fn compile_sequence_get_item(
748 &mut self,
749 atom: &ir::AtomS,
750 context_names: &ir::ContextNames,
751 span: SourceSpan,
752 ) -> error::SpannedResult<()> {
753 self.compile_variable(&context_names.position, span)?;
755 self.compile_atom(atom)?;
756 self.builder.emit(Instruction::SequenceGet, span);
757 Ok(())
758 }
759
760 fn compile_sequence_loop_iterate(
761 &mut self,
762 loop_start: BackwardJumpRef,
763 context_names: &ir::ContextNames,
764 span: SourceSpan,
765 ) -> error::SpannedResult<()> {
766 self.compile_variable(&context_names.position, span)?;
768 self.builder.emit_constant(ibig!(1).into(), span);
769 self.builder.emit(Instruction::Add, span);
770 self.compile_variable_set(&context_names.position, span)?;
771 self.builder
772 .emit_jump_backward(loop_start, JumpCondition::Always, span);
773 Ok(())
774 }
775
776 fn compile_sequence_loop_end(&mut self, span: SourceSpan) {
777 self.builder.emit(Instruction::Pop, span);
779 self.builder.emit(Instruction::Pop, span);
780 }
781
782 fn compile_xml_name(
783 &mut self,
784 xml_name: &ir::XmlName,
785 span: SourceSpan,
786 ) -> error::SpannedResult<()> {
787 self.compile_atom(&xml_name.namespace)?;
788 self.compile_atom(&xml_name.local_name)?;
789 self.builder.emit(Instruction::XmlName, span);
790 Ok(())
791 }
792
793 fn compile_xml_document(
794 &mut self,
795 _root: &ir::XmlRoot,
796 span: SourceSpan,
797 ) -> error::SpannedResult<()> {
798 self.builder.emit(Instruction::XmlDocument, span);
799 Ok(())
800 }
801
802 fn compile_xml_element(
803 &mut self,
804 element: &ir::XmlElement,
805 span: SourceSpan,
806 ) -> error::SpannedResult<()> {
807 self.compile_atom(&element.name)?;
808 self.builder.emit(Instruction::XmlElement, span);
809 Ok(())
810 }
811
812 fn compile_xml_attribute(
813 &mut self,
814 attribute: &ir::XmlAttribute,
815 span: SourceSpan,
816 ) -> error::SpannedResult<()> {
817 self.compile_atom(&attribute.name)?;
818 self.compile_atom(&attribute.value)?;
819 self.builder.emit(Instruction::XmlAttribute, span);
820 Ok(())
821 }
822
823 fn compile_xml_namespace(
824 &mut self,
825 prefix: &ir::XmlNamespace,
826 span: SourceSpan,
827 ) -> error::SpannedResult<()> {
828 self.compile_atom(&prefix.prefix)?;
829 self.compile_atom(&prefix.namespace)?;
830 self.builder.emit(Instruction::XmlNamespace, span);
831 Ok(())
832 }
833
834 fn compile_xml_text(
835 &mut self,
836 text: &ir::XmlText,
837 span: SourceSpan,
838 ) -> error::SpannedResult<()> {
839 self.compile_atom(&text.value)?;
841 self.builder.emit(Instruction::XmlText, span);
842 Ok(())
843 }
844
845 fn compile_xml_append(
846 &mut self,
847 append: &ir::XmlAppend,
848 span: SourceSpan,
849 ) -> error::SpannedResult<()> {
850 self.compile_atom(&append.parent)?;
851 self.compile_atom(&append.child)?;
852 self.builder.emit(Instruction::XmlAppend, span);
853 Ok(())
854 }
855
856 fn compile_xml_comment(
857 &mut self,
858 comment: &ir::XmlComment,
859 span: SourceSpan,
860 ) -> error::SpannedResult<()> {
861 self.compile_atom(&comment.value)?;
862 self.builder.emit(Instruction::XmlComment, span);
863 Ok(())
864 }
865
866 fn compile_xml_processing_instruction(
867 &mut self,
868 processing_instruction: &ir::XmlProcessingInstruction,
869 span: SourceSpan,
870 ) -> error::SpannedResult<()> {
871 self.compile_atom(&processing_instruction.target)?;
872 self.compile_atom(&processing_instruction.content)?;
873 self.builder
874 .emit(Instruction::XmlProcessingInstruction, span);
875 Ok(())
876 }
877
878 fn compile_apply_templates(
879 &mut self,
880 apply_templates: &ir::ApplyTemplates,
881 span: SourceSpan,
882 ) -> error::SpannedResult<()> {
883 self.compile_atom(&apply_templates.select)?;
884
885 let mode_id = if matches!(
886 apply_templates.mode,
887 ir::ApplyTemplatesModeValue::Named(_) | ir::ApplyTemplatesModeValue::Unnamed
888 ) {
889 self.mode_ids.get(&apply_templates.mode)
890 } else {
891 todo!("#current mode not handled yet")
892 };
893 if let Some(mode_id) = mode_id {
894 self.builder
895 .emit(Instruction::ApplyTemplates(mode_id.get() as u16), span);
896 } else {
897 self.builder
900 .emit_constant(sequence::Sequence::default(), span);
901 }
902 Ok(())
903 }
904
905 fn compile_copy_shallow(
906 &mut self,
907 copy_shallow: &ir::CopyShallow,
908 span: SourceSpan,
909 ) -> error::SpannedResult<()> {
910 self.compile_atom(©_shallow.select)?;
911 self.builder.emit(Instruction::CopyShallow, span);
912 Ok(())
913 }
914
915 fn compile_copy_deep(
916 &mut self,
917 copy_deep: &ir::CopyDeep,
918 span: SourceSpan,
919 ) -> error::SpannedResult<()> {
920 self.compile_atom(©_deep.select)?;
921 self.builder.emit(Instruction::CopyDeep, span);
922 Ok(())
923 }
924
925 fn compile_pattern_predicate(
926 &mut self,
927 predicate: &ir::PatternPredicate,
928 span: SourceSpan,
929 ) -> error::SpannedResult<()> {
930 self.compile_expr(&predicate.expr)?;
932 self.builder.emit(Instruction::Dup, span);
934 self.builder.emit(Instruction::IsNumeric, span);
936 let is_not_numeric = self.builder.emit_jump_forward(JumpCondition::False, span);
939 self.compile_variable(&predicate.context_names.position, span)?;
941 self.builder.emit(Instruction::Eq, span);
942 self.builder.patch_jump(is_not_numeric);
943 Ok(())
944 }
945}