diff --git a/src/ast/datatype_decl_plugin.cpp b/src/ast/datatype_decl_plugin.cpp index 33de8dd69..2c0c7f0b5 100644 --- a/src/ast/datatype_decl_plugin.cpp +++ b/src/ast/datatype_decl_plugin.cpp @@ -1121,6 +1121,56 @@ namespace datatype { return d; } + void util::batch_initialize_constructor_functions(sort * datatype) { + SASSERT(is_datatype(datatype)); + def const& dd = get_def(datatype); + + // Get all constructors for this datatype + ptr_vector const* constructors = get_datatype_constructors(datatype); + if (!constructors) return; + + // Process all constructors in a single pass to avoid O(n²) behavior + for (func_decl * con : *constructors) { + // Initialize recognizer if not already cached + if (!plugin().m_constructor2recognizer.contains(con)) { + symbol r; + for (constructor const* c : dd) { + if (c->name() == con->get_name()) { + r = c->recognizer(); + break; + } + } + parameter ps[2] = { parameter(con), parameter(r) }; + func_decl* d = m.mk_func_decl(fid(), OP_DT_RECOGNISER, 2, ps, 1, &datatype); + plugin().add_ast(con); + plugin().add_ast(d); + plugin().m_constructor2recognizer.insert(con, d); + } + + // Initialize accessors if not already cached + if (!plugin().m_constructor2accessors.contains(con)) { + ptr_vector* res = alloc(ptr_vector); + plugin().add_ast(con); + plugin().m_vectors.push_back(res); + plugin().m_constructor2accessors.insert(con, res); + + if (con->get_arity() > 0) { + // Find the constructor definition and create accessors + for (constructor const* c : dd) { + if (c->name() == con->get_name()) { + for (accessor const* a : *c) { + func_decl_ref fn = a->instantiate(datatype); + res->push_back(fn); + plugin().add_ast(fn); + } + break; + } + } + } + } + } + } + app* util::mk_is(func_decl * c, expr *f) { return m.mk_app(get_constructor_is(c), f); } diff --git a/src/ast/datatype_decl_plugin.h b/src/ast/datatype_decl_plugin.h index 4d91cbf40..29c0d4364 100644 --- a/src/ast/datatype_decl_plugin.h +++ b/src/ast/datatype_decl_plugin.h @@ -373,6 +373,7 @@ namespace datatype { func_decl * get_constructor_recognizer(func_decl * constructor); func_decl * get_constructor_is(func_decl * constructor); ptr_vector const * get_constructor_accessors(func_decl * constructor); + void batch_initialize_constructor_functions(sort * datatype); func_decl * get_accessor_constructor(func_decl * accessor); func_decl * get_recognizer_constructor(func_decl * recognizer) const; func_decl * get_update_accessor(func_decl * update) const; diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 4f093e749..8c32d1c32 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -2471,6 +2471,10 @@ cmd_context::dt_eh::dt_eh(cmd_context & owner): void cmd_context::dt_eh::operator()(sort * dt, pdecl* pd) { TRACE(new_dt_eh, tout << "new datatype: "; m_owner.pm().display(tout, dt); tout << "\n";); + + // Batch initialize all constructor functions to avoid O(n²) behavior for large datatypes + m_dt_util.batch_initialize_constructor_functions(dt); + for (func_decl * c : *m_dt_util.get_datatype_constructors(dt)) { TRACE(new_dt_eh, tout << "new constructor: " << c->get_name() << "\n";); m_owner.insert(c);