Files
whetstone_DSL/editor/src/AnnotationConflictExtended.h
Bill 87615a7187 Steps 297-302: Phase 11b complete + Phase 11c step 302 (68/68 tests)
Phase 11b — Validation & Conflict Completion:
- Step 297: Subject 2-4 validation rules E0600-E0805 (12/12)
- Step 298: Subject 5-8 validation rules E0900-E1202 (12/12)
- Step 299: Cross-type conflict detection, 6 conflict pairs (12/12)
- Step 300: TransformEngineExtended — float folding, dead var, annotation-aware (12/12)
- Step 301: Phase 11b integration tests (8/8)

Phase 11c — Parser Deepening (start):
- Step 302: New AST nodes — ClassDeclaration, InterfaceDeclaration,
  MethodDeclaration, GenericType, TypeParameter with JSON roundtrip (12/12)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 16:53:23 +00:00

91 lines
3.5 KiB
C++

#pragma once
// Step 299: Cross-type annotation conflict detection
//
// Detects conflicts between different annotation types on the same node.
// This extends AnnotationConflict.h which handles same-family parent/child
// conflicts. This file detects semantic conflicts across annotation families.
#include <string>
#include <vector>
#include <map>
#include <functional>
#include "ast/ASTNode.h"
#include "ast/Annotation.h"
#include "AnnotationConflict.h"
struct CrossTypeConflict {
std::string type1;
std::string type2;
std::string message;
std::string nodeId;
};
inline void collectCrossTypeConflicts(const ASTNode* node,
std::vector<CrossTypeConflict>& out) {
if (!node) return;
auto annos = node->getChildren("annotations");
// Build a set of annotation types present on this node
std::map<std::string, const ASTNode*> present;
for (const auto* a : annos) {
present[a->conceptType] = a;
}
// Check conflict pairs
auto checkPair = [&](const std::string& t1, const std::string& t2,
const std::string& msg,
std::function<bool()> condition = nullptr) {
if (present.count(t1) && present.count(t2)) {
if (!condition || condition()) {
out.push_back({t1, t2, msg, node->id});
}
}
};
// 1. @Pure + @Blocking → "Pure function cannot be blocking"
checkPair("PureAnnotation", "BlockingAnnotation",
"Pure function cannot be blocking");
// 2. @Atomic + @Sync → "Atomic operations conflict with sync primitives"
checkPair("AtomicAnnotation", "SyncAnnotation",
"Atomic operations conflict with sync primitives");
// 3. @Capture(move) + @Owner(Shared_ARC) → "Move capture conflicts with shared ownership"
checkPair("CaptureAnnotation", "OwnerAnnotation",
"Move capture conflicts with shared ownership",
[&]() {
auto* cap = static_cast<const CaptureAnnotation*>(present["CaptureAnnotation"]);
auto* own = static_cast<const OwnerAnnotation*>(present["OwnerAnnotation"]);
return cap->strategy == "move" && own->strategy == "Shared_ARC";
});
// 4. @ConstExpr + @Exec(async) → "Compile-time eval conflicts with async execution"
checkPair("ConstExprAnnotation", "ExecAnnotation",
"Compile-time eval conflicts with async execution",
[&]() {
auto* exec = static_cast<const ExecAnnotation*>(present["ExecAnnotation"]);
return exec->mode == "async";
});
// 5. @Inline(Always) + @TailCall → "Always-inline conflicts with tail call optimization"
checkPair("InlineAnnotation", "TailCallAnnotation",
"Always-inline conflicts with tail call optimization",
[&]() {
auto* inl = static_cast<const InlineAnnotation*>(present["InlineAnnotation"]);
return inl->mode == "Always";
});
// 6. @Pack + @Layout(aligned) → "Packed layout conflicts with alignment"
checkPair("PackAnnotation", "LayoutAnnotation",
"Packed layout conflicts with alignment",
[&]() {
auto* lay = static_cast<const LayoutAnnotation*>(present["LayoutAnnotation"]);
return lay->mode == "aligned";
});
// Recurse into children
for (auto* child : node->allChildren()) {
collectCrossTypeConflicts(child, out);
}
}