Address review: simplify enum implementation

Remove Enum_Access AST node type — reuse Id_AST_Node for enum value
lookups by combining "EnumName::ValueName" at parse time. Replace
std::set with std::vector for valid value tracking (enums are small).
Net removal of ~18 lines.

Requested by @lefticus in PR #679 review.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
leftibot 2026-04-13 18:15:17 -06:00
parent 20ed7e3410
commit a1fa15c496
3 changed files with 14 additions and 32 deletions

View File

@ -107,8 +107,7 @@ namespace chaiscript {
Compiled,
Const_Var_Decl,
Const_Assign_Decl,
Enum,
Enum_Access
Enum
};
enum class Operator_Precedence {
@ -129,7 +128,7 @@ namespace chaiscript {
namespace {
/// Helper lookup to get the name of each node type
constexpr const char *ast_node_type_to_string(AST_Node_Type ast_node_type) noexcept {
constexpr const char *const ast_node_types[] = {"Id", "Fun_Call", "Unused_Return_Fun_Call", "Arg_List", "Equation", "Var_Decl", "Assign_Decl", "Array_Call", "Dot_Access", "Lambda", "Block", "Scopeless_Block", "Def", "While", "If", "For", "Ranged_For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range", "Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled", "Const_Var_Decl", "Const_Assign_Decl", "Enum", "Enum_Access"};
constexpr const char *const ast_node_types[] = {"Id", "Fun_Call", "Unused_Return_Fun_Call", "Arg_List", "Equation", "Var_Decl", "Assign_Decl", "Array_Call", "Dot_Access", "Lambda", "Block", "Scopeless_Block", "Def", "While", "If", "For", "Ranged_For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range", "Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled", "Const_Var_Decl", "Const_Assign_Decl", "Enum"};
return ast_node_types[static_cast<int>(ast_node_type)];
}

View File

@ -16,7 +16,7 @@
#include <map>
#include <memory>
#include <ostream>
#include <set>
#include <algorithm>
#include <stdexcept>
#include <string>
#include <vector>
@ -897,12 +897,12 @@ namespace chaiscript {
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
const auto &enum_name = this->children[0]->text;
std::set<int> valid_values;
std::vector<int> valid_values;
for (size_t i = 1; i < this->children.size(); i += 2) {
const auto &val_name = this->children[i]->text;
const int val_int = Boxed_Number(this->children[i + 1]->eval(t_ss)).get_as<int>();
valid_values.insert(val_int);
valid_values.push_back(val_int);
dispatch::Dynamic_Object dobj(enum_name);
dobj.get_attr("value") = Boxed_Value(val_int);
@ -910,13 +910,13 @@ namespace chaiscript {
t_ss->add_global_const(const_var(dobj), enum_name + "::" + val_name);
}
auto shared_valid = std::make_shared<const std::set<int>>(std::move(valid_values));
auto shared_valid = std::make_shared<const std::vector<int>>(std::move(valid_values));
t_ss->add(
std::make_shared<dispatch::detail::Dynamic_Object_Constructor>(
enum_name,
fun([shared_valid, enum_name](dispatch::Dynamic_Object &t_obj, int t_val) {
if (shared_valid->count(t_val) == 0) {
if (std::find(shared_valid->begin(), shared_valid->end(), t_val) == shared_valid->end()) {
throw exception::eval_error("Value " + std::to_string(t_val) + " is not valid for enum '" + enum_name + "'");
}
t_obj.get_attr("value") = Boxed_Value(t_val);
@ -950,26 +950,6 @@ namespace chaiscript {
}
};
template<typename T>
struct Enum_Access_AST_Node final : AST_Node_Impl<T> {
Enum_Access_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children)
: AST_Node_Impl<T>(std::move(t_ast_node_text), AST_Node_Type::Enum_Access, std::move(t_loc), std::move(t_children))
, m_key(this->children[0]->text + "::" + this->children[1]->text) {
}
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
try {
return t_ss.get_object(m_key, m_loc);
} catch (std::exception &) {
throw exception::eval_error("Can not find enum value: " + m_key);
}
}
private:
const std::string m_key;
mutable std::atomic_uint_fast32_t m_loc = {0};
};
template<typename T>
struct If_AST_Node final : AST_Node_Impl<T> {
If_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector<AST_Node_Impl_Ptr<T>> t_children)

View File

@ -2452,14 +2452,17 @@ namespace chaiscript {
build_match<eval::Array_Call_AST_Node<Tracer>>(prev_stack_top);
} else if (!m_match_stack.empty() && m_match_stack.back()->identifier == AST_Node_Type::Id && Symbol("::")) {
has_more = true;
const auto enum_name = m_match_stack.back()->text;
const auto start_loc = m_match_stack.back()->location;
m_match_stack.pop_back();
if (!Id(true)) {
throw exception::eval_error("Expected identifier after '::'", File_Position(m_position.line, m_position.col), *m_filename);
}
if (std::distance(m_match_stack.begin() + static_cast<int>(prev_stack_top), m_match_stack.end()) != 2) {
throw exception::eval_error("Incomplete enum access", File_Position(m_position.line, m_position.col), *m_filename);
}
build_match<eval::Enum_Access_AST_Node<Tracer>>(prev_stack_top);
const auto val_name = m_match_stack.back()->text;
m_match_stack.pop_back();
m_match_stack.push_back(make_node<eval::Id_AST_Node<Tracer>>(enum_name + "::" + val_name, start_loc.start.line, start_loc.start.column));
} else if (Symbol(".")) {
has_more = true;
if (!(Id(true))) {