Files
whetstone_DSL/editor/tests/step302_test.cpp
Bill 87615a7187 Steps 297-302: Phase 11b complete + Phase 11c step 302 (68/68 tests)
Phase 11b — Validation & Conflict Completion:
- Step 297: Subject 2-4 validation rules E0600-E0805 (12/12)
- Step 298: Subject 5-8 validation rules E0900-E1202 (12/12)
- Step 299: Cross-type conflict detection, 6 conflict pairs (12/12)
- Step 300: TransformEngineExtended — float folding, dead var, annotation-aware (12/12)
- Step 301: Phase 11b integration tests (8/8)

Phase 11c — Parser Deepening (start):
- Step 302: New AST nodes — ClassDeclaration, InterfaceDeclaration,
  MethodDeclaration, GenericType, TypeParameter with JSON roundtrip (12/12)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 16:53:23 +00:00

302 lines
10 KiB
C++

// Step 302: New AST Nodes — Class/Interface/Generic (12 tests)
// Tests ClassDeclaration, InterfaceDeclaration, MethodDeclaration,
// GenericType, TypeParameter: construction, properties, children, serialization.
#include "ast/ClassDeclaration.h"
#include "ast/GenericType.h"
#include "ast/Serialization.h"
#include "ast/Variable.h"
#include "ast/Statement.h"
#include "ast/Expression.h"
#include <nlohmann/json.hpp>
#include <iostream>
#include <string>
#include <memory>
using json = nlohmann::json;
static int passed = 0, failed = 0;
#define TEST(name) { std::cout << " " << #name << "... "; }
#define PASS() { std::cout << "PASS\n"; ++passed; }
#define FAIL(msg) { std::cout << "FAIL: " << msg << "\n"; ++failed; }
#define CHECK(cond, msg) if (!(cond)) { FAIL(msg); return; } else {}
// 1. ClassDeclaration construction and properties
void test_class_construction() {
TEST(class_construction);
ClassDeclaration cls("cls1", "Animal");
cls.superClass = "Entity";
cls.isAbstract = true;
CHECK(cls.conceptType == "ClassDeclaration", "wrong conceptType");
CHECK(cls.id == "cls1", "wrong id");
CHECK(cls.name == "Animal", "wrong name");
CHECK(cls.superClass == "Entity", "wrong superClass");
CHECK(cls.isAbstract == true, "wrong isAbstract");
PASS();
}
// 2. ClassDeclaration child roles: methods, fields, annotations
void test_class_children() {
TEST(class_children);
auto cls = std::make_unique<ClassDeclaration>("cls1", "Dog");
cls->superClass = "Animal";
auto method = new MethodDeclaration("m1", "bark");
method->className = "Dog";
cls->addChild("methods", method);
auto field = new Variable("v1", "name");
cls->addChild("fields", field);
CHECK(cls->getChildren("methods").size() == 1, "expected 1 method");
CHECK(cls->getChildren("fields").size() == 1, "expected 1 field");
CHECK(static_cast<MethodDeclaration*>(cls->getChildren("methods")[0])->name == "bark",
"method name wrong");
PASS();
}
// 3. InterfaceDeclaration construction
void test_interface_construction() {
TEST(interface_construction);
InterfaceDeclaration iface("if1", "Serializable");
CHECK(iface.conceptType == "InterfaceDeclaration", "wrong conceptType");
CHECK(iface.name == "Serializable", "wrong name");
auto method = new MethodDeclaration("m1", "serialize");
method->isVirtual = true;
iface.addChild("methods", method);
CHECK(iface.getChildren("methods").size() == 1, "expected 1 method");
PASS();
}
// 4. MethodDeclaration extends Function with class-specific fields
void test_method_properties() {
TEST(method_properties);
MethodDeclaration meth("m1", "process");
meth.className = "Worker";
meth.isStatic = true;
meth.visibility = "private";
meth.isOverride = true;
meth.isVirtual = false;
CHECK(meth.conceptType == "MethodDeclaration", "wrong conceptType");
CHECK(meth.name == "process", "wrong name");
CHECK(meth.className == "Worker", "wrong className");
CHECK(meth.isStatic == true, "wrong isStatic");
CHECK(meth.visibility == "private", "wrong visibility");
CHECK(meth.isOverride == true, "wrong isOverride");
CHECK(meth.isVirtual == false, "wrong isVirtual");
PASS();
}
// 5. MethodDeclaration inherits Function children (parameters, body)
void test_method_inherits_function() {
TEST(method_inherits_function);
auto meth = std::make_unique<MethodDeclaration>("m1", "run");
auto param = new Parameter();
param->id = "p1";
param->name = "x";
meth->addChild("parameters", param);
auto ret = new Return();
ret->id = "r1";
meth->addChild("body", ret);
CHECK(meth->getChildren("parameters").size() == 1, "expected 1 parameter");
CHECK(meth->getChildren("body").size() == 1, "expected 1 body stmt");
PASS();
}
// 6. GenericType construction and children
void test_generic_type() {
TEST(generic_type);
GenericType gen("gt1", "Map");
CHECK(gen.conceptType == "GenericType", "wrong conceptType");
CHECK(gen.baseName == "Map", "wrong baseName");
auto k = new TypeParameter("tp1", "K");
k->constraint = "Comparable";
auto v = new TypeParameter("tp2", "V");
gen.addChild("typeParameters", k);
gen.addChild("typeParameters", v);
CHECK(gen.getChildren("typeParameters").size() == 2, "expected 2 type params");
PASS();
}
// 7. TypeParameter construction with constraint
void test_type_parameter() {
TEST(type_parameter);
TypeParameter tp("tp1", "T");
tp.constraint = "Hashable";
CHECK(tp.conceptType == "TypeParameter", "wrong conceptType");
CHECK(tp.name == "T", "wrong name");
CHECK(tp.constraint == "Hashable", "wrong constraint");
TypeParameter tp2("tp2", "U");
CHECK(tp2.constraint.empty(), "unconstrained should be empty");
PASS();
}
// 8. ClassDeclaration JSON roundtrip
void test_class_json_roundtrip() {
TEST(class_json_roundtrip);
auto cls = std::make_unique<ClassDeclaration>("cls1", "Shape");
cls->superClass = "Drawable";
cls->isAbstract = true;
auto method = new MethodDeclaration("m1", "draw");
method->className = "Shape";
method->isVirtual = true;
cls->addChild("methods", method);
json j = toJson(cls.get());
CHECK(j["concept"] == "ClassDeclaration", "concept wrong");
CHECK(j["properties"]["name"] == "Shape", "name wrong");
CHECK(j["properties"]["superClass"] == "Drawable", "superClass wrong");
CHECK(j["properties"]["isAbstract"] == true, "isAbstract wrong");
ASTNode* restored = fromJson(j);
CHECK(restored != nullptr, "fromJson returned null");
CHECK(restored->conceptType == "ClassDeclaration", "restored wrong type");
auto* rc = static_cast<ClassDeclaration*>(restored);
CHECK(rc->name == "Shape", "restored name wrong");
CHECK(rc->superClass == "Drawable", "restored superClass wrong");
CHECK(rc->isAbstract == true, "restored isAbstract wrong");
// Check children survived roundtrip
CHECK(restored->getChildren("methods").size() == 1, "restored methods wrong");
delete restored;
PASS();
}
// 9. InterfaceDeclaration JSON roundtrip
void test_interface_json_roundtrip() {
TEST(interface_json_roundtrip);
auto iface = std::make_unique<InterfaceDeclaration>("if1", "Iterable");
json j = toJson(iface.get());
CHECK(j["properties"]["name"] == "Iterable", "name wrong in JSON");
ASTNode* restored = fromJson(j);
CHECK(restored->conceptType == "InterfaceDeclaration", "restored wrong type");
CHECK(static_cast<InterfaceDeclaration*>(restored)->name == "Iterable",
"restored name wrong");
delete restored;
PASS();
}
// 10. MethodDeclaration JSON roundtrip preserves all fields
void test_method_json_roundtrip() {
TEST(method_json_roundtrip);
auto meth = std::make_unique<MethodDeclaration>("m1", "update");
meth->className = "Controller";
meth->isStatic = true;
meth->visibility = "protected";
meth->isOverride = true;
meth->isVirtual = false;
json j = toJson(meth.get());
ASTNode* restored = fromJson(j);
CHECK(restored->conceptType == "MethodDeclaration", "restored wrong type");
auto* rm = static_cast<MethodDeclaration*>(restored);
CHECK(rm->name == "update", "name");
CHECK(rm->className == "Controller", "className");
CHECK(rm->isStatic == true, "isStatic");
CHECK(rm->visibility == "protected", "visibility");
CHECK(rm->isOverride == true, "isOverride");
CHECK(rm->isVirtual == false, "isVirtual");
delete restored;
PASS();
}
// 11. GenericType + TypeParameter JSON roundtrip
void test_generic_json_roundtrip() {
TEST(generic_json_roundtrip);
auto gen = std::make_unique<GenericType>("gt1", "Optional");
auto tp = new TypeParameter("tp1", "T");
tp->constraint = "Sendable";
gen->addChild("typeParameters", tp);
json j = toJson(gen.get());
CHECK(j["properties"]["baseName"] == "Optional", "baseName wrong");
ASTNode* restored = fromJson(j);
CHECK(restored->conceptType == "GenericType", "type wrong");
auto* rg = static_cast<GenericType*>(restored);
CHECK(rg->baseName == "Optional", "baseName");
auto typeParams = restored->getChildren("typeParameters");
CHECK(typeParams.size() == 1, "expected 1 type param");
auto* rtp = static_cast<TypeParameter*>(typeParams[0]);
CHECK(rtp->name == "T", "param name");
CHECK(rtp->constraint == "Sendable", "param constraint");
delete restored;
PASS();
}
// 12. Nested structure: class with generic methods and fields
void test_nested_class_structure() {
TEST(nested_class_structure);
auto cls = std::make_unique<ClassDeclaration>("cls1", "Repository");
cls->isAbstract = false;
// Generic type parameter on class
auto gt = new GenericType("gt1", "Repository");
auto tp = new TypeParameter("tp1", "T");
gt->addChild("typeParameters", tp);
cls->addChild("interfaces", gt);
// Method with parameter
auto meth = new MethodDeclaration("m1", "find");
meth->className = "Repository";
meth->visibility = "public";
auto param = new Parameter();
param->id = "p1";
param->name = "id";
meth->addChild("parameters", param);
cls->addChild("methods", meth);
// Field
auto field = new Variable("v1", "items");
cls->addChild("fields", field);
// JSON roundtrip
json j = toJson(cls.get());
ASTNode* restored = fromJson(j);
CHECK(restored->conceptType == "ClassDeclaration", "type");
CHECK(restored->getChildren("methods").size() == 1, "methods");
CHECK(restored->getChildren("fields").size() == 1, "fields");
CHECK(restored->getChildren("interfaces").size() == 1, "interfaces");
auto* restoredMeth = static_cast<MethodDeclaration*>(
restored->getChildren("methods")[0]);
CHECK(restoredMeth->name == "find", "method name");
CHECK(restoredMeth->getChildren("parameters").size() == 1, "method params");
delete restored;
PASS();
}
int main() {
std::cout << "=== Step 302: New AST Nodes — Class/Interface/Generic ===\n";
test_class_construction();
test_class_children();
test_interface_construction();
test_method_properties();
test_method_inherits_function();
test_generic_type();
test_type_parameter();
test_class_json_roundtrip();
test_interface_json_roundtrip();
test_method_json_roundtrip();
test_generic_json_roundtrip();
test_nested_class_structure();
std::cout << "\nResults: " << passed << "/" << (passed + failed) << " passed\n";
return failed > 0 ? 1 : 0;
}