Complete step451 type system translation with tests

This commit is contained in:
Bill
2026-02-16 19:41:17 -07:00
parent 8ef369fbea
commit 4cd5156c7b
4 changed files with 324 additions and 0 deletions

View File

@@ -2938,4 +2938,13 @@ target_link_libraries(step450_test PRIVATE
tree_sitter_javascript tree_sitter_typescript
tree_sitter_java tree_sitter_rust tree_sitter_go)
add_executable(step451_test tests/step451_test.cpp)
target_include_directories(step451_test PRIVATE src)
target_link_libraries(step451_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)

View File

@@ -0,0 +1,140 @@
#pragma once
// Step 451: Type System Translation — maps type systems across languages
// with annotation-guided safety preservation.
#include <string>
#include <vector>
enum class TypeSafety { Preserved, Widened, Narrowed, Lossy };
struct TypeTranslation {
std::string sourceType;
std::string sourceLanguage;
std::string targetType;
std::string targetLanguage;
TypeSafety safety = TypeSafety::Preserved;
std::string annotation; // e.g. @Risk(medium) for lossy
std::string note;
};
struct TypeTranslationResult {
std::string sourceLanguage;
std::string targetLanguage;
std::vector<TypeTranslation> translations;
bool hasTranslation(const std::string& sourceType) const {
for (const auto& t : translations)
if (t.sourceType == sourceType) return true;
return false;
}
TypeTranslation getTranslation(const std::string& sourceType) const {
for (const auto& t : translations)
if (t.sourceType == sourceType) return t;
return {};
}
int countLossy() const {
int n = 0;
for (const auto& t : translations)
if (t.safety == TypeSafety::Lossy) ++n;
return n;
}
};
class TypeSystemTranslator {
public:
static TypeTranslationResult translate(const std::vector<std::string>& sourceTypes,
const std::string& srcLang,
const std::string& tgtLang) {
TypeTranslationResult result;
result.sourceLanguage = srcLang;
result.targetLanguage = tgtLang;
for (const auto& st : sourceTypes) {
auto tt = mapType(st, srcLang, tgtLang);
result.translations.push_back(std::move(tt));
}
return result;
}
private:
static TypeTranslation mapType(const std::string& type,
const std::string& src,
const std::string& tgt) {
TypeTranslation t;
t.sourceType = type;
t.sourceLanguage = src;
t.targetLanguage = tgt;
// Nullable types
if (type == "Optional" || type == "Optional<T>" || type == "T?") {
if (tgt == "rust") { t.targetType = "Option<T>"; t.safety = TypeSafety::Preserved; }
else if (tgt == "python") { t.targetType = "Optional[T]"; t.safety = TypeSafety::Preserved; }
else if (tgt == "java") { t.targetType = "Optional<T>"; t.safety = TypeSafety::Preserved; }
else if (tgt == "c" || tgt == "cpp") { t.targetType = "T*"; t.safety = TypeSafety::Lossy; t.annotation = "@Risk(medium)"; }
else { t.targetType = "nullable T"; t.safety = TypeSafety::Widened; }
}
// Generic collections
else if (type == "List<T>" || type == "Vec<T>" || type == "list") {
if (tgt == "rust") { t.targetType = "Vec<T>"; t.safety = TypeSafety::Preserved; }
else if (tgt == "python") { t.targetType = "list[T]"; t.safety = TypeSafety::Preserved; }
else if (tgt == "java") { t.targetType = "List<T>"; t.safety = TypeSafety::Preserved; }
else if (tgt == "c") { t.targetType = "void*"; t.safety = TypeSafety::Lossy; t.annotation = "@Risk(high)"; t.note = "Generics lost in C"; }
else if (tgt == "go") { t.targetType = "[]T"; t.safety = TypeSafety::Preserved; }
else { t.targetType = "array"; t.safety = TypeSafety::Widened; }
}
// Map/Dict
else if (type == "Map<K,V>" || type == "HashMap<K,V>" || type == "dict") {
if (tgt == "rust") { t.targetType = "HashMap<K,V>"; t.safety = TypeSafety::Preserved; }
else if (tgt == "python") { t.targetType = "dict[K,V]"; t.safety = TypeSafety::Preserved; }
else if (tgt == "java") { t.targetType = "Map<K,V>"; t.safety = TypeSafety::Preserved; }
else if (tgt == "go") { t.targetType = "map[K]V"; t.safety = TypeSafety::Preserved; }
else if (tgt == "c") { t.targetType = "void*"; t.safety = TypeSafety::Lossy; t.annotation = "@Risk(high)"; }
else { t.targetType = "map"; t.safety = TypeSafety::Widened; }
}
// Enum types
else if (type == "enum" || type == "Enum") {
if (tgt == "rust") { t.targetType = "enum"; t.safety = TypeSafety::Preserved; t.note = "Rust enum is more expressive (sum type)"; }
else if (tgt == "java") { t.targetType = "enum"; t.safety = TypeSafety::Preserved; }
else if (tgt == "python") { t.targetType = "Enum"; t.safety = TypeSafety::Preserved; }
else if (tgt == "c") { t.targetType = "enum/constants"; t.safety = TypeSafety::Narrowed; t.note = "C enum has no methods"; }
else if (tgt == "go") { t.targetType = "const iota"; t.safety = TypeSafety::Narrowed; }
else { t.targetType = "enum"; t.safety = TypeSafety::Preserved; }
}
// Class hierarchy → traits/interfaces
else if (type == "class" || type == "abstract class") {
if (tgt == "rust") { t.targetType = "trait + struct"; t.safety = TypeSafety::Preserved; t.note = "Composition over inheritance"; }
else if (tgt == "java") { t.targetType = "interface + class"; t.safety = TypeSafety::Preserved; }
else if (tgt == "go") { t.targetType = "interface + struct"; t.safety = TypeSafety::Preserved; }
else if (tgt == "c") { t.targetType = "struct + vtable"; t.safety = TypeSafety::Lossy; t.annotation = "@Risk(medium)"; }
else if (tgt == "python") { t.targetType = "class (ABC)"; t.safety = TypeSafety::Preserved; }
else { t.targetType = "class"; t.safety = TypeSafety::Preserved; }
}
// String types
else if (type == "String" || type == "string" || type == "str") {
if (tgt == "rust") { t.targetType = "String"; t.safety = TypeSafety::Preserved; }
else if (tgt == "python") { t.targetType = "str"; t.safety = TypeSafety::Preserved; }
else if (tgt == "java") { t.targetType = "String"; t.safety = TypeSafety::Preserved; }
else if (tgt == "c") { t.targetType = "char*"; t.safety = TypeSafety::Lossy; t.annotation = "@Risk(medium)"; t.note = "No length tracking"; }
else if (tgt == "go") { t.targetType = "string"; t.safety = TypeSafety::Preserved; }
else { t.targetType = "string"; t.safety = TypeSafety::Preserved; }
}
// Primitive int
else if (type == "int" || type == "i32" || type == "int32") {
if (tgt == "rust") { t.targetType = "i32"; t.safety = TypeSafety::Preserved; }
else if (tgt == "python") { t.targetType = "int"; t.safety = TypeSafety::Widened; t.note = "Python int is arbitrary precision"; }
else if (tgt == "java") { t.targetType = "int"; t.safety = TypeSafety::Preserved; }
else if (tgt == "c" || tgt == "cpp") { t.targetType = "int"; t.safety = TypeSafety::Preserved; }
else if (tgt == "go") { t.targetType = "int32"; t.safety = TypeSafety::Preserved; }
else { t.targetType = "int"; t.safety = TypeSafety::Preserved; }
}
else {
t.targetType = type;
t.safety = TypeSafety::Preserved;
t.note = "Unknown type — preserved as-is";
}
return t;
}
};

View File

@@ -0,0 +1,146 @@
// Step 451: Type System Translation Tests (12 tests)
#include "TypeSystemTranslator.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_nullable_to_rust_option() {
TEST(nullable_to_rust_option);
auto r = TypeSystemTranslator::translate({"Optional<T>"}, "java", "rust");
auto t = r.getTranslation("Optional<T>");
CHECK(t.targetType == "Option<T>", "expected Option<T>");
CHECK(t.safety == TypeSafety::Preserved, "nullable should be preserved");
PASS();
}
void test_nullable_to_c_is_lossy() {
TEST(nullable_to_c_is_lossy);
auto r = TypeSystemTranslator::translate({"Optional<T>"}, "java", "c");
auto t = r.getTranslation("Optional<T>");
CHECK(t.targetType == "T*", "expected pointer representation");
CHECK(t.safety == TypeSafety::Lossy, "nullable->C should be lossy");
CHECK(t.annotation == "@Risk(medium)", "expected risk annotation");
PASS();
}
void test_list_to_rust_vec() {
TEST(list_to_rust_vec);
auto r = TypeSystemTranslator::translate({"List<T>"}, "java", "rust");
auto t = r.getTranslation("List<T>");
CHECK(t.targetType == "Vec<T>", "expected Vec<T>");
CHECK(t.safety == TypeSafety::Preserved, "generic list should preserve");
PASS();
}
void test_list_to_c_void_ptr_lossy() {
TEST(list_to_c_void_ptr_lossy);
auto r = TypeSystemTranslator::translate({"List<T>"}, "java", "c");
auto t = r.getTranslation("List<T>");
CHECK(t.targetType == "void*", "expected void* in C");
CHECK(t.safety == TypeSafety::Lossy, "generics->C should be lossy");
CHECK(t.annotation == "@Risk(high)", "expected high risk annotation");
PASS();
}
void test_map_to_go_map_type() {
TEST(map_to_go_map_type);
auto r = TypeSystemTranslator::translate({"Map<K,V>"}, "java", "go");
auto t = r.getTranslation("Map<K,V>");
CHECK(t.targetType == "map[K]V", "expected Go map");
CHECK(t.safety == TypeSafety::Preserved, "map should preserve semantics");
PASS();
}
void test_enum_to_c_narrowed() {
TEST(enum_to_c_narrowed);
auto r = TypeSystemTranslator::translate({"Enum"}, "java", "c");
auto t = r.getTranslation("Enum");
CHECK(t.targetType == "enum/constants", "expected C enum/constants");
CHECK(t.safety == TypeSafety::Narrowed, "C enum should be narrowed");
PASS();
}
void test_class_to_rust_trait_struct() {
TEST(class_to_rust_trait_struct);
auto r = TypeSystemTranslator::translate({"abstract class"}, "java", "rust");
auto t = r.getTranslation("abstract class");
CHECK(t.targetType == "trait + struct", "expected trait + struct");
CHECK(t.safety == TypeSafety::Preserved, "should preserve behavior intent");
PASS();
}
void test_class_to_c_vtable_lossy() {
TEST(class_to_c_vtable_lossy);
auto r = TypeSystemTranslator::translate({"class"}, "java", "c");
auto t = r.getTranslation("class");
CHECK(t.targetType == "struct + vtable", "expected struct + vtable");
CHECK(t.safety == TypeSafety::Lossy, "class->C should be lossy");
CHECK(t.annotation == "@Risk(medium)", "expected risk annotation");
PASS();
}
void test_string_to_c_char_ptr_lossy() {
TEST(string_to_c_char_ptr_lossy);
auto r = TypeSystemTranslator::translate({"String"}, "java", "c");
auto t = r.getTranslation("String");
CHECK(t.targetType == "char*", "expected char*");
CHECK(t.safety == TypeSafety::Lossy, "String->char* should be lossy");
PASS();
}
void test_int_to_python_widened() {
TEST(int_to_python_widened);
auto r = TypeSystemTranslator::translate({"int"}, "c", "python");
auto t = r.getTranslation("int");
CHECK(t.targetType == "int", "expected python int");
CHECK(t.safety == TypeSafety::Widened, "expected widened numeric range");
PASS();
}
void test_unknown_type_preserved() {
TEST(unknown_type_preserved);
auto r = TypeSystemTranslator::translate({"CustomBlob"}, "java", "rust");
auto t = r.getTranslation("CustomBlob");
CHECK(t.targetType == "CustomBlob", "unknown type should stay unchanged");
CHECK(t.safety == TypeSafety::Preserved, "unknown type should preserve");
PASS();
}
void test_mixed_batch_translation_counts_lossy() {
TEST(mixed_batch_translation_counts_lossy);
auto r = TypeSystemTranslator::translate(
{"Optional<T>", "List<T>", "Map<K,V>", "int"},
"java",
"c");
CHECK(r.translations.size() == 4, "expected 4 translated types");
CHECK(r.countLossy() >= 3, "expected at least 3 lossy mappings");
CHECK(r.hasTranslation("Map<K,V>"), "expected map translation");
PASS();
}
int main() {
std::cout << "Step 451: Type System Translation Tests\n";
test_nullable_to_rust_option(); // 1
test_nullable_to_c_is_lossy(); // 2
test_list_to_rust_vec(); // 3
test_list_to_c_void_ptr_lossy(); // 4
test_map_to_go_map_type(); // 5
test_enum_to_c_narrowed(); // 6
test_class_to_rust_trait_struct(); // 7
test_class_to_c_vtable_lossy(); // 8
test_string_to_c_char_ptr_lossy(); // 9
test_int_to_python_widened(); // 10
test_unknown_type_preserved(); // 11
test_mixed_batch_translation_counts_lossy(); // 12
std::cout << "\nResults: " << passed << "/" << (passed + failed)
<< " passed\n";
return failed == 0 ? 0 : 1;
}

View File

@@ -5736,3 +5736,32 @@ literal/syntactic rewrites.
**Architecture gate check:**
- `editor/src/AlgorithmEquivalence.h` within header-size limit (`228` <= `600`)
- `editor/tests/step450_test.cpp` within test-file size guidance (`143` lines)
### Step 451: Type System Translation
**Status:** PASS (12/12 tests)
Completes type-system mapping across language boundaries with explicit safety
classification and risk annotations for lossy projections.
**Files added:**
- `editor/src/TypeSystemTranslator.h` — type translation engine:
- nullable mapping (`Optional<T>`/`T?`), generic collections, maps, enums
- class-hierarchy projection (`trait + struct`, `interface + struct`, `struct + vtable`)
- primitive/string translation across Rust/Python/Java/C/C++/Go
- safety classification (`Preserved`, `Widened`, `Narrowed`, `Lossy`)
- risk annotation tagging for lossy targets (`@Risk(medium|high)`)
- `editor/tests/step451_test.cpp` — 12 tests covering:
- nullable/generic/map translations and safety categories
- enum/class/string lossy/narrowed mappings
- unknown-type pass-through behavior
- mixed-batch translation with lossy-count validation
- `editor/CMakeLists.txt``step451_test` target
**Verification run:**
- `cmake --build editor/build-native --target step451_test` — PASS
- `./editor/build-native/step451_test` — PASS (12/12)
- `./editor/build-native/step450_test` — PASS (12/12) regression coverage
**Architecture gate check:**
- `editor/src/TypeSystemTranslator.h` within header-size limit (`140` <= `600`)
- `editor/tests/step451_test.cpp` within test-file size guidance (`146` lines)