Step 105: add optimization controls panel

This commit is contained in:
Bill
2026-02-09 11:02:25 -07:00
parent 8a85ba298d
commit f7da8eee8d
4 changed files with 228 additions and 0 deletions

View File

@@ -33,6 +33,8 @@
#include "MemoryStrategyInference.h"
#include "AnnotationConflict.h"
#include "StrategyDashboard.h"
#include "TransformEngine.h"
#include "StrategyAwareOptimizer.h"
#include "CrossLanguageProjector.h"
#include "ast/Generator.h"
#include "ast/Annotation.h"
@@ -127,6 +129,9 @@ struct EditorState {
std::vector<MemoryStrategyInference::Suggestion> suggestions;
bool showSuggestionPopup = false;
MemoryStrategyInference::Suggestion suggestionPopup;
std::string optimizeFoldSummary;
std::string optimizeDeadCodeSummary;
std::string optimizeApplySummary;
BufferState* active() { return activeBuffer; }
@@ -523,6 +528,20 @@ struct EditorState {
(preserved ? "yes" : "no") + ").\n";
}
void refreshActiveTextFromAST() {
if (!active()) return;
active()->editBuf = active()->sync.getText();
active()->editor.setContent(active()->editBuf, active()->language);
active()->highlightsDirty = true;
active()->modified = true;
if (lsp && active()->path.rfind("(untitled", 0) != 0) {
active()->lspVersion += 1;
lsp->didChange(toFileUri(active()->path), active()->editBuf, active()->lspVersion);
}
analysisPending = true;
analysisLastChange = ImGui::GetTime();
}
void updateCursorPos(int bytePos) {
if (!active()) return;
active()->cursorLine = 1;
@@ -591,6 +610,35 @@ static int countAnnotationNodes(const ASTNode* node) {
return count;
}
static std::string findOptimizationBlockReason(const ASTNode* node) {
if (!node) return "";
for (auto* anno : node->getChildren("annotations")) {
if (anno->conceptType == "OwnerAnnotation") {
auto* oa = static_cast<const OwnerAnnotation*>(anno);
if (oa->strategy == "Single") {
return "@Owner(Single) blocks optimization (aliasing risk)";
}
}
if (anno->conceptType == "DeallocateAnnotation") {
auto* da = static_cast<const DeallocateAnnotation*>(anno);
if (da->strategy == "Explicit") {
return "@Deallocate(Explicit) blocks optimization (reorder risk)";
}
}
if (anno->conceptType == "AllocateAnnotation") {
auto* aa = static_cast<const AllocateAnnotation*>(anno);
if (aa->strategy == "Static") {
return "@Allocate(Static) blocks optimization (dynamic alloc risk)";
}
}
}
for (auto* child : node->allChildren()) {
std::string found = findOptimizationBlockReason(child);
if (!found.empty()) return found;
}
return "";
}
// ---------------------------------------------------------------------------
// ImGui InputTextMultiline with std::string resize callback
@@ -1954,6 +2002,123 @@ int main(int, char**) {
ImGui::EndTabItem();
}
// Optimization controls
if (ImGui::BeginTabItem("Optimize")) {
ImGui::PushFont(uiFont);
Module* ast = state.active() ? state.active()->sync.getAST() : nullptr;
if (!state.active()) {
ImGui::TextDisabled("(no active buffer)");
} else if (!ast) {
ImGui::TextDisabled("(no AST)");
} else if (state.active()->readOnly) {
ImGui::TextDisabled("(read-only buffer)");
} else {
std::string blockReason = findOptimizationBlockReason(ast);
bool blocked = !blockReason.empty();
auto showBlockedTooltip = [&](const std::string& reason) {
if (!reason.empty() &&
ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
ImGui::BeginTooltip();
ImGui::TextUnformatted(reason.c_str());
ImGui::EndTooltip();
}
};
if (blocked) ImGui::BeginDisabled();
if (ImGui::Button("Constant Fold")) {
TransformEngine engine;
engine.setRoot(ast);
auto res = engine.constantFolding();
std::string summary = "Constant Fold: ";
if (res.applied) {
summary += "applied (" + std::to_string(res.nodesModified) + " nodes)";
} else {
summary += "no changes";
}
if (!res.warning.empty()) {
summary += " — warning: " + res.warning;
state.outputLog += res.warning + "\n";
}
state.optimizeFoldSummary = summary;
state.outputLog += summary + "\n";
if (res.applied) state.refreshActiveTextFromAST();
}
showBlockedTooltip(blockReason);
if (blocked) ImGui::EndDisabled();
if (!state.optimizeFoldSummary.empty()) {
ImGui::TextWrapped("%s", state.optimizeFoldSummary.c_str());
}
ImGui::Separator();
if (blocked) ImGui::BeginDisabled();
if (ImGui::Button("Dead Code Elimination")) {
TransformEngine engine;
engine.setRoot(ast);
auto res = engine.deadCodeElimination();
std::string summary = "Dead Code Elimination: ";
if (res.applied) {
summary += "applied (" + std::to_string(res.nodesModified) + " nodes)";
} else {
summary += "no changes";
}
if (!res.warning.empty()) {
summary += " — warning: " + res.warning;
state.outputLog += res.warning + "\n";
}
state.optimizeDeadCodeSummary = summary;
state.outputLog += summary + "\n";
if (res.applied) state.refreshActiveTextFromAST();
}
showBlockedTooltip(blockReason);
if (blocked) ImGui::EndDisabled();
if (!state.optimizeDeadCodeSummary.empty()) {
ImGui::TextWrapped("%s", state.optimizeDeadCodeSummary.c_str());
}
ImGui::Separator();
if (blocked) ImGui::BeginDisabled();
if (ImGui::Button("Apply All")) {
TransformEngine engine;
engine.setRoot(ast);
auto results = engine.applyAll();
int totalNodes = 0;
bool applied = false;
std::string warnings;
for (const auto& res : results) {
totalNodes += res.nodesModified;
if (res.applied) applied = true;
if (!res.warning.empty()) {
if (!warnings.empty()) warnings += "; ";
warnings += res.warning;
}
}
std::string summary = "Apply All: ";
if (applied) {
summary += "applied (" + std::to_string(totalNodes) + " nodes)";
} else {
summary += "no changes";
}
if (!warnings.empty()) {
summary += " — warning: " + warnings;
state.outputLog += warnings + "\n";
}
state.optimizeApplySummary = summary;
state.outputLog += summary + "\n";
if (applied) state.refreshActiveTextFromAST();
}
showBlockedTooltip(blockReason);
if (blocked) ImGui::EndDisabled();
if (!state.optimizeApplySummary.empty()) {
ImGui::TextWrapped("%s", state.optimizeApplySummary.c_str());
}
}
ImGui::PopFont();
ImGui::EndTabItem();
}
// AST view
if (ImGui::BeginTabItem("AST")) {
ImGui::PushFont(monoFont);