Files
whetstone_DSL/editor/tests/step299_test.cpp
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

259 lines
9.8 KiB
C++

// Step 299: Cross-Type Conflict Detection Tests (12 tests)
// Tests collectCrossTypeConflicts() from AnnotationConflictExtended.h.
#include "AnnotationConflictExtended.h"
#include "ast/Module.h"
#include "ast/Function.h"
#include "ast/Annotation.h"
#include <iostream>
#include <string>
#include <vector>
#include <memory>
static int passed = 0, failed = 0;
#define TEST(name) { std::cout << " " << #name << "... "; }
#define PASS() { std::cout << "PASS\n"; ++passed; }
#define FAIL(msg) { std::cout << "FAIL: " << msg << "\n"; ++failed; }
#define CHECK(cond, msg) if (!(cond)) { FAIL(msg); return; } else {}
static bool hasConflict(const std::vector<CrossTypeConflict>& conflicts,
const std::string& t1, const std::string& t2) {
for (const auto& c : conflicts)
if ((c.type1 == t1 && c.type2 == t2) || (c.type1 == t2 && c.type2 == t1))
return true;
return false;
}
// 1. Pure + Blocking detected
void test_pure_blocking() {
TEST(pure_blocking_conflict);
auto mod = std::make_unique<Module>();
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
fn->addChild("annotations", new PureAnnotation());
auto bl = new BlockingAnnotation(); bl->kind = "io";
fn->addChild("annotations", bl);
mod->addChild("functions", fn);
std::vector<CrossTypeConflict> conflicts;
collectCrossTypeConflicts(mod.get(), conflicts);
CHECK(hasConflict(conflicts, "PureAnnotation", "BlockingAnnotation"),
"expected Pure+Blocking conflict");
PASS();
}
// 2. Atomic + Sync detected
void test_atomic_sync() {
TEST(atomic_sync_conflict);
auto mod = std::make_unique<Module>();
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
auto at = new AtomicAnnotation(); at->consistency = "seq_cst";
fn->addChild("annotations", at);
auto sy = new SyncAnnotation(); sy->primitive = "monitor";
fn->addChild("annotations", sy);
mod->addChild("functions", fn);
std::vector<CrossTypeConflict> conflicts;
collectCrossTypeConflicts(mod.get(), conflicts);
CHECK(hasConflict(conflicts, "AtomicAnnotation", "SyncAnnotation"),
"expected Atomic+Sync conflict");
PASS();
}
// 3. Capture(move) + Owner(Shared_ARC) detected
void test_capture_move_owner_shared() {
TEST(capture_move_owner_shared_conflict);
auto mod = std::make_unique<Module>();
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
auto cap = new CaptureAnnotation(); cap->strategy = "move";
fn->addChild("annotations", cap);
auto own = new OwnerAnnotation(); own->strategy = "Shared_ARC";
fn->addChild("annotations", own);
mod->addChild("functions", fn);
std::vector<CrossTypeConflict> conflicts;
collectCrossTypeConflicts(mod.get(), conflicts);
CHECK(hasConflict(conflicts, "CaptureAnnotation", "OwnerAnnotation"),
"expected Capture(move)+Owner(Shared_ARC) conflict");
PASS();
}
// 4. Capture(value) + Owner(Shared_ARC) -> no conflict
void test_capture_value_owner_shared() {
TEST(capture_value_owner_shared_no_conflict);
auto mod = std::make_unique<Module>();
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
auto cap = new CaptureAnnotation(); cap->strategy = "value";
fn->addChild("annotations", cap);
auto own = new OwnerAnnotation(); own->strategy = "Shared_ARC";
fn->addChild("annotations", own);
mod->addChild("functions", fn);
std::vector<CrossTypeConflict> conflicts;
collectCrossTypeConflicts(mod.get(), conflicts);
CHECK(!hasConflict(conflicts, "CaptureAnnotation", "OwnerAnnotation"),
"should not trigger conflict for value+Shared_ARC");
PASS();
}
// 5. ConstExpr + Exec(async) detected
void test_constexpr_exec_async() {
TEST(constexpr_exec_async_conflict);
auto mod = std::make_unique<Module>();
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
fn->addChild("annotations", new ConstExprAnnotation());
auto exec = new ExecAnnotation(); exec->mode = "async";
fn->addChild("annotations", exec);
mod->addChild("functions", fn);
std::vector<CrossTypeConflict> conflicts;
collectCrossTypeConflicts(mod.get(), conflicts);
CHECK(hasConflict(conflicts, "ConstExprAnnotation", "ExecAnnotation"),
"expected ConstExpr+Exec(async) conflict");
PASS();
}
// 6. ConstExpr + Exec(event) -> no conflict
void test_constexpr_exec_event() {
TEST(constexpr_exec_event_no_conflict);
auto mod = std::make_unique<Module>();
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
fn->addChild("annotations", new ConstExprAnnotation());
auto exec = new ExecAnnotation(); exec->mode = "event";
fn->addChild("annotations", exec);
mod->addChild("functions", fn);
std::vector<CrossTypeConflict> conflicts;
collectCrossTypeConflicts(mod.get(), conflicts);
CHECK(!hasConflict(conflicts, "ConstExprAnnotation", "ExecAnnotation"),
"should not trigger conflict for ConstExpr+event");
PASS();
}
// 7. Inline(Always) + TailCall detected
void test_inline_always_tailcall() {
TEST(inline_always_tailcall_conflict);
auto mod = std::make_unique<Module>();
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
auto inl = new InlineAnnotation(); inl->mode = "Always";
fn->addChild("annotations", inl);
fn->addChild("annotations", new TailCallAnnotation());
mod->addChild("functions", fn);
std::vector<CrossTypeConflict> conflicts;
collectCrossTypeConflicts(mod.get(), conflicts);
CHECK(hasConflict(conflicts, "InlineAnnotation", "TailCallAnnotation"),
"expected Inline(Always)+TailCall conflict");
PASS();
}
// 8. Pack + Layout(aligned) detected
void test_pack_layout_aligned() {
TEST(pack_layout_aligned_conflict);
auto mod = std::make_unique<Module>();
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
fn->addChild("annotations", new PackAnnotation());
auto lay = new LayoutAnnotation(); lay->mode = "aligned";
fn->addChild("annotations", lay);
mod->addChild("functions", fn);
std::vector<CrossTypeConflict> conflicts;
collectCrossTypeConflicts(mod.get(), conflicts);
CHECK(hasConflict(conflicts, "PackAnnotation", "LayoutAnnotation"),
"expected Pack+Layout(aligned) conflict");
PASS();
}
// 9. Pack + Layout(packed) -> no conflict
void test_pack_layout_packed() {
TEST(pack_layout_packed_no_conflict);
auto mod = std::make_unique<Module>();
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
fn->addChild("annotations", new PackAnnotation());
auto lay = new LayoutAnnotation(); lay->mode = "packed";
fn->addChild("annotations", lay);
mod->addChild("functions", fn);
std::vector<CrossTypeConflict> conflicts;
collectCrossTypeConflicts(mod.get(), conflicts);
CHECK(!hasConflict(conflicts, "PackAnnotation", "LayoutAnnotation"),
"should not trigger conflict for Pack+Layout(packed)");
PASS();
}
// 10. No conflicts on clean node -> empty
void test_no_conflicts_clean() {
TEST(no_conflicts_clean_node);
auto mod = std::make_unique<Module>();
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
auto bw = new BitWidthAnnotation(); bw->width = 32;
fn->addChild("annotations", bw);
auto lo = new LoopAnnotation(); lo->hint = "unroll";
fn->addChild("annotations", lo);
mod->addChild("functions", fn);
std::vector<CrossTypeConflict> conflicts;
collectCrossTypeConflicts(mod.get(), conflicts);
CHECK(conflicts.empty(), "expected no conflicts for non-conflicting annotations");
PASS();
}
// 11. Recursive detection in children
void test_recursive_detection() {
TEST(recursive_conflict_in_children);
auto mod = std::make_unique<Module>();
// Conflict is on a child function, not the module
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
fn->addChild("annotations", new PureAnnotation());
auto bl = new BlockingAnnotation(); bl->kind = "io";
fn->addChild("annotations", bl);
mod->addChild("functions", fn);
std::vector<CrossTypeConflict> conflicts;
collectCrossTypeConflicts(mod.get(), conflicts);
CHECK(conflicts.size() == 1, "expected 1 conflict from child, got " + std::to_string(conflicts.size()));
CHECK(conflicts[0].nodeId == "fn1", "conflict should be on fn1");
PASS();
}
// 12. Multiple conflicts on same node
void test_multiple_conflicts() {
TEST(multiple_conflicts_same_node);
auto mod = std::make_unique<Module>();
auto fn = new Function(); fn->id = "fn1"; fn->name = "f";
// Pure + Blocking
fn->addChild("annotations", new PureAnnotation());
auto bl = new BlockingAnnotation(); bl->kind = "io";
fn->addChild("annotations", bl);
// Atomic + Sync
auto at = new AtomicAnnotation(); at->consistency = "seq_cst";
fn->addChild("annotations", at);
auto sy = new SyncAnnotation(); sy->primitive = "monitor";
fn->addChild("annotations", sy);
mod->addChild("functions", fn);
std::vector<CrossTypeConflict> conflicts;
collectCrossTypeConflicts(mod.get(), conflicts);
CHECK(conflicts.size() >= 2, "expected at least 2 conflicts, got " + std::to_string(conflicts.size()));
CHECK(hasConflict(conflicts, "PureAnnotation", "BlockingAnnotation"), "missing Pure+Blocking");
CHECK(hasConflict(conflicts, "AtomicAnnotation", "SyncAnnotation"), "missing Atomic+Sync");
PASS();
}
int main() {
std::cout << "=== Step 299: Cross-Type Conflict Detection Tests ===\n";
test_pure_blocking();
test_atomic_sync();
test_capture_move_owner_shared();
test_capture_value_owner_shared();
test_constexpr_exec_async();
test_constexpr_exec_event();
test_inline_always_tailcall();
test_pack_layout_aligned();
test_pack_layout_packed();
test_no_conflicts_clean();
test_recursive_detection();
test_multiple_conflicts();
std::cout << "\nResults: " << passed << "/" << (passed + failed) << " passed\n";
return failed > 0 ? 1 : 0;
}