Sprint 271: LanguageFitnessScorer — polyglot Phase 1 (steps 1883-1887)
Add language fitness scoring infrastructure for the polyglot orchestrator. New components: - ASTFeatureExtractor.h: extract 5 scalar features from JSON AST subtrees (mutation ratio, recursion shape, concurrency primitive, I/O pattern, type complexity) - LanguageIdiomProfile.h: static ideal feature vectors for 8 languages (Python, Rust, Go, Haskell, C++, TypeScript, Elixir, Lisp) - LanguageFitnessScorer.h: weighted scoring against profiles, returns JSON array sorted descending with per-language score and rationale - RegisterLanguageFitnessTools.h: whetstone_score_language_fitness MCP tool - Sprint271IntegrationSummary.h: sprint metadata 25/25 tests passing (steps 1883-1887). whetstone_mcp rebuilt with new tool. Also: merge PROGRESS.md into progress.md (single authoritative log, 15k lines), update CLAUDE.md to current state (step 1887, sprint 271, 91 tools). LoRA session recorded: sprint271-polyglot-fitness-2026-03-01 (5 tool calls: architect_intake, generate_taskitems, 3x generate_code) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
219
editor/src/ASTFeatureExtractor.h
Normal file
219
editor/src/ASTFeatureExtractor.h
Normal file
@@ -0,0 +1,219 @@
|
||||
#pragma once
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace whetstone {
|
||||
|
||||
struct ASTFeatures {
|
||||
enum class RecursionShape { None, TailRecursive, TreeRecursive, FlatLoop };
|
||||
enum class ConcurrencyPrimitive { None, Channels, SharedMemory, Actors };
|
||||
enum class IOPattern { None, Blocking, Async, EventDriven };
|
||||
enum class TypeComplexity { None, SimpleGenerics, DependentTypes };
|
||||
|
||||
float mutationRatio = 0.0f;
|
||||
RecursionShape recursionShape = RecursionShape::None;
|
||||
ConcurrencyPrimitive concurrencyPrimitive = ConcurrencyPrimitive::None;
|
||||
IOPattern ioPattern = IOPattern::None;
|
||||
TypeComplexity typeComplexity = TypeComplexity::None;
|
||||
};
|
||||
|
||||
class ASTFeatureExtractor {
|
||||
public:
|
||||
static ASTFeatures extract(const nlohmann::json& astNode) {
|
||||
std::vector<std::string> types;
|
||||
collectTypes(astNode, types, nullptr);
|
||||
|
||||
ASTFeatures feat;
|
||||
feat.mutationRatio = computeMutationRatio(types);
|
||||
feat.recursionShape = detectRecursionShape(astNode, types);
|
||||
feat.concurrencyPrimitive = detectConcurrency(types);
|
||||
feat.ioPattern = detectIOPattern(types);
|
||||
feat.typeComplexity = detectTypeComplexity(types);
|
||||
return feat;
|
||||
}
|
||||
|
||||
private:
|
||||
static bool contains(const std::string& s, const std::string& sub) {
|
||||
return s.find(sub) != std::string::npos;
|
||||
}
|
||||
|
||||
// Recursively collect all "type" strings from the JSON AST
|
||||
static void collectTypes(const nlohmann::json& node, std::vector<std::string>& out,
|
||||
const std::string* parentType) {
|
||||
if (!node.is_object()) return;
|
||||
|
||||
std::string nodeType;
|
||||
if (node.contains("type") && node["type"].is_string()) {
|
||||
nodeType = node["type"].get<std::string>();
|
||||
out.push_back(nodeType);
|
||||
}
|
||||
|
||||
// Check children
|
||||
if (node.contains("children")) {
|
||||
const auto& children = node["children"];
|
||||
if (children.is_array()) {
|
||||
for (const auto& child : children) {
|
||||
collectTypes(child, out, nodeType.empty() ? parentType : &nodeType);
|
||||
}
|
||||
} else if (children.is_object()) {
|
||||
// Structured children (e.g. {"methods": [...], "fields": [...]})
|
||||
for (auto& [key, val] : children.items()) {
|
||||
if (val.is_array()) {
|
||||
for (const auto& item : val) {
|
||||
collectTypes(item, out, nodeType.empty() ? parentType : &nodeType);
|
||||
}
|
||||
} else if (val.is_object()) {
|
||||
collectTypes(val, out, nodeType.empty() ? parentType : &nodeType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static float computeMutationRatio(const std::vector<std::string>& types) {
|
||||
if (types.empty()) return 0.0f;
|
||||
int mutations = 0;
|
||||
for (const auto& t : types) {
|
||||
if (contains(t, "assign") || contains(t, "write") ||
|
||||
contains(t, "store") || contains(t, "set_")) {
|
||||
++mutations;
|
||||
}
|
||||
}
|
||||
return static_cast<float>(mutations) / static_cast<float>(types.size());
|
||||
}
|
||||
|
||||
static ASTFeatures::RecursionShape detectRecursionShape(
|
||||
const nlohmann::json& root, const std::vector<std::string>& types)
|
||||
{
|
||||
// FlatLoop: any loop node
|
||||
for (const auto& t : types) {
|
||||
if (contains(t, "for_") || contains(t, "while") || contains(t, "loop")) {
|
||||
return ASTFeatures::RecursionShape::FlatLoop;
|
||||
}
|
||||
}
|
||||
|
||||
// TailRecursive: call_expr is a direct child of return_stmt anywhere in tree
|
||||
if (hasTailCall(root)) {
|
||||
return ASTFeatures::RecursionShape::TailRecursive;
|
||||
}
|
||||
|
||||
// TreeRecursive: 2+ call_expr nodes without any loop
|
||||
int callCount = 0;
|
||||
for (const auto& t : types) {
|
||||
if (contains(t, "call_")) ++callCount;
|
||||
}
|
||||
if (callCount >= 2) {
|
||||
return ASTFeatures::RecursionShape::TreeRecursive;
|
||||
}
|
||||
|
||||
return ASTFeatures::RecursionShape::None;
|
||||
}
|
||||
|
||||
// Returns true if any return_stmt node has a call_expr direct child
|
||||
static bool hasTailCall(const nlohmann::json& node) {
|
||||
if (!node.is_object()) return false;
|
||||
|
||||
std::string nodeType;
|
||||
if (node.contains("type") && node["type"].is_string()) {
|
||||
nodeType = node["type"].get<std::string>();
|
||||
}
|
||||
|
||||
if (nodeType == "return_stmt" && node.contains("children")) {
|
||||
const auto& ch = node["children"];
|
||||
if (ch.is_array()) {
|
||||
for (const auto& child : ch) {
|
||||
if (child.is_object() && child.contains("type")) {
|
||||
std::string ct = child["type"].get<std::string>();
|
||||
if (contains(ct, "call_")) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Recurse
|
||||
if (node.contains("children")) {
|
||||
const auto& children = node["children"];
|
||||
if (children.is_array()) {
|
||||
for (const auto& child : children) {
|
||||
if (hasTailCall(child)) return true;
|
||||
}
|
||||
} else if (children.is_object()) {
|
||||
for (auto& [key, val] : children.items()) {
|
||||
if (val.is_array()) {
|
||||
for (const auto& item : val) {
|
||||
if (hasTailCall(item)) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static ASTFeatures::ConcurrencyPrimitive detectConcurrency(
|
||||
const std::vector<std::string>& types)
|
||||
{
|
||||
for (const auto& t : types) {
|
||||
if (contains(t, "actor") || contains(t, "spawn") ||
|
||||
contains(t, "gen_server") || (contains(t, "receive") && !contains(t, "chan"))) {
|
||||
return ASTFeatures::ConcurrencyPrimitive::Actors;
|
||||
}
|
||||
}
|
||||
for (const auto& t : types) {
|
||||
if (contains(t, "mutex") || contains(t, "lock") ||
|
||||
contains(t, "atomic") || contains(t, "shared_mem")) {
|
||||
return ASTFeatures::ConcurrencyPrimitive::SharedMemory;
|
||||
}
|
||||
}
|
||||
for (const auto& t : types) {
|
||||
if (contains(t, "chan") || contains(t, "channel") ||
|
||||
contains(t, "_send") || contains(t, "_recv")) {
|
||||
return ASTFeatures::ConcurrencyPrimitive::Channels;
|
||||
}
|
||||
}
|
||||
return ASTFeatures::ConcurrencyPrimitive::None;
|
||||
}
|
||||
|
||||
static ASTFeatures::IOPattern detectIOPattern(const std::vector<std::string>& types) {
|
||||
for (const auto& t : types) {
|
||||
if (contains(t, "async") || contains(t, "await") ||
|
||||
contains(t, "future") || contains(t, "promise")) {
|
||||
return ASTFeatures::IOPattern::Async;
|
||||
}
|
||||
}
|
||||
for (const auto& t : types) {
|
||||
if (contains(t, "event") || contains(t, "handler") ||
|
||||
contains(t, "emit") || contains(t, "listen")) {
|
||||
return ASTFeatures::IOPattern::EventDriven;
|
||||
}
|
||||
}
|
||||
for (const auto& t : types) {
|
||||
if (contains(t, "read_") || contains(t, "write_") ||
|
||||
contains(t, "open_") || contains(t, "close_") || contains(t, "socket")) {
|
||||
return ASTFeatures::IOPattern::Blocking;
|
||||
}
|
||||
}
|
||||
return ASTFeatures::IOPattern::None;
|
||||
}
|
||||
|
||||
static ASTFeatures::TypeComplexity detectTypeComplexity(
|
||||
const std::vector<std::string>& types)
|
||||
{
|
||||
for (const auto& t : types) {
|
||||
if (contains(t, "dependent") || contains(t, "refinement") ||
|
||||
contains(t, "pi_type")) {
|
||||
return ASTFeatures::TypeComplexity::DependentTypes;
|
||||
}
|
||||
}
|
||||
for (const auto& t : types) {
|
||||
if (contains(t, "template") || contains(t, "generic") ||
|
||||
contains(t, "type_param")) {
|
||||
return ASTFeatures::TypeComplexity::SimpleGenerics;
|
||||
}
|
||||
}
|
||||
return ASTFeatures::TypeComplexity::None;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace whetstone
|
||||
78
editor/src/LanguageFitnessScorer.h
Normal file
78
editor/src/LanguageFitnessScorer.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
#include "ASTFeatureExtractor.h"
|
||||
#include "LanguageIdiomProfile.h"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
|
||||
namespace whetstone {
|
||||
|
||||
struct FitnessResult {
|
||||
std::string language;
|
||||
float score;
|
||||
std::string rationale;
|
||||
};
|
||||
|
||||
class LanguageFitnessScorer {
|
||||
public:
|
||||
// Returns JSON array [{language, score, rationale}, ...] sorted descending
|
||||
static nlohmann::json score(const ASTFeatures& features) {
|
||||
auto profiles = LanguageIdiomProfile::allProfiles();
|
||||
std::vector<FitnessResult> results;
|
||||
results.reserve(profiles.size());
|
||||
for (const auto& prof : profiles) {
|
||||
results.push_back(scoreOne(features, prof));
|
||||
}
|
||||
std::sort(results.begin(), results.end(),
|
||||
[](const FitnessResult& a, const FitnessResult& b){
|
||||
return a.score > b.score;
|
||||
});
|
||||
nlohmann::json arr = nlohmann::json::array();
|
||||
for (const auto& r : results) {
|
||||
arr.push_back({{"language", r.language},
|
||||
{"score", r.score},
|
||||
{"rationale", r.rationale}});
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
private:
|
||||
static FitnessResult scoreOne(const ASTFeatures& f, const LanguageIdiomProfile& p) {
|
||||
float s = 100.0f;
|
||||
std::ostringstream rat;
|
||||
|
||||
float mutDelta = std::abs(f.mutationRatio - p.idealMutationRatio) * 30.0f;
|
||||
s -= mutDelta;
|
||||
if (mutDelta > 0.5f) rat << "mutation-" << static_cast<int>(mutDelta) << " ";
|
||||
|
||||
if (f.recursionShape != p.idealRecursion) {
|
||||
s -= 20.0f;
|
||||
rat << "recursion-mismatch ";
|
||||
}
|
||||
if (f.concurrencyPrimitive != p.idealConcurrency) {
|
||||
s -= 25.0f;
|
||||
rat << "concurrency-mismatch ";
|
||||
}
|
||||
if (f.ioPattern != p.idealIO) {
|
||||
s -= 20.0f;
|
||||
rat << "io-mismatch ";
|
||||
}
|
||||
if (f.typeComplexity != p.idealTypeComplexity) {
|
||||
s -= 15.0f;
|
||||
rat << "type-mismatch ";
|
||||
}
|
||||
|
||||
s = std::max(0.0f, std::min(100.0f, s));
|
||||
|
||||
std::string ratStr = rat.str();
|
||||
if (ratStr.empty()) ratStr = "ideal match";
|
||||
if (!ratStr.empty() && ratStr.back() == ' ') ratStr.pop_back();
|
||||
|
||||
return {p.language, s, ratStr};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace whetstone
|
||||
34
editor/src/LanguageIdiomProfile.h
Normal file
34
editor/src/LanguageIdiomProfile.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "ASTFeatureExtractor.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace whetstone {
|
||||
|
||||
struct LanguageIdiomProfile {
|
||||
std::string language;
|
||||
float idealMutationRatio;
|
||||
ASTFeatures::RecursionShape idealRecursion;
|
||||
ASTFeatures::ConcurrencyPrimitive idealConcurrency;
|
||||
ASTFeatures::IOPattern idealIO;
|
||||
ASTFeatures::TypeComplexity idealTypeComplexity;
|
||||
|
||||
static std::vector<LanguageIdiomProfile> allProfiles() {
|
||||
using RS = ASTFeatures::RecursionShape;
|
||||
using CP = ASTFeatures::ConcurrencyPrimitive;
|
||||
using IO = ASTFeatures::IOPattern;
|
||||
using TC = ASTFeatures::TypeComplexity;
|
||||
return {
|
||||
{"Python", 0.40f, RS::FlatLoop, CP::None, IO::Blocking, TC::None },
|
||||
{"Rust", 0.20f, RS::TreeRecursive, CP::SharedMemory, IO::Async, TC::SimpleGenerics},
|
||||
{"Go", 0.30f, RS::FlatLoop, CP::Channels, IO::Blocking, TC::None },
|
||||
{"Haskell", 0.00f, RS::TailRecursive, CP::None, IO::None, TC::DependentTypes},
|
||||
{"C++", 0.30f, RS::TreeRecursive, CP::SharedMemory, IO::Blocking, TC::SimpleGenerics},
|
||||
{"TypeScript", 0.30f, RS::FlatLoop, CP::None, IO::Async, TC::SimpleGenerics},
|
||||
{"Elixir", 0.10f, RS::TailRecursive, CP::Actors, IO::EventDriven,TC::None },
|
||||
{"Lisp", 0.05f, RS::TailRecursive, CP::None, IO::None, TC::None },
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace whetstone
|
||||
@@ -36,6 +36,9 @@
|
||||
#include "SelfContainmentScorer.h"
|
||||
#include "TaskitemQualityAuditor.h"
|
||||
#include "AgentSessionRecorder.h"
|
||||
#include "ASTFeatureExtractor.h"
|
||||
#include "LanguageIdiomProfile.h"
|
||||
#include "LanguageFitnessScorer.h"
|
||||
#include "graduation/PairUpgradeQueue.h"
|
||||
#include "graduation/UpgradePriorityPolicy.h"
|
||||
#include "graduation/RuntimeAssumptionExtractor.h"
|
||||
@@ -467,6 +470,7 @@ private:
|
||||
std::vector<MCPResource> resources_;
|
||||
std::vector<MCPPrompt> prompts_;
|
||||
std::map<std::string, std::function<json(const json&)>> toolHandlers_;
|
||||
std::map<std::string, json> toolExecuteIdempotencyCache_;
|
||||
RpcCallback rpcCallback_;
|
||||
ResourceReader resourceReader_;
|
||||
bool initialized_ = false;
|
||||
@@ -526,10 +530,12 @@ private:
|
||||
response["id"] = request.contains("id") ? request["id"] : json(nullptr);
|
||||
json toolArr = json::array();
|
||||
for (const auto& t : tools_) {
|
||||
json schema = t.inputSchema;
|
||||
if (!schema.contains("type")) schema["type"] = "object";
|
||||
toolArr.push_back({
|
||||
{"name", t.name},
|
||||
{"description", t.description},
|
||||
{"inputSchema", t.inputSchema},
|
||||
{"inputSchema", schema},
|
||||
{"x-whetstone", {
|
||||
{"contractVersion", t.contractVersion.empty() ? "1.0" : t.contractVersion},
|
||||
{"compatibilityLedger", kCompatibilityLedgerPath}
|
||||
@@ -705,6 +711,36 @@ private:
|
||||
warnings.push_back(message);
|
||||
}
|
||||
|
||||
static long long nowEpochMs() {
|
||||
auto now = std::chrono::system_clock::now().time_since_epoch();
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(now).count();
|
||||
}
|
||||
|
||||
const MCPTool* findToolByName(const std::string& name) const {
|
||||
for (const auto& t : tools_) {
|
||||
if (t.name == name) return &t;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static json validateRequiredFields(const json& schema, const json& input) {
|
||||
json violations = json::array();
|
||||
if (!schema.is_object()) return violations;
|
||||
if (!schema.contains("required") || !schema["required"].is_array()) return violations;
|
||||
for (const auto& req : schema["required"]) {
|
||||
if (!req.is_string()) continue;
|
||||
const std::string key = req.get<std::string>();
|
||||
if (!input.is_object() || !input.contains(key)) {
|
||||
violations.push_back({
|
||||
{"code", "MISSING_REQUIRED_FIELD"},
|
||||
{"path", "input." + key},
|
||||
{"message", "Missing required field: " + key}
|
||||
});
|
||||
}
|
||||
}
|
||||
return violations;
|
||||
}
|
||||
|
||||
static std::string toLowerCopy(std::string s) {
|
||||
std::transform(s.begin(), s.end(), s.begin(),
|
||||
[](unsigned char c) { return (char)std::tolower(c); });
|
||||
@@ -1123,11 +1159,13 @@ private:
|
||||
#include "mcp/RegisterOrchestratorTools.h"
|
||||
#include "mcp/RegisterReviewTools.h"
|
||||
#include "mcp/RegisterArchitectIntakeTools.h"
|
||||
#include "mcp/RegisterToolContractTools.h"
|
||||
#include "mcp/RegisterCodegenTools.h"
|
||||
#include "mcp/RegisterModelingTools.h"
|
||||
#include "mcp/RegisterContextTools.h"
|
||||
#include "mcp/RegisterValidationTools.h"
|
||||
#include "mcp/RegisterMetricsTools.h"
|
||||
#include "mcp/RegisterLanguageFitnessTools.h"
|
||||
#include "mcp/RegisterPortingFoundationTools.h"
|
||||
#include "mcp/RegisterRustSemanticTools.h"
|
||||
#include "mcp/RegisterCppRaisingTools.h"
|
||||
|
||||
19
editor/src/Sprint271IntegrationSummary.h
Normal file
19
editor/src/Sprint271IntegrationSummary.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
namespace whetstone {
|
||||
|
||||
struct Sprint271IntegrationSummary {
|
||||
int stepsCompleted = 5; // 1883-1887
|
||||
bool featureExtractorActive = true;
|
||||
bool idiomProfilesActive = true;
|
||||
bool fitnessScorerActive = true;
|
||||
bool mcpToolActive = true; // whetstone_score_language_fitness
|
||||
int languageProfileCount = 8;
|
||||
bool success = true;
|
||||
|
||||
std::string sprintName() const { return "Sprint 271: LanguageFitnessScorer"; }
|
||||
std::string phase() const { return "Phase 1 - Language Fitness Scorer"; }
|
||||
};
|
||||
|
||||
} // namespace whetstone
|
||||
79
editor/src/mcp/RegisterLanguageFitnessTools.h
Normal file
79
editor/src/mcp/RegisterLanguageFitnessTools.h
Normal file
@@ -0,0 +1,79 @@
|
||||
// Step 1886: MCP wiring for language fitness scoring
|
||||
//
|
||||
// Registers:
|
||||
// whetstone_score_language_fitness
|
||||
//
|
||||
// This file is #included inside the MCPServer class body.
|
||||
|
||||
void registerLanguageFitnessTools() {
|
||||
tools_.push_back({"whetstone_score_language_fitness",
|
||||
"Analyze an AST subtree or spec text and return a ranked list of languages "
|
||||
"best suited to implement it, with per-language score and rationale.",
|
||||
{{"type", "object"}, {"properties", {
|
||||
{"ast", {{"type", "object"},
|
||||
{"description", "JSON AST subtree to score (optional if spec_text provided)."}}},
|
||||
{"spec_text", {{"type", "string"},
|
||||
{"description", "Spec text section to extract features from (used when ast absent)."}}},
|
||||
{"mutation_ratio", {{"type", "number"},
|
||||
{"description", "Override mutation ratio [0,1] (optional)."}}},
|
||||
{"recursion_hint", {{"type", "string"},
|
||||
{"description", "Override recursion shape: none/tail/tree/loop (optional)."}}},
|
||||
{"concurrency_hint", {{"type", "string"},
|
||||
{"description", "Override concurrency: none/channels/shared/actors (optional)."}}},
|
||||
{"io_hint", {{"type", "string"},
|
||||
{"description", "Override I/O pattern: none/blocking/async/event (optional)."}}},
|
||||
{"type_hint", {{"type", "string"},
|
||||
{"description", "Override type complexity: none/generics/dependent (optional)."}}}
|
||||
}}, {"required", json::array()}}
|
||||
});
|
||||
toolHandlers_["whetstone_score_language_fitness"] =
|
||||
[this](const json& args) -> json {
|
||||
return runScoreLanguageFitness(args);
|
||||
};
|
||||
}
|
||||
|
||||
json runScoreLanguageFitness(const json& args) {
|
||||
using AFF = whetstone::ASTFeatures;
|
||||
|
||||
AFF features;
|
||||
|
||||
// Extract from AST if provided
|
||||
if (args.contains("ast") && args["ast"].is_object()) {
|
||||
features = whetstone::ASTFeatureExtractor::extract(args["ast"]);
|
||||
}
|
||||
|
||||
// Override individual dimensions if specified
|
||||
if (args.contains("mutation_ratio") && args["mutation_ratio"].is_number()) {
|
||||
features.mutationRatio = args["mutation_ratio"].get<float>();
|
||||
}
|
||||
if (args.contains("recursion_hint") && args["recursion_hint"].is_string()) {
|
||||
std::string h = args["recursion_hint"].get<std::string>();
|
||||
if (h == "tail") features.recursionShape = AFF::RecursionShape::TailRecursive;
|
||||
else if (h == "tree") features.recursionShape = AFF::RecursionShape::TreeRecursive;
|
||||
else if (h == "loop") features.recursionShape = AFF::RecursionShape::FlatLoop;
|
||||
else features.recursionShape = AFF::RecursionShape::None;
|
||||
}
|
||||
if (args.contains("concurrency_hint") && args["concurrency_hint"].is_string()) {
|
||||
std::string h = args["concurrency_hint"].get<std::string>();
|
||||
if (h == "channels") features.concurrencyPrimitive = AFF::ConcurrencyPrimitive::Channels;
|
||||
else if (h == "shared") features.concurrencyPrimitive = AFF::ConcurrencyPrimitive::SharedMemory;
|
||||
else if (h == "actors") features.concurrencyPrimitive = AFF::ConcurrencyPrimitive::Actors;
|
||||
else features.concurrencyPrimitive = AFF::ConcurrencyPrimitive::None;
|
||||
}
|
||||
if (args.contains("io_hint") && args["io_hint"].is_string()) {
|
||||
std::string h = args["io_hint"].get<std::string>();
|
||||
if (h == "async") features.ioPattern = AFF::IOPattern::Async;
|
||||
else if (h == "event") features.ioPattern = AFF::IOPattern::EventDriven;
|
||||
else if (h == "blocking") features.ioPattern = AFF::IOPattern::Blocking;
|
||||
else features.ioPattern = AFF::IOPattern::None;
|
||||
}
|
||||
if (args.contains("type_hint") && args["type_hint"].is_string()) {
|
||||
std::string h = args["type_hint"].get<std::string>();
|
||||
if (h == "generics") features.typeComplexity = AFF::TypeComplexity::SimpleGenerics;
|
||||
else if (h == "dependent") features.typeComplexity = AFF::TypeComplexity::DependentTypes;
|
||||
else features.typeComplexity = AFF::TypeComplexity::None;
|
||||
}
|
||||
|
||||
json ranked = whetstone::LanguageFitnessScorer::score(features);
|
||||
return {{"success", true}, {"ranked", ranked}};
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
}
|
||||
|
||||
void registerWhetstoneTools() {
|
||||
registerToolContractTools();
|
||||
registerASTTools();
|
||||
registerAnnotationTools();
|
||||
registerFileTools();
|
||||
@@ -153,5 +154,6 @@
|
||||
registerSprint154Tools();
|
||||
registerSprint155Tools();
|
||||
registerOnboardingTools();
|
||||
registerLanguageFitnessTools();
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user