Steps 272-277: Phase 10c — type system, concurrency & scope annotations (68/68 tests)
- Step 272: Type layout/constraints — BitWidth, Endian, Layout, Nullability, Variance (37 tests) - Step 273: Type identity/mutability — Identity, Mut, TypeState (25 tests) - Step 274: Concurrency primitives — Atomic, Sync, ThreadModel, MemoryBarrier (25 tests) - Step 275: Async/error handling — Exec, Blocking, Parallel, Trap, Exception, Panic (36 tests) - Step 276: Scope/namespace — Binding, Lookup, Capture, Visibility, Namespace, Scope (32 tests) - Step 277: Integration tests — cross-subject workflows, sidecar roundtrip, RPC (16 tests) - 24 new annotation classes with JSON roundtrip, compact AST, sidecar persistence - Generic fallback in getSemanticAnnotations RPC for extensible annotation queries Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
201
editor/tests/step272_test.cpp
Normal file
201
editor/tests/step272_test.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
// Step 272: Type System Annotations — Layout & Constraints (12 tests)
|
||||
// Tests: BitWidthAnnotation, EndianAnnotation, LayoutAnnotation,
|
||||
// NullabilityAnnotation, VarianceAnnotation
|
||||
// + JSON roundtrip + compact AST integration
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "ast/ASTNode.h"
|
||||
#include "ast/Module.h"
|
||||
#include "ast/Function.h"
|
||||
#include "ast/Annotation.h"
|
||||
#include "ast/Serialization.h"
|
||||
#include "ASTUtils.h"
|
||||
#include "CompactAST.h"
|
||||
|
||||
static int passed = 0;
|
||||
static int failed = 0;
|
||||
|
||||
static void check(bool cond, const std::string& name) {
|
||||
if (cond) { std::cout << " PASS: " << name << "\n"; ++passed; }
|
||||
else { std::cout << " FAIL: " << name << "\n"; ++failed; }
|
||||
}
|
||||
|
||||
// --- Test 1: BitWidthAnnotation creation and fields ---
|
||||
static void test_bitwidth_annotation() {
|
||||
BitWidthAnnotation bw;
|
||||
check(bw.conceptType == "BitWidthAnnotation", "conceptType is BitWidthAnnotation");
|
||||
bw.width = 32;
|
||||
check(bw.width == 32, "width field set to 32");
|
||||
}
|
||||
|
||||
// --- Test 2: EndianAnnotation creation and fields ---
|
||||
static void test_endian_annotation() {
|
||||
EndianAnnotation ea;
|
||||
check(ea.conceptType == "EndianAnnotation", "conceptType is EndianAnnotation");
|
||||
ea.order = "big";
|
||||
check(ea.order == "big", "order field set to big");
|
||||
}
|
||||
|
||||
// --- Test 3: LayoutAnnotation creation and fields ---
|
||||
static void test_layout_annotation() {
|
||||
LayoutAnnotation la;
|
||||
check(la.conceptType == "LayoutAnnotation", "conceptType is LayoutAnnotation");
|
||||
la.mode = "packed";
|
||||
la.alignment = 8;
|
||||
check(la.mode == "packed", "mode field set to packed");
|
||||
check(la.alignment == 8, "alignment field set to 8");
|
||||
}
|
||||
|
||||
// --- Test 4: NullabilityAnnotation creation and fields ---
|
||||
static void test_nullability_annotation() {
|
||||
NullabilityAnnotation na;
|
||||
check(na.conceptType == "NullabilityAnnotation", "conceptType is NullabilityAnnotation");
|
||||
na.nullable = true;
|
||||
na.strategy = "strict";
|
||||
check(na.nullable == true, "nullable field set to true");
|
||||
check(na.strategy == "strict", "strategy field set to strict");
|
||||
}
|
||||
|
||||
// --- Test 5: VarianceAnnotation creation and fields ---
|
||||
static void test_variance_annotation() {
|
||||
VarianceAnnotation va;
|
||||
check(va.conceptType == "VarianceAnnotation", "conceptType is VarianceAnnotation");
|
||||
va.variance = "covariant";
|
||||
check(va.variance == "covariant", "variance field set to covariant");
|
||||
}
|
||||
|
||||
// --- Test 6: BitWidthAnnotation JSON roundtrip ---
|
||||
static void test_bitwidth_json_roundtrip() {
|
||||
auto* bw = new BitWidthAnnotation();
|
||||
bw->id = "bw1";
|
||||
bw->width = 64;
|
||||
json j = toJson(bw);
|
||||
check(j["concept"] == "BitWidthAnnotation", "JSON concept correct");
|
||||
check(j["properties"]["width"] == 64, "JSON width correct");
|
||||
ASTNode* restored = fromJson(j);
|
||||
auto* rbw = dynamic_cast<BitWidthAnnotation*>(restored);
|
||||
check(rbw != nullptr, "fromJson creates BitWidthAnnotation");
|
||||
check(rbw->width == 64, "roundtrip width preserved");
|
||||
delete bw;
|
||||
delete restored;
|
||||
}
|
||||
|
||||
// --- Test 7: LayoutAnnotation JSON roundtrip ---
|
||||
static void test_layout_json_roundtrip() {
|
||||
auto* la = new LayoutAnnotation();
|
||||
la->id = "la1";
|
||||
la->mode = "aligned";
|
||||
la->alignment = 16;
|
||||
json j = toJson(la);
|
||||
ASTNode* restored = fromJson(j);
|
||||
auto* rla = dynamic_cast<LayoutAnnotation*>(restored);
|
||||
check(rla != nullptr, "fromJson creates LayoutAnnotation");
|
||||
check(rla->mode == "aligned", "roundtrip mode preserved");
|
||||
check(rla->alignment == 16, "roundtrip alignment preserved");
|
||||
delete la;
|
||||
delete restored;
|
||||
}
|
||||
|
||||
// --- Test 8: NullabilityAnnotation JSON roundtrip ---
|
||||
static void test_nullability_json_roundtrip() {
|
||||
auto* na = new NullabilityAnnotation();
|
||||
na->id = "na1";
|
||||
na->nullable = true;
|
||||
na->strategy = "nullable";
|
||||
json j = toJson(na);
|
||||
check(j["properties"]["nullable"] == true, "JSON nullable correct");
|
||||
ASTNode* restored = fromJson(j);
|
||||
auto* rna = dynamic_cast<NullabilityAnnotation*>(restored);
|
||||
check(rna != nullptr, "fromJson creates NullabilityAnnotation");
|
||||
check(rna->nullable == true, "roundtrip nullable preserved");
|
||||
check(rna->strategy == "nullable", "roundtrip strategy preserved");
|
||||
delete na;
|
||||
delete restored;
|
||||
}
|
||||
|
||||
// --- Test 9: All 5 types survive createNode factory ---
|
||||
static void test_create_node_factory() {
|
||||
std::vector<std::string> types = {
|
||||
"BitWidthAnnotation", "EndianAnnotation", "LayoutAnnotation",
|
||||
"NullabilityAnnotation", "VarianceAnnotation"
|
||||
};
|
||||
for (const auto& t : types) {
|
||||
ASTNode* node = createNode(t);
|
||||
check(node != nullptr && node->conceptType == t,
|
||||
"createNode(" + t + ") works");
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Test 10: Compact AST shows bitWidth in semantic summary ---
|
||||
static void test_compact_ast_bitwidth() {
|
||||
auto* func = new Function();
|
||||
func->id = "f1";
|
||||
func->name = "getInt";
|
||||
auto* bw = new BitWidthAnnotation();
|
||||
bw->width = 32;
|
||||
func->addChild("annotations", bw);
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(!sem.empty(), "semantic summary not empty");
|
||||
check(sem.contains("bitWidth"), "bitWidth in semantic summary");
|
||||
check(sem["bitWidth"] == 32, "bitWidth value correct");
|
||||
delete func;
|
||||
}
|
||||
|
||||
// --- Test 11: Compact AST shows layout in semantic summary ---
|
||||
static void test_compact_ast_layout() {
|
||||
auto* func = new Function();
|
||||
func->id = "f2";
|
||||
func->name = "pack";
|
||||
auto* la = new LayoutAnnotation();
|
||||
la->mode = "packed";
|
||||
la->alignment = 4;
|
||||
func->addChild("annotations", la);
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem.contains("layout"), "layout in semantic summary");
|
||||
check(sem["layout"]["mode"] == "packed", "layout mode correct");
|
||||
check(sem["layout"]["alignment"] == 4, "layout alignment correct");
|
||||
delete func;
|
||||
}
|
||||
|
||||
// --- Test 12: Multiple type annotations on one node ---
|
||||
static void test_multiple_type_annotations() {
|
||||
auto* func = new Function();
|
||||
func->id = "f3";
|
||||
func->name = "convert";
|
||||
auto* bw = new BitWidthAnnotation();
|
||||
bw->width = 16;
|
||||
func->addChild("annotations", bw);
|
||||
auto* ea = new EndianAnnotation();
|
||||
ea->order = "little";
|
||||
func->addChild("annotations", ea);
|
||||
auto* va = new VarianceAnnotation();
|
||||
va->variance = "invariant";
|
||||
func->addChild("annotations", va);
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem["bitWidth"] == 16, "bitWidth present in multi-annotation");
|
||||
check(sem["endian"] == "little", "endian present in multi-annotation");
|
||||
check(sem["variance"] == "invariant", "variance present in multi-annotation");
|
||||
delete func;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "=== Step 272: Type System Annotations — Layout & Constraints ===\n";
|
||||
test_bitwidth_annotation();
|
||||
test_endian_annotation();
|
||||
test_layout_annotation();
|
||||
test_nullability_annotation();
|
||||
test_variance_annotation();
|
||||
test_bitwidth_json_roundtrip();
|
||||
test_layout_json_roundtrip();
|
||||
test_nullability_json_roundtrip();
|
||||
test_create_node_factory();
|
||||
test_compact_ast_bitwidth();
|
||||
test_compact_ast_layout();
|
||||
test_multiple_type_annotations();
|
||||
std::cout << "\nResults: " << passed << " passed, " << failed << " failed out of "
|
||||
<< (passed + failed) << "\n";
|
||||
return failed > 0 ? 1 : 0;
|
||||
}
|
||||
205
editor/tests/step273_test.cpp
Normal file
205
editor/tests/step273_test.cpp
Normal file
@@ -0,0 +1,205 @@
|
||||
// Step 273: Type System Annotations — Identity & Mutability (12 tests)
|
||||
// Tests: IdentityAnnotation, MutAnnotation, TypeStateAnnotation
|
||||
// + JSON roundtrip + compact AST + all 8 type annotation types together
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "ast/ASTNode.h"
|
||||
#include "ast/Module.h"
|
||||
#include "ast/Function.h"
|
||||
#include "ast/Annotation.h"
|
||||
#include "ast/Serialization.h"
|
||||
#include "ASTUtils.h"
|
||||
#include "CompactAST.h"
|
||||
|
||||
static int passed = 0;
|
||||
static int failed = 0;
|
||||
|
||||
static void check(bool cond, const std::string& name) {
|
||||
if (cond) { std::cout << " PASS: " << name << "\n"; ++passed; }
|
||||
else { std::cout << " FAIL: " << name << "\n"; ++failed; }
|
||||
}
|
||||
|
||||
// --- Test 1: IdentityAnnotation creation ---
|
||||
static void test_identity_annotation() {
|
||||
IdentityAnnotation ia;
|
||||
check(ia.conceptType == "IdentityAnnotation", "conceptType is IdentityAnnotation");
|
||||
ia.mode = "nominal";
|
||||
check(ia.mode == "nominal", "mode field set to nominal");
|
||||
}
|
||||
|
||||
// --- Test 2: MutAnnotation creation ---
|
||||
static void test_mut_annotation() {
|
||||
MutAnnotation ma;
|
||||
check(ma.conceptType == "MutAnnotation", "conceptType is MutAnnotation");
|
||||
ma.depth = "deep";
|
||||
check(ma.depth == "deep", "depth field set to deep");
|
||||
}
|
||||
|
||||
// --- Test 3: TypeStateAnnotation creation ---
|
||||
static void test_typestate_annotation() {
|
||||
TypeStateAnnotation ts;
|
||||
check(ts.conceptType == "TypeStateAnnotation", "conceptType is TypeStateAnnotation");
|
||||
ts.state = "reified";
|
||||
check(ts.state == "reified", "state field set to reified");
|
||||
}
|
||||
|
||||
// --- Test 4: IdentityAnnotation JSON roundtrip ---
|
||||
static void test_identity_json_roundtrip() {
|
||||
auto* ia = new IdentityAnnotation();
|
||||
ia->id = "id1";
|
||||
ia->mode = "structural";
|
||||
json j = toJson(ia);
|
||||
check(j["properties"]["mode"] == "structural", "JSON mode correct");
|
||||
ASTNode* restored = fromJson(j);
|
||||
auto* ria = dynamic_cast<IdentityAnnotation*>(restored);
|
||||
check(ria != nullptr, "fromJson creates IdentityAnnotation");
|
||||
check(ria->mode == "structural", "roundtrip mode preserved");
|
||||
delete ia;
|
||||
delete restored;
|
||||
}
|
||||
|
||||
// --- Test 5: MutAnnotation JSON roundtrip ---
|
||||
static void test_mut_json_roundtrip() {
|
||||
auto* ma = new MutAnnotation();
|
||||
ma->id = "mut1";
|
||||
ma->depth = "interior";
|
||||
json j = toJson(ma);
|
||||
ASTNode* restored = fromJson(j);
|
||||
auto* rma = dynamic_cast<MutAnnotation*>(restored);
|
||||
check(rma != nullptr, "fromJson creates MutAnnotation");
|
||||
check(rma->depth == "interior", "roundtrip depth preserved");
|
||||
delete ma;
|
||||
delete restored;
|
||||
}
|
||||
|
||||
// --- Test 6: TypeStateAnnotation JSON roundtrip ---
|
||||
static void test_typestate_json_roundtrip() {
|
||||
auto* ts = new TypeStateAnnotation();
|
||||
ts->id = "ts1";
|
||||
ts->state = "erased";
|
||||
json j = toJson(ts);
|
||||
ASTNode* restored = fromJson(j);
|
||||
auto* rts = dynamic_cast<TypeStateAnnotation*>(restored);
|
||||
check(rts != nullptr, "fromJson creates TypeStateAnnotation");
|
||||
check(rts->state == "erased", "roundtrip state preserved");
|
||||
delete ts;
|
||||
delete restored;
|
||||
}
|
||||
|
||||
// --- Test 7: createNode factory for Step 273 types ---
|
||||
static void test_create_node_factory() {
|
||||
std::vector<std::string> types = {
|
||||
"IdentityAnnotation", "MutAnnotation", "TypeStateAnnotation"
|
||||
};
|
||||
for (const auto& t : types) {
|
||||
ASTNode* node = createNode(t);
|
||||
check(node != nullptr && node->conceptType == t,
|
||||
"createNode(" + t + ") works");
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Test 8: Compact AST shows identity in semantic summary ---
|
||||
static void test_compact_ast_identity() {
|
||||
auto* func = new Function();
|
||||
func->id = "f1";
|
||||
func->name = "compare";
|
||||
auto* ia = new IdentityAnnotation();
|
||||
ia->mode = "nominal";
|
||||
func->addChild("annotations", ia);
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem.contains("identity"), "identity in semantic summary");
|
||||
check(sem["identity"] == "nominal", "identity value correct");
|
||||
delete func;
|
||||
}
|
||||
|
||||
// --- Test 9: Compact AST shows mutability in semantic summary ---
|
||||
static void test_compact_ast_mutability() {
|
||||
auto* func = new Function();
|
||||
func->id = "f2";
|
||||
func->name = "freeze";
|
||||
auto* ma = new MutAnnotation();
|
||||
ma->depth = "deep";
|
||||
func->addChild("annotations", ma);
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem.contains("mutability"), "mutability in semantic summary");
|
||||
check(sem["mutability"] == "deep", "mutability value correct");
|
||||
delete func;
|
||||
}
|
||||
|
||||
// --- Test 10: Compact AST shows typeState in semantic summary ---
|
||||
static void test_compact_ast_typestate() {
|
||||
auto* func = new Function();
|
||||
func->id = "f3";
|
||||
func->name = "reflect";
|
||||
auto* ts = new TypeStateAnnotation();
|
||||
ts->state = "reified";
|
||||
func->addChild("annotations", ts);
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem.contains("typeState"), "typeState in semantic summary");
|
||||
check(sem["typeState"] == "reified", "typeState value correct");
|
||||
delete func;
|
||||
}
|
||||
|
||||
// --- Test 11: All 8 Subject 2 type annotations on one function ---
|
||||
static void test_all_subject2_annotations() {
|
||||
auto* func = new Function();
|
||||
func->id = "f4";
|
||||
func->name = "fullType";
|
||||
auto* bw = new BitWidthAnnotation(); bw->width = 32;
|
||||
auto* ea = new EndianAnnotation(); ea->order = "little";
|
||||
auto* la = new LayoutAnnotation(); la->mode = "aligned"; la->alignment = 8;
|
||||
auto* na = new NullabilityAnnotation(); na->nullable = false; na->strategy = "strict";
|
||||
auto* va = new VarianceAnnotation(); va->variance = "covariant";
|
||||
auto* id = new IdentityAnnotation(); id->mode = "nominal";
|
||||
auto* mu = new MutAnnotation(); mu->depth = "shallow";
|
||||
auto* ts = new TypeStateAnnotation(); ts->state = "erased";
|
||||
func->addChild("annotations", bw);
|
||||
func->addChild("annotations", ea);
|
||||
func->addChild("annotations", la);
|
||||
func->addChild("annotations", na);
|
||||
func->addChild("annotations", va);
|
||||
func->addChild("annotations", id);
|
||||
func->addChild("annotations", mu);
|
||||
func->addChild("annotations", ts);
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem.contains("bitWidth") && sem.contains("endian") &&
|
||||
sem.contains("layout") && sem.contains("nullability") &&
|
||||
sem.contains("variance") && sem.contains("identity") &&
|
||||
sem.contains("mutability") && sem.contains("typeState"),
|
||||
"all 8 type system annotations in semantic summary");
|
||||
delete func;
|
||||
}
|
||||
|
||||
// --- Test 12: MutAnnotation drives const qualification hint ---
|
||||
static void test_mut_const_qualification() {
|
||||
// MutAnnotation("deep") → implies deeply immutable
|
||||
MutAnnotation ma;
|
||||
ma.depth = "deep";
|
||||
check(ma.depth == "deep", "deep mutability implies deeply immutable");
|
||||
// MutAnnotation("shallow") → only top-level const
|
||||
MutAnnotation ma2;
|
||||
ma2.depth = "shallow";
|
||||
check(ma2.depth == "shallow", "shallow mutability implies top-level const");
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "=== Step 273: Type System Annotations — Identity & Mutability ===\n";
|
||||
test_identity_annotation();
|
||||
test_mut_annotation();
|
||||
test_typestate_annotation();
|
||||
test_identity_json_roundtrip();
|
||||
test_mut_json_roundtrip();
|
||||
test_typestate_json_roundtrip();
|
||||
test_create_node_factory();
|
||||
test_compact_ast_identity();
|
||||
test_compact_ast_mutability();
|
||||
test_compact_ast_typestate();
|
||||
test_all_subject2_annotations();
|
||||
test_mut_const_qualification();
|
||||
std::cout << "\nResults: " << passed << " passed, " << failed << " failed out of "
|
||||
<< (passed + failed) << "\n";
|
||||
return failed > 0 ? 1 : 0;
|
||||
}
|
||||
188
editor/tests/step274_test.cpp
Normal file
188
editor/tests/step274_test.cpp
Normal file
@@ -0,0 +1,188 @@
|
||||
// Step 274: Concurrency Annotations — Primitives & Memory Model (12 tests)
|
||||
// Tests: AtomicAnnotation, SyncAnnotation, ThreadModelAnnotation,
|
||||
// MemoryBarrierAnnotation + JSON roundtrip + compact AST
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "ast/ASTNode.h"
|
||||
#include "ast/Module.h"
|
||||
#include "ast/Function.h"
|
||||
#include "ast/Annotation.h"
|
||||
#include "ast/Serialization.h"
|
||||
#include "ASTUtils.h"
|
||||
#include "CompactAST.h"
|
||||
|
||||
static int passed = 0;
|
||||
static int failed = 0;
|
||||
|
||||
static void check(bool cond, const std::string& name) {
|
||||
if (cond) { std::cout << " PASS: " << name << "\n"; ++passed; }
|
||||
else { std::cout << " FAIL: " << name << "\n"; ++failed; }
|
||||
}
|
||||
|
||||
// --- Test 1: AtomicAnnotation creation ---
|
||||
static void test_atomic_annotation() {
|
||||
AtomicAnnotation aa;
|
||||
check(aa.conceptType == "AtomicAnnotation", "conceptType is AtomicAnnotation");
|
||||
aa.consistency = "seq_cst";
|
||||
check(aa.consistency == "seq_cst", "consistency field set to seq_cst");
|
||||
}
|
||||
|
||||
// --- Test 2: SyncAnnotation creation ---
|
||||
static void test_sync_annotation() {
|
||||
SyncAnnotation sa;
|
||||
check(sa.conceptType == "SyncAnnotation", "conceptType is SyncAnnotation");
|
||||
sa.primitive = "monitor";
|
||||
check(sa.primitive == "monitor", "primitive field set to monitor");
|
||||
}
|
||||
|
||||
// --- Test 3: ThreadModelAnnotation creation ---
|
||||
static void test_threadmodel_annotation() {
|
||||
ThreadModelAnnotation tm;
|
||||
check(tm.conceptType == "ThreadModelAnnotation", "conceptType is ThreadModelAnnotation");
|
||||
tm.model = "green";
|
||||
check(tm.model == "green", "model field set to green");
|
||||
}
|
||||
|
||||
// --- Test 4: MemoryBarrierAnnotation creation (marker, no fields) ---
|
||||
static void test_memorybarrier_annotation() {
|
||||
MemoryBarrierAnnotation mb;
|
||||
check(mb.conceptType == "MemoryBarrierAnnotation", "conceptType is MemoryBarrierAnnotation");
|
||||
}
|
||||
|
||||
// --- Test 5: AtomicAnnotation JSON roundtrip ---
|
||||
static void test_atomic_json_roundtrip() {
|
||||
auto* aa = new AtomicAnnotation();
|
||||
aa->id = "a1";
|
||||
aa->consistency = "relaxed";
|
||||
json j = toJson(aa);
|
||||
check(j["properties"]["consistency"] == "relaxed", "JSON consistency correct");
|
||||
ASTNode* restored = fromJson(j);
|
||||
auto* raa = dynamic_cast<AtomicAnnotation*>(restored);
|
||||
check(raa != nullptr, "fromJson creates AtomicAnnotation");
|
||||
check(raa->consistency == "relaxed", "roundtrip consistency preserved");
|
||||
delete aa;
|
||||
delete restored;
|
||||
}
|
||||
|
||||
// --- Test 6: SyncAnnotation JSON roundtrip ---
|
||||
static void test_sync_json_roundtrip() {
|
||||
auto* sa = new SyncAnnotation();
|
||||
sa->id = "s1";
|
||||
sa->primitive = "semaphore";
|
||||
json j = toJson(sa);
|
||||
ASTNode* restored = fromJson(j);
|
||||
auto* rsa = dynamic_cast<SyncAnnotation*>(restored);
|
||||
check(rsa != nullptr, "fromJson creates SyncAnnotation");
|
||||
check(rsa->primitive == "semaphore", "roundtrip primitive preserved");
|
||||
delete sa;
|
||||
delete restored;
|
||||
}
|
||||
|
||||
// --- Test 7: ThreadModelAnnotation JSON roundtrip ---
|
||||
static void test_threadmodel_json_roundtrip() {
|
||||
auto* tm = new ThreadModelAnnotation();
|
||||
tm->id = "tm1";
|
||||
tm->model = "fiber";
|
||||
json j = toJson(tm);
|
||||
ASTNode* restored = fromJson(j);
|
||||
auto* rtm = dynamic_cast<ThreadModelAnnotation*>(restored);
|
||||
check(rtm != nullptr, "fromJson creates ThreadModelAnnotation");
|
||||
check(rtm->model == "fiber", "roundtrip model preserved");
|
||||
delete tm;
|
||||
delete restored;
|
||||
}
|
||||
|
||||
// --- Test 8: MemoryBarrierAnnotation JSON roundtrip ---
|
||||
static void test_memorybarrier_json_roundtrip() {
|
||||
auto* mb = new MemoryBarrierAnnotation();
|
||||
mb->id = "mb1";
|
||||
json j = toJson(mb);
|
||||
check(j["concept"] == "MemoryBarrierAnnotation", "JSON concept correct");
|
||||
ASTNode* restored = fromJson(j);
|
||||
auto* rmb = dynamic_cast<MemoryBarrierAnnotation*>(restored);
|
||||
check(rmb != nullptr, "fromJson creates MemoryBarrierAnnotation");
|
||||
delete mb;
|
||||
delete restored;
|
||||
}
|
||||
|
||||
// --- Test 9: createNode factory for Step 274 types ---
|
||||
static void test_create_node_factory() {
|
||||
std::vector<std::string> types = {
|
||||
"AtomicAnnotation", "SyncAnnotation",
|
||||
"ThreadModelAnnotation", "MemoryBarrierAnnotation"
|
||||
};
|
||||
for (const auto& t : types) {
|
||||
ASTNode* node = createNode(t);
|
||||
check(node != nullptr && node->conceptType == t,
|
||||
"createNode(" + t + ") works");
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Test 10: Compact AST shows atomic in semantic summary ---
|
||||
static void test_compact_ast_atomic() {
|
||||
auto* func = new Function();
|
||||
func->id = "f1";
|
||||
func->name = "incrementCounter";
|
||||
auto* aa = new AtomicAnnotation();
|
||||
aa->consistency = "seq_cst";
|
||||
func->addChild("annotations", aa);
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem.contains("atomic"), "atomic in semantic summary");
|
||||
check(sem["atomic"] == "seq_cst", "atomic value correct");
|
||||
delete func;
|
||||
}
|
||||
|
||||
// --- Test 11: Compact AST shows memoryBarrier marker ---
|
||||
static void test_compact_ast_memorybarrier() {
|
||||
auto* func = new Function();
|
||||
func->id = "f2";
|
||||
func->name = "fence";
|
||||
auto* mb = new MemoryBarrierAnnotation();
|
||||
func->addChild("annotations", mb);
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem.contains("memoryBarrier"), "memoryBarrier in semantic summary");
|
||||
check(sem["memoryBarrier"] == true, "memoryBarrier is true");
|
||||
delete func;
|
||||
}
|
||||
|
||||
// --- Test 12: All 4 concurrency annotations on one function ---
|
||||
static void test_all_concurrency_annotations() {
|
||||
auto* func = new Function();
|
||||
func->id = "f3";
|
||||
func->name = "concurrentOp";
|
||||
auto* aa = new AtomicAnnotation(); aa->consistency = "acquire";
|
||||
auto* sa = new SyncAnnotation(); sa->primitive = "spin";
|
||||
auto* tm = new ThreadModelAnnotation(); tm->model = "os";
|
||||
auto* mb = new MemoryBarrierAnnotation();
|
||||
func->addChild("annotations", aa);
|
||||
func->addChild("annotations", sa);
|
||||
func->addChild("annotations", tm);
|
||||
func->addChild("annotations", mb);
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem.contains("atomic") && sem.contains("sync") &&
|
||||
sem.contains("threadModel") && sem.contains("memoryBarrier"),
|
||||
"all 4 concurrency annotations in semantic summary");
|
||||
delete func;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "=== Step 274: Concurrency Annotations — Primitives & Memory Model ===\n";
|
||||
test_atomic_annotation();
|
||||
test_sync_annotation();
|
||||
test_threadmodel_annotation();
|
||||
test_memorybarrier_annotation();
|
||||
test_atomic_json_roundtrip();
|
||||
test_sync_json_roundtrip();
|
||||
test_threadmodel_json_roundtrip();
|
||||
test_memorybarrier_json_roundtrip();
|
||||
test_create_node_factory();
|
||||
test_compact_ast_atomic();
|
||||
test_compact_ast_memorybarrier();
|
||||
test_all_concurrency_annotations();
|
||||
std::cout << "\nResults: " << passed << " passed, " << failed << " failed out of "
|
||||
<< (passed + failed) << "\n";
|
||||
return failed > 0 ? 1 : 0;
|
||||
}
|
||||
221
editor/tests/step275_test.cpp
Normal file
221
editor/tests/step275_test.cpp
Normal file
@@ -0,0 +1,221 @@
|
||||
// Step 275: Async, Parallelism & Error Handling Annotations (12 tests)
|
||||
// Tests: ExecAnnotation, BlockingAnnotation, ParallelAnnotation,
|
||||
// TrapAnnotation, ExceptionAnnotation, PanicAnnotation
|
||||
// + JSON roundtrip + compact AST
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "ast/ASTNode.h"
|
||||
#include "ast/Module.h"
|
||||
#include "ast/Function.h"
|
||||
#include "ast/Annotation.h"
|
||||
#include "ast/Serialization.h"
|
||||
#include "ASTUtils.h"
|
||||
#include "CompactAST.h"
|
||||
|
||||
static int passed = 0;
|
||||
static int failed = 0;
|
||||
|
||||
static void check(bool cond, const std::string& name) {
|
||||
if (cond) { std::cout << " PASS: " << name << "\n"; ++passed; }
|
||||
else { std::cout << " FAIL: " << name << "\n"; ++failed; }
|
||||
}
|
||||
|
||||
// --- Test 1: ExecAnnotation creation ---
|
||||
static void test_exec_annotation() {
|
||||
ExecAnnotation ea;
|
||||
check(ea.conceptType == "ExecAnnotation", "conceptType is ExecAnnotation");
|
||||
ea.mode = "async";
|
||||
ea.runtimeHint = "tokio";
|
||||
check(ea.mode == "async", "mode field set to async");
|
||||
check(ea.runtimeHint == "tokio", "runtimeHint field set to tokio");
|
||||
}
|
||||
|
||||
// --- Test 2: BlockingAnnotation creation ---
|
||||
static void test_blocking_annotation() {
|
||||
BlockingAnnotation ba;
|
||||
check(ba.conceptType == "BlockingAnnotation", "conceptType is BlockingAnnotation");
|
||||
ba.kind = "io";
|
||||
check(ba.kind == "io", "kind field set to io");
|
||||
}
|
||||
|
||||
// --- Test 3: ParallelAnnotation creation ---
|
||||
static void test_parallel_annotation() {
|
||||
ParallelAnnotation pa;
|
||||
check(pa.conceptType == "ParallelAnnotation", "conceptType is ParallelAnnotation");
|
||||
pa.kind = "data";
|
||||
check(pa.kind == "data", "kind field set to data");
|
||||
}
|
||||
|
||||
// --- Test 4: TrapAnnotation, ExceptionAnnotation, PanicAnnotation ---
|
||||
static void test_error_annotations() {
|
||||
TrapAnnotation ta;
|
||||
check(ta.conceptType == "TrapAnnotation", "TrapAnnotation conceptType");
|
||||
ta.signal = "SIGSEGV";
|
||||
check(ta.signal == "SIGSEGV", "signal set to SIGSEGV");
|
||||
|
||||
ExceptionAnnotation ea;
|
||||
check(ea.conceptType == "ExceptionAnnotation", "ExceptionAnnotation conceptType");
|
||||
ea.style = "checked";
|
||||
check(ea.style == "checked", "style set to checked");
|
||||
|
||||
PanicAnnotation pa;
|
||||
check(pa.conceptType == "PanicAnnotation", "PanicAnnotation conceptType");
|
||||
pa.behavior = "unwind";
|
||||
check(pa.behavior == "unwind", "behavior set to unwind");
|
||||
}
|
||||
|
||||
// --- Test 5: ExecAnnotation JSON roundtrip ---
|
||||
static void test_exec_json_roundtrip() {
|
||||
auto* ea = new ExecAnnotation();
|
||||
ea->id = "e1";
|
||||
ea->mode = "event";
|
||||
ea->runtimeHint = "libuv";
|
||||
json j = toJson(ea);
|
||||
check(j["properties"]["mode"] == "event", "JSON mode correct");
|
||||
check(j["properties"]["runtimeHint"] == "libuv", "JSON runtimeHint correct");
|
||||
ASTNode* restored = fromJson(j);
|
||||
auto* rea = dynamic_cast<ExecAnnotation*>(restored);
|
||||
check(rea != nullptr, "fromJson creates ExecAnnotation");
|
||||
check(rea->mode == "event" && rea->runtimeHint == "libuv",
|
||||
"roundtrip fields preserved");
|
||||
delete ea;
|
||||
delete restored;
|
||||
}
|
||||
|
||||
// --- Test 6: PanicAnnotation JSON roundtrip ---
|
||||
static void test_panic_json_roundtrip() {
|
||||
auto* pa = new PanicAnnotation();
|
||||
pa->id = "p1";
|
||||
pa->behavior = "abort";
|
||||
json j = toJson(pa);
|
||||
ASTNode* restored = fromJson(j);
|
||||
auto* rpa = dynamic_cast<PanicAnnotation*>(restored);
|
||||
check(rpa != nullptr, "fromJson creates PanicAnnotation");
|
||||
check(rpa->behavior == "abort", "roundtrip behavior preserved");
|
||||
delete pa;
|
||||
delete restored;
|
||||
}
|
||||
|
||||
// --- Test 7: createNode factory for Step 275 types ---
|
||||
static void test_create_node_factory() {
|
||||
std::vector<std::string> types = {
|
||||
"ExecAnnotation", "BlockingAnnotation", "ParallelAnnotation",
|
||||
"TrapAnnotation", "ExceptionAnnotation", "PanicAnnotation"
|
||||
};
|
||||
for (const auto& t : types) {
|
||||
ASTNode* node = createNode(t);
|
||||
check(node != nullptr && node->conceptType == t,
|
||||
"createNode(" + t + ") works");
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Test 8: Compact AST shows exec in semantic summary ---
|
||||
static void test_compact_ast_exec() {
|
||||
auto* func = new Function();
|
||||
func->id = "f1";
|
||||
func->name = "fetchData";
|
||||
auto* ea = new ExecAnnotation();
|
||||
ea->mode = "async";
|
||||
ea->runtimeHint = "tokio";
|
||||
func->addChild("annotations", ea);
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem.contains("exec"), "exec in semantic summary");
|
||||
check(sem["exec"]["mode"] == "async", "exec mode correct");
|
||||
check(sem["exec"]["runtime"] == "tokio", "exec runtime correct");
|
||||
delete func;
|
||||
}
|
||||
|
||||
// --- Test 9: Compact AST shows parallel and blocking ---
|
||||
static void test_compact_ast_parallel_blocking() {
|
||||
auto* func = new Function();
|
||||
func->id = "f2";
|
||||
func->name = "processArray";
|
||||
auto* pa = new ParallelAnnotation(); pa->kind = "data";
|
||||
auto* ba = new BlockingAnnotation(); ba->kind = "compute";
|
||||
func->addChild("annotations", pa);
|
||||
func->addChild("annotations", ba);
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem["parallel"] == "data", "parallel in semantic summary");
|
||||
check(sem["blocking"] == "compute", "blocking in semantic summary");
|
||||
delete func;
|
||||
}
|
||||
|
||||
// --- Test 10: Compact AST shows error handling annotations ---
|
||||
static void test_compact_ast_error_handling() {
|
||||
auto* func = new Function();
|
||||
func->id = "f3";
|
||||
func->name = "riskyOp";
|
||||
auto* ta = new TrapAnnotation(); ta->signal = "SIGFPE";
|
||||
auto* ea = new ExceptionAnnotation(); ea->style = "unchecked";
|
||||
auto* pa = new PanicAnnotation(); pa->behavior = "unwind";
|
||||
func->addChild("annotations", ta);
|
||||
func->addChild("annotations", ea);
|
||||
func->addChild("annotations", pa);
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem["trap"] == "SIGFPE", "trap in semantic summary");
|
||||
check(sem["exception"] == "unchecked", "exception in semantic summary");
|
||||
check(sem["panic"] == "unwind", "panic in semantic summary");
|
||||
delete func;
|
||||
}
|
||||
|
||||
// --- Test 11: All 6 async/error annotations on one function ---
|
||||
static void test_all_async_error_annotations() {
|
||||
auto* func = new Function();
|
||||
func->id = "f4";
|
||||
func->name = "fullAsync";
|
||||
func->addChild("annotations", [&]{ auto* a = new ExecAnnotation(); a->mode = "async"; return a; }());
|
||||
func->addChild("annotations", [&]{ auto* a = new BlockingAnnotation(); a->kind = "io"; return a; }());
|
||||
func->addChild("annotations", [&]{ auto* a = new ParallelAnnotation(); a->kind = "task"; return a; }());
|
||||
func->addChild("annotations", [&]{ auto* a = new TrapAnnotation(); a->signal = "SIGSEGV"; return a; }());
|
||||
func->addChild("annotations", [&]{ auto* a = new ExceptionAnnotation(); a->style = "checked"; return a; }());
|
||||
func->addChild("annotations", [&]{ auto* a = new PanicAnnotation(); a->behavior = "abort"; return a; }());
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem.contains("exec") && sem.contains("blocking") &&
|
||||
sem.contains("parallel") && sem.contains("trap") &&
|
||||
sem.contains("exception") && sem.contains("panic"),
|
||||
"all 6 async/error annotations in semantic summary");
|
||||
delete func;
|
||||
}
|
||||
|
||||
// --- Test 12: TrapAnnotation and ExceptionAnnotation JSON roundtrip ---
|
||||
static void test_trap_exception_roundtrip() {
|
||||
auto* ta = new TrapAnnotation();
|
||||
ta->id = "t1";
|
||||
ta->signal = "SIGABRT";
|
||||
json jt = toJson(ta);
|
||||
ASTNode* rt = fromJson(jt);
|
||||
auto* rta = dynamic_cast<TrapAnnotation*>(rt);
|
||||
check(rta != nullptr && rta->signal == "SIGABRT", "TrapAnnotation roundtrip");
|
||||
|
||||
auto* ea = new ExceptionAnnotation();
|
||||
ea->id = "ex1";
|
||||
ea->style = "checked";
|
||||
json je = toJson(ea);
|
||||
ASTNode* re = fromJson(je);
|
||||
auto* rea = dynamic_cast<ExceptionAnnotation*>(re);
|
||||
check(rea != nullptr && rea->style == "checked", "ExceptionAnnotation roundtrip");
|
||||
|
||||
delete ta; delete rt; delete ea; delete re;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "=== Step 275: Async, Parallelism & Error Handling Annotations ===\n";
|
||||
test_exec_annotation();
|
||||
test_blocking_annotation();
|
||||
test_parallel_annotation();
|
||||
test_error_annotations();
|
||||
test_exec_json_roundtrip();
|
||||
test_panic_json_roundtrip();
|
||||
test_create_node_factory();
|
||||
test_compact_ast_exec();
|
||||
test_compact_ast_parallel_blocking();
|
||||
test_compact_ast_error_handling();
|
||||
test_all_async_error_annotations();
|
||||
test_trap_exception_roundtrip();
|
||||
std::cout << "\nResults: " << passed << " passed, " << failed << " failed out of "
|
||||
<< (passed + failed) << "\n";
|
||||
return failed > 0 ? 1 : 0;
|
||||
}
|
||||
211
editor/tests/step276_test.cpp
Normal file
211
editor/tests/step276_test.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
// Step 276: Scope & Namespace Annotations (12 tests)
|
||||
// Tests: BindingAnnotation, LookupAnnotation, CaptureAnnotation,
|
||||
// VisibilityAnnotation, NamespaceAnnotation, ScopeAnnotation
|
||||
// + JSON roundtrip + compact AST
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "ast/ASTNode.h"
|
||||
#include "ast/Module.h"
|
||||
#include "ast/Function.h"
|
||||
#include "ast/Annotation.h"
|
||||
#include "ast/Serialization.h"
|
||||
#include "ASTUtils.h"
|
||||
#include "CompactAST.h"
|
||||
|
||||
static int passed = 0;
|
||||
static int failed = 0;
|
||||
|
||||
static void check(bool cond, const std::string& name) {
|
||||
if (cond) { std::cout << " PASS: " << name << "\n"; ++passed; }
|
||||
else { std::cout << " FAIL: " << name << "\n"; ++failed; }
|
||||
}
|
||||
|
||||
// --- Test 1: BindingAnnotation creation ---
|
||||
static void test_binding_annotation() {
|
||||
BindingAnnotation ba;
|
||||
check(ba.conceptType == "BindingAnnotation", "conceptType is BindingAnnotation");
|
||||
ba.time = "static";
|
||||
check(ba.time == "static", "time field set to static");
|
||||
}
|
||||
|
||||
// --- Test 2: LookupAnnotation creation ---
|
||||
static void test_lookup_annotation() {
|
||||
LookupAnnotation la;
|
||||
check(la.conceptType == "LookupAnnotation", "conceptType is LookupAnnotation");
|
||||
la.mode = "lexical";
|
||||
check(la.mode == "lexical", "mode field set to lexical");
|
||||
}
|
||||
|
||||
// --- Test 3: CaptureAnnotation creation ---
|
||||
static void test_capture_annotation() {
|
||||
CaptureAnnotation ca;
|
||||
check(ca.conceptType == "CaptureAnnotation", "conceptType is CaptureAnnotation");
|
||||
ca.strategy = "move";
|
||||
check(ca.strategy == "move", "strategy field set to move");
|
||||
}
|
||||
|
||||
// --- Test 4: VisibilityAnnotation, NamespaceAnnotation, ScopeAnnotation ---
|
||||
static void test_visibility_namespace_scope() {
|
||||
VisibilityAnnotation va;
|
||||
check(va.conceptType == "VisibilityAnnotation", "VisibilityAnnotation conceptType");
|
||||
va.level = "friend";
|
||||
check(va.level == "friend", "level set to friend");
|
||||
|
||||
NamespaceAnnotation na;
|
||||
check(na.conceptType == "NamespaceAnnotation", "NamespaceAnnotation conceptType");
|
||||
na.style = "qualified";
|
||||
check(na.style == "qualified", "style set to qualified");
|
||||
|
||||
ScopeAnnotation sa;
|
||||
check(sa.conceptType == "ScopeAnnotation", "ScopeAnnotation conceptType");
|
||||
sa.kind = "singleton";
|
||||
check(sa.kind == "singleton", "kind set to singleton");
|
||||
}
|
||||
|
||||
// --- Test 5: CaptureAnnotation JSON roundtrip ---
|
||||
static void test_capture_json_roundtrip() {
|
||||
auto* ca = new CaptureAnnotation();
|
||||
ca->id = "c1";
|
||||
ca->strategy = "ref";
|
||||
json j = toJson(ca);
|
||||
check(j["properties"]["strategy"] == "ref", "JSON strategy correct");
|
||||
ASTNode* restored = fromJson(j);
|
||||
auto* rca = dynamic_cast<CaptureAnnotation*>(restored);
|
||||
check(rca != nullptr, "fromJson creates CaptureAnnotation");
|
||||
check(rca->strategy == "ref", "roundtrip strategy preserved");
|
||||
delete ca;
|
||||
delete restored;
|
||||
}
|
||||
|
||||
// --- Test 6: VisibilityAnnotation JSON roundtrip ---
|
||||
static void test_visibility_json_roundtrip() {
|
||||
auto* va = new VisibilityAnnotation();
|
||||
va->id = "v1";
|
||||
va->level = "internal";
|
||||
json j = toJson(va);
|
||||
ASTNode* restored = fromJson(j);
|
||||
auto* rva = dynamic_cast<VisibilityAnnotation*>(restored);
|
||||
check(rva != nullptr, "fromJson creates VisibilityAnnotation");
|
||||
check(rva->level == "internal", "roundtrip level preserved");
|
||||
delete va;
|
||||
delete restored;
|
||||
}
|
||||
|
||||
// --- Test 7: ScopeAnnotation JSON roundtrip ---
|
||||
static void test_scope_json_roundtrip() {
|
||||
auto* sa = new ScopeAnnotation();
|
||||
sa->id = "s1";
|
||||
sa->kind = "global_leaked";
|
||||
json j = toJson(sa);
|
||||
ASTNode* restored = fromJson(j);
|
||||
auto* rsa = dynamic_cast<ScopeAnnotation*>(restored);
|
||||
check(rsa != nullptr, "fromJson creates ScopeAnnotation");
|
||||
check(rsa->kind == "global_leaked", "roundtrip kind preserved");
|
||||
delete sa;
|
||||
delete restored;
|
||||
}
|
||||
|
||||
// --- Test 8: createNode factory for Step 276 types ---
|
||||
static void test_create_node_factory() {
|
||||
std::vector<std::string> types = {
|
||||
"BindingAnnotation", "LookupAnnotation", "CaptureAnnotation",
|
||||
"VisibilityAnnotation", "NamespaceAnnotation", "ScopeAnnotation"
|
||||
};
|
||||
for (const auto& t : types) {
|
||||
ASTNode* node = createNode(t);
|
||||
check(node != nullptr && node->conceptType == t,
|
||||
"createNode(" + t + ") works");
|
||||
delete node;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Test 9: Compact AST shows binding and lookup ---
|
||||
static void test_compact_ast_binding_lookup() {
|
||||
auto* func = new Function();
|
||||
func->id = "f1";
|
||||
func->name = "resolve";
|
||||
auto* ba = new BindingAnnotation(); ba->time = "dynamic";
|
||||
auto* la = new LookupAnnotation(); la->mode = "hoisted";
|
||||
func->addChild("annotations", ba);
|
||||
func->addChild("annotations", la);
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem["binding"] == "dynamic", "binding in semantic summary");
|
||||
check(sem["lookup"] == "hoisted", "lookup in semantic summary");
|
||||
delete func;
|
||||
}
|
||||
|
||||
// --- Test 10: Compact AST shows capture and visibility ---
|
||||
static void test_compact_ast_capture_visibility() {
|
||||
auto* func = new Function();
|
||||
func->id = "f2";
|
||||
func->name = "closureFactory";
|
||||
auto* ca = new CaptureAnnotation(); ca->strategy = "value";
|
||||
auto* va = new VisibilityAnnotation(); va->level = "private";
|
||||
func->addChild("annotations", ca);
|
||||
func->addChild("annotations", va);
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem["capture"] == "value", "capture in semantic summary");
|
||||
check(sem["visibility"] == "private", "visibility in semantic summary");
|
||||
delete func;
|
||||
}
|
||||
|
||||
// --- Test 11: All 6 scope annotations on one function ---
|
||||
static void test_all_scope_annotations() {
|
||||
auto* func = new Function();
|
||||
func->id = "f3";
|
||||
func->name = "fullScope";
|
||||
func->addChild("annotations", [&]{ auto* a = new BindingAnnotation(); a->time = "static"; return a; }());
|
||||
func->addChild("annotations", [&]{ auto* a = new LookupAnnotation(); a->mode = "lexical"; return a; }());
|
||||
func->addChild("annotations", [&]{ auto* a = new CaptureAnnotation(); a->strategy = "move"; return a; }());
|
||||
func->addChild("annotations", [&]{ auto* a = new VisibilityAnnotation(); a->level = "public"; return a; }());
|
||||
func->addChild("annotations", [&]{ auto* a = new NamespaceAnnotation(); a->style = "flat"; return a; }());
|
||||
func->addChild("annotations", [&]{ auto* a = new ScopeAnnotation(); a->kind = "local"; return a; }());
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem.contains("binding") && sem.contains("lookup") &&
|
||||
sem.contains("capture") && sem.contains("visibility") &&
|
||||
sem.contains("namespace") && sem.contains("scope"),
|
||||
"all 6 scope annotations in semantic summary");
|
||||
delete func;
|
||||
}
|
||||
|
||||
// --- Test 12: BindingAnnotation and NamespaceAnnotation JSON roundtrip ---
|
||||
static void test_binding_namespace_roundtrip() {
|
||||
auto* ba = new BindingAnnotation();
|
||||
ba->id = "b1";
|
||||
ba->time = "dynamic";
|
||||
json jb = toJson(ba);
|
||||
ASTNode* rb = fromJson(jb);
|
||||
auto* rba = dynamic_cast<BindingAnnotation*>(rb);
|
||||
check(rba != nullptr && rba->time == "dynamic", "BindingAnnotation roundtrip");
|
||||
|
||||
auto* na = new NamespaceAnnotation();
|
||||
na->id = "n1";
|
||||
na->style = "qualified";
|
||||
json jn = toJson(na);
|
||||
ASTNode* rn = fromJson(jn);
|
||||
auto* rna = dynamic_cast<NamespaceAnnotation*>(rn);
|
||||
check(rna != nullptr && rna->style == "qualified", "NamespaceAnnotation roundtrip");
|
||||
|
||||
delete ba; delete rb; delete na; delete rn;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "=== Step 276: Scope & Namespace Annotations ===\n";
|
||||
test_binding_annotation();
|
||||
test_lookup_annotation();
|
||||
test_capture_annotation();
|
||||
test_visibility_namespace_scope();
|
||||
test_capture_json_roundtrip();
|
||||
test_visibility_json_roundtrip();
|
||||
test_scope_json_roundtrip();
|
||||
test_create_node_factory();
|
||||
test_compact_ast_binding_lookup();
|
||||
test_compact_ast_capture_visibility();
|
||||
test_all_scope_annotations();
|
||||
test_binding_namespace_roundtrip();
|
||||
std::cout << "\nResults: " << passed << " passed, " << failed << " failed out of "
|
||||
<< (passed + failed) << "\n";
|
||||
return failed > 0 ? 1 : 0;
|
||||
}
|
||||
324
editor/tests/step277_test.cpp
Normal file
324
editor/tests/step277_test.cpp
Normal file
@@ -0,0 +1,324 @@
|
||||
// Step 277: Phase 10c Integration Tests (8 tests)
|
||||
// Cross-subject annotation workflows: type + concurrency + scope on AST,
|
||||
// compact AST, sidecar roundtrip, RPC set/get for new types.
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include "ast/ASTNode.h"
|
||||
#include "ast/Module.h"
|
||||
#include "ast/Function.h"
|
||||
#include "ast/Variable.h"
|
||||
#include "ast/Parameter.h"
|
||||
#include "ast/Statement.h"
|
||||
#include "ast/Expression.h"
|
||||
#include "ast/Annotation.h"
|
||||
#include "ast/Serialization.h"
|
||||
#include "ASTUtils.h"
|
||||
#include "CompactAST.h"
|
||||
#include "SidecarPersistence.h"
|
||||
#include "HeadlessEditorState.h"
|
||||
#include <memory>
|
||||
|
||||
static int passed = 0;
|
||||
static int failed = 0;
|
||||
|
||||
static void check(bool cond, const std::string& name) {
|
||||
if (cond) { std::cout << " PASS: " << name << "\n"; ++passed; }
|
||||
else { std::cout << " FAIL: " << name << "\n"; ++failed; }
|
||||
}
|
||||
|
||||
// Helper: build a simple function AST
|
||||
static Module* buildTestAST() {
|
||||
auto* mod = new Module();
|
||||
mod->id = "mod1";
|
||||
mod->name = "test_module";
|
||||
|
||||
auto* fn = new Function();
|
||||
fn->id = "fn1";
|
||||
fn->name = "processData";
|
||||
mod->addChild("functions", fn);
|
||||
|
||||
auto* fn2 = new Function();
|
||||
fn2->id = "fn2";
|
||||
fn2->name = "transformItem";
|
||||
mod->addChild("functions", fn2);
|
||||
|
||||
return mod;
|
||||
}
|
||||
|
||||
// Helper: invoke RPC
|
||||
static json rpc(HeadlessEditorState& state, const std::string& method,
|
||||
const json& params = {}, const std::string& session = "s1") {
|
||||
json req = {{"jsonrpc", "2.0"}, {"id", 1}, {"method", method}};
|
||||
if (!params.empty()) req["params"] = params;
|
||||
return handleHeadlessAgentRequest(state, req, session);
|
||||
}
|
||||
|
||||
// --- Test 1: Type annotations drive compact AST output ---
|
||||
static void test_type_annotations_compact_ast() {
|
||||
auto* mod = buildTestAST();
|
||||
auto* fn = findNodeById(mod, "fn1");
|
||||
|
||||
// Add type annotations
|
||||
auto* bw = new BitWidthAnnotation(); bw->width = 32;
|
||||
auto* la = new LayoutAnnotation(); la->mode = "aligned"; la->alignment = 8;
|
||||
auto* mu = new MutAnnotation(); mu->depth = "deep";
|
||||
fn->addChild("annotations", bw);
|
||||
fn->addChild("annotations", la);
|
||||
fn->addChild("annotations", mu);
|
||||
|
||||
json compact = toJsonCompactSummary(mod);
|
||||
// Find fn1 in compact summary
|
||||
bool found = false;
|
||||
for (const auto& node : compact) {
|
||||
if (node.value("id", "") == "fn1" && node.contains("semantic")) {
|
||||
auto& sem = node["semantic"];
|
||||
found = sem.contains("bitWidth") && sem.contains("layout") &&
|
||||
sem.contains("mutability");
|
||||
}
|
||||
}
|
||||
check(found, "type annotations appear in compact AST summary");
|
||||
delete mod;
|
||||
}
|
||||
|
||||
// --- Test 2: Concurrency annotations in compact AST ---
|
||||
static void test_concurrency_annotations_compact_ast() {
|
||||
auto* mod = buildTestAST();
|
||||
auto* fn = findNodeById(mod, "fn1");
|
||||
|
||||
auto* aa = new AtomicAnnotation(); aa->consistency = "seq_cst";
|
||||
auto* sa = new SyncAnnotation(); sa->primitive = "monitor";
|
||||
fn->addChild("annotations", aa);
|
||||
fn->addChild("annotations", sa);
|
||||
|
||||
json compact = toJsonCompactSummary(mod);
|
||||
bool found = false;
|
||||
for (const auto& node : compact) {
|
||||
if (node.value("id", "") == "fn1" && node.contains("semantic")) {
|
||||
auto& sem = node["semantic"];
|
||||
found = sem.contains("atomic") && sem.contains("sync");
|
||||
}
|
||||
}
|
||||
check(found, "concurrency annotations appear in compact AST summary");
|
||||
delete mod;
|
||||
}
|
||||
|
||||
// --- Test 3: Scope annotations in compact AST ---
|
||||
static void test_scope_annotations_compact_ast() {
|
||||
auto* mod = buildTestAST();
|
||||
auto* fn = findNodeById(mod, "fn2");
|
||||
|
||||
auto* ca = new CaptureAnnotation(); ca->strategy = "ref";
|
||||
auto* va = new VisibilityAnnotation(); va->level = "private";
|
||||
fn->addChild("annotations", ca);
|
||||
fn->addChild("annotations", va);
|
||||
|
||||
json compact = toJsonCompactSummary(mod);
|
||||
bool found = false;
|
||||
for (const auto& node : compact) {
|
||||
if (node.value("id", "") == "fn2" && node.contains("semantic")) {
|
||||
auto& sem = node["semantic"];
|
||||
found = sem.contains("capture") && sem.contains("visibility");
|
||||
}
|
||||
}
|
||||
check(found, "scope annotations appear in compact AST summary");
|
||||
delete mod;
|
||||
}
|
||||
|
||||
// --- Test 4: All Subject 2-4 annotations survive sidecar save/load ---
|
||||
static void test_sidecar_roundtrip() {
|
||||
namespace fs = std::filesystem;
|
||||
std::string workspace = "/tmp/step277_test_ws";
|
||||
fs::create_directories(workspace);
|
||||
|
||||
auto* mod = buildTestAST();
|
||||
auto* fn1 = findNodeById(mod, "fn1");
|
||||
auto* fn2 = findNodeById(mod, "fn2");
|
||||
|
||||
// Add one annotation from each subject
|
||||
auto* bw = new BitWidthAnnotation(); bw->width = 64;
|
||||
fn1->addChild("annotations", bw);
|
||||
auto* aa = new AtomicAnnotation(); aa->consistency = "relaxed";
|
||||
fn1->addChild("annotations", aa);
|
||||
auto* ba = new BindingAnnotation(); ba->time = "static";
|
||||
fn2->addChild("annotations", ba);
|
||||
|
||||
auto saveResult = saveSidecarAST(workspace, "test.wh", mod);
|
||||
check(saveResult.success, "sidecar save succeeds");
|
||||
check(saveResult.annotationCount == 3, "3 annotations saved");
|
||||
|
||||
// Build fresh AST and load
|
||||
auto* mod2 = buildTestAST();
|
||||
auto loadResult = loadSidecarAST(workspace, "test.wh", mod2);
|
||||
check(loadResult.success, "sidecar load succeeds");
|
||||
check(loadResult.mergedCount == 3, "3 annotations merged");
|
||||
|
||||
// Verify annotations on reloaded AST
|
||||
auto* rfn1 = findNodeById(mod2, "fn1");
|
||||
auto annos1 = rfn1->getChildren("annotations");
|
||||
bool hasBitWidth = false, hasAtomic = false;
|
||||
for (auto* a : annos1) {
|
||||
if (a->conceptType == "BitWidthAnnotation") hasBitWidth = true;
|
||||
if (a->conceptType == "AtomicAnnotation") hasAtomic = true;
|
||||
}
|
||||
check(hasBitWidth && hasAtomic, "type and concurrency annotations survive roundtrip");
|
||||
|
||||
delete mod;
|
||||
delete mod2;
|
||||
fs::remove_all(workspace);
|
||||
}
|
||||
|
||||
// --- Test 5: Mixed annotations on single function ---
|
||||
static void test_mixed_annotations_single_function() {
|
||||
auto* func = new Function();
|
||||
func->id = "f1";
|
||||
func->name = "mixedOp";
|
||||
|
||||
// Subject 2: type
|
||||
auto* bw = new BitWidthAnnotation(); bw->width = 16;
|
||||
auto* id = new IdentityAnnotation(); id->mode = "structural";
|
||||
// Subject 3: concurrency
|
||||
auto* tm = new ThreadModelAnnotation(); tm->model = "green";
|
||||
auto* ea = new ExecAnnotation(); ea->mode = "async";
|
||||
// Subject 4: scope
|
||||
auto* va = new VisibilityAnnotation(); va->level = "public";
|
||||
auto* ca = new CaptureAnnotation(); ca->strategy = "value";
|
||||
|
||||
func->addChild("annotations", bw);
|
||||
func->addChild("annotations", id);
|
||||
func->addChild("annotations", tm);
|
||||
func->addChild("annotations", ea);
|
||||
func->addChild("annotations", va);
|
||||
func->addChild("annotations", ca);
|
||||
|
||||
json sem = extractSemanticSummary(func);
|
||||
check(sem.contains("bitWidth") && sem.contains("identity") &&
|
||||
sem.contains("threadModel") && sem.contains("exec") &&
|
||||
sem.contains("visibility") && sem.contains("capture"),
|
||||
"mixed annotations from 3 subjects on single function");
|
||||
delete func;
|
||||
}
|
||||
|
||||
// --- Test 6: getSemanticAnnotations returns Subject 2-4 types via RPC ---
|
||||
static void test_rpc_get_annotations() {
|
||||
HeadlessEditorState state;
|
||||
state.openBuffer("test.wh", "", "python");
|
||||
auto* mod = buildTestAST();
|
||||
state.activeBuffer->sync.setAST(std::unique_ptr<Module>(mod));
|
||||
state.setAgentRole("s1", AgentRole::Refactor);
|
||||
|
||||
// Set type annotation via RPC
|
||||
auto r1 = rpc(state, "setSemanticAnnotation", {
|
||||
{"nodeId", "fn1"}, {"type", "bitWidth"}, {"fields", {{"width", 32}}}
|
||||
});
|
||||
check(r1.contains("result"), "setSemanticAnnotation bitWidth via RPC");
|
||||
|
||||
// Set concurrency annotation via RPC
|
||||
auto r2 = rpc(state, "setSemanticAnnotation", {
|
||||
{"nodeId", "fn1"}, {"type", "atomic"}, {"fields", {{"consistency", "seq_cst"}}}
|
||||
});
|
||||
check(r2.contains("result"), "setSemanticAnnotation atomic via RPC");
|
||||
|
||||
// Set scope annotation via RPC
|
||||
auto r3 = rpc(state, "setSemanticAnnotation", {
|
||||
{"nodeId", "fn1"}, {"type", "visibility"}, {"fields", {{"level", "public"}}}
|
||||
});
|
||||
check(r3.contains("result"), "setSemanticAnnotation visibility via RPC");
|
||||
|
||||
// Query all annotations
|
||||
auto r4 = rpc(state, "getSemanticAnnotations", {{"nodeId", "fn1"}});
|
||||
auto annos = r4["result"]["annotations"];
|
||||
bool hasBW = false, hasAtom = false, hasVis = false;
|
||||
for (const auto& a : annos) {
|
||||
std::string t = a.value("type", "");
|
||||
if (t == "BitWidthAnnotation") hasBW = true;
|
||||
if (t == "AtomicAnnotation") hasAtom = true;
|
||||
if (t == "VisibilityAnnotation") hasVis = true;
|
||||
}
|
||||
check(hasBW && hasAtom && hasVis,
|
||||
"getSemanticAnnotations returns Subject 2-4 types");
|
||||
}
|
||||
|
||||
// --- Test 7: setSemanticAnnotation works for all new type keys ---
|
||||
static void test_rpc_set_all_new_types() {
|
||||
HeadlessEditorState state;
|
||||
state.openBuffer("test.wh", "", "python");
|
||||
auto* mod = buildTestAST();
|
||||
state.activeBuffer->sync.setAST(std::unique_ptr<Module>(mod));
|
||||
state.setAgentRole("s1", AgentRole::Refactor);
|
||||
|
||||
// Test a representative selection of new type keys
|
||||
std::vector<std::pair<std::string, json>> tests = {
|
||||
{"endian", {{"order", "big"}}},
|
||||
{"layout", {{"mode", "packed"}, {"alignment", 4}}},
|
||||
{"nullability", {{"nullable", true}, {"strategy", "strict"}}},
|
||||
{"variance", {{"variance", "covariant"}}},
|
||||
{"identity", {{"mode", "nominal"}}},
|
||||
{"mut", {{"depth", "deep"}}},
|
||||
{"typeState", {{"state", "reified"}}},
|
||||
{"sync", {{"primitive", "monitor"}}},
|
||||
{"threadModel", {{"model", "os"}}},
|
||||
{"memoryBarrier", json::object()},
|
||||
{"exec", {{"mode", "async"}, {"runtimeHint", "tokio"}}},
|
||||
{"blocking", {{"kind", "io"}}},
|
||||
{"parallel", {{"kind", "data"}}},
|
||||
{"trap", {{"signal", "SIGSEGV"}}},
|
||||
{"exception", {{"style", "checked"}}},
|
||||
{"panic", {{"behavior", "abort"}}},
|
||||
{"binding", {{"time", "static"}}},
|
||||
{"lookup", {{"mode", "lexical"}}},
|
||||
{"capture", {{"strategy", "move"}}},
|
||||
{"namespace", {{"style", "qualified"}}},
|
||||
{"scope", {{"kind", "local"}}},
|
||||
};
|
||||
|
||||
int successCount = 0;
|
||||
for (const auto& [type, fields] : tests) {
|
||||
auto r = rpc(state, "setSemanticAnnotation", {
|
||||
{"nodeId", "fn2"}, {"type", type}, {"fields", fields}
|
||||
});
|
||||
if (r.contains("result") && r["result"].value("success", false))
|
||||
++successCount;
|
||||
}
|
||||
check(successCount == (int)tests.size(),
|
||||
"all 21 new type keys accepted by setSemanticAnnotation RPC");
|
||||
}
|
||||
|
||||
// --- Test 8: isSemanticAnnotation recognizes all new types ---
|
||||
static void test_is_semantic_annotation() {
|
||||
std::vector<std::string> allTypes = {
|
||||
"BitWidthAnnotation", "EndianAnnotation", "LayoutAnnotation",
|
||||
"NullabilityAnnotation", "VarianceAnnotation",
|
||||
"IdentityAnnotation", "MutAnnotation", "TypeStateAnnotation",
|
||||
"AtomicAnnotation", "SyncAnnotation", "ThreadModelAnnotation",
|
||||
"MemoryBarrierAnnotation",
|
||||
"ExecAnnotation", "BlockingAnnotation", "ParallelAnnotation",
|
||||
"TrapAnnotation", "ExceptionAnnotation", "PanicAnnotation",
|
||||
"BindingAnnotation", "LookupAnnotation", "CaptureAnnotation",
|
||||
"VisibilityAnnotation", "NamespaceAnnotation", "ScopeAnnotation"
|
||||
};
|
||||
int recognized = 0;
|
||||
for (const auto& t : allTypes) {
|
||||
if (isSemanticAnnotation(t)) ++recognized;
|
||||
}
|
||||
check(recognized == 24, "isSemanticAnnotation recognizes all 24 new types");
|
||||
check(!isSemanticAnnotation("DerefStrategy"),
|
||||
"isSemanticAnnotation rejects non-semantic DerefStrategy");
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "=== Step 277: Phase 10c Integration Tests ===\n";
|
||||
test_type_annotations_compact_ast();
|
||||
test_concurrency_annotations_compact_ast();
|
||||
test_scope_annotations_compact_ast();
|
||||
test_sidecar_roundtrip();
|
||||
test_mixed_annotations_single_function();
|
||||
test_rpc_get_annotations();
|
||||
test_rpc_set_all_new_types();
|
||||
test_is_semantic_annotation();
|
||||
std::cout << "\nResults: " << passed << " passed, " << failed << " failed out of "
|
||||
<< (passed + failed) << "\n";
|
||||
return failed > 0 ? 1 : 0;
|
||||
}
|
||||
Reference in New Issue
Block a user