Complete step469 initializer list and STL pattern support with tests

This commit is contained in:
Bill
2026-02-16 20:36:44 -07:00
parent 58e96178ab
commit cdb35da6d7
4 changed files with 312 additions and 0 deletions

View File

@@ -3100,4 +3100,13 @@ target_link_libraries(step468_test PRIVATE
tree_sitter_javascript tree_sitter_typescript tree_sitter_javascript tree_sitter_typescript
tree_sitter_java tree_sitter_rust tree_sitter_go) tree_sitter_java tree_sitter_rust tree_sitter_go)
add_executable(step469_test tests/step469_test.cpp)
target_include_directories(step469_test PRIVATE src)
target_link_libraries(step469_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)
# Step 12: Dear ImGui shell scaffolding created (main.cpp exists but not built due to dependencies) # Step 12: Dear ImGui shell scaffolding created (main.cpp exists but not built due to dependencies)

View File

@@ -0,0 +1,135 @@
#pragma once
// Step 469: Initializer Lists + STL Patterns
// Focused helpers for parsing initializer-list expressions and recognizing
// common STL/iterator loop patterns with lightweight annotations.
#include "ASTNode.h"
#include <nlohmann/json.hpp>
#include <regex>
#include <sstream>
#include <string>
#include <vector>
using json = nlohmann::json;
class InitializerListExpression : public ASTNode {
public:
std::vector<std::string> elements;
InitializerListExpression() { conceptType = "InitializerListExpression"; }
};
struct StlContainerInfo {
std::string rawType; // std::vector<int>
std::string containerKind; // vector/map/set/string/unknown
std::string elementType; // int, pair<...>, ...
std::vector<std::string> annotations;
};
struct IteratorPatternInfo {
bool isIteratorLoop = false;
std::vector<std::string> annotations; // includes @Loop(...) when detected
};
class CppInitializerStl {
public:
static bool parseInitializerList(const std::string& source, InitializerListExpression& out) {
std::regex rx(R"(\{([^}]*)\})");
std::smatch m;
if (!std::regex_search(source, m, rx)) return false;
out.elements = splitCsv(m[1].str());
return true;
}
static StlContainerInfo recognizeContainer(const std::string& declaration) {
StlContainerInfo info;
std::regex rx(R"((std::[A-Za-z_]\w*(?:\s*<[^>]+>)?)\s+[A-Za-z_]\w*)");
std::smatch m;
if (!std::regex_search(declaration, m, rx)) {
info.containerKind = "unknown";
info.rawType = "";
return info;
}
info.rawType = trim(m[1].str());
auto lowered = toLower(info.rawType);
if (lowered.find("std::vector") == 0) info.containerKind = "vector";
else if (lowered.find("std::map") == 0) info.containerKind = "map";
else if (lowered.find("std::set") == 0) info.containerKind = "set";
else if (lowered.find("std::string") == 0) info.containerKind = "string";
else info.containerKind = "unknown";
info.elementType = extractTemplateArg(info.rawType);
info.annotations.push_back("@Container(" + info.containerKind + ")");
if (!info.elementType.empty()) info.annotations.push_back("@ElementType(" + info.elementType + ")");
return info;
}
static IteratorPatternInfo detectIteratorPattern(const std::string& source) {
IteratorPatternInfo info;
std::string s = toLower(source);
bool hasBeginEnd = s.find(".begin()") != std::string::npos && s.find(".end()") != std::string::npos;
bool hasIteratorDecl = s.find("::iterator") != std::string::npos || s.find("auto it") != std::string::npos;
bool hasIncrement = s.find("++it") != std::string::npos || s.find("it++") != std::string::npos;
if (hasBeginEnd && hasIteratorDecl && hasIncrement) {
info.isIteratorLoop = true;
info.annotations.push_back("@Loop(iterator)");
}
return info;
}
static json toJson(const InitializerListExpression& e) {
return {
{"concept", e.conceptType},
{"elements", e.elements}
};
}
static InitializerListExpression fromJson(const json& j) {
InitializerListExpression e;
e.elements = j.value("elements", std::vector<std::string>{});
return e;
}
private:
static std::string trim(const std::string& s) {
size_t start = s.find_first_not_of(" \t\r\n");
if (start == std::string::npos) return "";
size_t end = s.find_last_not_of(" \t\r\n");
return s.substr(start, end - start + 1);
}
static std::string toLower(std::string s) {
for (char& c : s) c = static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
return s;
}
static std::vector<std::string> splitCsv(const std::string& in) {
std::vector<std::string> out;
std::string cur;
int depth = 0;
for (char c : in) {
if (c == '<') ++depth;
if (c == '>') --depth;
if (c == ',' && depth == 0) {
auto t = trim(cur);
if (!t.empty()) out.push_back(t);
cur.clear();
} else {
cur.push_back(c);
}
}
auto t = trim(cur);
if (!t.empty()) out.push_back(t);
return out;
}
static std::string extractTemplateArg(const std::string& type) {
size_t lt = type.find('<');
size_t gt = type.rfind('>');
if (lt == std::string::npos || gt == std::string::npos || gt <= lt) return "";
return trim(type.substr(lt + 1, gt - lt - 1));
}
};

View File

@@ -0,0 +1,138 @@
// Step 469: Initializer Lists + STL Patterns Tests (12 tests)
#include "ast/CppInitializerStl.h"
#include <iostream>
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 {}
void test_parse_initializer_list_simple_ints() {
TEST(parse_initializer_list_simple_ints);
InitializerListExpression e;
bool ok = CppInitializerStl::parseInitializerList("{1, 2, 3}", e);
CHECK(ok, "parse should succeed");
CHECK(e.elements.size() == 3, "expected 3 elements");
CHECK(e.elements[0] == "1" && e.elements[2] == "3", "wrong elements");
PASS();
}
void test_parse_initializer_list_strings() {
TEST(parse_initializer_list_strings);
InitializerListExpression e;
bool ok = CppInitializerStl::parseInitializerList("{\"a\", \"b\"}", e);
CHECK(ok, "parse should succeed");
CHECK(e.elements.size() == 2, "expected 2 elements");
PASS();
}
void test_initializer_list_json_roundtrip() {
TEST(initializer_list_json_roundtrip);
InitializerListExpression e;
e.elements = {"1", "2", "3"};
auto j = CppInitializerStl::toJson(e);
auto out = CppInitializerStl::fromJson(j);
CHECK(out.elements.size() == 3, "roundtrip element count mismatch");
CHECK(out.elements[1] == "2", "roundtrip element mismatch");
PASS();
}
void test_recognize_std_vector_container() {
TEST(recognize_std_vector_container);
auto info = CppInitializerStl::recognizeContainer("std::vector<int> v = {1,2,3};");
CHECK(info.containerKind == "vector", "expected vector kind");
CHECK(info.elementType == "int", "expected int element type");
PASS();
}
void test_recognize_std_map_container() {
TEST(recognize_std_map_container);
auto info = CppInitializerStl::recognizeContainer("std::map<std::string,int> m;");
CHECK(info.containerKind == "map", "expected map kind");
CHECK(info.elementType.find("std::string") != std::string::npos, "expected map template args");
PASS();
}
void test_recognize_std_set_container() {
TEST(recognize_std_set_container);
auto info = CppInitializerStl::recognizeContainer("std::set<long> s;");
CHECK(info.containerKind == "set", "expected set kind");
PASS();
}
void test_recognize_std_string_container() {
TEST(recognize_std_string_container);
auto info = CppInitializerStl::recognizeContainer("std::string name;");
CHECK(info.containerKind == "string", "expected string kind");
PASS();
}
void test_unknown_container_fallback() {
TEST(unknown_container_fallback);
auto info = CppInitializerStl::recognizeContainer("CustomList<int> c;");
CHECK(info.containerKind == "unknown", "expected unknown kind");
PASS();
}
void test_container_annotations_include_type_info() {
TEST(container_annotations_include_type_info);
auto info = CppInitializerStl::recognizeContainer("std::vector<int> v;");
bool hasContainer = false, hasElement = false;
for (const auto& a : info.annotations) {
if (a.find("@Container(") != std::string::npos) hasContainer = true;
if (a.find("@ElementType(") != std::string::npos) hasElement = true;
}
CHECK(hasContainer, "missing container annotation");
CHECK(hasElement, "missing element type annotation");
PASS();
}
void test_detect_iterator_pattern_begin_end_loop() {
TEST(detect_iterator_pattern_begin_end_loop);
std::string src = "for (std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) { use(*it); }";
auto info = CppInitializerStl::detectIteratorPattern(src);
CHECK(info.isIteratorLoop, "expected iterator loop detection");
CHECK(!info.annotations.empty(), "expected loop annotation");
PASS();
}
void test_detect_iterator_pattern_auto_it_loop() {
TEST(detect_iterator_pattern_auto_it_loop);
std::string src = "for (auto it = values.begin(); it != values.end(); it++) { sum += *it; }";
auto info = CppInitializerStl::detectIteratorPattern(src);
CHECK(info.isIteratorLoop, "expected iterator loop detection");
PASS();
}
void test_non_iterator_loop_not_annotated() {
TEST(non_iterator_loop_not_annotated);
std::string src = "for (int i = 0; i < n; ++i) { sum += i; }";
auto info = CppInitializerStl::detectIteratorPattern(src);
CHECK(!info.isIteratorLoop, "should not detect iterator loop");
CHECK(info.annotations.empty(), "should not add loop annotations");
PASS();
}
int main() {
std::cout << "Step 469: Initializer Lists + STL Patterns Tests\n";
test_parse_initializer_list_simple_ints(); // 1
test_parse_initializer_list_strings(); // 2
test_initializer_list_json_roundtrip(); // 3
test_recognize_std_vector_container(); // 4
test_recognize_std_map_container(); // 5
test_recognize_std_set_container(); // 6
test_recognize_std_string_container(); // 7
test_unknown_container_fallback(); // 8
test_container_annotations_include_type_info(); // 9
test_detect_iterator_pattern_begin_end_loop(); // 10
test_detect_iterator_pattern_auto_it_loop(); // 11
test_non_iterator_loop_not_annotated(); // 12
std::cout << "\nResults: " << passed << "/" << (passed + failed)
<< " passed\n";
return failed == 0 ? 0 : 1;
}

View File

@@ -6360,3 +6360,33 @@ named methods in Java/Python.
**Architecture gate check:** **Architecture gate check:**
- `editor/src/ast/CppOperators.h` within header-size limit (`129` <= `600`) - `editor/src/ast/CppOperators.h` within header-size limit (`129` <= `600`)
- `editor/tests/step468_test.cpp` within test-file size guidance (`152` lines) - `editor/tests/step468_test.cpp` within test-file size guidance (`152` lines)
### Step 469: Initializer Lists + STL Patterns
**Status:** PASS (12/12 tests)
Adds focused support for C++ initializer-list parsing plus STL container and
iterator-loop pattern recognition with lightweight annotation outputs.
**Files added:**
- `editor/src/ast/CppInitializerStl.h` — initializer/STL helpers:
- `InitializerListExpression` model
- initializer-list parser
- STL container recognition (`vector`, `map`, `set`, `string`)
- element-type extraction from template arguments
- iterator-loop pattern detector with `@Loop(iterator)` annotation
- JSON round-trip helpers for initializer-list node
- `editor/tests/step469_test.cpp` — 12 tests covering:
- initializer-list parsing and round-trip
- STL container kind/type recognition
- container annotation output checks
- iterator-pattern detection (`begin/end`, `auto it`) and non-iterator negative case
- `editor/CMakeLists.txt``step469_test` target
**Verification run:**
- `cmake --build editor/build-native --target step469_test` — PASS
- `./editor/build-native/step469_test` — PASS (12/12)
- `./editor/build-native/step468_test` — PASS (12/12) regression coverage
**Architecture gate check:**
- `editor/src/ast/CppInitializerStl.h` within header-size limit (`135` <= `600`)
- `editor/tests/step469_test.cpp` within test-file size guidance (`138` lines)