Complete step465 phase22a integration tests and summary
This commit is contained in:
@@ -3064,4 +3064,13 @@ target_link_libraries(step464_test PRIVATE
|
||||
tree_sitter_javascript tree_sitter_typescript
|
||||
tree_sitter_java tree_sitter_rust tree_sitter_go)
|
||||
|
||||
add_executable(step465_test tests/step465_test.cpp)
|
||||
target_include_directories(step465_test PRIVATE src)
|
||||
target_link_libraries(step465_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)
|
||||
|
||||
150
editor/tests/step465_test.cpp
Normal file
150
editor/tests/step465_test.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
// Step 465: Phase 22a Integration Tests (8 tests)
|
||||
|
||||
#include "ast/ArmAssemblyParser.h"
|
||||
#include "ast/AssemblyAnnotationMapper.h"
|
||||
#include "ast/AssemblyGenerator.h"
|
||||
#include "ast/X86AssemblyParser.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_realistic_x86_to_valid_ast() {
|
||||
TEST(parse_realistic_x86_to_valid_ast);
|
||||
std::string src =
|
||||
".global main\n"
|
||||
".text\n"
|
||||
"main:\n"
|
||||
" push rbp\n"
|
||||
" mov rbp, rsp\n"
|
||||
" add rax, 1\n"
|
||||
" pop rbp\n"
|
||||
" ret\n";
|
||||
auto mod = X86AssemblyParser::parseX86(src);
|
||||
CHECK(mod->getChildren("functions").size() == 1, "expected one function");
|
||||
auto* fn = static_cast<Function*>(mod->getChildren("functions")[0]);
|
||||
CHECK(fn->getChildren("body").size() >= 6, "expected label + instructions");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_parse_realistic_arm_to_valid_ast() {
|
||||
TEST(parse_realistic_arm_to_valid_ast);
|
||||
std::string src =
|
||||
".global main\n"
|
||||
".text\n"
|
||||
"main:\n"
|
||||
" MOV x0, x1\n"
|
||||
" ADD x0, x0, #1\n"
|
||||
" RET\n";
|
||||
auto mod = ArmAssemblyParser::parseArm(src);
|
||||
CHECK(mod->getChildren("functions").size() == 1, "expected one function");
|
||||
auto* fn = static_cast<Function*>(mod->getChildren("functions")[0]);
|
||||
CHECK(fn->getChildren("body").size() >= 4, "expected label + instructions");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_cross_arch_x86_to_arm_simple_translation() {
|
||||
TEST(cross_arch_x86_to_arm_simple_translation);
|
||||
std::string src = ".text\nmain:\n mov rax, rbx\n add rax, 1\n jmp done\n ret\ndone:\n ret\n";
|
||||
auto mod = X86AssemblyParser::parseX86(src);
|
||||
auto* fn = static_cast<Function*>(mod->getChildren("functions")[0]);
|
||||
std::vector<AssemblyInstruction> insts;
|
||||
for (auto* n : fn->getChildren("body")) {
|
||||
if (n->conceptType == "AssemblyInstruction")
|
||||
insts.push_back(*static_cast<AssemblyInstruction*>(n));
|
||||
}
|
||||
auto mapped = AssemblyGenerator::translateX86ToArmSimple(insts);
|
||||
CHECK(mapped.size() >= 3, "expected mapped instructions");
|
||||
CHECK(mapped[0].opcode == "mov", "mov mapping failed");
|
||||
CHECK(mapped[2].opcode == "b", "jmp should map to b");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_assembly_to_c_lifting_produces_stub() {
|
||||
TEST(assembly_to_c_lifting_produces_stub);
|
||||
std::string src = ".text\nmain:\n mov rax, rbx\n ret\n";
|
||||
auto mod = X86AssemblyParser::parseX86(src);
|
||||
auto* fn = static_cast<Function*>(mod->getChildren("functions")[0]);
|
||||
auto c = AssemblyAnnotationMapper::liftAssemblyToC(*fn);
|
||||
CHECK(c.find("int main()") != std::string::npos, "missing lifted function");
|
||||
CHECK(c.find("return 0;") != std::string::npos, "missing return in lifted stub");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_c_to_assembly_lowering_annotations_and_shape() {
|
||||
TEST(c_to_assembly_lowering_annotations_and_shape);
|
||||
auto x86 = AssemblyAnnotationMapper::lowerCToAssembly("int add(int a, int b)", "x86");
|
||||
auto arm = AssemblyAnnotationMapper::lowerCToAssembly("int add(int a, int b)", "arm");
|
||||
CHECK(x86.find(".global add") != std::string::npos, "missing x86 global");
|
||||
CHECK(arm.find(".global add") != std::string::npos, "missing arm global");
|
||||
CHECK(arm.find("@ lowered from C function") != std::string::npos, "missing arm comment style");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_annotations_meaningful_for_assembly() {
|
||||
TEST(annotations_meaningful_for_assembly);
|
||||
std::string src = ".text\nmain:\n mov rax, rbx\n add rax, 1\n ret\n";
|
||||
auto mod = X86AssemblyParser::parseX86(src);
|
||||
auto* fn = static_cast<Function*>(mod->getChildren("functions")[0]);
|
||||
auto report = AssemblyAnnotationMapper::analyzeFunction(*fn);
|
||||
bool hasExec = false, hasRisk = false, hasComplexity = false;
|
||||
for (const auto& a : report.annotations) {
|
||||
if (a == "@Exec(native)") hasExec = true;
|
||||
if (a == "@Risk(high)") hasRisk = true;
|
||||
if (a.find("@Complexity(") != std::string::npos) hasComplexity = true;
|
||||
}
|
||||
CHECK(hasExec && hasRisk && hasComplexity, "expected core assembly annotations");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_end_to_end_parse_annotate_generate_arm() {
|
||||
TEST(end_to_end_parse_annotate_generate_arm);
|
||||
std::string src = ".text\nmain:\n MOV r0, r1\n RET\n";
|
||||
auto mod = ArmAssemblyParser::parseArm(src);
|
||||
auto* fn = static_cast<Function*>(mod->getChildren("functions")[0]);
|
||||
auto report = AssemblyAnnotationMapper::analyzeFunction(*fn);
|
||||
auto out = AssemblyGenerator::generateArm(*mod);
|
||||
CHECK(!report.annotations.empty(), "expected annotations");
|
||||
CHECK(out.find("main:") != std::string::npos, "expected generated arm label");
|
||||
CHECK(out.find("mov r0, r1") != std::string::npos, "expected generated arm instruction");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_assembly_ast_node_roundtrip_serialization() {
|
||||
TEST(assembly_ast_node_roundtrip_serialization);
|
||||
AssemblyInstruction i("add", {"r0", "r1"});
|
||||
i.registers.emplace_back("r0", 32);
|
||||
i.registers.emplace_back("r1", 32);
|
||||
AssemblyMemoryOperand m;
|
||||
m.baseRegister = "r2";
|
||||
m.offset = 4;
|
||||
i.memoryOperands.push_back(m);
|
||||
auto j = toJson(i);
|
||||
auto out = instructionFromJson(j);
|
||||
CHECK(out.opcode == "add", "opcode roundtrip failed");
|
||||
CHECK(out.operands.size() == 2, "operand roundtrip failed");
|
||||
CHECK(out.registers.size() == 2, "register roundtrip failed");
|
||||
CHECK(out.memoryOperands.size() == 1, "memory roundtrip failed");
|
||||
PASS();
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "Step 465: Phase 22a Integration Tests\n";
|
||||
|
||||
test_parse_realistic_x86_to_valid_ast(); // 1
|
||||
test_parse_realistic_arm_to_valid_ast(); // 2
|
||||
test_cross_arch_x86_to_arm_simple_translation(); // 3
|
||||
test_assembly_to_c_lifting_produces_stub(); // 4
|
||||
test_c_to_assembly_lowering_annotations_and_shape(); // 5
|
||||
test_annotations_meaningful_for_assembly(); // 6
|
||||
test_end_to_end_parse_annotate_generate_arm(); // 7
|
||||
test_assembly_ast_node_roundtrip_serialization(); // 8
|
||||
|
||||
std::cout << "\nResults: " << passed << "/" << (passed + failed)
|
||||
<< " passed\n";
|
||||
return failed == 0 ? 0 : 1;
|
||||
}
|
||||
44
progress.md
44
progress.md
@@ -6208,3 +6208,47 @@ projection helpers.
|
||||
**Architecture gate check:**
|
||||
- `editor/src/ast/AssemblyAnnotationMapper.h` within header-size limit (`128` <= `600`)
|
||||
- `editor/tests/step464_test.cpp` within test-file size guidance (`177` lines)
|
||||
|
||||
### Step 465: Phase 22a Integration
|
||||
**Status:** PASS (8/8 tests)
|
||||
|
||||
Adds Phase 22a integration coverage across x86/ARM parsing, simple
|
||||
cross-architecture translation, annotation mapping, lift/lower helpers, and
|
||||
assembly node round-trip serialization.
|
||||
|
||||
**Files added:**
|
||||
- `editor/tests/step465_test.cpp` — 8 integration tests covering:
|
||||
- realistic x86 parse to valid AST
|
||||
- realistic ARM parse to valid AST
|
||||
- x86→ARM simple instruction mapping
|
||||
- assembly→C lifting stub generation
|
||||
- C→assembly lowering shape checks (x86 + ARM)
|
||||
- annotation usefulness checks on assembly functions
|
||||
- parse→annotate→generate end-to-end ARM flow
|
||||
- assembly node JSON round-trip
|
||||
- `editor/CMakeLists.txt` — `step465_test` target
|
||||
|
||||
**Verification run:**
|
||||
- `cmake --build editor/build-native --target step465_test` — PASS
|
||||
- `./editor/build-native/step465_test` — PASS (8/8)
|
||||
- `./editor/build-native/step464_test` — PASS (12/12) regression coverage
|
||||
|
||||
**Architecture gate check:**
|
||||
- `editor/tests/step465_test.cpp` within test-file size guidance (`150` lines)
|
||||
- No new production header introduced in this integration step
|
||||
|
||||
**Phase 22a totals (460-465):**
|
||||
- **Steps:** 6
|
||||
- **Tests:** 68/68 passing
|
||||
- **Headers added:** 5
|
||||
- `ast/AssemblyNodes.h`
|
||||
- `ast/X86AssemblyParser.h`
|
||||
- `ast/ArmAssemblyParser.h`
|
||||
- `ast/AssemblyGenerator.h`
|
||||
- `ast/AssemblyAnnotationMapper.h`
|
||||
- **Capabilities delivered:**
|
||||
- assembly AST node model with JSON round-trip helpers
|
||||
- x86 parser (Intel + AT&T) with label/directive/addressing support
|
||||
- ARM/AArch64 parser with addressing mode support
|
||||
- x86/ARM code generation + simple x86→ARM opcode mapping
|
||||
- assembly semantic annotation mapping (`@Exec`, `@Target`, `@Risk`, `@Complexity`, `@Align`)
|
||||
|
||||
Reference in New Issue
Block a user