1use crate::parser::{
8 Expression, Invocation, Literal, SpannedExprKind, SpannedExpression, SpannedInvocation,
9 SpannedTerm, Term, TypeSpecifier,
10};
11use crate::type_inference::{TypeContext, infer_expression_type};
12use serde_json::{Value, json};
13
14pub fn expression_to_debug_tree(expr: &Expression, context: &TypeContext) -> Value {
26 expression_to_debug_tree_inner(expr, context)
27}
28
29fn expression_to_debug_tree_inner(expr: &Expression, context: &TypeContext) -> Value {
30 let return_type = infer_expression_type(expr, context).map(|t| t.to_display_string());
32
33 let mut node = match expr {
34 Expression::Term(term) => term_to_debug_tree(term, context),
35
36 Expression::Invocation(base_expr, invocation) => {
37 let mut inv_node = invocation_to_debug_tree(invocation, context);
40
41 let mut args = inv_node
43 .get("Arguments")
44 .and_then(|a| a.as_array())
45 .cloned()
46 .unwrap_or_default();
47
48 let base_node = expression_to_debug_tree_inner(base_expr, context);
50 args.insert(0, base_node);
51
52 inv_node["Arguments"] = json!(args);
53 inv_node
54 }
55
56 Expression::Indexer(expr, index) => {
57 json!({
58 "ExpressionType": "IndexerExpression",
59 "Name": "[]",
60 "Arguments": vec![
61 expression_to_debug_tree_inner(expr, context),
62 expression_to_debug_tree_inner(index, context)
63 ]
64 })
65 }
66
67 Expression::Polarity(op, expr) => {
68 json!({
69 "ExpressionType": "UnaryExpression",
70 "Name": op.to_string(),
71 "Arguments": vec![expression_to_debug_tree_inner(expr, context)]
72 })
73 }
74
75 Expression::Multiplicative(left, op, right)
76 | Expression::Additive(left, op, right)
77 | Expression::Inequality(left, op, right)
78 | Expression::Equality(left, op, right)
79 | Expression::Membership(left, op, right) => {
80 json!({
81 "ExpressionType": "BinaryExpression",
82 "Name": op,
83 "Arguments": vec![
84 expression_to_debug_tree_inner(left, context),
85 expression_to_debug_tree_inner(right, context)
86 ]
87 })
88 }
89
90 Expression::Type(expr, op, type_spec) => {
91 json!({
92 "ExpressionType": "TypeExpression",
93 "Name": op,
94 "Arguments": vec![
95 expression_to_debug_tree_inner(expr, context),
96 type_specifier_to_debug_tree(type_spec)
97 ]
98 })
99 }
100
101 Expression::Union(left, right) => {
102 json!({
103 "ExpressionType": "BinaryExpression",
104 "Name": "|",
105 "Arguments": vec![
106 expression_to_debug_tree_inner(left, context),
107 expression_to_debug_tree_inner(right, context)
108 ]
109 })
110 }
111
112 Expression::And(left, right) => {
113 json!({
114 "ExpressionType": "BinaryExpression",
115 "Name": "and",
116 "Arguments": vec![
117 expression_to_debug_tree_inner(left, context),
118 expression_to_debug_tree_inner(right, context)
119 ]
120 })
121 }
122
123 Expression::Or(left, op, right) => {
124 json!({
125 "ExpressionType": "BinaryExpression",
126 "Name": op,
127 "Arguments": vec![
128 expression_to_debug_tree_inner(left, context),
129 expression_to_debug_tree_inner(right, context)
130 ]
131 })
132 }
133
134 Expression::Implies(left, right) => {
135 json!({
136 "ExpressionType": "BinaryExpression",
137 "Name": "implies",
138 "Arguments": vec![
139 expression_to_debug_tree_inner(left, context),
140 expression_to_debug_tree_inner(right, context)
141 ]
142 })
143 }
144
145 Expression::Lambda(param, expr) => {
146 let mut node = json!({
147 "ExpressionType": "LambdaExpression",
148 "Name": "=>",
149 "Arguments": vec![expression_to_debug_tree_inner(expr, context)]
150 });
151 if let Some(param_name) = param {
152 node["Parameter"] = json!(param_name);
153 }
154 node
155 }
156 Expression::InstanceSelector(type_name, fields) => {
157 let field_nodes: Vec<Value> = fields
158 .iter()
159 .map(|(name, expr)| {
160 json!({
161 "FieldName": name,
162 "Value": expression_to_debug_tree_inner(expr, context)
163 })
164 })
165 .collect();
166 json!({
167 "ExpressionType": "InstanceSelector",
168 "TypeName": type_name,
169 "Fields": field_nodes
170 })
171 }
172 };
173
174 if let Some(rt) = return_type {
176 node["ReturnType"] = json!(rt);
177 }
178
179 node
180}
181
182fn term_to_debug_tree(term: &Term, context: &TypeContext) -> Value {
183 match term {
184 Term::Literal(lit) => literal_to_debug_tree(lit),
185
186 Term::Invocation(invocation) => {
187 let mut inv_node = invocation_to_debug_tree(invocation, context);
190
191 if matches!(invocation, Invocation::Member(_)) {
193 let that_node = json!({
194 "ExpressionType": "AxisExpression",
195 "Name": "builtin.that",
196 "ReturnType": context.current_type.as_ref()
197 .map(|t| t.to_display_string())
198 .unwrap_or_else(|| "Any".to_string())
199 });
200
201 let mut args = vec![that_node];
202 if let Some(existing_args) = inv_node.get("Arguments").and_then(|a| a.as_array()) {
203 args.extend(existing_args.clone());
204 }
205 inv_node["Arguments"] = json!(args);
206 }
207
208 inv_node
209 }
210
211 Term::ExternalConstant(name) => {
212 let mut node = json!({
213 "ExpressionType": "VariableRefExpression",
214 "Name": name
215 });
216
217 if let Some(var_type) = context.variables.get(name) {
219 node["ReturnType"] = json!(var_type.to_display_string());
220 }
221
222 node
223 }
224
225 Term::Parenthesized(expr) => expression_to_debug_tree_inner(expr, context),
226 }
227}
228
229fn literal_to_debug_tree(literal: &Literal) -> Value {
230 match literal {
231 Literal::Null => {
232 json!({
233 "ExpressionType": "ConstantExpression",
234 "Name": "{}",
235 "ReturnType": "null"
236 })
237 }
238
239 Literal::Boolean(b) => {
240 json!({
241 "ExpressionType": "ConstantExpression",
242 "Name": b.to_string(),
243 "ReturnType": "system.Boolean"
244 })
245 }
246
247 Literal::String(s) => {
248 json!({
249 "ExpressionType": "ConstantExpression",
250 "Name": s,
251 "ReturnType": "system.String"
252 })
253 }
254
255 Literal::Number(n) => {
256 json!({
257 "ExpressionType": "ConstantExpression",
258 "Name": n.to_string(),
259 "ReturnType": "system.Decimal"
260 })
261 }
262
263 Literal::Integer(i) => {
264 json!({
265 "ExpressionType": "ConstantExpression",
266 "Name": i.to_string(),
267 "ReturnType": "system.Integer"
268 })
269 }
270
271 Literal::Date(d) => {
272 json!({
273 "ExpressionType": "ConstantExpression",
274 "Name": format!("@{}", d.original_string()),
275 "ReturnType": "system.Date"
276 })
277 }
278
279 Literal::DateTime(dt) => {
280 json!({
281 "ExpressionType": "ConstantExpression",
282 "Name": format!("@{}", dt.original_string()),
283 "ReturnType": "system.DateTime"
284 })
285 }
286
287 Literal::Time(t) => {
288 json!({
289 "ExpressionType": "ConstantExpression",
290 "Name": format!("@T{}", t.original_string()),
291 "ReturnType": "system.Time"
292 })
293 }
294
295 Literal::Quantity(value, unit) => {
296 json!({
297 "ExpressionType": "ConstantExpression",
298 "Name": format!("{} '{}'", value, unit),
299 "ReturnType": "system.Quantity"
300 })
301 }
302 }
303}
304
305fn invocation_to_debug_tree(invocation: &Invocation, context: &TypeContext) -> Value {
306 match invocation {
307 Invocation::Function(name, args) => {
308 let mut node = json!({
309 "ExpressionType": "FunctionCallExpression",
310 "Name": name
311 });
312
313 if !args.is_empty() {
314 node["Arguments"] = json!(
315 args.iter()
316 .map(|arg| expression_to_debug_tree_inner(arg, context))
317 .collect::<Vec<_>>()
318 );
319 } else {
320 node["Arguments"] = json!([]);
321 }
322
323 node
324 }
325
326 Invocation::Member(name) => {
327 json!({
328 "ExpressionType": "ChildExpression",
329 "Name": name,
330 "Arguments": []
331 })
332 }
333
334 Invocation::This => {
335 json!({
336 "ExpressionType": "AxisExpression",
337 "Name": "builtin.this"
338 })
339 }
340
341 Invocation::Index => {
342 json!({
343 "ExpressionType": "AxisExpression",
344 "Name": "builtin.index"
345 })
346 }
347
348 Invocation::Total => {
349 json!({
350 "ExpressionType": "AxisExpression",
351 "Name": "builtin.total"
352 })
353 }
354 }
355}
356
357fn type_specifier_to_debug_tree(type_spec: &TypeSpecifier) -> Value {
358 match type_spec {
359 TypeSpecifier::QualifiedIdentifier(namespace_or_type, type_opt) => {
360 let type_name = match type_opt {
361 Some(t) => format!("{}.{}", namespace_or_type, t),
362 None => namespace_or_type.clone(),
363 };
364 json!({
365 "ExpressionType": "TypeSpecifier",
366 "Name": type_name
367 })
368 }
369 }
370}
371
372pub fn spanned_expression_to_debug_tree(expr: &SpannedExpression, context: &TypeContext) -> Value {
378 spanned_expression_to_debug_tree_inner(expr, context)
379}
380
381fn spanned_expression_to_debug_tree_inner(
382 expr: &SpannedExpression,
383 context: &TypeContext,
384) -> Value {
385 let unspanned = expr.to_expression();
387 let return_type = infer_expression_type(&unspanned, context).map(|t| t.to_display_string());
388
389 let mut node = match &expr.kind {
390 SpannedExprKind::Term(term) => spanned_term_to_debug_tree(term, expr, context),
391
392 SpannedExprKind::Invocation(base_expr, invocation) => {
393 let mut inv_node = spanned_invocation_to_debug_tree(invocation, context);
394
395 let mut args = inv_node
396 .get("Arguments")
397 .and_then(|a| a.as_array())
398 .cloned()
399 .unwrap_or_default();
400
401 let base_node = spanned_expression_to_debug_tree_inner(base_expr, context);
402 args.insert(0, base_node);
403
404 inv_node["Arguments"] = json!(args);
405 inv_node
406 }
407
408 SpannedExprKind::Indexer(expr_inner, index) => {
409 json!({
410 "ExpressionType": "IndexerExpression",
411 "Name": "[]",
412 "Arguments": vec![
413 spanned_expression_to_debug_tree_inner(expr_inner, context),
414 spanned_expression_to_debug_tree_inner(index, context)
415 ]
416 })
417 }
418
419 SpannedExprKind::Polarity(op, expr_inner) => {
420 json!({
421 "ExpressionType": "UnaryExpression",
422 "Name": op.to_string(),
423 "Arguments": vec![spanned_expression_to_debug_tree_inner(expr_inner, context)]
424 })
425 }
426
427 SpannedExprKind::Multiplicative(left, op, right)
428 | SpannedExprKind::Additive(left, op, right)
429 | SpannedExprKind::Inequality(left, op, right)
430 | SpannedExprKind::Equality(left, op, right)
431 | SpannedExprKind::Membership(left, op, right) => {
432 json!({
433 "ExpressionType": "BinaryExpression",
434 "Name": op,
435 "Arguments": vec![
436 spanned_expression_to_debug_tree_inner(left, context),
437 spanned_expression_to_debug_tree_inner(right, context)
438 ]
439 })
440 }
441
442 SpannedExprKind::Type(expr_inner, op, type_spec) => {
443 json!({
444 "ExpressionType": "TypeExpression",
445 "Name": op,
446 "Arguments": vec![
447 spanned_expression_to_debug_tree_inner(expr_inner, context),
448 type_specifier_to_debug_tree(type_spec)
449 ]
450 })
451 }
452
453 SpannedExprKind::Union(left, right) => {
454 json!({
455 "ExpressionType": "BinaryExpression",
456 "Name": "|",
457 "Arguments": vec![
458 spanned_expression_to_debug_tree_inner(left, context),
459 spanned_expression_to_debug_tree_inner(right, context)
460 ]
461 })
462 }
463
464 SpannedExprKind::And(left, right) => {
465 json!({
466 "ExpressionType": "BinaryExpression",
467 "Name": "and",
468 "Arguments": vec![
469 spanned_expression_to_debug_tree_inner(left, context),
470 spanned_expression_to_debug_tree_inner(right, context)
471 ]
472 })
473 }
474
475 SpannedExprKind::Or(left, op, right) => {
476 json!({
477 "ExpressionType": "BinaryExpression",
478 "Name": op,
479 "Arguments": vec![
480 spanned_expression_to_debug_tree_inner(left, context),
481 spanned_expression_to_debug_tree_inner(right, context)
482 ]
483 })
484 }
485
486 SpannedExprKind::Implies(left, right) => {
487 json!({
488 "ExpressionType": "BinaryExpression",
489 "Name": "implies",
490 "Arguments": vec![
491 spanned_expression_to_debug_tree_inner(left, context),
492 spanned_expression_to_debug_tree_inner(right, context)
493 ]
494 })
495 }
496
497 SpannedExprKind::Lambda(param, expr_inner) => {
498 let mut node = json!({
499 "ExpressionType": "LambdaExpression",
500 "Name": "=>",
501 "Arguments": vec![spanned_expression_to_debug_tree_inner(expr_inner, context)]
502 });
503 if let Some(param_name) = param {
504 node["Parameter"] = json!(param_name);
505 }
506 node
507 }
508
509 SpannedExprKind::InstanceSelector(type_name, fields) => {
510 let field_nodes: Vec<Value> = fields
511 .iter()
512 .map(|(name, expr_inner)| {
513 json!({
514 "FieldName": name,
515 "Value": spanned_expression_to_debug_tree_inner(expr_inner, context)
516 })
517 })
518 .collect();
519 json!({
520 "ExpressionType": "InstanceSelector",
521 "TypeName": type_name,
522 "Fields": field_nodes
523 })
524 }
525 };
526
527 node["Position"] = json!(expr.span.position);
529 node["Length"] = json!(expr.span.length);
530
531 if let Some(rt) = return_type {
533 node["ReturnType"] = json!(rt);
534 }
535
536 node
537}
538
539fn spanned_term_to_debug_tree(
540 term: &SpannedTerm,
541 parent: &SpannedExpression,
542 context: &TypeContext,
543) -> Value {
544 match term {
545 SpannedTerm::Literal(lit) => literal_to_debug_tree(lit),
546
547 SpannedTerm::Invocation(invocation) => {
548 let mut inv_node = spanned_invocation_to_debug_tree(invocation, context);
549
550 if matches!(invocation, SpannedInvocation::Member(_)) {
552 let that_node = json!({
553 "ExpressionType": "AxisExpression",
554 "Name": "builtin.that",
555 "Position": parent.span.position,
556 "Length": 0,
557 "ReturnType": context.current_type.as_ref()
558 .map(|t| t.to_display_string())
559 .unwrap_or_else(|| "Any".to_string())
560 });
561
562 let mut args = vec![that_node];
563 if let Some(existing_args) = inv_node.get("Arguments").and_then(|a| a.as_array()) {
564 args.extend(existing_args.clone());
565 }
566 inv_node["Arguments"] = json!(args);
567 }
568
569 inv_node
570 }
571
572 SpannedTerm::ExternalConstant(name) => {
573 let mut node = json!({
574 "ExpressionType": "VariableRefExpression",
575 "Name": name
576 });
577 if let Some(var_type) = context.variables.get(name) {
578 node["ReturnType"] = json!(var_type.to_display_string());
579 }
580 node
581 }
582
583 SpannedTerm::Parenthesized(expr) => spanned_expression_to_debug_tree_inner(expr, context),
584 }
585}
586
587fn spanned_invocation_to_debug_tree(
588 invocation: &SpannedInvocation,
589 context: &TypeContext,
590) -> Value {
591 match invocation {
592 SpannedInvocation::Function(name, args) => {
593 let mut node = json!({
594 "ExpressionType": "FunctionCallExpression",
595 "Name": name
596 });
597
598 if !args.is_empty() {
599 node["Arguments"] = json!(
600 args.iter()
601 .map(|arg| spanned_expression_to_debug_tree_inner(arg, context))
602 .collect::<Vec<_>>()
603 );
604 } else {
605 node["Arguments"] = json!([]);
606 }
607
608 node
609 }
610
611 SpannedInvocation::Member(name) => {
612 json!({
613 "ExpressionType": "ChildExpression",
614 "Name": name,
615 "Arguments": []
616 })
617 }
618
619 SpannedInvocation::This => {
620 json!({
621 "ExpressionType": "AxisExpression",
622 "Name": "builtin.this"
623 })
624 }
625
626 SpannedInvocation::Index => {
627 json!({
628 "ExpressionType": "AxisExpression",
629 "Name": "builtin.index"
630 })
631 }
632
633 SpannedInvocation::Total => {
634 json!({
635 "ExpressionType": "AxisExpression",
636 "Name": "builtin.total"
637 })
638 }
639 }
640}
641
642pub fn generate_parse_debug(expr: &Expression) -> String {
646 let mut output = String::new();
647 generate_parse_debug_inner(expr, &mut output, 0);
648 output
649}
650
651fn generate_parse_debug_inner(expr: &Expression, output: &mut String, indent: usize) {
652 let indent_str = " ".repeat(indent);
653
654 match expr {
655 Expression::Term(term) => match term {
656 Term::Literal(lit) => output.push_str(&format!("{}{:?}\n", indent_str, lit)),
657 Term::Invocation(inv) => output.push_str(&format!("{}{:?}\n", indent_str, inv)),
658 Term::ExternalConstant(name) => output.push_str(&format!("{}%{}\n", indent_str, name)),
659 Term::Parenthesized(expr) => {
660 output.push_str(&format!("{}(\n", indent_str));
661 generate_parse_debug_inner(expr, output, indent + 1);
662 output.push_str(&format!("{})\n", indent_str));
663 }
664 },
665
666 Expression::Invocation(expr, inv) => {
667 generate_parse_debug_inner(expr, output, indent);
668 output.push_str(&format!("{}.{:?}\n", indent_str, inv));
669 }
670
671 Expression::Indexer(expr, index) => {
672 generate_parse_debug_inner(expr, output, indent);
673 output.push_str(&format!("{}[\n", indent_str));
674 generate_parse_debug_inner(index, output, indent + 1);
675 output.push_str(&format!("{}]\n", indent_str));
676 }
677
678 Expression::Polarity(op, expr) => {
679 output.push_str(&format!("{}{}\n", indent_str, op));
680 generate_parse_debug_inner(expr, output, indent + 1);
681 }
682
683 Expression::Multiplicative(left, op, right)
684 | Expression::Additive(left, op, right)
685 | Expression::Inequality(left, op, right)
686 | Expression::Equality(left, op, right)
687 | Expression::Membership(left, op, right) => {
688 generate_parse_debug_inner(left, output, indent);
689 output.push_str(&format!("{}{}\n", indent_str, op));
690 generate_parse_debug_inner(right, output, indent + 1);
691 }
692
693 Expression::Type(expr, op, type_spec) => {
694 generate_parse_debug_inner(expr, output, indent);
695 output.push_str(&format!("{}{} {:?}\n", indent_str, op, type_spec));
696 }
697
698 Expression::Union(left, right) => {
699 generate_parse_debug_inner(left, output, indent);
700 output.push_str(&format!("{}|\n", indent_str));
701 generate_parse_debug_inner(right, output, indent + 1);
702 }
703
704 Expression::And(left, right) => {
705 generate_parse_debug_inner(left, output, indent);
706 output.push_str(&format!("{}and\n", indent_str));
707 generate_parse_debug_inner(right, output, indent + 1);
708 }
709
710 Expression::Or(left, op, right) => {
711 generate_parse_debug_inner(left, output, indent);
712 output.push_str(&format!("{}{}\n", indent_str, op));
713 generate_parse_debug_inner(right, output, indent + 1);
714 }
715
716 Expression::Implies(left, right) => {
717 generate_parse_debug_inner(left, output, indent);
718 output.push_str(&format!("{}implies\n", indent_str));
719 generate_parse_debug_inner(right, output, indent + 1);
720 }
721
722 Expression::Lambda(param, expr) => {
723 if let Some(p) = param {
724 output.push_str(&format!("{}{} =>\n", indent_str, p));
725 } else {
726 output.push_str(&format!("{}=>\n", indent_str));
727 }
728 generate_parse_debug_inner(expr, output, indent + 1);
729 }
730 Expression::InstanceSelector(type_name, fields) => {
731 output.push_str(&format!("{}{} {{\n", indent_str, type_name));
732 for (name, expr) in fields {
733 output.push_str(&format!("{} {}: ", indent_str, name));
734 generate_parse_debug_inner(expr, output, indent + 2);
735 }
736 output.push_str(&format!("{}}}\n", indent_str));
737 }
738 }
739}