#pragma once #include #include #include #include namespace whetstone { struct RunResult { std::string language; std::string output; int exitCode = 0; bool ran = false; }; class PolyglotSpecRunner { public: // Register a language variant (executable path stored but not used in mock mode). void registerVariant(const std::string& astNodeId, const std::string& language, const std::string& executablePath) { variants_[astNodeId][language] = executablePath; } // Pre-record the output a run would return (deterministic testing). void recordOutput(const std::string& astNodeId, const std::string& language, const std::string& output, int exitCode = 0) { recorded_[{astNodeId, language}] = {language, output, exitCode, true}; } // Run all registered variants for astNodeId, returning recorded outputs. // Variants with no recorded output get ran=false. std::vector runAll(const std::string& astNodeId, const std::string& /*input*/) const { std::vector results; auto vit = variants_.find(astNodeId); if (vit == variants_.end()) return results; for (const auto& [lang, path] : vit->second) { auto key = std::make_pair(astNodeId, lang); auto rit = recorded_.find(key); if (rit != recorded_.end()) results.push_back(rit->second); else results.push_back({lang, "", -1, false}); } return results; } std::vector registeredLanguages(const std::string& astNodeId) const { std::vector langs; auto it = variants_.find(astNodeId); if (it == variants_.end()) return langs; for (const auto& [lang, path] : it->second) langs.push_back(lang); return langs; } int variantCount(const std::string& astNodeId) const { auto it = variants_.find(astNodeId); return it == variants_.end() ? 0 : static_cast(it->second.size()); } // All registered nodeIds. std::vector registeredNodes() const { std::vector nodes; for (const auto& [id, _] : variants_) nodes.push_back(id); return nodes; } private: // nodeId → language → executablePath std::map> variants_; // (nodeId, language) → RunResult std::map, RunResult> recorded_; }; } // namespace whetstone