sim_expr_tree_calc/
policy.rs1use sim_kernel::{
2 Cx, Demand, Error as KernelError, EvalPolicy, Expr, Phase, PreparedArgs, Symbol, Value,
3 object::RawArgs,
4};
5
6pub const EXPR_TREE_REF: &str = "expr-tree/ref";
7
8pub struct ExprTreeRefPolicy<P> {
9 inner: P,
10}
11
12impl<P> ExprTreeRefPolicy<P> {
13 pub fn new(inner: P) -> Self {
14 Self { inner }
15 }
16
17 pub fn inner(&self) -> &P {
18 &self.inner
19 }
20}
21
22impl<P: EvalPolicy> EvalPolicy for ExprTreeRefPolicy<P> {
23 fn name(&self) -> &'static str {
24 "expr-tree-ref"
25 }
26
27 fn allow_macro_expansion(&self, phase: Phase) -> bool {
28 self.inner.allow_macro_expansion(phase)
29 }
30
31 fn prepare_call_args(
32 &self,
33 cx: &mut Cx,
34 raw: RawArgs,
35 demands: &[Demand],
36 ) -> sim_kernel::Result<PreparedArgs> {
37 self.inner.prepare_call_args(cx, raw, demands)
38 }
39
40 fn force(&self, cx: &mut Cx, value: Value, demand: Demand) -> sim_kernel::Result<Value> {
41 self.inner.force(cx, value, demand)
42 }
43
44 fn eval_expr(&self, cx: &mut Cx, expr: Expr) -> sim_kernel::Result<Value> {
45 self.inner.eval_expr(cx, expr)
46 }
47
48 fn resolve_unbound_symbol(&self, cx: &mut Cx, symbol: Symbol) -> sim_kernel::Result<Value> {
49 cx.factory().string(format!("expr-tree/ref:{symbol}"))
50 }
51
52 fn resolve_unbound_call(
53 &self,
54 cx: &mut Cx,
55 operator: Symbol,
56 args: Vec<Expr>,
57 ) -> sim_kernel::Result<Value> {
58 if operator.to_string() == EXPR_TREE_REF {
59 let Some(reference) = args.first() else {
60 return Err(KernelError::Eval(
61 "expr-tree/ref requires a reference".to_owned(),
62 ));
63 };
64 return cx
65 .factory()
66 .string(format!("expr-tree/ref:{}", expr_text(reference)));
67 }
68 self.inner.resolve_unbound_call(cx, operator, args)
69 }
70}
71
72fn expr_text(expr: &Expr) -> String {
73 match expr {
74 Expr::String(value) => value.clone(),
75 Expr::Symbol(symbol) => symbol.to_string(),
76 other => format!("{other:?}"),
77 }
78}