1use xee_interpreter::{context, error, error::Error, function, xml};
2use xee_ir::{ir, ir::AtomS, Binding, Bindings, Variables};
3use xee_schema_type::Xs;
4use xee_xpath_ast::{ast, ast::Span, span::Spanned, FN_NAMESPACE};
5use xot::xmlname::NameStrInfo;
6
7#[derive(Debug)]
8pub struct IrConverter<'a> {
9 variables: &'a mut Variables,
10 static_context: &'a context::StaticContext,
11 fn_position: ast::Name,
12 fn_last: ast::Name,
13}
14
15impl<'a> IrConverter<'a> {
16 pub fn new(variables: &'a mut Variables, static_context: &'a context::StaticContext) -> Self {
17 Self {
18 variables,
19 static_context,
20 fn_position: ast::Name::new(
21 "position".to_string(),
22 FN_NAMESPACE.to_string(),
23 String::new(),
24 ),
25 fn_last: ast::Name::new("last".to_string(), FN_NAMESPACE.to_string(), String::new()),
26 }
27 }
28
29 #[cfg(test)]
30 fn convert_expr_single(&mut self, ast: &ast::ExprSingleS) -> error::SpannedResult<ir::ExprS> {
31 let bindings = self.expr_single(ast)?;
32 Ok(bindings.expr())
33 }
34
35 pub(crate) fn convert_xpath(&mut self, ast: &ast::XPath) -> error::SpannedResult<ir::ExprS> {
36 let bindings = self.xpath(ast)?;
37 Ok(bindings.expr())
38 }
39
40 pub fn xpath(&mut self, ast: &ast::XPath) -> error::SpannedResult<Bindings> {
41 let context_names = self.variables.push_context();
42 let mut ir_names = Vec::new();
44 for name in self.static_context.variable_names() {
45 ir_names.push(self.variables.new_var_name(name));
46 }
47 let exprs_bindings = self.expr(&ast.0)?;
48 self.variables.pop_context();
49 let mut params = vec![
50 ir::Param {
51 name: context_names.item,
52 type_: None,
53 },
54 ir::Param {
55 name: context_names.position,
56 type_: None,
57 },
58 ir::Param {
59 name: context_names.last,
60 type_: None,
61 },
62 ];
63 for ir_name in ir_names {
65 params.push(ir::Param {
66 name: ir_name,
67 type_: None,
68 });
69 }
70 let outer_function_expr = ir::Expr::FunctionDefinition(ir::FunctionDefinition {
71 params,
72 return_type: None,
73 body: Box::new(exprs_bindings.expr()),
74 });
75 let binding = self.variables.new_binding(outer_function_expr, ast.0.span);
76 Ok(Bindings::new(binding))
77 }
78
79 fn expr_single(&mut self, ast: &ast::ExprSingleS) -> error::SpannedResult<Bindings> {
80 let outer_ast = &ast.value;
81 let span = ast.span;
82 match outer_ast {
83 ast::ExprSingle::Path(ast) => self.path_expr(ast),
84 ast::ExprSingle::Apply(ast) => self.apply_expr(ast, span),
85 ast::ExprSingle::Let(ast) => self.let_expr(ast, span),
86 ast::ExprSingle::If(ast) => self.if_expr(ast, span),
87 ast::ExprSingle::Binary(ast) => self.binary_expr(ast, span),
88 ast::ExprSingle::For(ast) => self.for_expr(ast, span),
89 ast::ExprSingle::Quantified(ast) => self.quantified_expr(ast, span),
90 }
91 }
92
93 fn path_expr(&mut self, ast: &ast::PathExpr) -> error::SpannedResult<Bindings> {
94 let first_step = &ast.steps[0];
95 let rest_steps = &ast.steps[1..];
96 let first_step_bindings = Ok(self.step_expr(first_step)?);
97 rest_steps
98 .iter()
99 .fold(first_step_bindings, |acc, step_expr| {
100 let mut step_bindings = acc?;
101 let step_atom = step_bindings.atom();
102 let context_names = self.variables.push_context();
103 let return_bindings = self.step_expr(step_expr)?;
104 self.variables.pop_context();
105 let expr = ir::Expr::Map(ir::Map {
106 context_names,
107 var_atom: step_atom,
108 return_expr: Box::new(return_bindings.expr()),
109 });
110 let deduplicate_expr =
112 ir::Expr::Deduplicate(Box::new(Spanned::new(expr, step_expr.span)));
113
114 let binding = self.variables.new_binding(deduplicate_expr, step_expr.span);
115 Ok(step_bindings.bind(binding))
116 })
117 }
118
119 fn step_expr(&mut self, ast: &ast::StepExprS) -> error::SpannedResult<Bindings> {
120 let outer_ast = &ast.value;
121 let span = ast.span;
122 match outer_ast {
123 ast::StepExpr::PrimaryExpr(ast) => self.primary_expr(ast),
124 ast::StepExpr::PostfixExpr { primary, postfixes } => self.postfixes(primary, postfixes),
125 ast::StepExpr::AxisStep(ast) => self.axis_step(ast, span),
126 }
127 }
128
129 fn primary_expr(&mut self, ast: &ast::PrimaryExprS) -> error::SpannedResult<Bindings> {
130 let outer_ast = &ast.value;
131 let span = ast.span;
132 match outer_ast {
133 ast::PrimaryExpr::Literal(ast) => Ok(self.literal(ast, span)?),
134 ast::PrimaryExpr::VarRef(ast) => self.variables.var_ref(ast, span),
135 ast::PrimaryExpr::Expr(expr) => self.expr_or_empty(expr),
136 ast::PrimaryExpr::ContextItem => self.variables.context_item(span),
137 ast::PrimaryExpr::InlineFunction(ast) => self.inline_function(ast, span),
138 ast::PrimaryExpr::FunctionCall(ast) => self.function_call(ast, span),
139 ast::PrimaryExpr::NamedFunctionRef(ast) => self.named_function_ref(ast, span),
140 ast::PrimaryExpr::MapConstructor(ast) => self.map_constructor(ast, span),
141 ast::PrimaryExpr::ArrayConstructor(ast) => self.array_constructor(ast, span),
142 ast::PrimaryExpr::UnaryLookup(ast) => self.unary_lookup(ast, span),
143 }
144 }
145
146 fn postfixes(
147 &mut self,
148 primary: &ast::PrimaryExprS,
149 postfixes: &[ast::Postfix],
150 ) -> error::SpannedResult<Bindings> {
151 let primary_bindings = self.primary_expr(primary);
152 postfixes.iter().fold(primary_bindings, |acc, postfix| {
153 let mut bindings = acc?;
154 match postfix {
155 ast::Postfix::Predicate(exprs) => {
156 let atom = bindings.atom();
157 let context_names = self.variables.push_context();
158 let return_bindings = self.expr(exprs)?;
159 self.variables.pop_context();
160 let expr = ir::Expr::Filter(ir::Filter {
161 context_names,
162 var_atom: atom,
163 return_expr: Box::new(return_bindings.expr()),
164 });
165 let binding = self.variables.new_binding(expr, exprs.span);
167 Ok(bindings.bind(binding))
168 }
169 ast::Postfix::ArgumentList(exprs) => {
170 let atom = bindings.atom();
171 let (arg_bindings, atoms) = self.args(exprs)?;
172 let expr = ir::Expr::FunctionCall(ir::FunctionCall { atom, args: atoms });
173 let empty_span = (0..0).into();
175 let binding = self.variables.new_binding(expr, empty_span);
176 Ok(bindings.concat(arg_bindings).bind(binding))
177 }
178 ast::Postfix::Lookup(key_specifier) => {
179 self.postfix_lookup(key_specifier, &mut bindings)
180 }
181 }
182 })
183 }
184
185 fn postfix_lookup(
186 &mut self,
187 key_specifier: &ast::KeySpecifier,
188 bindings: &mut Bindings,
189 ) -> error::SpannedResult<Bindings> {
190 let span = (0..0).into();
191
192 let var_atom = bindings.atom();
194
195 let name = self.variables.new_name();
197 let mut bindings = bindings.bind(Binding::new(
199 name.clone(),
200 ir::Expr::Atom(Spanned::new(ir::Atom::Variable(name.clone()), span)),
201 span,
202 ));
203
204 let atom = bindings.atom();
205
206 let return_bindings = match key_specifier {
207 ast::KeySpecifier::NcName(ncname) => {
208 let arg_atom =
209 Spanned::new(ir::Atom::Const(ir::Const::String(ncname.clone())), span);
210 let arg_bindings = self.atom(arg_atom, span);
211 let mut bindings = bindings.concat(arg_bindings);
212 let arg_atom = bindings.atom();
213 let expr = ir::Expr::Lookup(ir::Lookup { atom, arg_atom });
214 let binding = self.variables.new_binding(expr, span);
215 bindings.bind(binding)
216 }
217 ast::KeySpecifier::Integer(integer) => {
218 let arg_atom =
219 Spanned::new(ir::Atom::Const(ir::Const::Integer(integer.clone())), span);
220 let arg_bindings = self.atom(arg_atom, span);
221 let mut bindings = bindings.concat(arg_bindings);
222 let arg_atom = bindings.atom();
223 let expr = ir::Expr::Lookup(ir::Lookup { atom, arg_atom });
224 let binding = self.variables.new_binding(expr, span);
225 bindings.bind(binding)
226 }
227 ast::KeySpecifier::Expr(expr) => {
228 let arg_bindings = self.expr_or_empty(expr)?;
229 let mut bindings = bindings.concat(arg_bindings);
230 let arg_atom = bindings.atom();
231 let expr = ir::Expr::Lookup(ir::Lookup { atom, arg_atom });
232 let binding = self.variables.new_binding(expr, span);
233 bindings.bind(binding)
234 }
235 ast::KeySpecifier::Star => {
236 let expr = ir::Expr::WildcardLookup(ir::WildcardLookup { atom });
237 let binding = self.variables.new_binding(expr, span);
238 bindings.bind(binding)
239 }
240 };
241 let context_names = self.variables.explicit_context_names(name);
243 let expr = ir::Expr::Map(ir::Map {
244 context_names,
245 var_atom,
246 return_expr: Box::new(return_bindings.expr()),
247 });
248 let binding = self.variables.new_binding(expr, span);
249 Ok(bindings.bind(binding))
250 }
251
252 fn axis_step(&mut self, ast: &ast::AxisStep, span: Span) -> error::SpannedResult<Bindings> {
253 let mut current_context_bindings = self.variables.context_item(span)?;
255
256 if matches!(ast.axis, ast::Axis::Namespace) {
257 return Err(Error::XPST0010.with_ast_span(span));
258 }
259
260 let step = xml::Step {
261 axis: ast.axis.clone(),
262 node_test: ast.node_test.clone(),
263 };
264
265 let expr = ir::Expr::Step(ir::Step {
267 step,
268 context: current_context_bindings.atom(),
269 });
270
271 let binding = self.variables.new_binding(expr, span);
273
274 let bindings = Ok(Bindings::new(binding));
275
276 ast.predicates.iter().fold(bindings, |acc, predicate| {
278 let mut bindings = acc?;
279 let atom = bindings.atom();
280 let context_names = self.variables.push_context();
281 let return_bindings = self.expr(predicate)?;
282 self.variables.pop_context();
283 let expr = ir::Expr::Filter(ir::Filter {
284 context_names,
285 var_atom: atom,
286 return_expr: Box::new(return_bindings.expr()),
287 });
288 let binding = self.variables.new_binding(expr, predicate.span);
289 Ok(bindings.bind(binding))
290 })
291 }
292
293 fn literal(&mut self, ast: &ast::Literal, span: Span) -> error::SpannedResult<Bindings> {
294 let atom = match ast {
295 ast::Literal::Integer(i) => ir::Atom::Const(ir::Const::Integer(i.clone())),
296 ast::Literal::String(s) => ir::Atom::Const(ir::Const::String(s.clone())),
297 ast::Literal::Double(d) => ir::Atom::Const(ir::Const::Double(*d)),
298 ast::Literal::Decimal(d) => ir::Atom::Const(ir::Const::Decimal(*d)),
299 };
300 let expr = ir::Expr::Atom(Spanned::new(atom, span));
301 let binding = self.variables.new_binding(expr, span);
302 Ok(Bindings::new(binding))
303 }
304
305 pub fn expr(&mut self, expr: &ast::ExprS) -> error::SpannedResult<Bindings> {
306 self.expr_with_span(&expr.value, expr.span)
307 }
308
309 fn expr_with_span(&mut self, expr: &ast::Expr, span: Span) -> error::SpannedResult<Bindings> {
310 let expr = &expr.0;
311
312 let first_expr = &expr[0];
314 let span_start = span.start;
315 let rest_exprs = &expr[1..];
316 rest_exprs
317 .iter()
318 .fold(self.expr_single(first_expr), |acc, expr_single| {
319 let mut left_bindings = acc?;
320 let mut right_bindings = self.expr_single(expr_single)?;
321 let expr = ir::Expr::Binary(ir::Binary {
322 left: left_bindings.atom(),
323 op: ir::BinaryOperator::Comma,
324 right: right_bindings.atom(),
325 });
326 let span_end = expr_single.span.end;
327 let span = (span_start..span_end).into();
328 let binding = self.variables.new_binding(expr, span);
329 Ok(left_bindings.concat(right_bindings).bind(binding))
330 })
331 }
332
333 fn expr_or_empty(&mut self, expr: &ast::ExprOrEmptyS) -> error::SpannedResult<Bindings> {
334 let span = expr.span;
335 if let Some(expr) = &expr.value {
336 self.expr_with_span(expr, span)
337 } else {
338 let expr = ir::Expr::Atom(Spanned::new(
339 ir::Atom::Const(ir::Const::EmptySequence),
340 span,
341 ));
342 let binding = self.variables.new_binding(expr, span);
343 Ok(Bindings::new(binding))
344 }
345 }
346
347 fn binary_expr(&mut self, ast: &ast::BinaryExpr, span: Span) -> error::SpannedResult<Bindings> {
348 let mut left_bindings = self.path_expr(&ast.left)?;
349 let mut right_bindings = self.path_expr(&ast.right)?;
350 let op = self.binary_op(ast.operator);
351 let expr = ir::Expr::Binary(ir::Binary {
352 left: left_bindings.atom(),
353 op,
354 right: right_bindings.atom(),
355 });
356 let binding = self.variables.new_binding(expr, span);
357
358 Ok(left_bindings.concat(right_bindings).bind(binding))
359 }
360
361 fn binary_op(&mut self, operator: ast::BinaryOperator) -> ir::BinaryOperator {
362 operator
363 }
364
365 fn apply_expr(&mut self, ast: &ast::ApplyExpr, span: Span) -> error::SpannedResult<Bindings> {
366 match &ast.operator {
367 ast::ApplyOperator::SimpleMap(path_exprs) => {
368 let path_bindings = self.path_expr(&ast.path_expr);
369 path_exprs.iter().fold(path_bindings, |acc, path_expr| {
370 let mut path_bindings = acc?;
371 let path_atom = path_bindings.atom();
372 let context_names = self.variables.push_context();
373 let return_bindings = self.path_expr(path_expr)?;
374 self.variables.pop_context();
375 let expr = ir::Expr::Map(ir::Map {
376 context_names,
377 var_atom: path_atom,
378 return_expr: Box::new(return_bindings.expr()),
379 });
380 let binding = self.variables.new_binding(expr, span);
381 Ok(path_bindings.bind(binding))
382 })
383 }
384 ast::ApplyOperator::Unary(ops) => {
385 let bindings = self.path_expr(&ast.path_expr);
386 ops.iter().rev().fold(bindings, |acc, op| {
387 let mut bindings = acc?;
388 let expr = ir::Expr::Unary(ir::Unary {
389 op: op.clone(),
390 atom: bindings.atom(),
391 });
392 let binding = self.variables.new_binding(expr, span);
393 Ok(bindings.bind(binding))
394 })
395 }
396 ast::ApplyOperator::Cast(single_type) => {
397 let xs = Xs::by_name(
398 single_type.name.value.namespace(),
399 single_type.name.value.local_name(),
400 );
401 if let Some(xs) = xs {
402 if !xs.derives_from(Xs::AnySimpleType) {
403 return Err(Error::XQST0052.with_ast_span(span));
404 }
405 if xs == Xs::Notation || xs == Xs::AnySimpleType || xs == Xs::AnyAtomicType {
406 return Err(Error::XPST0080.with_ast_span(span));
407 }
408 let mut bindings = self.path_expr(&ast.path_expr)?;
409 let expr = ir::Expr::Cast(ir::Cast {
410 atom: bindings.atom(),
411 xs,
412 empty_sequence_allowed: single_type.optional,
413 });
414 let binding = self.variables.new_binding(expr, span);
415 Ok(bindings.bind(binding))
416 } else {
417 Err(Error::XQST0052.with_ast_span(span))
418 }
419 }
420 ast::ApplyOperator::Castable(single_type) => {
421 let xs = Xs::by_name(
422 single_type.name.value.namespace(),
423 single_type.name.value.local_name(),
424 );
425 if let Some(xs) = xs {
426 if !xs.derives_from(Xs::AnySimpleType) {
427 return Err(Error::XQST0052.with_ast_span(span));
428 }
429 if xs == Xs::Notation || xs == Xs::AnySimpleType || xs == Xs::AnyAtomicType {
430 return Err(Error::XPST0080.with_ast_span(span));
431 }
432 let mut bindings = self.path_expr(&ast.path_expr)?;
433 let expr = ir::Expr::Castable(ir::Castable {
434 atom: bindings.atom(),
435 xs,
436 empty_sequence_allowed: single_type.optional,
437 });
438 let binding = self.variables.new_binding(expr, span);
439 Ok(bindings.bind(binding))
440 } else {
441 Err(Error::XQST0052.with_ast_span(span))
442 }
443 }
444 ast::ApplyOperator::InstanceOf(sequence_type) => {
445 let mut bindings = self.path_expr(&ast.path_expr)?;
446 let expr = ir::Expr::InstanceOf(ir::InstanceOf {
447 atom: bindings.atom(),
448 sequence_type: sequence_type.clone(),
449 });
450 let binding = self.variables.new_binding(expr, span);
451 Ok(bindings.bind(binding))
452 }
453 ast::ApplyOperator::Treat(sequence_type) => {
454 let mut bindings = self.path_expr(&ast.path_expr)?;
455 let expr = ir::Expr::Treat(ir::Treat {
456 atom: bindings.atom(),
457 sequence_type: sequence_type.clone(),
458 });
459 let binding = self.variables.new_binding(expr, span);
460 Ok(bindings.bind(binding))
461 }
462 }
463 }
464
465 fn if_expr(&mut self, ast: &ast::IfExpr, span: Span) -> error::SpannedResult<Bindings> {
466 let mut condition_bindings = self.expr(&ast.condition)?;
467 let then_bindings = self.expr_single(&ast.then)?;
468 let else_bindings = self.expr_single(&ast.else_)?;
469 let expr = ir::Expr::If(ir::If {
470 condition: condition_bindings.atom(),
471 then: Box::new(then_bindings.expr()),
472 else_: Box::new(else_bindings.expr()),
473 });
474 let binding = self.variables.new_binding(expr, span);
475 Ok(condition_bindings.bind(binding))
476 }
477
478 fn let_expr(&mut self, ast: &ast::LetExpr, span: Span) -> error::SpannedResult<Bindings> {
479 let name = self.variables.new_var_name(&ast.var_name.value);
480 let var_bindings = self.expr_single(&ast.var_expr)?;
481 let return_bindings = self.expr_single(&ast.return_expr)?;
482 let expr = ir::Expr::Let(ir::Let {
483 name,
484 var_expr: Box::new(var_bindings.expr()),
485 return_expr: Box::new(return_bindings.expr()),
486 });
487 Ok(Bindings::new(self.variables.new_binding(expr, span)))
488 }
489
490 fn for_expr(&mut self, ast: &ast::ForExpr, span: Span) -> error::SpannedResult<Bindings> {
491 let name = self.variables.new_var_name(&ast.var_name.value);
492 let mut var_bindings = self.expr_single(&ast.var_expr)?;
493 let var_atom = var_bindings.atom();
494 let context_names = self.variables.explicit_context_names(name);
495 let return_bindings = self.expr_single(&ast.return_expr)?;
496 let expr = ir::Expr::Map(ir::Map {
497 context_names,
498 var_atom,
499 return_expr: Box::new(return_bindings.expr()),
500 });
501
502 let binding = self.variables.new_binding(expr, span);
503 Ok(var_bindings.bind(binding))
504 }
505
506 fn quantified_expr(
507 &mut self,
508 ast: &ast::QuantifiedExpr,
509 span: Span,
510 ) -> error::SpannedResult<Bindings> {
511 let name = self.variables.new_var_name(&ast.var_name.value);
512 let mut var_bindings = self.expr_single(&ast.var_expr)?;
513 let var_atom = var_bindings.atom();
514
515 let context_names = self.variables.explicit_context_names(name);
516 let satisfies_bindings = self.expr_single(&ast.satisfies_expr)?;
517 let expr = ir::Expr::Quantified(ir::Quantified {
518 quantifier: self.quantifier(&ast.quantifier),
519 context_names,
520 var_atom,
521 satisifies_expr: Box::new(satisfies_bindings.expr()),
522 });
523
524 let binding = self.variables.new_binding(expr, span);
525 Ok(var_bindings.bind(binding))
526 }
527
528 fn quantifier(&mut self, quantifier: &ast::Quantifier) -> ir::Quantifier {
529 match quantifier {
530 ast::Quantifier::Some => ir::Quantifier::Some,
531 ast::Quantifier::Every => ir::Quantifier::Every,
532 }
533 }
534
535 fn inline_function(
536 &mut self,
537 inline_function: &ast::InlineFunction,
538 span: Span,
539 ) -> error::SpannedResult<Bindings> {
540 let params = inline_function
541 .params
542 .iter()
543 .map(|param| self.param(param))
544 .collect();
545 if !inline_function.wrapper {
549 self.variables.push_absent_context();
550 }
551 let body_bindings = self.expr_or_empty(&inline_function.body)?;
552 if !inline_function.wrapper {
553 self.variables.pop_context();
554 }
555 let expr = ir::Expr::FunctionDefinition(ir::FunctionDefinition {
556 params,
557 return_type: inline_function.return_type.clone(),
558 body: Box::new(body_bindings.expr()),
559 });
560 let binding = self.variables.new_binding(expr, span);
561 Ok(Bindings::new(binding))
562 }
563
564 fn param(&mut self, param: &ast::Param) -> ir::Param {
565 ir::Param {
566 name: self.variables.new_var_name(¶m.name),
567 type_: param.type_.clone(),
568 }
569 }
570
571 fn function_call(
572 &mut self,
573 ast: &ast::FunctionCall,
574 span: Span,
575 ) -> error::SpannedResult<Bindings> {
576 let arity = ast.arguments.len();
577 if arity > u8::MAX as usize {
578 return Err(Error::XPDY0130.with_ast_span(span));
579 }
580 if ast.name.value == self.fn_position {
587 if arity != 0 {
588 return Err(Error::XPST0017.with_ast_span(span));
590 }
591 return self.variables.fn_position(span);
592 } else if ast.name.value == self.fn_last {
593 if arity != 0 {
594 return Err(Error::XPST0017.with_ast_span(span));
596 }
597 return self.variables.fn_last(span);
598 }
599
600 let static_function_id = self
602 .static_context
603 .function_id_by_name(&ast.name.value, arity as u8)
604 .ok_or(Error::XPST0017.with_ast_span(span))?;
605 let empty_span = (0..0).into();
607 let mut static_function_ref_bindings =
608 self.static_function_ref(static_function_id, empty_span);
609 let atom = static_function_ref_bindings.atom();
610 let (arg_bindings, atoms) = self.args(&ast.arguments)?;
611 let expr = ir::Expr::FunctionCall(ir::FunctionCall { atom, args: atoms });
612 let binding = self.variables.new_binding(expr, span);
613 Ok(static_function_ref_bindings
614 .concat(arg_bindings)
615 .bind(binding))
616 }
617
618 fn named_function_ref(
619 &mut self,
620 ast: &ast::NamedFunctionRef,
621 span: Span,
622 ) -> error::SpannedResult<Bindings> {
623 let static_function_id = self
625 .static_context
626 .function_id_by_name(&ast.name.value, ast.arity)
627 .ok_or(Error::XPST0017.with_ast_span(span))?;
628 Ok(self.static_function_ref(static_function_id, span))
629 }
630
631 fn static_function_ref(
632 &mut self,
633 static_function_id: function::StaticFunctionId,
634 span: Span,
635 ) -> Bindings {
636 let atom = ir::Atom::Const(ir::Const::StaticFunctionReference(
637 static_function_id,
638 self.variables.current_context_names(),
639 ));
640 let expr = ir::Expr::Atom(Spanned::new(atom, span));
641 let binding = self.variables.new_binding(expr, span);
642 Bindings::new(binding)
643 }
644
645 fn args(&mut self, args: &[ast::ExprSingleS]) -> error::SpannedResult<(Bindings, Vec<AtomS>)> {
646 if args.is_empty() {
647 return Ok((Bindings::empty(), vec![]));
648 }
649 let first = &args[0];
650 let rest = &args[1..];
651 let mut bindings = self.expr_single(first)?;
652 let atoms = vec![bindings.atom()];
653 rest.iter()
654 .try_fold((bindings, atoms), |(bindings, atoms), arg| {
655 let mut arg_bindings = self.expr_single(arg)?;
656 let mut atoms = atoms.clone();
657 atoms.push(arg_bindings.atom());
658 Ok((bindings.concat(arg_bindings), atoms))
659 })
660 }
661
662 fn unary_lookup(
663 &mut self,
664 ast: &ast::KeySpecifier,
665 span: Span,
666 ) -> error::SpannedResult<Bindings> {
667 let mut bindings = self.variables.context_item(span)?;
668 let context_atom = bindings.atom();
669
670 match ast {
671 ast::KeySpecifier::NcName(ncname) => {
672 let arg_atom =
673 Spanned::new(ir::Atom::Const(ir::Const::String(ncname.clone())), span);
674 let arg_bindings = self.atom(arg_atom, span);
675 let mut bindings = bindings.concat(arg_bindings);
676 let arg_atom = bindings.atom();
677 let expr = ir::Expr::Lookup(ir::Lookup {
678 atom: context_atom,
679 arg_atom,
680 });
681 let binding = self.variables.new_binding(expr, span);
682 Ok(bindings.bind(binding))
683 }
684 ast::KeySpecifier::Integer(i) => {
685 let arg_atom = Spanned::new(ir::Atom::Const(ir::Const::Integer(i.clone())), span);
686 let arg_bindings = self.atom(arg_atom, span);
687 let mut bindings = bindings.concat(arg_bindings);
688 let arg_atom = bindings.atom();
689 let expr = ir::Expr::Lookup(ir::Lookup {
690 atom: context_atom,
691 arg_atom,
692 });
693 let binding = self.variables.new_binding(expr, span);
694 Ok(bindings.bind(binding))
695 }
696 ast::KeySpecifier::Expr(expr) => {
697 let arg_bindings = self.expr_or_empty(expr)?;
698 let mut bindings = bindings.concat(arg_bindings);
699 let arg_atom = bindings.atom();
700 let expr = ir::Expr::Lookup(ir::Lookup {
701 atom: context_atom,
702 arg_atom,
703 });
704 let binding = self.variables.new_binding(expr, span);
705 Ok(bindings.bind(binding))
706 }
707 ast::KeySpecifier::Star => {
708 let mut bindings = self.variables.context_item(span)?;
709 let context_atom = bindings.atom();
710 let expr = ir::Expr::WildcardLookup(ir::WildcardLookup { atom: context_atom });
711 let binding = self.variables.new_binding(expr, span);
712 Ok(bindings.bind(binding))
713 }
714 }
715 }
716
717 fn atom(&mut self, atom: AtomS, span: Span) -> Bindings {
718 let expr = ir::Expr::Atom(atom);
719 let binding = self.variables.new_binding(expr, span);
720 Bindings::new(binding)
721 }
722
723 fn map_constructor(
724 &mut self,
725 ast: &ast::MapConstructor,
726 span: Span,
727 ) -> error::SpannedResult<Bindings> {
728 let keys = ast
729 .entries
730 .iter()
731 .map(|entry| entry.key.clone())
732 .collect::<Vec<_>>();
733 let values = ast
734 .entries
735 .iter()
736 .map(|entry| entry.value.clone())
737 .collect::<Vec<_>>();
738 let (key_bindings, key_atoms) = self.args(&keys)?;
739 let (value_bindings, value_atoms) = self.args(&values)?;
740 let members = key_atoms.into_iter().zip(value_atoms).collect::<Vec<_>>();
741 let expr = ir::Expr::MapConstructor(ir::MapConstructor { members });
742 let expr_binding = self.variables.new_binding(expr, span);
743 let bindings = key_bindings.concat(value_bindings).bind(expr_binding);
744 Ok(bindings)
745 }
746
747 fn array_constructor(
748 &mut self,
749 ast: &ast::ArrayConstructor,
750 span: Span,
751 ) -> error::SpannedResult<Bindings> {
752 match ast {
753 ast::ArrayConstructor::Square(expr) => {
754 let (bindings, atoms) = self.args(&expr.value.0)?;
755 let expr = ir::Expr::ArrayConstructor(ir::ArrayConstructor::Square(atoms));
756 let binding = self.variables.new_binding(expr, span);
757 Ok(bindings.bind(binding))
758 }
759 ast::ArrayConstructor::Curly(expr_or_empty) => {
760 let mut bindings = self.expr_or_empty(expr_or_empty)?;
761 let expr = ir::Expr::ArrayConstructor(ir::ArrayConstructor::Curly(bindings.atom()));
762 let binding = self.variables.new_binding(expr, span);
763 Ok(bindings.bind(binding))
764 }
765 }
766 }
767}
768
769#[cfg(test)]
770mod tests {
771 use super::*;
772 use insta::assert_debug_snapshot;
773
774 fn convert_expr_single(s: &str) -> error::SpannedResult<ir::ExprS> {
775 let ast = ast::ExprSingle::parse(s)?;
776 let static_context = context::StaticContext::default();
777 let mut variables = Variables::new();
778 let mut converter = IrConverter::new(&mut variables, &static_context);
779 converter.convert_expr_single(&ast)
780 }
781
782 pub(crate) fn convert_xpath(s: &str) -> error::SpannedResult<ir::ExprS> {
783 let static_context = context::StaticContext::default();
784 let ast = static_context.parse_xpath(s)?;
785 let mut variables = Variables::new();
786 let mut converter = IrConverter::new(&mut variables, &static_context);
787 converter.convert_xpath(&ast)
788 }
789
790 #[test]
791 fn test_integer() {
792 assert_debug_snapshot!(convert_expr_single("1"));
793 }
794
795 #[test]
796 fn test_add() {
797 assert_debug_snapshot!(convert_expr_single("1 + 2"));
798 }
799
800 #[test]
801 fn test_add2() {
802 assert_debug_snapshot!(convert_expr_single("1 + 2 + 3"));
803 }
804
805 #[test]
806 fn test_if() {
807 assert_debug_snapshot!(convert_expr_single("if (1 gt 2) then 1 + 2 else 3 + 4"));
808 }
809
810 #[test]
811 fn test_comma() {
812 assert_debug_snapshot!(convert_xpath("1, 2"));
813 }
814
815 #[test]
816 fn test_comma2() {
817 assert_debug_snapshot!(convert_xpath("1, 2, 3"));
818 }
819
820 #[test]
821 fn test_empty_sequence() {
822 assert_debug_snapshot!(convert_xpath("()"));
823 }
824
825 #[test]
826 fn test_let_expr() {
827 assert_debug_snapshot!(convert_expr_single("let $x := 1 return 2"));
828 }
829
830 #[test]
831 fn test_let_expr_variable() {
832 assert_debug_snapshot!(convert_expr_single("let $x := 1 return $x"));
833 }
834
835 #[test]
836 fn test_let_expr_with_add() {
837 assert_debug_snapshot!(convert_expr_single("let $x := (1 + 2) return $x"));
838 }
839
840 #[test]
841 fn test_for_expr() {
842 assert_debug_snapshot!(convert_expr_single("for $x in 1 return 2"));
843 }
844
845 #[test]
846 fn test_for_expr2() {
847 assert_debug_snapshot!(convert_expr_single("for $x in (1, 2) return $x + 1"));
848 }
849
850 #[test]
851 fn test_simple_map() {
852 assert_debug_snapshot!(convert_expr_single("(1, 2) ! 1"));
853 }
854
855 #[test]
856 fn test_simple_map_with_context() {
857 assert_debug_snapshot!(convert_expr_single("(1, 2) ! (. + 1)"));
858 }
859
860 #[test]
861 fn test_nested_simple_map_with_context() {
862 assert_debug_snapshot!(convert_expr_single("(1, 2) ! (. + 1) ! (. + 2)"));
863 }
864
865 #[test]
866 fn test_quantified() {
867 assert_debug_snapshot!(convert_expr_single("some $x in (1, 2) satisfies $x gt 1"));
868 }
869
870 #[test]
871 fn test_postfix_filter() {
872 assert_debug_snapshot!(convert_expr_single("(1, 2)[. gt 2]"));
873 }
874
875 #[test]
876 fn test_postfix_filter_nested() {
877 assert_debug_snapshot!(convert_expr_single("(1, 2)[. gt 2][. lt 3]"));
878 }
879
880 #[test]
881 fn test_postfix_index() {
882 assert_debug_snapshot!(convert_expr_single("(1, 2)[1]"));
883 }
884
885 #[test]
886 fn test_function_definition() {
887 assert_debug_snapshot!(convert_expr_single("function($x) { $x + 1 }"));
888 }
889
890 #[test]
891 fn test_function_call() {
892 assert_debug_snapshot!(convert_expr_single("function($x) { $x + 1 }(3)"));
893 }
894
895 #[test]
896 fn test_function_call2() {
897 assert_debug_snapshot!(convert_expr_single("function($x) { $x + 1 }(3 + 5)"));
898 }
899
900 #[test]
901 fn test_static_function_call() {
902 assert_debug_snapshot!(convert_expr_single("my_function(5, 2)"));
903 }
904
905 #[test]
906 fn test_static_function_call2() {
907 assert_debug_snapshot!(convert_expr_single("my_function(1 + 2, 3 + 4)"));
908 }
909
910 #[test]
911 fn test_static_function_call3() {
912 assert_debug_snapshot!(convert_expr_single("my_function(1 + 2 + 3, 4 + 5)"));
913 }
914
915 #[test]
916 fn test_named_function_ref() {
917 assert_debug_snapshot!(convert_expr_single("my_function#2"));
918 }
919
920 #[test]
921 fn test_named_function_ref2() {
922 assert_debug_snapshot!(convert_xpath("my_function#2"));
923 }
924
925 #[test]
926 fn test_path_expr() {
927 assert_debug_snapshot!(convert_expr_single("(1, 2) / (. + 1)"));
928 }
929
930 #[test]
931 fn test_nested_path_expr() {
932 assert_debug_snapshot!(convert_expr_single("(1, 2) / (. + 1) / (. + 2)"));
933 }
934
935 #[test]
936 fn test_single_axis_step() {
937 assert_debug_snapshot!(convert_xpath("child::a"));
938 }
939
940 #[test]
941 fn test_multiple_axis_steps() {
942 assert_debug_snapshot!(convert_xpath("child::a/child::b"));
943 }
944
945 #[test]
946 fn test_axis_step_with_predicates() {
947 assert_debug_snapshot!(convert_xpath("child::a[. gt 1]"));
948 }
949
950 #[test]
951 fn test_absent_context_in_function() {
952 assert_debug_snapshot!(convert_xpath("function() { . }"));
953 }
954
955 #[test]
956 fn test_unknown_static_function_name() {
957 assert_debug_snapshot!(convert_expr_single("unknown_function()"));
958 }
959
960 #[test]
961 fn test_wrong_amount_of_arguments() {
962 assert_debug_snapshot!(convert_expr_single("fn:string(1, 2, 3)"));
963 }
964
965 #[test]
966 fn test_unknown_variable_name() {
967 assert_debug_snapshot!(convert_expr_single("$unknown"));
968 }
969
970 #[test]
971 fn test_unknown_named_function_ref() {
972 assert_debug_snapshot!(convert_expr_single("unknown_function#2"));
973 }
974
975 #[test]
976 fn test_unary() {
977 assert_debug_snapshot!(convert_expr_single("-1"));
978 }
979
980 #[test]
981 fn test_unary_plus() {
982 assert_debug_snapshot!(convert_expr_single("+1"));
983 }
984
985 #[test]
986 fn test_unary_combo() {
987 assert_debug_snapshot!(convert_expr_single("-+1"));
988 }
989
990 #[test]
991 fn test_cast() {
992 assert_debug_snapshot!(convert_expr_single("1 cast as xs:string"));
993 }
994
995 #[test]
996 fn test_cast_question_mark() {
997 assert_debug_snapshot!(convert_expr_single("1 cast as xs:string?"));
998 }
999
1000 #[test]
1001 fn test_castable() {
1002 assert_debug_snapshot!(convert_expr_single("1 castable as xs:string"));
1003 }
1004
1005 #[test]
1006 fn test_castable_question_mark() {
1007 assert_debug_snapshot!(convert_expr_single("1 castable as xs:string?"));
1008 }
1009
1010 #[test]
1011 fn test_cast_unknown_schema_type() {
1012 assert_debug_snapshot!(convert_expr_single("1 cast as unknown"));
1013 }
1014
1015 #[test]
1016 fn test_cast_non_simple_schema_type() {
1017 assert_debug_snapshot!(convert_expr_single("1 cast as xs:untyped"));
1018 }
1019
1020 #[test]
1021 fn test_cast_illegal_simple_type() {
1022 assert_debug_snapshot!(convert_expr_single("1 cast as xs:NOTATION"));
1023 }
1024
1025 #[test]
1026 fn test_instance_of_atomic() {
1027 assert_debug_snapshot!(convert_expr_single("1 instance of xs:string"));
1028 }
1029
1030 #[test]
1031 fn test_instance_of_kind_test() {
1032 assert_debug_snapshot!(convert_expr_single("1 instance of node()"));
1033 }
1034
1035 #[test]
1036 fn test_function_call_with_sequence() {
1037 assert_debug_snapshot!(
1038 convert_expr_single(
1039 "compare('a', 'b', ((), 'http://www.w3.org/2005/xpath-functions/collation/codepoint', ()))"));
1040 }
1041
1042 #[test]
1043 fn test_ncname_key_specifier() {
1044 assert_debug_snapshot!(convert_xpath("? foo"));
1045 }
1046
1047 #[test]
1048 fn test_integer_key_specifier() {
1049 assert_debug_snapshot!(convert_xpath("? 1"));
1050 }
1051
1052 #[test]
1053 fn test_postfix_lookup() {
1054 assert_debug_snapshot!(convert_xpath("1 ? foo"));
1055 }
1056}