Files
whetstone_DSL/editor/tests/step43_test.cpp
Bill d966eae2cf Step 43 TDD test: Memory strategy code generation
Tests canonical annotation classes (DeallocateAnnotation, LifetimeAnnotation,
ReclaimAnnotation, OwnerAnnotation, AllocateAnnotation) exist and inherit from
Annotation. Tests C++ generation: @Deallocate(Explicit)->raw pointers,
@Lifetime(RAII)->unique_ptr, @Reclaim(Tracing)->shared_ptr,
@Owner(Shared_ARC)->shared_ptr. Verifies old DerefStrategy backward compat.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 08:20:04 -07:00

226 lines
7.5 KiB
C++

// Step 43 TDD Test: Memory strategy code generation
//
// Tests the refactoring from DerefStrategy to canonical annotation types
// and their effect on C++ code generation:
// 1. DeallocateAnnotation("Explicit") → raw pointers with new/delete
// 2. LifetimeAnnotation("RAII") → std::unique_ptr<T>, RAII destructors
// 3. ReclaimAnnotation("Tracing") → std::shared_ptr<T> for GC-like ref counting
// 4. OwnerAnnotation("Single") → std::unique_ptr<T> with strict ownership
// 5. OwnerAnnotation("Shared_ARC") → std::shared_ptr<T> with ARC semantics
// 6. New annotation classes exist and inherit from Annotation
// 7. DerefStrategy still works as deprecated wrapper
//
// Will fail to compile until canonical annotation classes are created in Annotation.h.
#include <iostream>
#include <string>
#include <cassert>
#include "ast/Generator.h"
static bool contains(const std::string& haystack, const std::string& needle) {
return haystack.find(needle) != std::string::npos;
}
int main() {
int passed = 0;
int failed = 0;
// --- Test 1: DeallocateAnnotation exists and inherits from Annotation ---
{
DeallocateAnnotation anno;
anno.strategy = "Explicit";
Annotation* base = &anno;
(void)base;
assert(anno.strategy == "Explicit" && "Should store strategy");
std::cout << "Test 1 PASS: DeallocateAnnotation exists with strategy field" << std::endl;
++passed;
}
// --- Test 2: LifetimeAnnotation exists ---
{
LifetimeAnnotation anno;
anno.strategy = "RAII";
Annotation* base = &anno;
(void)base;
assert(anno.strategy == "RAII" && "Should store strategy");
std::cout << "Test 2 PASS: LifetimeAnnotation exists with strategy field" << std::endl;
++passed;
}
// --- Test 3: ReclaimAnnotation exists ---
{
ReclaimAnnotation anno;
anno.strategy = "Tracing";
Annotation* base = &anno;
(void)base;
assert(anno.strategy == "Tracing" && "Should store strategy");
std::cout << "Test 3 PASS: ReclaimAnnotation exists with strategy field" << std::endl;
++passed;
}
// --- Test 4: OwnerAnnotation exists ---
{
OwnerAnnotation anno;
anno.strategy = "Single";
Annotation* base = &anno;
(void)base;
assert(anno.strategy == "Single" && "Should store strategy");
std::cout << "Test 4 PASS: OwnerAnnotation exists with strategy field" << std::endl;
++passed;
}
// --- Test 5: AllocateAnnotation exists ---
{
AllocateAnnotation anno;
anno.strategy = "Static";
Annotation* base = &anno;
(void)base;
assert(anno.strategy == "Static" && "Should store strategy");
std::cout << "Test 5 PASS: AllocateAnnotation exists with strategy field" << std::endl;
++passed;
}
// --- Test 6: @Deallocate(Explicit) → raw pointer in C++ ---
{
// Build a function with DeallocateAnnotation
Function fn("f1", "allocateWidget");
PrimitiveType* retType = new PrimitiveType("t1", "int");
fn.setChild("returnType", retType);
DeallocateAnnotation* anno = new DeallocateAnnotation();
anno->strategy = "Explicit";
fn.addChild("annotations", anno);
// Add a variable declaration in body
Variable* var = new Variable("v1", "widget");
CustomType* widgetType = new CustomType("t2", "Widget");
var->setChild("type", widgetType);
fn.addChild("body", var);
CppGenerator gen;
std::string output = gen.generate(&fn);
// With @Deallocate(Explicit), should use raw pointers
assert(contains(output, "Widget") && "Should contain the type name");
assert(contains(output, "allocateWidget") && "Should contain function name");
// Should produce raw pointer syntax (Widget* or new Widget)
assert((contains(output, "*") || contains(output, "new")) &&
"@Deallocate(Explicit) should produce raw pointer or new operator");
std::cout << "Test 6 PASS: @Deallocate(Explicit) produces raw pointer code" << std::endl;
++passed;
delete widgetType;
delete var;
delete anno;
delete retType;
}
// --- Test 7: @Lifetime(RAII) → unique_ptr in C++ ---
{
Function fn("f1", "createWidget");
PrimitiveType* retType = new PrimitiveType("t1", "int");
fn.setChild("returnType", retType);
LifetimeAnnotation* anno = new LifetimeAnnotation();
anno->strategy = "RAII";
fn.addChild("annotations", anno);
Variable* var = new Variable("v1", "widget");
CustomType* widgetType = new CustomType("t2", "Widget");
var->setChild("type", widgetType);
fn.addChild("body", var);
CppGenerator gen;
std::string output = gen.generate(&fn);
assert(contains(output, "unique_ptr") && "@Lifetime(RAII) should produce unique_ptr");
std::cout << "Test 7 PASS: @Lifetime(RAII) produces unique_ptr code" << std::endl;
++passed;
delete widgetType;
delete var;
delete anno;
delete retType;
}
// --- Test 8: @Reclaim(Tracing) → shared_ptr in C++ ---
{
Function fn("f1", "getWidget");
PrimitiveType* retType = new PrimitiveType("t1", "int");
fn.setChild("returnType", retType);
ReclaimAnnotation* anno = new ReclaimAnnotation();
anno->strategy = "Tracing";
fn.addChild("annotations", anno);
Variable* var = new Variable("v1", "widget");
CustomType* widgetType = new CustomType("t2", "Widget");
var->setChild("type", widgetType);
fn.addChild("body", var);
CppGenerator gen;
std::string output = gen.generate(&fn);
assert(contains(output, "shared_ptr") && "@Reclaim(Tracing) should produce shared_ptr");
std::cout << "Test 8 PASS: @Reclaim(Tracing) produces shared_ptr code" << std::endl;
++passed;
delete widgetType;
delete var;
delete anno;
delete retType;
}
// --- Test 9: @Owner(Shared_ARC) → shared_ptr in C++ ---
{
Function fn("f1", "shareWidget");
PrimitiveType* retType = new PrimitiveType("t1", "int");
fn.setChild("returnType", retType);
OwnerAnnotation* anno = new OwnerAnnotation();
anno->strategy = "Shared_ARC";
fn.addChild("annotations", anno);
Variable* var = new Variable("v1", "widget");
CustomType* widgetType = new CustomType("t2", "Widget");
var->setChild("type", widgetType);
fn.addChild("body", var);
CppGenerator gen;
std::string output = gen.generate(&fn);
assert(contains(output, "shared_ptr") && "@Owner(Shared_ARC) should produce shared_ptr");
std::cout << "Test 9 PASS: @Owner(Shared_ARC) produces shared_ptr code" << std::endl;
++passed;
delete widgetType;
delete var;
delete anno;
delete retType;
}
// --- Test 10: Old DerefStrategy still works (backward compat) ---
{
DerefStrategy deref("d1", "imperative");
Annotation* base = &deref;
(void)base;
assert(deref.strategy == "imperative" && "Old DerefStrategy should still work");
std::cout << "Test 10 PASS: DerefStrategy still functional (backward compat)" << std::endl;
++passed;
}
// --- Summary ---
std::cout << "\n=== Step 43 Results: " << passed << " passed, " << failed << " failed ===" << std::endl;
return failed > 0 ? 1 : 0;
}