tfparser_core/eval/mod.rs
1//! Best-effort HCL expression evaluator.
2//!
3//! Given a parsed [`Component`] and an [`EvalContext`], the evaluator reduces
4//! every [`Expression`] it can statically — variables bound from
5//! `*.tfvars`, locals via a worklist fixpoint, stdlib + Terraform-only
6//! functions, and sandboxed file functions — leaving references that depend
7//! on apply-time data ([`Expression::Unresolved`], `data.*`, resource
8//! attributes, module outputs) intact.
9//!
10//! The evaluator is **best-effort by contract**, per
11//! [99-key-decisions.md] D4: an unresolved leaf is not a parse error — it is
12//! the correct outcome when the source-only parser does not have apply-time
13//! information. The Phase 4 contract is pinned in [13-evaluator.md].
14//!
15//! # Architecture
16//!
17//! `eval` is a pure walk over our [`Expression`] tree (`reduce.rs`). The
18//! spec ([13-evaluator.md § 4]) describes "feeding our context into the
19//! `hcl-rs::eval` evaluator and reading the result back into our IR"; in
20//! practice that pattern is partially unreachable because `hcl::eval::FuncDef`
21//! accepts a [`fn`-pointer], not a closure, so stateful functions
22//! (`file()`, `get_env()`, the Terragrunt helpers) cannot carry sandbox /
23//! workspace-root context through it. See [93-improvements-review.md]
24//! S-010 / S-011 for the recorded spec defects.
25//!
26//! The walker keeps the contract the spec actually cares about: every public
27//! IR shape that flows through is *ours*. The [`value_to_hcl`] / [`hcl_to_value`]
28//! adapters convert at the boundary so future delegations (Phase 6 Terragrunt
29//! funcs) can lean on `hcl::Value` without changing this module.
30//!
31//! [13-evaluator.md]: ../../../specs/13-evaluator.md
32//! [13-evaluator.md § 4]: ../../../specs/13-evaluator.md
33//! [99-key-decisions.md]: ../../../specs/99-key-decisions.md
34//! [93-improvements-review.md]: ../../../specs/93-improvements-review.md
35//! [`Component`]: crate::ir::Component
36//! [`Expression`]: crate::ir::Expression
37//! [`Expression::Unresolved`]: crate::ir::Expression::Unresolved
38//! [`fn`-pointer]: https://doc.rust-lang.org/std/primitive.fn.html
39
40mod adapter;
41mod component;
42mod context;
43mod error;
44mod files;
45mod locals;
46pub(crate) mod reduce;
47mod registry;
48mod stdlib;
49mod tf_funcs;
50
51pub use adapter::{hcl_to_value, value_to_hcl};
52pub use component::{EvaluatedComponent, Evaluator, HclEvaluator};
53pub use context::{EnvVarMode, EvalContext, EvalLimits};
54pub use error::EvalError;
55pub use locals::CycleParticipant;
56pub use registry::{CallCx, FuncError, FuncRegistry, FuncRegistryBuilder, HclFunc};