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:
Bill
2026-02-12 18:15:21 +00:00
parent a049d6010b
commit e2d1872f35
12 changed files with 1959 additions and 14 deletions

View File

@@ -1662,4 +1662,40 @@ target_link_libraries(step271_test PRIVATE
tree_sitter_java tree_sitter_rust tree_sitter_go tree_sitter_java tree_sitter_rust tree_sitter_go
tree_sitter_org) tree_sitter_org)
# Step 272: Type System — Layout & Constraints
add_executable(step272_test tests/step272_test.cpp)
target_include_directories(step272_test PRIVATE src)
target_link_libraries(step272_test PRIVATE nlohmann_json::nlohmann_json)
# Step 273: Type System — Identity & Mutability
add_executable(step273_test tests/step273_test.cpp)
target_include_directories(step273_test PRIVATE src)
target_link_libraries(step273_test PRIVATE nlohmann_json::nlohmann_json)
# Step 274: Concurrency — Primitives & Memory Model
add_executable(step274_test tests/step274_test.cpp)
target_include_directories(step274_test PRIVATE src)
target_link_libraries(step274_test PRIVATE nlohmann_json::nlohmann_json)
# Step 275: Async, Parallelism & Error Handling
add_executable(step275_test tests/step275_test.cpp)
target_include_directories(step275_test PRIVATE src)
target_link_libraries(step275_test PRIVATE nlohmann_json::nlohmann_json)
# Step 276: Scope & Namespace Annotations
add_executable(step276_test tests/step276_test.cpp)
target_include_directories(step276_test PRIVATE src)
target_link_libraries(step276_test PRIVATE nlohmann_json::nlohmann_json)
# Step 277: Phase 10c Integration Tests
add_executable(step277_test tests/step277_test.cpp)
target_include_directories(step277_test PRIVATE src)
target_link_libraries(step277_test PRIVATE
nlohmann_json::nlohmann_json
unofficial::tree-sitter::tree-sitter
tree_sitter_python tree_sitter_cpp tree_sitter_elisp
tree_sitter_javascript tree_sitter_typescript
tree_sitter_java tree_sitter_rust tree_sitter_go
tree_sitter_org)
# Step 12: Dear ImGui shell scaffolding created (main.cpp exists but not built due to dependencies) # Step 12: Dear ImGui shell scaffolding created (main.cpp exists but not built due to dependencies)

View File

@@ -58,6 +58,115 @@ inline json extractSemanticSummary(const ASTNode* node) {
auto* ta = static_cast<const SemanticTagAnnotation*>(a); auto* ta = static_cast<const SemanticTagAnnotation*>(a);
if (!ta->tags.empty()) sem["tags"] = ta->tags; if (!ta->tags.empty()) sem["tags"] = ta->tags;
} }
// Type System — Layout & Constraints (Step 272)
else if (a->conceptType == "BitWidthAnnotation") {
auto* ba = static_cast<const BitWidthAnnotation*>(a);
sem["bitWidth"] = ba->width;
}
else if (a->conceptType == "EndianAnnotation") {
auto* ea = static_cast<const EndianAnnotation*>(a);
if (!ea->order.empty()) sem["endian"] = ea->order;
}
else if (a->conceptType == "LayoutAnnotation") {
auto* la = static_cast<const LayoutAnnotation*>(a);
json obj;
if (!la->mode.empty()) obj["mode"] = la->mode;
if (la->alignment > 0) obj["alignment"] = la->alignment;
if (!obj.empty()) sem["layout"] = obj;
}
else if (a->conceptType == "NullabilityAnnotation") {
auto* na = static_cast<const NullabilityAnnotation*>(a);
json obj;
obj["nullable"] = na->nullable;
if (!na->strategy.empty()) obj["strategy"] = na->strategy;
sem["nullability"] = obj;
}
else if (a->conceptType == "VarianceAnnotation") {
auto* va = static_cast<const VarianceAnnotation*>(a);
if (!va->variance.empty()) sem["variance"] = va->variance;
}
// Type System — Identity & Mutability (Step 273)
else if (a->conceptType == "IdentityAnnotation") {
auto* ia = static_cast<const IdentityAnnotation*>(a);
if (!ia->mode.empty()) sem["identity"] = ia->mode;
}
else if (a->conceptType == "MutAnnotation") {
auto* ma = static_cast<const MutAnnotation*>(a);
if (!ma->depth.empty()) sem["mutability"] = ma->depth;
}
else if (a->conceptType == "TypeStateAnnotation") {
auto* ts = static_cast<const TypeStateAnnotation*>(a);
if (!ts->state.empty()) sem["typeState"] = ts->state;
}
// Concurrency (Step 274)
else if (a->conceptType == "AtomicAnnotation") {
auto* aa = static_cast<const AtomicAnnotation*>(a);
if (!aa->consistency.empty()) sem["atomic"] = aa->consistency;
}
else if (a->conceptType == "SyncAnnotation") {
auto* sa = static_cast<const SyncAnnotation*>(a);
if (!sa->primitive.empty()) sem["sync"] = sa->primitive;
}
else if (a->conceptType == "ThreadModelAnnotation") {
auto* tm = static_cast<const ThreadModelAnnotation*>(a);
if (!tm->model.empty()) sem["threadModel"] = tm->model;
}
else if (a->conceptType == "MemoryBarrierAnnotation") {
sem["memoryBarrier"] = true;
}
// Async, Parallelism & Error Handling (Step 275)
else if (a->conceptType == "ExecAnnotation") {
auto* ea = static_cast<const ExecAnnotation*>(a);
json obj;
if (!ea->mode.empty()) obj["mode"] = ea->mode;
if (!ea->runtimeHint.empty()) obj["runtime"] = ea->runtimeHint;
if (!obj.empty()) sem["exec"] = obj;
}
else if (a->conceptType == "BlockingAnnotation") {
auto* ba = static_cast<const BlockingAnnotation*>(a);
if (!ba->kind.empty()) sem["blocking"] = ba->kind;
}
else if (a->conceptType == "ParallelAnnotation") {
auto* pa = static_cast<const ParallelAnnotation*>(a);
if (!pa->kind.empty()) sem["parallel"] = pa->kind;
}
else if (a->conceptType == "TrapAnnotation") {
auto* ta = static_cast<const TrapAnnotation*>(a);
if (!ta->signal.empty()) sem["trap"] = ta->signal;
}
else if (a->conceptType == "ExceptionAnnotation") {
auto* ea = static_cast<const ExceptionAnnotation*>(a);
if (!ea->style.empty()) sem["exception"] = ea->style;
}
else if (a->conceptType == "PanicAnnotation") {
auto* pa = static_cast<const PanicAnnotation*>(a);
if (!pa->behavior.empty()) sem["panic"] = pa->behavior;
}
// Scope & Namespace (Step 276)
else if (a->conceptType == "BindingAnnotation") {
auto* ba = static_cast<const BindingAnnotation*>(a);
if (!ba->time.empty()) sem["binding"] = ba->time;
}
else if (a->conceptType == "LookupAnnotation") {
auto* la = static_cast<const LookupAnnotation*>(a);
if (!la->mode.empty()) sem["lookup"] = la->mode;
}
else if (a->conceptType == "CaptureAnnotation") {
auto* ca = static_cast<const CaptureAnnotation*>(a);
if (!ca->strategy.empty()) sem["capture"] = ca->strategy;
}
else if (a->conceptType == "VisibilityAnnotation") {
auto* va = static_cast<const VisibilityAnnotation*>(a);
if (!va->level.empty()) sem["visibility"] = va->level;
}
else if (a->conceptType == "NamespaceAnnotation") {
auto* na = static_cast<const NamespaceAnnotation*>(a);
if (!na->style.empty()) sem["namespace"] = na->style;
}
else if (a->conceptType == "ScopeAnnotation") {
auto* sa = static_cast<const ScopeAnnotation*>(a);
if (!sa->kind.empty()) sem["scope"] = sa->kind;
}
} }
return sem.empty() ? json() : sem; return sem.empty() ? json() : sem;
} }

View File

@@ -1654,6 +1654,34 @@ inline json handleHeadlessAgentRequest(HeadlessEditorState& state,
else if (type == "risk") conceptType = "RiskAnnotation"; else if (type == "risk") conceptType = "RiskAnnotation";
else if (type == "contract") conceptType = "ContractAnnotation"; else if (type == "contract") conceptType = "ContractAnnotation";
else if (type == "tags") conceptType = "SemanticTagAnnotation"; else if (type == "tags") conceptType = "SemanticTagAnnotation";
// Type System (Steps 272-273)
else if (type == "bitWidth") conceptType = "BitWidthAnnotation";
else if (type == "endian") conceptType = "EndianAnnotation";
else if (type == "layout") conceptType = "LayoutAnnotation";
else if (type == "nullability") conceptType = "NullabilityAnnotation";
else if (type == "variance") conceptType = "VarianceAnnotation";
else if (type == "identity") conceptType = "IdentityAnnotation";
else if (type == "mut") conceptType = "MutAnnotation";
else if (type == "typeState") conceptType = "TypeStateAnnotation";
// Concurrency (Step 274)
else if (type == "atomic") conceptType = "AtomicAnnotation";
else if (type == "sync") conceptType = "SyncAnnotation";
else if (type == "threadModel") conceptType = "ThreadModelAnnotation";
else if (type == "memoryBarrier") conceptType = "MemoryBarrierAnnotation";
// Async / Error Handling (Step 275)
else if (type == "exec") conceptType = "ExecAnnotation";
else if (type == "blocking") conceptType = "BlockingAnnotation";
else if (type == "parallel") conceptType = "ParallelAnnotation";
else if (type == "trap") conceptType = "TrapAnnotation";
else if (type == "exception") conceptType = "ExceptionAnnotation";
else if (type == "panic") conceptType = "PanicAnnotation";
// Scope & Namespace (Step 276)
else if (type == "binding") conceptType = "BindingAnnotation";
else if (type == "lookup") conceptType = "LookupAnnotation";
else if (type == "capture") conceptType = "CaptureAnnotation";
else if (type == "visibility") conceptType = "VisibilityAnnotation";
else if (type == "namespace") conceptType = "NamespaceAnnotation";
else if (type == "scope") conceptType = "ScopeAnnotation";
else return headlessRpcError(id, -32602, "Unknown annotation type: " + type); else return headlessRpcError(id, -32602, "Unknown annotation type: " + type);
// Remove existing annotation of same type (update semantics) // Remove existing annotation of same type (update semantics)
@@ -1722,6 +1750,12 @@ inline json handleHeadlessAgentRequest(HeadlessEditorState& state,
} else if (a->conceptType == "SemanticTagAnnotation") { } else if (a->conceptType == "SemanticTagAnnotation") {
auto* ta = static_cast<SemanticTagAnnotation*>(a); auto* ta = static_cast<SemanticTagAnnotation*>(a);
entry = {{"type", "tags"}, {"tags", ta->tags}}; entry = {{"type", "tags"}, {"tags", ta->tags}};
} else {
// Generic fallback for all other semantic annotations
entry = {{"type", a->conceptType}};
json props = propertiesToJson(a);
for (auto& [k, v] : props.items())
entry[k] = v;
} }
if (!entry.empty()) annos.push_back(entry); if (!entry.empty()) annos.push_back(entry);
} }
@@ -1749,6 +1783,11 @@ inline json handleHeadlessAgentRequest(HeadlessEditorState& state,
} else if (a->conceptType == "SemanticTagAnnotation") { } else if (a->conceptType == "SemanticTagAnnotation") {
auto* ta = static_cast<SemanticTagAnnotation*>(a); auto* ta = static_cast<SemanticTagAnnotation*>(a);
entry = {{"type", "tags"}, {"tags", ta->tags}}; entry = {{"type", "tags"}, {"tags", ta->tags}};
} else {
entry = {{"type", a->conceptType}};
json props = propertiesToJson(a);
for (auto& [k, v] : props.items())
entry[k] = v;
} }
if (!entry.empty()) annoList.push_back(entry); if (!entry.empty()) annoList.push_back(entry);
} }

View File

@@ -23,17 +23,50 @@ inline std::string sidecarPath(const std::string& workspaceRoot,
return (base / (filePath + ".ast.json")).string(); return (base / (filePath + ".ast.json")).string();
} }
// --- Check if a node type is a semantic annotation ---
inline bool isSemanticAnnotation(const std::string& conceptType) {
return conceptType == "IntentAnnotation" ||
conceptType == "ComplexityAnnotation" ||
conceptType == "RiskAnnotation" ||
conceptType == "ContractAnnotation" ||
conceptType == "SemanticTagAnnotation" ||
// Type System (Steps 272-273)
conceptType == "BitWidthAnnotation" ||
conceptType == "EndianAnnotation" ||
conceptType == "LayoutAnnotation" ||
conceptType == "NullabilityAnnotation" ||
conceptType == "VarianceAnnotation" ||
conceptType == "IdentityAnnotation" ||
conceptType == "MutAnnotation" ||
conceptType == "TypeStateAnnotation" ||
// Concurrency (Step 274)
conceptType == "AtomicAnnotation" ||
conceptType == "SyncAnnotation" ||
conceptType == "ThreadModelAnnotation" ||
conceptType == "MemoryBarrierAnnotation" ||
// Async / Error Handling (Step 275)
conceptType == "ExecAnnotation" ||
conceptType == "BlockingAnnotation" ||
conceptType == "ParallelAnnotation" ||
conceptType == "TrapAnnotation" ||
conceptType == "ExceptionAnnotation" ||
conceptType == "PanicAnnotation" ||
// Scope & Namespace (Step 276)
conceptType == "BindingAnnotation" ||
conceptType == "LookupAnnotation" ||
conceptType == "CaptureAnnotation" ||
conceptType == "VisibilityAnnotation" ||
conceptType == "NamespaceAnnotation" ||
conceptType == "ScopeAnnotation";
}
// --- Count semantic annotations in an AST --- // --- Count semantic annotations in an AST ---
inline int countSemanticAnnotations(const ASTNode* node) { inline int countSemanticAnnotations(const ASTNode* node) {
if (!node) return 0; if (!node) return 0;
int count = 0; int count = 0;
auto annos = node->getChildren("annotations"); auto annos = node->getChildren("annotations");
for (const auto* a : annos) { for (const auto* a : annos) {
if (a->conceptType == "IntentAnnotation" || if (isSemanticAnnotation(a->conceptType))
a->conceptType == "ComplexityAnnotation" ||
a->conceptType == "RiskAnnotation" ||
a->conceptType == "ContractAnnotation" ||
a->conceptType == "SemanticTagAnnotation")
++count; ++count;
} }
for (const auto* child : node->allChildren()) { for (const auto* child : node->allChildren()) {
@@ -77,15 +110,6 @@ inline SidecarSaveResult saveSidecarAST(const std::string& workspaceRoot,
return result; return result;
} }
// --- Check if a node type is a semantic annotation ---
inline bool isSemanticAnnotation(const std::string& conceptType) {
return conceptType == "IntentAnnotation" ||
conceptType == "ComplexityAnnotation" ||
conceptType == "RiskAnnotation" ||
conceptType == "ContractAnnotation" ||
conceptType == "SemanticTagAnnotation";
}
// --- Find a matching node in the live AST --- // --- Find a matching node in the live AST ---
// Tries ID match first, then falls back to concept+name match // Tries ID match first, then falls back to concept+name match
// (node IDs are ephemeral and change across re-parses). // (node IDs are ephemeral and change across re-parses).

View File

@@ -182,3 +182,159 @@ public:
std::vector<std::string> tags; // e.g. ["@serialize", "@validation"] std::vector<std::string> tags; // e.g. ["@serialize", "@validation"]
SemanticTagAnnotation() { conceptType = "SemanticTagAnnotation"; } SemanticTagAnnotation() { conceptType = "SemanticTagAnnotation"; }
}; };
// Type System Annotations — Layout & Constraints (Step 272, Subject 2)
class BitWidthAnnotation : public Annotation {
public:
int width = 0; // e.g. 32 for Java int
BitWidthAnnotation() { conceptType = "BitWidthAnnotation"; }
};
class EndianAnnotation : public Annotation {
public:
std::string order; // "big" | "little"
EndianAnnotation() { conceptType = "EndianAnnotation"; }
};
class LayoutAnnotation : public Annotation {
public:
std::string mode; // "packed" | "aligned"
int alignment = 0;
LayoutAnnotation() { conceptType = "LayoutAnnotation"; }
};
class NullabilityAnnotation : public Annotation {
public:
bool nullable = false;
std::string strategy; // "strict" | "nullable"
NullabilityAnnotation() { conceptType = "NullabilityAnnotation"; }
};
class VarianceAnnotation : public Annotation {
public:
std::string variance; // "covariant" | "contravariant" | "invariant"
VarianceAnnotation() { conceptType = "VarianceAnnotation"; }
};
// Type System Annotations — Identity & Mutability (Step 273, Subject 2)
class IdentityAnnotation : public Annotation {
public:
std::string mode; // "nominal" | "structural"
IdentityAnnotation() { conceptType = "IdentityAnnotation"; }
};
class MutAnnotation : public Annotation {
public:
std::string depth; // "shallow" | "deep" | "interior"
MutAnnotation() { conceptType = "MutAnnotation"; }
};
class TypeStateAnnotation : public Annotation {
public:
std::string state; // "erased" | "reified"
TypeStateAnnotation() { conceptType = "TypeStateAnnotation"; }
};
// Concurrency Annotations — Primitives & Memory Model (Step 274, Subject 3)
class AtomicAnnotation : public Annotation {
public:
std::string consistency; // "seq_cst" | "relaxed" | "acquire" | "release"
AtomicAnnotation() { conceptType = "AtomicAnnotation"; }
};
class SyncAnnotation : public Annotation {
public:
std::string primitive; // "monitor" | "spin" | "semaphore"
SyncAnnotation() { conceptType = "SyncAnnotation"; }
};
class ThreadModelAnnotation : public Annotation {
public:
std::string model; // "green" | "os" | "fiber"
ThreadModelAnnotation() { conceptType = "ThreadModelAnnotation"; }
};
class MemoryBarrierAnnotation : public Annotation {
public:
MemoryBarrierAnnotation() { conceptType = "MemoryBarrierAnnotation"; }
};
// Async, Parallelism & Error Handling Annotations (Step 275, Subject 3)
class ExecAnnotation : public Annotation {
public:
std::string mode; // "async" | "event"
std::string runtimeHint; // e.g. "tokio", "libuv"
ExecAnnotation() { conceptType = "ExecAnnotation"; }
};
class BlockingAnnotation : public Annotation {
public:
std::string kind; // "io" | "compute"
BlockingAnnotation() { conceptType = "BlockingAnnotation"; }
};
class ParallelAnnotation : public Annotation {
public:
std::string kind; // "data" | "task"
ParallelAnnotation() { conceptType = "ParallelAnnotation"; }
};
class TrapAnnotation : public Annotation {
public:
std::string signal; // e.g. "SIGSEGV", "SIGFPE"
TrapAnnotation() { conceptType = "TrapAnnotation"; }
};
class ExceptionAnnotation : public Annotation {
public:
std::string style; // "checked" | "unchecked"
ExceptionAnnotation() { conceptType = "ExceptionAnnotation"; }
};
class PanicAnnotation : public Annotation {
public:
std::string behavior; // "abort" | "unwind"
PanicAnnotation() { conceptType = "PanicAnnotation"; }
};
// Scope & Namespace Annotations (Step 276, Subject 4)
class BindingAnnotation : public Annotation {
public:
std::string time; // "static" | "dynamic"
BindingAnnotation() { conceptType = "BindingAnnotation"; }
};
class LookupAnnotation : public Annotation {
public:
std::string mode; // "lexical" | "hoisted"
LookupAnnotation() { conceptType = "LookupAnnotation"; }
};
class CaptureAnnotation : public Annotation {
public:
std::string strategy; // "value" | "ref" | "move"
CaptureAnnotation() { conceptType = "CaptureAnnotation"; }
};
class VisibilityAnnotation : public Annotation {
public:
std::string level; // "private" | "internal" | "friend" | "public"
VisibilityAnnotation() { conceptType = "VisibilityAnnotation"; }
};
class NamespaceAnnotation : public Annotation {
public:
std::string style; // "qualified" | "flat"
NamespaceAnnotation() { conceptType = "NamespaceAnnotation"; }
};
class ScopeAnnotation : public Annotation {
public:
std::string kind; // "local" | "global_leaked" | "singleton"
ScopeAnnotation() { conceptType = "ScopeAnnotation"; }
};

View File

@@ -163,6 +163,107 @@ inline json propertiesToJson(const ASTNode* node) {
auto* n = static_cast<const SemanticTagAnnotation*>(node); auto* n = static_cast<const SemanticTagAnnotation*>(node);
if (!n->tags.empty()) props["tags"] = n->tags; if (!n->tags.empty()) props["tags"] = n->tags;
} }
// Type System — Layout & Constraints (Step 272)
else if (ct == "BitWidthAnnotation") {
auto* n = static_cast<const BitWidthAnnotation*>(node);
props["width"] = n->width;
}
else if (ct == "EndianAnnotation") {
auto* n = static_cast<const EndianAnnotation*>(node);
if (!n->order.empty()) props["order"] = n->order;
}
else if (ct == "LayoutAnnotation") {
auto* n = static_cast<const LayoutAnnotation*>(node);
if (!n->mode.empty()) props["mode"] = n->mode;
props["alignment"] = n->alignment;
}
else if (ct == "NullabilityAnnotation") {
auto* n = static_cast<const NullabilityAnnotation*>(node);
props["nullable"] = n->nullable;
if (!n->strategy.empty()) props["strategy"] = n->strategy;
}
else if (ct == "VarianceAnnotation") {
auto* n = static_cast<const VarianceAnnotation*>(node);
if (!n->variance.empty()) props["variance"] = n->variance;
}
// Type System — Identity & Mutability (Step 273)
else if (ct == "IdentityAnnotation") {
auto* n = static_cast<const IdentityAnnotation*>(node);
if (!n->mode.empty()) props["mode"] = n->mode;
}
else if (ct == "MutAnnotation") {
auto* n = static_cast<const MutAnnotation*>(node);
if (!n->depth.empty()) props["depth"] = n->depth;
}
else if (ct == "TypeStateAnnotation") {
auto* n = static_cast<const TypeStateAnnotation*>(node);
if (!n->state.empty()) props["state"] = n->state;
}
// Concurrency — Primitives & Memory Model (Step 274)
else if (ct == "AtomicAnnotation") {
auto* n = static_cast<const AtomicAnnotation*>(node);
if (!n->consistency.empty()) props["consistency"] = n->consistency;
}
else if (ct == "SyncAnnotation") {
auto* n = static_cast<const SyncAnnotation*>(node);
if (!n->primitive.empty()) props["primitive"] = n->primitive;
}
else if (ct == "ThreadModelAnnotation") {
auto* n = static_cast<const ThreadModelAnnotation*>(node);
if (!n->model.empty()) props["model"] = n->model;
}
// MemoryBarrierAnnotation has no extra fields
// Async, Parallelism & Error Handling (Step 275)
else if (ct == "ExecAnnotation") {
auto* n = static_cast<const ExecAnnotation*>(node);
if (!n->mode.empty()) props["mode"] = n->mode;
if (!n->runtimeHint.empty()) props["runtimeHint"] = n->runtimeHint;
}
else if (ct == "BlockingAnnotation") {
auto* n = static_cast<const BlockingAnnotation*>(node);
if (!n->kind.empty()) props["kind"] = n->kind;
}
else if (ct == "ParallelAnnotation") {
auto* n = static_cast<const ParallelAnnotation*>(node);
if (!n->kind.empty()) props["kind"] = n->kind;
}
else if (ct == "TrapAnnotation") {
auto* n = static_cast<const TrapAnnotation*>(node);
if (!n->signal.empty()) props["signal"] = n->signal;
}
else if (ct == "ExceptionAnnotation") {
auto* n = static_cast<const ExceptionAnnotation*>(node);
if (!n->style.empty()) props["style"] = n->style;
}
else if (ct == "PanicAnnotation") {
auto* n = static_cast<const PanicAnnotation*>(node);
if (!n->behavior.empty()) props["behavior"] = n->behavior;
}
// Scope & Namespace (Step 276)
else if (ct == "BindingAnnotation") {
auto* n = static_cast<const BindingAnnotation*>(node);
if (!n->time.empty()) props["time"] = n->time;
}
else if (ct == "LookupAnnotation") {
auto* n = static_cast<const LookupAnnotation*>(node);
if (!n->mode.empty()) props["mode"] = n->mode;
}
else if (ct == "CaptureAnnotation") {
auto* n = static_cast<const CaptureAnnotation*>(node);
if (!n->strategy.empty()) props["strategy"] = n->strategy;
}
else if (ct == "VisibilityAnnotation") {
auto* n = static_cast<const VisibilityAnnotation*>(node);
if (!n->level.empty()) props["level"] = n->level;
}
else if (ct == "NamespaceAnnotation") {
auto* n = static_cast<const NamespaceAnnotation*>(node);
if (!n->style.empty()) props["style"] = n->style;
}
else if (ct == "ScopeAnnotation") {
auto* n = static_cast<const ScopeAnnotation*>(node);
if (!n->kind.empty()) props["kind"] = n->kind;
}
// NullLiteral, ListLiteral, IndexAccess, Block, Assignment, IfStatement, // NullLiteral, ListLiteral, IndexAccess, Block, Assignment, IfStatement,
// WhileLoop, Return, ExpressionStatement, ListType, SetType, MapType, // WhileLoop, Return, ExpressionStatement, ListType, SetType, MapType,
// TupleType, ArrayType, OptionalType — no extra properties // TupleType, ArrayType, OptionalType — no extra properties
@@ -240,6 +341,35 @@ inline ASTNode* createNode(const std::string& conceptName) {
if (conceptName == "RiskAnnotation") return new RiskAnnotation(); if (conceptName == "RiskAnnotation") return new RiskAnnotation();
if (conceptName == "ContractAnnotation") return new ContractAnnotation(); if (conceptName == "ContractAnnotation") return new ContractAnnotation();
if (conceptName == "SemanticTagAnnotation") return new SemanticTagAnnotation(); if (conceptName == "SemanticTagAnnotation") return new SemanticTagAnnotation();
// Type System — Layout & Constraints (Step 272)
if (conceptName == "BitWidthAnnotation") return new BitWidthAnnotation();
if (conceptName == "EndianAnnotation") return new EndianAnnotation();
if (conceptName == "LayoutAnnotation") return new LayoutAnnotation();
if (conceptName == "NullabilityAnnotation") return new NullabilityAnnotation();
if (conceptName == "VarianceAnnotation") return new VarianceAnnotation();
// Type System — Identity & Mutability (Step 273)
if (conceptName == "IdentityAnnotation") return new IdentityAnnotation();
if (conceptName == "MutAnnotation") return new MutAnnotation();
if (conceptName == "TypeStateAnnotation") return new TypeStateAnnotation();
// Concurrency (Step 274)
if (conceptName == "AtomicAnnotation") return new AtomicAnnotation();
if (conceptName == "SyncAnnotation") return new SyncAnnotation();
if (conceptName == "ThreadModelAnnotation") return new ThreadModelAnnotation();
if (conceptName == "MemoryBarrierAnnotation") return new MemoryBarrierAnnotation();
// Async, Parallelism & Error Handling (Step 275)
if (conceptName == "ExecAnnotation") return new ExecAnnotation();
if (conceptName == "BlockingAnnotation") return new BlockingAnnotation();
if (conceptName == "ParallelAnnotation") return new ParallelAnnotation();
if (conceptName == "TrapAnnotation") return new TrapAnnotation();
if (conceptName == "ExceptionAnnotation") return new ExceptionAnnotation();
if (conceptName == "PanicAnnotation") return new PanicAnnotation();
// Scope & Namespace (Step 276)
if (conceptName == "BindingAnnotation") return new BindingAnnotation();
if (conceptName == "LookupAnnotation") return new LookupAnnotation();
if (conceptName == "CaptureAnnotation") return new CaptureAnnotation();
if (conceptName == "VisibilityAnnotation") return new VisibilityAnnotation();
if (conceptName == "NamespaceAnnotation") return new NamespaceAnnotation();
if (conceptName == "ScopeAnnotation") return new ScopeAnnotation();
return nullptr; return nullptr;
} }
@@ -396,6 +526,107 @@ inline void setPropertiesFromJson(ASTNode* node, const json& props) {
} }
} }
} }
// Type System — Layout & Constraints (Step 272)
else if (ct == "BitWidthAnnotation") {
auto* n = static_cast<BitWidthAnnotation*>(node);
if (props.contains("width")) n->width = props["width"].get<int>();
}
else if (ct == "EndianAnnotation") {
auto* n = static_cast<EndianAnnotation*>(node);
if (props.contains("order")) n->order = props["order"].get<std::string>();
}
else if (ct == "LayoutAnnotation") {
auto* n = static_cast<LayoutAnnotation*>(node);
if (props.contains("mode")) n->mode = props["mode"].get<std::string>();
if (props.contains("alignment")) n->alignment = props["alignment"].get<int>();
}
else if (ct == "NullabilityAnnotation") {
auto* n = static_cast<NullabilityAnnotation*>(node);
if (props.contains("nullable")) n->nullable = props["nullable"].get<bool>();
if (props.contains("strategy")) n->strategy = props["strategy"].get<std::string>();
}
else if (ct == "VarianceAnnotation") {
auto* n = static_cast<VarianceAnnotation*>(node);
if (props.contains("variance")) n->variance = props["variance"].get<std::string>();
}
// Type System — Identity & Mutability (Step 273)
else if (ct == "IdentityAnnotation") {
auto* n = static_cast<IdentityAnnotation*>(node);
if (props.contains("mode")) n->mode = props["mode"].get<std::string>();
}
else if (ct == "MutAnnotation") {
auto* n = static_cast<MutAnnotation*>(node);
if (props.contains("depth")) n->depth = props["depth"].get<std::string>();
}
else if (ct == "TypeStateAnnotation") {
auto* n = static_cast<TypeStateAnnotation*>(node);
if (props.contains("state")) n->state = props["state"].get<std::string>();
}
// Concurrency (Step 274)
else if (ct == "AtomicAnnotation") {
auto* n = static_cast<AtomicAnnotation*>(node);
if (props.contains("consistency")) n->consistency = props["consistency"].get<std::string>();
}
else if (ct == "SyncAnnotation") {
auto* n = static_cast<SyncAnnotation*>(node);
if (props.contains("primitive")) n->primitive = props["primitive"].get<std::string>();
}
else if (ct == "ThreadModelAnnotation") {
auto* n = static_cast<ThreadModelAnnotation*>(node);
if (props.contains("model")) n->model = props["model"].get<std::string>();
}
// MemoryBarrierAnnotation has no extra fields
// Async, Parallelism & Error Handling (Step 275)
else if (ct == "ExecAnnotation") {
auto* n = static_cast<ExecAnnotation*>(node);
if (props.contains("mode")) n->mode = props["mode"].get<std::string>();
if (props.contains("runtimeHint")) n->runtimeHint = props["runtimeHint"].get<std::string>();
}
else if (ct == "BlockingAnnotation") {
auto* n = static_cast<BlockingAnnotation*>(node);
if (props.contains("kind")) n->kind = props["kind"].get<std::string>();
}
else if (ct == "ParallelAnnotation") {
auto* n = static_cast<ParallelAnnotation*>(node);
if (props.contains("kind")) n->kind = props["kind"].get<std::string>();
}
else if (ct == "TrapAnnotation") {
auto* n = static_cast<TrapAnnotation*>(node);
if (props.contains("signal")) n->signal = props["signal"].get<std::string>();
}
else if (ct == "ExceptionAnnotation") {
auto* n = static_cast<ExceptionAnnotation*>(node);
if (props.contains("style")) n->style = props["style"].get<std::string>();
}
else if (ct == "PanicAnnotation") {
auto* n = static_cast<PanicAnnotation*>(node);
if (props.contains("behavior")) n->behavior = props["behavior"].get<std::string>();
}
// Scope & Namespace (Step 276)
else if (ct == "BindingAnnotation") {
auto* n = static_cast<BindingAnnotation*>(node);
if (props.contains("time")) n->time = props["time"].get<std::string>();
}
else if (ct == "LookupAnnotation") {
auto* n = static_cast<LookupAnnotation*>(node);
if (props.contains("mode")) n->mode = props["mode"].get<std::string>();
}
else if (ct == "CaptureAnnotation") {
auto* n = static_cast<CaptureAnnotation*>(node);
if (props.contains("strategy")) n->strategy = props["strategy"].get<std::string>();
}
else if (ct == "VisibilityAnnotation") {
auto* n = static_cast<VisibilityAnnotation*>(node);
if (props.contains("level")) n->level = props["level"].get<std::string>();
}
else if (ct == "NamespaceAnnotation") {
auto* n = static_cast<NamespaceAnnotation*>(node);
if (props.contains("style")) n->style = props["style"].get<std::string>();
}
else if (ct == "ScopeAnnotation") {
auto* n = static_cast<ScopeAnnotation*>(node);
if (props.contains("kind")) n->kind = props["kind"].get<std::string>();
}
} }
inline std::string generateNodeId() { inline std::string generateNodeId() {

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}