pax_language/interpreter/
property_resolution.rs1use std::collections::HashMap;
2
3use pax_runtime_api::{LocalProperty, PaxValue, Variable};
4
5use super::{
6 PaxAccessor, PaxExpression, PaxInfix, PaxNullCoalesce, PaxPostfix, PaxPrefix, PaxPrimary,
7 PaxTernary,
8};
9
10pub trait IdentifierResolver {
13 fn resolve(&self, name: String) -> Result<Variable, String>;
14}
15
16pub trait DependencyCollector {
18 fn collect_dependencies(&self) -> Vec<String>;
19}
20
21impl DependencyCollector for PaxExpression {
22 fn collect_dependencies(&self) -> Vec<String> {
23 match self {
24 PaxExpression::Primary(p) => p.collect_dependencies(),
25 PaxExpression::Prefix(p) => p.collect_dependencies(),
26 PaxExpression::Infix(p) => p.collect_dependencies(),
27 PaxExpression::Postfix(p) => p.collect_dependencies(),
28 PaxExpression::Ternary(p) => p.collect_dependencies(),
29 PaxExpression::NullCoalesce(p) => p.collect_dependencies(),
30 }
31 }
32}
33
34impl DependencyCollector for PaxPrimary {
35 fn collect_dependencies(&self) -> Vec<String> {
36 let mut ret = match self {
37 PaxPrimary::Literal(_) => vec![],
38 PaxPrimary::Grouped(expr, _) => expr.collect_dependencies(),
39 PaxPrimary::Identifier(i, accessors) => {
40 let mut deps = vec![i.name.clone()];
41 for accessor in accessors {
42 if let PaxAccessor::List(index) = accessor {
43 deps.extend(index.collect_dependencies());
44 }
45 }
46 deps
47 }
48 PaxPrimary::Object(o) => o
49 .iter()
50 .flat_map(|(_, v)| v.collect_dependencies())
51 .collect(),
52 PaxPrimary::FunctionOrEnum(_, _, args) => {
53 args.iter().flat_map(|a| a.collect_dependencies()).collect()
54 }
55 PaxPrimary::Range(start, end) => {
56 let mut deps = start.collect_dependencies();
57 deps.extend(end.collect_dependencies());
58 deps
59 }
60 PaxPrimary::Tuple(t) => t.iter().flat_map(|e| e.collect_dependencies()).collect(),
61 PaxPrimary::List(l) => l.iter().flat_map(|e| e.collect_dependencies()).collect(),
62 };
63 let mut seen = std::collections::HashSet::new();
66 ret.retain(|dependency| seen.insert(dependency.clone()));
67 ret
68 }
69}
70
71impl DependencyCollector for PaxPrefix {
72 fn collect_dependencies(&self) -> Vec<String> {
73 self.rhs.collect_dependencies()
74 }
75}
76
77impl DependencyCollector for PaxInfix {
78 fn collect_dependencies(&self) -> Vec<String> {
79 let mut deps = self.lhs.collect_dependencies();
80 deps.extend(self.rhs.collect_dependencies());
81 deps
82 }
83}
84
85impl DependencyCollector for PaxPostfix {
86 fn collect_dependencies(&self) -> Vec<String> {
87 self.lhs.collect_dependencies()
88 }
89}
90
91impl DependencyCollector for PaxTernary {
92 fn collect_dependencies(&self) -> Vec<String> {
93 let mut deps = self.condition.collect_dependencies();
94 deps.extend(self.then_branch.collect_dependencies());
95 deps.extend(self.else_branch.collect_dependencies());
96 deps
97 }
98}
99
100impl DependencyCollector for PaxNullCoalesce {
101 fn collect_dependencies(&self) -> Vec<String> {
102 let mut deps = self.lhs.collect_dependencies();
103 deps.extend(self.rhs.collect_dependencies());
104 deps
105 }
106}
107
108impl IdentifierResolver for HashMap<String, PaxValue> {
109 fn resolve(&self, name: String) -> Result<Variable, String> {
110 self.get(&name)
111 .map(|v| Variable::new_from_typed_property(LocalProperty::new(v.clone())))
114 .ok_or(format!("Identifier not found: {}", name))
115 }
116}