@@ -1766,11 +1766,18 @@ void CodeGenerator::generateExternalPackageStubs(std::ofstream &out,
17661766 {
17671767 for (const auto &use_stmt : iface.use_statements )
17681768 {
1769- if (!use_stmt.source_package .empty () &&
1770- external_packages.find (use_stmt.source_package ) == external_packages.end ())
1769+ if (!use_stmt.source_package .empty ())
17711770 {
1772- newly_discovered.insert (use_stmt.source_package );
1773- external_packages.insert (use_stmt.source_package );
1771+ if (!use_stmt.source_interface .empty ())
1772+ {
1773+ package_interfaces[use_stmt.source_package ].insert (use_stmt.source_interface );
1774+ }
1775+
1776+ if (external_packages.find (use_stmt.source_package ) == external_packages.end ())
1777+ {
1778+ newly_discovered.insert (use_stmt.source_package );
1779+ external_packages.insert (use_stmt.source_package );
1780+ }
17741781 }
17751782 }
17761783 }
@@ -1855,23 +1862,102 @@ void CodeGenerator::generateExternalPackageStubs(std::ofstream &out,
18551862 out << " namespace " << cpp_namespace << " {\n " ;
18561863
18571864 // Determine which interfaces to generate
1858- std::set<std::string> interfaces_to_generate ;
1865+ std::set<std::string> requested_interfaces ;
18591866 if (package_interfaces.count (package_spec) && !package_interfaces[package_spec].empty ())
18601867 {
18611868 // Specific interfaces requested via use statements
1862- interfaces_to_generate = package_interfaces[package_spec];
1869+ requested_interfaces = package_interfaces[package_spec];
18631870 }
18641871 else
18651872 {
18661873 // Generate all interfaces in the package (for world imports/exports)
18671874 for (const auto &iface : package->interfaces )
18681875 {
1869- interfaces_to_generate .insert (iface.name );
1876+ requested_interfaces .insert (iface.name );
18701877 }
18711878 }
18721879
1873- // Generate stub interfaces
1880+ // Expand requested interfaces to include same-package dependencies via use statements
1881+ std::set<std::string> interfaces_to_generate;
1882+ std::function<void (const std::string &)> add_interface_with_deps = [&](const std::string &iface_name)
1883+ {
1884+ if (!interfaces_to_generate.insert (iface_name).second )
1885+ {
1886+ return ; // already processed
1887+ }
1888+
1889+ if (auto *iface_ptr_dep = package->get_interface (iface_name))
1890+ {
1891+ for (const auto &use_stmt_dep : iface_ptr_dep->use_statements )
1892+ {
1893+ if (use_stmt_dep.source_package .empty () && !use_stmt_dep.source_interface .empty ())
1894+ {
1895+ add_interface_with_deps (use_stmt_dep.source_interface );
1896+ }
1897+ }
1898+ }
1899+ };
1900+
1901+ if (!requested_interfaces.empty ())
1902+ {
1903+ for (const auto &iface_name : requested_interfaces)
1904+ {
1905+ add_interface_with_deps (iface_name);
1906+ }
1907+ }
1908+ else
1909+ {
1910+ for (const auto &iface : package->interfaces )
1911+ {
1912+ add_interface_with_deps (iface.name );
1913+ }
1914+ }
1915+
1916+ // Build dependency map for ordering (same-package dependencies only)
1917+ std::map<std::string, std::set<std::string>> interface_deps;
18741918 for (const auto &iface_name : interfaces_to_generate)
1919+ {
1920+ if (auto *iface_ptr_dep = package->get_interface (iface_name))
1921+ {
1922+ for (const auto &use_stmt_dep : iface_ptr_dep->use_statements )
1923+ {
1924+ if (use_stmt_dep.source_package .empty () && !use_stmt_dep.source_interface .empty () &&
1925+ interfaces_to_generate.count (use_stmt_dep.source_interface ))
1926+ {
1927+ interface_deps[iface_name].insert (use_stmt_dep.source_interface );
1928+ }
1929+ }
1930+ }
1931+ }
1932+
1933+ std::vector<std::string> interface_order;
1934+ std::set<std::string> visited_interfaces;
1935+ std::function<void (const std::string &)> visit_interface = [&](const std::string &iface_name)
1936+ {
1937+ if (visited_interfaces.count (iface_name))
1938+ {
1939+ return ;
1940+ }
1941+ visited_interfaces.insert (iface_name);
1942+
1943+ if (interface_deps.count (iface_name))
1944+ {
1945+ for (const auto &dep : interface_deps[iface_name])
1946+ {
1947+ visit_interface (dep);
1948+ }
1949+ }
1950+
1951+ interface_order.push_back (iface_name);
1952+ };
1953+
1954+ for (const auto &iface_name : interfaces_to_generate)
1955+ {
1956+ visit_interface (iface_name);
1957+ }
1958+
1959+ // Generate stub interfaces
1960+ for (const auto &iface_name : interface_order)
18751961 {
18761962 auto *iface_ptr = package->get_interface (iface_name);
18771963 if (!iface_ptr)
@@ -1881,27 +1967,74 @@ void CodeGenerator::generateExternalPackageStubs(std::ofstream &out,
18811967
18821968 out << " namespace " << sanitize_identifier (iface_name) << " {\n " ;
18831969
1884- // Generate use declarations (type imports from other packages)
1970+ // Generate use declarations (type imports from other packages or interfaces)
1971+ auto emit_using_decls = [&](const UseStatement &use_stmt, const std::string &ns_prefix)
1972+ {
1973+ for (const auto &type_name : use_stmt.imported_types )
1974+ {
1975+ std::string local_name = use_stmt.type_renames .count (type_name)
1976+ ? use_stmt.type_renames .at (type_name)
1977+ : type_name;
1978+ out << " using " << sanitize_identifier (local_name)
1979+ << " = ::" << ns_prefix << " ::" << sanitize_identifier (use_stmt.source_interface )
1980+ << " ::" << sanitize_identifier (type_name) << " ;\n " ;
1981+ }
1982+ };
1983+
1984+ bool emitted_use_decl = false ;
18851985 for (const auto &use_stmt : iface_ptr->use_statements )
18861986 {
18871987 if (!use_stmt.source_package .empty ())
18881988 {
1889- // This is a cross-package use - generate using declaration
1890- auto use_pkg_id = PackageId::parse (use_stmt.source_package );
1891- if (use_pkg_id)
1989+ // Cross-package use statement
1990+ if (auto use_pkg_id = PackageId::parse (use_stmt.source_package ))
18921991 {
1893- std::string use_cpp_ns = use_pkg_id->to_cpp_namespace ();
1894- for (const auto &type_name : use_stmt.imported_types )
1992+ emit_using_decls (use_stmt, use_pkg_id->to_cpp_namespace ());
1993+ emitted_use_decl = true ;
1994+ }
1995+ }
1996+ else if (!use_stmt.source_interface .empty () && use_stmt.source_interface != iface_name)
1997+ {
1998+ // Same-package interface reference
1999+ emit_using_decls (use_stmt, cpp_namespace);
2000+ emitted_use_decl = true ;
2001+ }
2002+ }
2003+
2004+ if (emitted_use_decl)
2005+ {
2006+ out << " \n " ;
2007+ }
2008+
2009+ // Generate resource handle stubs
2010+ if (!iface_ptr->resources .empty ())
2011+ {
2012+ for (const auto &resource : iface_ptr->resources )
2013+ {
2014+ out << " // Resource type (handle represented as uint32_t): "
2015+ << resource.name << " \n " ;
2016+ out << " using " << sanitize_identifier (resource.name ) << " = uint32_t;\n " ;
2017+ }
2018+ out << " \n " ;
2019+ }
2020+
2021+ // Generate flag definitions
2022+ if (!iface_ptr->flags .empty ())
2023+ {
2024+ for (const auto &flags_def : iface_ptr->flags )
2025+ {
2026+ out << " using " << sanitize_identifier (flags_def.name ) << " = cmcpp::flags_t<" ;
2027+ for (size_t i = 0 ; i < flags_def.flags .size (); ++i)
2028+ {
2029+ out << " \" " << sanitize_identifier (flags_def.flags [i]) << " \" " ;
2030+ if (i < flags_def.flags .size () - 1 )
18952031 {
1896- std::string local_name = use_stmt.type_renames .count (type_name)
1897- ? use_stmt.type_renames .at (type_name)
1898- : type_name;
1899- out << " using " << sanitize_identifier (local_name)
1900- << " = ::" << use_cpp_ns << " ::" << sanitize_identifier (use_stmt.source_interface )
1901- << " ::" << sanitize_identifier (type_name) << " ;\n " ;
2032+ out << " , " ;
19022033 }
19032034 }
2035+ out << " >;\n " ;
19042036 }
2037+ out << " \n " ;
19052038 }
19062039
19072040 // Generate type aliases for types used from this interface
0 commit comments