| 111 | } |
| 112 | |
| 113 | Errata |
| 114 | FeatureGroup::load_expr(Config &cfg, Tracking &tracking, Tracking::Info *info, YAML::Node const &node) |
| 115 | { |
| 116 | /* A bit tricky, but not unduly so. The goal is to traverse all of the specifiers in the |
| 117 | * expression and convert generic "this" extractors to the "this" extractor for @a this |
| 118 | * feature group instance. This struct is required by the visitation rules of @c std::variant. |
| 119 | * There's an overload for each variant type in @c Expr plus a common helper method. |
| 120 | * It's not possible to use lambda gathering because the @c List case is recursive. |
| 121 | */ |
| 122 | struct V { |
| 123 | V(FeatureGroup &fg, Config &cfg, Tracking &tracking) : _fg(fg), _cfg(cfg), _tracking(tracking) {} |
| 124 | FeatureGroup &_fg; |
| 125 | Config &_cfg; |
| 126 | Tracking &_tracking; |
| 127 | bool _dependent_p = false; |
| 128 | |
| 129 | /// Update @a spec as needed to have the correct "this" extractor. |
| 130 | Errata |
| 131 | load_spec(Extractor::Spec &spec) |
| 132 | { |
| 133 | if (spec._exf == &ex_this) { |
| 134 | auto &&[tinfo, errata] = _fg.load_key(_cfg, _tracking, spec._ext); |
| 135 | if (errata.is_ok()) { |
| 136 | spec._exf = &_fg._ex_this; |
| 137 | // Don't track if the target is a literal - no runtime extraction needed. |
| 138 | if (!tinfo->_expr.is_literal()) { |
| 139 | _dependent_p = true; |
| 140 | // If not already marked as a reference target mark it. |
| 141 | if (tinfo->_exf_idx == INVALID_IDX) { |
| 142 | tinfo->_exf_idx = _fg._ref_count++; |
| 143 | // This marking happens after the depth first dependency chain has been explored |
| 144 | // therefore all dependencies for this target are already in the @a _order_idx |
| 145 | // elements, and therefore it is time to add this one. |
| 146 | _tracking._info[tinfo->_exf_idx]._order_idx = tinfo - _tracking._info.data(); |
| 147 | } |
| 148 | // Invariant - @a _dependent_p is true => @a _ref_count is non-zero. |
| 149 | } |
| 150 | } |
| 151 | return std::move(errata); |
| 152 | } |
| 153 | return {}; |
| 154 | } |
| 155 | |
| 156 | Errata |
| 157 | operator()(std::monostate) |
| 158 | { |
| 159 | return {}; |
| 160 | } |
| 161 | Errata |
| 162 | operator()(Feature const &) |
| 163 | { |
| 164 | return {}; |
| 165 | } |
| 166 | Errata |
| 167 | operator()(Expr::Direct &d) |
| 168 | { |
| 169 | return this->load_spec(d._spec); |
| 170 | } |
no test coverage detected