1use crate::parser::{
7 ExprSpan, Expression, SpannedExprKind, SpannedExpression, SpannedInvocation, SpannedTerm,
8};
9use helios_fhirpath_support::EvaluationResult;
10use std::collections::HashMap;
11
12#[derive(Debug, Clone)]
14pub struct DebugTraceStep {
15 pub position: usize,
16 pub length: usize,
17 pub function_name: String,
18 pub result: EvaluationResult,
19}
20
21#[derive(Debug)]
23pub struct DebugTracer {
24 pub steps: Vec<DebugTraceStep>,
25 pub span_map: HashMap<*const Expression, ExprSpan>,
26}
27
28unsafe impl Send for DebugTracer {}
32unsafe impl Sync for DebugTracer {}
33
34impl DebugTracer {
35 pub fn new(span_map: HashMap<*const Expression, ExprSpan>) -> Self {
36 Self {
37 steps: Vec::new(),
38 span_map,
39 }
40 }
41
42 pub fn record(&mut self, expr: &Expression, result: &EvaluationResult) {
44 let ptr = expr as *const Expression;
45 if let Some(span) = self.span_map.get(&ptr) {
46 self.steps.push(DebugTraceStep {
47 position: span.position,
48 length: span.length,
49 function_name: expression_debug_name(expr),
50 result: result.clone(),
51 });
52 }
53 }
54}
55
56pub fn build_span_map(
62 spanned: &SpannedExpression,
63 expr: &Expression,
64) -> HashMap<*const Expression, ExprSpan> {
65 let mut map = HashMap::new();
66 build_span_map_inner(spanned, expr, &mut map);
67 map
68}
69
70fn build_span_map_inner(
71 spanned: &SpannedExpression,
72 expr: &Expression,
73 map: &mut HashMap<*const Expression, ExprSpan>,
74) {
75 map.insert(expr as *const Expression, spanned.span.clone());
77
78 match (&spanned.kind, expr) {
80 (SpannedExprKind::Term(st), Expression::Term(t)) => match (st, t) {
81 (SpannedTerm::Parenthesized(se), crate::parser::Term::Parenthesized(e)) => {
82 build_span_map_inner(se, e, map);
83 }
84 (
85 SpannedTerm::Invocation(SpannedInvocation::Function(_, sargs)),
86 crate::parser::Term::Invocation(crate::parser::Invocation::Function(_, args)),
87 ) => {
88 for (sa, a) in sargs.iter().zip(args.iter()) {
89 build_span_map_inner(sa, a, map);
90 }
91 }
92 _ => {}
93 },
94 (SpannedExprKind::Invocation(sb, sinv), Expression::Invocation(eb, _einv)) => {
95 build_span_map_inner(sb, eb, map);
96 if let (
98 SpannedInvocation::Function(_, sargs),
99 crate::parser::Invocation::Function(_, args),
100 ) = (sinv, _einv)
101 {
102 for (sa, a) in sargs.iter().zip(args.iter()) {
103 build_span_map_inner(sa, a, map);
104 }
105 }
106 }
107 (SpannedExprKind::Indexer(se, si), Expression::Indexer(ee, ei)) => {
108 build_span_map_inner(se, ee, map);
109 build_span_map_inner(si, ei, map);
110 }
111 (SpannedExprKind::Polarity(_, se), Expression::Polarity(_, ee)) => {
112 build_span_map_inner(se, ee, map);
113 }
114 (SpannedExprKind::Multiplicative(sl, _, sr), Expression::Multiplicative(el, _, er))
115 | (SpannedExprKind::Additive(sl, _, sr), Expression::Additive(el, _, er))
116 | (SpannedExprKind::Inequality(sl, _, sr), Expression::Inequality(el, _, er))
117 | (SpannedExprKind::Equality(sl, _, sr), Expression::Equality(el, _, er))
118 | (SpannedExprKind::Membership(sl, _, sr), Expression::Membership(el, _, er))
119 | (SpannedExprKind::Or(sl, _, sr), Expression::Or(el, _, er)) => {
120 build_span_map_inner(sl, el, map);
121 build_span_map_inner(sr, er, map);
122 }
123 (SpannedExprKind::Type(se, _, _), Expression::Type(ee, _, _)) => {
124 build_span_map_inner(se, ee, map);
125 }
126 (SpannedExprKind::Union(sl, sr), Expression::Union(el, er))
127 | (SpannedExprKind::And(sl, sr), Expression::And(el, er))
128 | (SpannedExprKind::Implies(sl, sr), Expression::Implies(el, er)) => {
129 build_span_map_inner(sl, el, map);
130 build_span_map_inner(sr, er, map);
131 }
132 (SpannedExprKind::Lambda(_, se), Expression::Lambda(_, ee)) => {
133 build_span_map_inner(se, ee, map);
134 }
135 _ => {}
136 }
137}
138
139fn expression_debug_name(expr: &Expression) -> String {
141 match expr {
142 Expression::Term(t) => match t {
143 crate::parser::Term::Literal(lit) => format!("{}", lit),
144 crate::parser::Term::Invocation(inv) => match inv {
145 crate::parser::Invocation::Member(name) => name.clone(),
146 crate::parser::Invocation::Function(name, _) => format!("{}()", name),
147 crate::parser::Invocation::This => "$this".to_string(),
148 crate::parser::Invocation::Index => "$index".to_string(),
149 crate::parser::Invocation::Total => "$total".to_string(),
150 },
151 crate::parser::Term::ExternalConstant(name) => format!("%{}", name),
152 crate::parser::Term::Parenthesized(_) => "()".to_string(),
153 },
154 Expression::Invocation(_, inv) => match inv {
155 crate::parser::Invocation::Member(name) => name.clone(),
156 crate::parser::Invocation::Function(name, _) => format!("{}()", name),
157 crate::parser::Invocation::This => "$this".to_string(),
158 crate::parser::Invocation::Index => "$index".to_string(),
159 crate::parser::Invocation::Total => "$total".to_string(),
160 },
161 Expression::Indexer(_, _) => "[]".to_string(),
162 Expression::Polarity(op, _) => format!("unary {}", op),
163 Expression::Multiplicative(_, op, _) => op.clone(),
164 Expression::Additive(_, op, _) => op.clone(),
165 Expression::Type(_, op, _) => op.clone(),
166 Expression::Union(_, _) => "|".to_string(),
167 Expression::Inequality(_, op, _) => op.clone(),
168 Expression::Equality(_, op, _) => op.clone(),
169 Expression::Membership(_, op, _) => op.clone(),
170 Expression::And(_, _) => "and".to_string(),
171 Expression::Or(_, op, _) => op.clone(),
172 Expression::Implies(_, _) => "implies".to_string(),
173 Expression::Lambda(_, _) => "=>".to_string(),
174 Expression::InstanceSelector(type_name, _) => format!("{} {{...}}", type_name),
175 }
176}