Step 338: EnumDeclaration + NamespaceDeclaration (12/12 tests)
Added EnumDeclaration, EnumMember, NamespaceDeclaration, TypeAlias AST nodes with full serialization roundtrip and CompactAST support. Enums support scoped/unscoped, underlying type, member values. Namespaces support nesting. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
60
editor/src/ast/EnumNamespaceNodes.h
Normal file
60
editor/src/ast/EnumNamespaceNodes.h
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
#include "ASTNode.h"
|
||||
#include <string>
|
||||
|
||||
// Enum, namespace, and type alias AST nodes — statement-level.
|
||||
|
||||
class EnumMember : public ASTNode {
|
||||
public:
|
||||
std::string name;
|
||||
std::string value; // Optional explicit value ("1", "0xFF")
|
||||
|
||||
EnumMember() { conceptType = "EnumMember"; }
|
||||
EnumMember(const std::string& id, const std::string& n, const std::string& v = "")
|
||||
: name(n), value(v) {
|
||||
this->id = id;
|
||||
conceptType = "EnumMember";
|
||||
}
|
||||
};
|
||||
|
||||
class EnumDeclaration : public ASTNode {
|
||||
public:
|
||||
std::string name;
|
||||
bool isScoped = false; // enum class (true) vs plain enum (false)
|
||||
std::string underlyingType; // Optional: "int", "uint8_t", etc.
|
||||
// Children role "members": vector of EnumMember nodes
|
||||
|
||||
EnumDeclaration() { conceptType = "EnumDeclaration"; }
|
||||
EnumDeclaration(const std::string& id, const std::string& n, bool scoped = false)
|
||||
: name(n), isScoped(scoped) {
|
||||
this->id = id;
|
||||
conceptType = "EnumDeclaration";
|
||||
}
|
||||
};
|
||||
|
||||
class NamespaceDeclaration : public ASTNode {
|
||||
public:
|
||||
std::string name; // Empty for anonymous namespaces
|
||||
// Children role "body": statements/declarations inside
|
||||
|
||||
NamespaceDeclaration() { conceptType = "NamespaceDeclaration"; }
|
||||
NamespaceDeclaration(const std::string& id, const std::string& n)
|
||||
: name(n) {
|
||||
this->id = id;
|
||||
conceptType = "NamespaceDeclaration";
|
||||
}
|
||||
};
|
||||
|
||||
class TypeAlias : public ASTNode {
|
||||
public:
|
||||
std::string aliasName; // The new name
|
||||
std::string targetType; // What it aliases
|
||||
bool isUsing = true; // using (true) vs typedef (false)
|
||||
|
||||
TypeAlias() { conceptType = "TypeAlias"; }
|
||||
TypeAlias(const std::string& id, const std::string& alias, const std::string& target, bool usingStyle = true)
|
||||
: aliasName(alias), targetType(target), isUsing(usingStyle) {
|
||||
this->id = id;
|
||||
conceptType = "TypeAlias";
|
||||
}
|
||||
};
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "GenericType.h"
|
||||
#include "AsyncNodes.h"
|
||||
#include "PreprocessorNodes.h"
|
||||
#include "EnumNamespaceNodes.h"
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
@@ -523,6 +524,28 @@ inline json propertiesToJson(const ASTNode* node) {
|
||||
if (n->isFunctionLike) props["isFunctionLike"] = n->isFunctionLike;
|
||||
if (!n->parameters.empty()) props["parameters"] = n->parameters;
|
||||
}
|
||||
// Enum/Namespace/TypeAlias nodes (Step 338)
|
||||
else if (ct == "EnumDeclaration") {
|
||||
auto* n = static_cast<const EnumDeclaration*>(node);
|
||||
props["name"] = n->name;
|
||||
if (n->isScoped) props["isScoped"] = n->isScoped;
|
||||
if (!n->underlyingType.empty()) props["underlyingType"] = n->underlyingType;
|
||||
}
|
||||
else if (ct == "EnumMember") {
|
||||
auto* n = static_cast<const EnumMember*>(node);
|
||||
props["name"] = n->name;
|
||||
if (!n->value.empty()) props["value"] = n->value;
|
||||
}
|
||||
else if (ct == "NamespaceDeclaration") {
|
||||
auto* n = static_cast<const NamespaceDeclaration*>(node);
|
||||
props["name"] = n->name;
|
||||
}
|
||||
else if (ct == "TypeAlias") {
|
||||
auto* n = static_cast<const TypeAlias*>(node);
|
||||
props["aliasName"] = n->aliasName;
|
||||
props["targetType"] = n->targetType;
|
||||
if (!n->isUsing) props["isUsing"] = n->isUsing;
|
||||
}
|
||||
// NullLiteral, ListLiteral, IndexAccess, Block, Assignment, IfStatement,
|
||||
// WhileLoop, Return, ExpressionStatement, ListType, SetType, MapType,
|
||||
// TupleType, ArrayType, OptionalType — no extra properties
|
||||
@@ -689,6 +712,10 @@ inline ASTNode* createNode(const std::string& conceptName) {
|
||||
if (conceptName == "IncludeDirective") return new IncludeDirective();
|
||||
if (conceptName == "PragmaDirective") return new PragmaDirective();
|
||||
if (conceptName == "MacroDefinition") return new MacroDefinition();
|
||||
if (conceptName == "EnumDeclaration") return new EnumDeclaration();
|
||||
if (conceptName == "EnumMember") return new EnumMember();
|
||||
if (conceptName == "NamespaceDeclaration") return new NamespaceDeclaration();
|
||||
if (conceptName == "TypeAlias") return new TypeAlias();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1230,6 +1257,28 @@ inline void setPropertiesFromJson(ASTNode* node, const json& props) {
|
||||
if (p.is_string()) n->parameters.push_back(p.get<std::string>());
|
||||
}
|
||||
}
|
||||
// Enum/Namespace/TypeAlias nodes (Step 338)
|
||||
else if (ct == "EnumDeclaration") {
|
||||
auto* n = static_cast<EnumDeclaration*>(node);
|
||||
if (props.contains("name")) n->name = props["name"].get<std::string>();
|
||||
if (props.contains("isScoped")) n->isScoped = props["isScoped"].get<bool>();
|
||||
if (props.contains("underlyingType")) n->underlyingType = props["underlyingType"].get<std::string>();
|
||||
}
|
||||
else if (ct == "EnumMember") {
|
||||
auto* n = static_cast<EnumMember*>(node);
|
||||
if (props.contains("name")) n->name = props["name"].get<std::string>();
|
||||
if (props.contains("value")) n->value = props["value"].get<std::string>();
|
||||
}
|
||||
else if (ct == "NamespaceDeclaration") {
|
||||
auto* n = static_cast<NamespaceDeclaration*>(node);
|
||||
if (props.contains("name")) n->name = props["name"].get<std::string>();
|
||||
}
|
||||
else if (ct == "TypeAlias") {
|
||||
auto* n = static_cast<TypeAlias*>(node);
|
||||
if (props.contains("aliasName")) n->aliasName = props["aliasName"].get<std::string>();
|
||||
if (props.contains("targetType")) n->targetType = props["targetType"].get<std::string>();
|
||||
if (props.contains("isUsing")) n->isUsing = props["isUsing"].get<bool>();
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string generateNodeId() {
|
||||
|
||||
Reference in New Issue
Block a user