@@ -303,6 +303,28 @@ void ExprRule::dump() const {
303303 }
304304}
305305
306+ std::array<const char *, kMaxGenerics > kGenericPlaceholders = {
307+ " T1" , " T2" , " T3" , " T4" , " T5" , " T6" , " T7" , " T8" , " T9" };
308+
309+ void ExprRule::validate (const std::string &name) const {
310+ if (src.empty ()) {
311+ llvm::errs () << name << ' \n ' ;
312+ dump ();
313+ assert (0 && " Expr rule loaded from IR but has no src" );
314+ }
315+
316+ for (unsigned i = 0 , e = generics.size (); i < e; ++i) {
317+ const char *placeholder = kGenericPlaceholders [i];
318+ if (src.find (placeholder) == std::string::npos) {
319+ llvm::errs () << name << ' \n ' ;
320+ dump ();
321+ llvm::errs () << " generic " << placeholder
322+ << " declared but missing from src: " << src << ' \n ' ;
323+ assert (0 && " Expr rule declares a generic absent from its src" );
324+ }
325+ }
326+ }
327+
306328void GenericFragment::dump () const { log () << " generic: " << n << ' \n ' ; }
307329
308330void TypeInfo::dump () const {
@@ -339,11 +361,7 @@ std::pair<ExprRules, TypeRules> Load(const std::filesystem::path &path,
339361 LoadIrSrc (exprs, types, dir / " ir_src.json" );
340362
341363 for (auto &[name, rule] : exprs) {
342- if (rule.src .empty ()) {
343- llvm::errs () << name << ' \n ' ;
344- rule.dump ();
345- assert (0 && " Expr rule loaded from IR but has no src" );
346- }
364+ rule.validate (name);
347365 }
348366 for (auto &[name, rule] : types) {
349367 if (rule.src .empty ()) {
0 commit comments