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:
@@ -1662,4 +1662,40 @@ target_link_libraries(step271_test PRIVATE
|
||||
tree_sitter_java tree_sitter_rust tree_sitter_go
|
||||
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)
|
||||
|
||||
@@ -58,6 +58,115 @@ inline json extractSemanticSummary(const ASTNode* node) {
|
||||
auto* ta = static_cast<const SemanticTagAnnotation*>(a);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1654,6 +1654,34 @@ inline json handleHeadlessAgentRequest(HeadlessEditorState& state,
|
||||
else if (type == "risk") conceptType = "RiskAnnotation";
|
||||
else if (type == "contract") conceptType = "ContractAnnotation";
|
||||
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);
|
||||
|
||||
// Remove existing annotation of same type (update semantics)
|
||||
@@ -1722,6 +1750,12 @@ inline json handleHeadlessAgentRequest(HeadlessEditorState& state,
|
||||
} else if (a->conceptType == "SemanticTagAnnotation") {
|
||||
auto* ta = static_cast<SemanticTagAnnotation*>(a);
|
||||
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);
|
||||
}
|
||||
@@ -1749,6 +1783,11 @@ inline json handleHeadlessAgentRequest(HeadlessEditorState& state,
|
||||
} else if (a->conceptType == "SemanticTagAnnotation") {
|
||||
auto* ta = static_cast<SemanticTagAnnotation*>(a);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -23,17 +23,50 @@ inline std::string sidecarPath(const std::string& workspaceRoot,
|
||||
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 ---
|
||||
inline int countSemanticAnnotations(const ASTNode* node) {
|
||||
if (!node) return 0;
|
||||
int count = 0;
|
||||
auto annos = node->getChildren("annotations");
|
||||
for (const auto* a : annos) {
|
||||
if (a->conceptType == "IntentAnnotation" ||
|
||||
a->conceptType == "ComplexityAnnotation" ||
|
||||
a->conceptType == "RiskAnnotation" ||
|
||||
a->conceptType == "ContractAnnotation" ||
|
||||
a->conceptType == "SemanticTagAnnotation")
|
||||
if (isSemanticAnnotation(a->conceptType))
|
||||
++count;
|
||||
}
|
||||
for (const auto* child : node->allChildren()) {
|
||||
@@ -77,15 +110,6 @@ inline SidecarSaveResult saveSidecarAST(const std::string& workspaceRoot,
|
||||
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 ---
|
||||
// Tries ID match first, then falls back to concept+name match
|
||||
// (node IDs are ephemeral and change across re-parses).
|
||||
|
||||
@@ -182,3 +182,159 @@ public:
|
||||
std::vector<std::string> tags; // e.g. ["@serialize", "@validation"]
|
||||
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"; }
|
||||
};
|
||||
|
||||
@@ -163,6 +163,107 @@ inline json propertiesToJson(const ASTNode* node) {
|
||||
auto* n = static_cast<const SemanticTagAnnotation*>(node);
|
||||
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,
|
||||
// WhileLoop, Return, ExpressionStatement, ListType, SetType, MapType,
|
||||
// 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 == "ContractAnnotation") return new ContractAnnotation();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
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