| 242 | } |
| 243 | |
| 244 | Expect<void> |
| 245 | Validator::validateComponent(const AST::Component::Component &Comp) noexcept { |
| 246 | // Validation enters a fresh component scope and walks sections in their |
| 247 | // binary order. The per-sort index spaces are built incrementally as |
| 248 | // definitions are validated, so sortidx references in later sections |
| 249 | // only resolve against entries already introduced. Custom sections are |
| 250 | // ignored. Nested components recurse through this same function. |
| 251 | auto ReportError = [](auto E) { |
| 252 | spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Component)); |
| 253 | return E; |
| 254 | }; |
| 255 | |
| 256 | CompCtx.enterComponent(&Comp); |
| 257 | for (const auto &Sec : Comp.getSections()) { |
| 258 | auto Func = [&](auto &&S) -> Expect<void> { |
| 259 | using T = std::decay_t<decltype(S)>; |
| 260 | if constexpr (std::is_same_v<T, AST::CustomSection>) { |
| 261 | // Always pass validation. |
| 262 | } else { |
| 263 | EXPECTED_TRY(validate(S).map_error(ReportError)); |
| 264 | } |
| 265 | return {}; |
| 266 | }; |
| 267 | EXPECTED_TRY(std::visit(Func, Sec)); |
| 268 | } |
| 269 | CompCtx.exitComponent(); |
| 270 | return {}; |
| 271 | } |
| 272 | |
| 273 | Expect<void> |
| 274 | Validator::validate(const AST::Component::CoreModuleSection &ModSec) noexcept { |
nothing calls this directly
no test coverage detected