Step 408: add VB.NET generator and generate routing
This commit is contained in:
@@ -2551,4 +2551,13 @@ target_link_libraries(step407_test PRIVATE
|
||||
tree_sitter_javascript tree_sitter_typescript
|
||||
tree_sitter_java tree_sitter_rust tree_sitter_go)
|
||||
|
||||
add_executable(step408_test tests/step408_test.cpp)
|
||||
target_include_directories(step408_test PRIVATE src)
|
||||
target_link_libraries(step408_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)
|
||||
|
||||
@@ -183,6 +183,9 @@ public:
|
||||
} else if (language == "fsharp" || language == "f#" || language == "fs") {
|
||||
FSharpGenerator gen;
|
||||
return gen.generate(ast);
|
||||
} else if (language == "vbnet" || language == "vb" || language == "vb.net") {
|
||||
VBNetGenerator gen;
|
||||
return gen.generate(ast);
|
||||
} else if (language == "c") {
|
||||
CGenerator gen;
|
||||
return gen.generate(ast);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "KotlinGenerator.h"
|
||||
#include "CSharpGenerator.h"
|
||||
#include "FSharpGenerator.h"
|
||||
#include "VBNetGenerator.h"
|
||||
#include "CGenerator.h"
|
||||
#include "WatGenerator.h"
|
||||
#include "CommonLispGenerator.h"
|
||||
|
||||
261
editor/src/ast/VBNetGenerator.h
Normal file
261
editor/src/ast/VBNetGenerator.h
Normal file
@@ -0,0 +1,261 @@
|
||||
#pragma once
|
||||
|
||||
#include "ProjectionGenerator.h"
|
||||
#include "ClassDeclaration.h"
|
||||
#include "EnumNamespaceNodes.h"
|
||||
#include "../SemannoAnnotationImpl.h"
|
||||
|
||||
class VBNetGenerator : public ProjectionGenerator, public SemannoAnnotationImpl<VBNetGenerator> {
|
||||
public:
|
||||
std::string commentPrefix() const { return "' "; }
|
||||
|
||||
std::string generate(const ASTNode* node) override {
|
||||
return dispatchGenerate(this, node, "' Unknown concept: ");
|
||||
}
|
||||
|
||||
std::string visitModule(const Module* module) override {
|
||||
std::ostringstream oss;
|
||||
oss << "' Module: " << module->name << "\n\n";
|
||||
for (const auto* stmt : module->getChildren("statements")) oss << generate(stmt) << "\n";
|
||||
if (!module->getChildren("statements").empty()) oss << "\n";
|
||||
for (const auto* var : module->getChildren("variables")) oss << generate(var) << "\n";
|
||||
if (!module->getChildren("variables").empty()) oss << "\n";
|
||||
for (const auto* fn : module->getChildren("functions")) oss << generate(fn) << "\n";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string visitFunction(const Function* function) override {
|
||||
std::ostringstream oss;
|
||||
for (const auto* anno : function->getChildren("annotations")) oss << generate(anno) << "\n";
|
||||
|
||||
auto* retType = function->getChild("returnType");
|
||||
const bool hasReturn = retType != nullptr;
|
||||
oss << (hasReturn ? "Function " : "Sub ") << function->name << "(";
|
||||
auto params = function->getChildren("parameters");
|
||||
for (size_t i = 0; i < params.size(); ++i) {
|
||||
if (i > 0) oss << ", ";
|
||||
oss << generate(params[i]);
|
||||
}
|
||||
oss << ")";
|
||||
if (hasReturn) oss << " As " << generate(retType);
|
||||
oss << "\n";
|
||||
|
||||
for (const auto* stmt : function->getChildren("body")) {
|
||||
oss << " " << generate(stmt) << "\n";
|
||||
}
|
||||
oss << (hasReturn ? "End Function" : "End Sub");
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string visitVariable(const Variable* variable) override {
|
||||
std::ostringstream oss;
|
||||
oss << "Dim " << variable->name;
|
||||
auto* type = variable->getChild("type");
|
||||
if (type) oss << " As " << generate(type);
|
||||
auto* init = variable->getChild("initializer");
|
||||
if (init) oss << " = " << generate(init);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string visitParameter(const Parameter* parameter) override {
|
||||
auto* type = parameter->getChild("type");
|
||||
if (!type) return parameter->name;
|
||||
return parameter->name + " As " + generate(type);
|
||||
}
|
||||
|
||||
std::string visitAssignment(const Assignment* a) override {
|
||||
auto* t = a->getChild("target");
|
||||
auto* v = a->getChild("value");
|
||||
return (t ? generate(t) : "") + " = " + (v ? generate(v) : "Nothing");
|
||||
}
|
||||
|
||||
std::string visitReturn(const Return* r) override {
|
||||
auto* v = r->getChild("value");
|
||||
return v ? "Return " + generate(v) : "Return";
|
||||
}
|
||||
|
||||
std::string visitBinaryOperation(const BinaryOperation* b) override {
|
||||
auto* l = b->getChild("left");
|
||||
auto* r = b->getChild("right");
|
||||
return (l ? generate(l) : "") + " " + b->op + " " + (r ? generate(r) : "");
|
||||
}
|
||||
|
||||
std::string visitVariableReference(const VariableReference* v) override { return v->variableName; }
|
||||
std::string visitIntegerLiteral(const IntegerLiteral* l) override { return std::to_string(l->value); }
|
||||
std::string visitFloatLiteral(const FloatLiteral* l) override { return l->value; }
|
||||
std::string visitStringLiteral(const StringLiteral* l) override { return "\"" + l->value + "\""; }
|
||||
std::string visitBooleanLiteral(const BooleanLiteral* l) override { return l->value ? "True" : "False"; }
|
||||
std::string visitNullLiteral(const NullLiteral*) override { return "Nothing"; }
|
||||
|
||||
std::string visitIfStatement(const IfStatement* s) override {
|
||||
std::ostringstream oss;
|
||||
auto* cond = s->getChild("condition");
|
||||
oss << "If " << (cond ? generate(cond) : "True") << " Then\n";
|
||||
for (const auto* t : s->getChildren("thenBranch")) oss << " " << generate(t) << "\n";
|
||||
auto elseBranch = s->getChildren("elseBranch");
|
||||
if (!elseBranch.empty()) {
|
||||
oss << "Else\n";
|
||||
for (const auto* e : elseBranch) oss << " " << generate(e) << "\n";
|
||||
}
|
||||
oss << "End If";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string visitWhileLoop(const WhileLoop* l) override {
|
||||
std::ostringstream oss;
|
||||
auto* cond = l->getChild("condition");
|
||||
oss << "While " << (cond ? generate(cond) : "True") << "\n";
|
||||
for (const auto* s : l->getChildren("body")) oss << " " << generate(s) << "\n";
|
||||
oss << "End While";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string visitForLoop(const ForLoop* l) override {
|
||||
std::ostringstream oss;
|
||||
auto* iter = l->getChild("iterable");
|
||||
oss << "For Each " << (l->iteratorName.empty() ? "item" : l->iteratorName)
|
||||
<< " In " << (iter ? generate(iter) : "collection") << "\n";
|
||||
for (const auto* s : l->getChildren("body")) oss << " " << generate(s) << "\n";
|
||||
oss << "Next";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string visitExpressionStatement(const ExpressionStatement* s) override {
|
||||
auto* expr = s->getChild("expression");
|
||||
return expr ? generate(expr) : "";
|
||||
}
|
||||
|
||||
std::string visitUnaryOperation(const UnaryOperation* u) override {
|
||||
auto* o = u->getChild("operand");
|
||||
return u->op + (o ? generate(o) : "");
|
||||
}
|
||||
|
||||
std::string visitFunctionCall(const FunctionCall* c) override {
|
||||
std::ostringstream oss;
|
||||
oss << c->functionName << "(";
|
||||
auto args = c->getChildren("arguments");
|
||||
for (size_t i = 0; i < args.size(); ++i) {
|
||||
if (i > 0) oss << ", ";
|
||||
oss << generate(args[i]);
|
||||
}
|
||||
oss << ")";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string visitBlock(const Block* b) override {
|
||||
std::ostringstream oss;
|
||||
for (const auto* s : b->getChildren("statements")) oss << generate(s) << "\n";
|
||||
return trimTrailingNewline(oss.str());
|
||||
}
|
||||
|
||||
std::string visitListLiteral(const ListLiteral* l) override {
|
||||
std::ostringstream oss;
|
||||
oss << "{";
|
||||
auto elems = l->getChildren("elements");
|
||||
for (size_t i = 0; i < elems.size(); ++i) {
|
||||
if (i > 0) oss << ", ";
|
||||
oss << generate(elems[i]);
|
||||
}
|
||||
oss << "}";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string visitIndexAccess(const IndexAccess* a) override {
|
||||
auto* t = a->getChild("target");
|
||||
auto* i = a->getChild("index");
|
||||
return (t ? generate(t) : "") + "(" + (i ? generate(i) : "") + ")";
|
||||
}
|
||||
|
||||
std::string visitMemberAccess(const MemberAccess* a) override {
|
||||
auto* t = a->getChild("target");
|
||||
return (t ? generate(t) : "") + "." + a->memberName;
|
||||
}
|
||||
|
||||
std::string visitPrimitiveType(const PrimitiveType* t) override {
|
||||
if (t->kind == "int") return "Integer";
|
||||
if (t->kind == "float" || t->kind == "double") return "Double";
|
||||
if (t->kind == "string") return "String";
|
||||
if (t->kind == "bool") return "Boolean";
|
||||
if (t->kind == "void") return "Object";
|
||||
return t->kind;
|
||||
}
|
||||
std::string visitListType(const ListType* t) override {
|
||||
auto* e = t->getChild("elementType");
|
||||
return "List(Of " + std::string(e ? generate(e) : "Object") + ")";
|
||||
}
|
||||
std::string visitSetType(const SetType* t) override {
|
||||
auto* e = t->getChild("elementType");
|
||||
return "HashSet(Of " + std::string(e ? generate(e) : "Object") + ")";
|
||||
}
|
||||
std::string visitMapType(const MapType* t) override {
|
||||
auto* k = t->getChild("keyType");
|
||||
auto* v = t->getChild("valueType");
|
||||
return "Dictionary(Of " + std::string(k ? generate(k) : "Object") + ", " +
|
||||
std::string(v ? generate(v) : "Object") + ")";
|
||||
}
|
||||
std::string visitTupleType(const TupleType* t) override {
|
||||
std::ostringstream oss;
|
||||
oss << "Tuple(Of ";
|
||||
auto elems = t->getChildren("elementTypes");
|
||||
for (size_t i = 0; i < elems.size(); ++i) {
|
||||
if (i > 0) oss << ", ";
|
||||
oss << generate(elems[i]);
|
||||
}
|
||||
oss << ")";
|
||||
return oss.str();
|
||||
}
|
||||
std::string visitArrayType(const ArrayType* t) override {
|
||||
auto* e = t->getChild("elementType");
|
||||
return (e ? generate(e) : "Object") + "()";
|
||||
}
|
||||
std::string visitOptionalType(const OptionalType* t) override {
|
||||
auto* inner = t->getChild("innerType");
|
||||
return "Nullable(Of " + std::string(inner ? generate(inner) : "Object") + ")";
|
||||
}
|
||||
std::string visitCustomType(const CustomType* t) override { return t->typeName; }
|
||||
|
||||
// Subject 1 annotations not covered by SemannoAnnotationImpl.
|
||||
std::string visitDerefStrategy(const DerefStrategy* a) override { return commentPrefix() + SemannoEmitter::emit(a); }
|
||||
std::string visitOptimizationLock(const OptimizationLock* a) override { return commentPrefix() + SemannoEmitter::emit(a); }
|
||||
std::string visitLangSpecific(const LangSpecific* a) override { return commentPrefix() + SemannoEmitter::emit(a); }
|
||||
std::string visitDeallocateAnnotation(const DeallocateAnnotation* a) override { return commentPrefix() + SemannoEmitter::emit(a); }
|
||||
std::string visitLifetimeAnnotation(const LifetimeAnnotation* a) override { return commentPrefix() + SemannoEmitter::emit(a); }
|
||||
std::string visitReclaimAnnotation(const ReclaimAnnotation* a) override { return commentPrefix() + SemannoEmitter::emit(a); }
|
||||
std::string visitOwnerAnnotation(const OwnerAnnotation* a) override { return commentPrefix() + SemannoEmitter::emit(a); }
|
||||
std::string visitAllocateAnnotation(const AllocateAnnotation* a) override { return commentPrefix() + SemannoEmitter::emit(a); }
|
||||
std::string visitHotColdAnnotation(const HotColdAnnotation* a) override { return commentPrefix() + SemannoEmitter::emit(a); }
|
||||
std::string visitInlineAnnotation(const InlineAnnotation* a) override { return commentPrefix() + SemannoEmitter::emit(a); }
|
||||
std::string visitPureAnnotation(const PureAnnotation* a) override { return commentPrefix() + SemannoEmitter::emit(a); }
|
||||
std::string visitConstExprAnnotation(const ConstExprAnnotation* a) override { return commentPrefix() + SemannoEmitter::emit(a); }
|
||||
|
||||
std::string visitClassDeclaration(const ASTNode* node) override {
|
||||
auto* cls = static_cast<const ClassDeclaration*>(node);
|
||||
std::ostringstream oss;
|
||||
oss << "Class " << cls->name << "\n";
|
||||
for (const auto* f : cls->getChildren("fields")) {
|
||||
oss << " " << generate(f) << "\n";
|
||||
}
|
||||
oss << "End Class";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string visitInterfaceDeclaration(const ASTNode* node) override {
|
||||
auto* iface = static_cast<const InterfaceDeclaration*>(node);
|
||||
std::ostringstream oss;
|
||||
oss << "Interface " << iface->name << "\nEnd Interface";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string visitNamespaceDeclaration(const ASTNode* node) override {
|
||||
auto* ns = static_cast<const NamespaceDeclaration*>(node);
|
||||
std::ostringstream oss;
|
||||
oss << "Module " << ns->name << "\nEnd Module";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
private:
|
||||
static std::string trimTrailingNewline(std::string s) {
|
||||
while (!s.empty() && (s.back() == '\n' || s.back() == '\r')) s.pop_back();
|
||||
return s;
|
||||
}
|
||||
};
|
||||
186
editor/tests/step408_test.cpp
Normal file
186
editor/tests/step408_test.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
// Step 408: VB.NET Generator Tests (12 tests)
|
||||
|
||||
#include "ast/VBNetGenerator.h"
|
||||
#include "ast/Module.h"
|
||||
#include "ast/Function.h"
|
||||
#include "ast/Variable.h"
|
||||
#include "ast/Parameter.h"
|
||||
#include "ast/Statement.h"
|
||||
#include "ast/Expression.h"
|
||||
#include "ast/ClassDeclaration.h"
|
||||
#include "ast/Type.h"
|
||||
#include "ast/Annotation.h"
|
||||
#include "Pipeline.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
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_generate_sub_form() {
|
||||
TEST(generate_sub_form);
|
||||
Function fn("f1", "DoWork");
|
||||
fn.addChild("parameters", new Parameter("p1", "x"));
|
||||
VBNetGenerator gen;
|
||||
std::string out = gen.generate(&fn);
|
||||
CHECK(out.find("Sub DoWork(") != std::string::npos, "expected Sub form");
|
||||
CHECK(out.find("End Sub") != std::string::npos, "expected End Sub");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_generate_function_form() {
|
||||
TEST(generate_function_form);
|
||||
Function fn("f1", "Sum");
|
||||
fn.addChild("parameters", new Parameter("p1", "a"));
|
||||
fn.addChild("parameters", new Parameter("p2", "b"));
|
||||
fn.setChild("returnType", new PrimitiveType("t1", "int"));
|
||||
VBNetGenerator gen;
|
||||
std::string out = gen.generate(&fn);
|
||||
CHECK(out.find("Function Sum(") != std::string::npos, "expected Function form");
|
||||
CHECK(out.find("As Integer") != std::string::npos, "expected return type");
|
||||
CHECK(out.find("End Function") != std::string::npos, "expected End Function");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_generate_class() {
|
||||
TEST(generate_class);
|
||||
ClassDeclaration cls("c1", "Person");
|
||||
cls.addChild("fields", new Variable("v1", "Name"));
|
||||
VBNetGenerator gen;
|
||||
std::string out = gen.generate(&cls);
|
||||
CHECK(out.find("Class Person") != std::string::npos, "expected class declaration");
|
||||
CHECK(out.find("End Class") != std::string::npos, "expected End Class");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_generate_interface() {
|
||||
TEST(generate_interface);
|
||||
InterfaceDeclaration iface("i1", "IWorker");
|
||||
VBNetGenerator gen;
|
||||
std::string out = gen.generate(&iface);
|
||||
CHECK(out.find("Interface IWorker") != std::string::npos, "expected interface declaration");
|
||||
CHECK(out.find("End Interface") != std::string::npos, "expected End Interface");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_generate_module_namespace() {
|
||||
TEST(generate_module_namespace);
|
||||
NamespaceDeclaration ns("n1", "Utils");
|
||||
VBNetGenerator gen;
|
||||
std::string out = gen.generate(&ns);
|
||||
CHECK(out.find("Module Utils") != std::string::npos, "expected module declaration");
|
||||
CHECK(out.find("End Module") != std::string::npos, "expected End Module");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_generate_dim_variable() {
|
||||
TEST(generate_dim_variable);
|
||||
Variable v("v1", "count");
|
||||
v.setChild("type", new PrimitiveType("t1", "int"));
|
||||
v.setChild("initializer", new IntegerLiteral("i1", 5));
|
||||
VBNetGenerator gen;
|
||||
std::string out = gen.generate(&v);
|
||||
CHECK(out.find("Dim count As Integer = 5") != std::string::npos, "expected Dim As Integer");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_generate_if_statement() {
|
||||
TEST(generate_if_statement);
|
||||
IfStatement ifs;
|
||||
ifs.id = "if1";
|
||||
ifs.setChild("condition", new BooleanLiteral("b1", true));
|
||||
ifs.addChild("thenBranch", new Return());
|
||||
VBNetGenerator gen;
|
||||
std::string out = gen.generate(&ifs);
|
||||
CHECK(out.find("If True Then") != std::string::npos, "expected If Then");
|
||||
CHECK(out.find("End If") != std::string::npos, "expected End If");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_generate_for_each() {
|
||||
TEST(generate_for_each);
|
||||
ForLoop loop;
|
||||
loop.id = "for1";
|
||||
loop.iteratorName = "item";
|
||||
loop.setChild("iterable", new VariableReference("vr1", "items"));
|
||||
VBNetGenerator gen;
|
||||
std::string out = gen.generate(&loop);
|
||||
CHECK(out.find("For Each item In items") != std::string::npos, "expected For Each");
|
||||
CHECK(out.find("Next") != std::string::npos, "expected Next");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_type_mapping() {
|
||||
TEST(type_mapping);
|
||||
VBNetGenerator gen;
|
||||
PrimitiveType tInt("t1", "int");
|
||||
PrimitiveType tDouble("t2", "double");
|
||||
PrimitiveType tString("t3", "string");
|
||||
PrimitiveType tBool("t4", "bool");
|
||||
CHECK(gen.generate(&tInt) == "Integer", "int->Integer");
|
||||
CHECK(gen.generate(&tDouble) == "Double", "double->Double");
|
||||
CHECK(gen.generate(&tString) == "String", "string->String");
|
||||
CHECK(gen.generate(&tBool) == "Boolean", "bool->Boolean");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_comment_prefix() {
|
||||
TEST(comment_prefix);
|
||||
VBNetGenerator gen;
|
||||
CHECK(gen.commentPrefix() == "' ", "expected apostrophe comment prefix");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_semanno_output() {
|
||||
TEST(semanno_output);
|
||||
Function fn("f1", "Compute");
|
||||
auto* risk = new RiskAnnotation();
|
||||
risk->id = "r1";
|
||||
risk->level = "high";
|
||||
fn.addChild("annotations", risk);
|
||||
VBNetGenerator gen;
|
||||
std::string out = gen.generate(&fn);
|
||||
CHECK(out.find("@semanno:risk") != std::string::npos, "expected semanno risk output");
|
||||
PASS();
|
||||
}
|
||||
|
||||
void test_pipeline_generate_routing() {
|
||||
TEST(pipeline_generate_routing);
|
||||
Module mod;
|
||||
mod.id = "m1";
|
||||
mod.name = "demo";
|
||||
mod.addChild("functions", new Function("f1", "Main"));
|
||||
Pipeline p;
|
||||
std::string o1 = p.generate(&mod, "vbnet");
|
||||
std::string o2 = p.generate(&mod, "vb");
|
||||
std::string o3 = p.generate(&mod, "vb.net");
|
||||
CHECK(o1.find("Sub Main") != std::string::npos, "vbnet route");
|
||||
CHECK(o2.find("Sub Main") != std::string::npos, "vb route");
|
||||
CHECK(o3.find("Sub Main") != std::string::npos, "vb.net route");
|
||||
PASS();
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::cout << "Step 408: VB.NET Generator Tests\n";
|
||||
|
||||
test_generate_sub_form(); // 1
|
||||
test_generate_function_form(); // 2
|
||||
test_generate_class(); // 3
|
||||
test_generate_interface(); // 4
|
||||
test_generate_module_namespace(); // 5
|
||||
test_generate_dim_variable(); // 6
|
||||
test_generate_if_statement(); // 7
|
||||
test_generate_for_each(); // 8
|
||||
test_type_mapping(); // 9
|
||||
test_comment_prefix(); // 10
|
||||
test_semanno_output(); // 11
|
||||
test_pipeline_generate_routing(); // 12
|
||||
|
||||
std::cout << "\nResults: " << passed << "/" << (passed + failed)
|
||||
<< " passed\n";
|
||||
return failed == 0 ? 0 : 1;
|
||||
}
|
||||
47
progress.md
47
progress.md
@@ -3773,6 +3773,53 @@ core block forms and declarations. Covers `Sub`/`Function`, `Class`,
|
||||
- `editor/src/MCPServer.h` (`1679` > `600`)
|
||||
- `editor/src/HeadlessAgentRPCHandler.h` (`2623` > `600`)
|
||||
|
||||
### Step 408: VB.NET Generator
|
||||
**Status:** PASS (12/12 tests)
|
||||
|
||||
Added a dedicated VB.NET generator and pipeline generation routing aliases.
|
||||
Outputs VB-style `Sub`/`Function` blocks, `Dim` declarations, `If...Then...End If`,
|
||||
`For Each...Next`, and .NET type-name mappings.
|
||||
|
||||
**Files created:**
|
||||
- `editor/src/ast/VBNetGenerator.h` — VB.NET generation support:
|
||||
- module/function/class/interface/module-namespace generation
|
||||
- `Sub` vs `Function ... As Type` emission
|
||||
- `Dim name As Type = value` variable emission
|
||||
- `If ... Then ... End If` and `For Each ... In ... Next`
|
||||
- .NET type mapping (`Integer`, `Double`, `String`, `Boolean`, `Object`)
|
||||
- Semanno output with VB comment prefix (`' `)
|
||||
- `editor/tests/step408_test.cpp` — 12 tests covering:
|
||||
1. Sub generation
|
||||
2. Function generation with return type
|
||||
3. class generation
|
||||
4. interface generation
|
||||
5. module/namespace generation
|
||||
6. Dim variable generation
|
||||
7. If generation
|
||||
8. For Each generation
|
||||
9. type mapping
|
||||
10. comment prefix
|
||||
11. Semanno annotation output
|
||||
12. pipeline generate routing for `vbnet` / `vb` / `vb.net`
|
||||
|
||||
**Files modified:**
|
||||
- `editor/src/ast/Generator.h` — include `VBNetGenerator.h`
|
||||
- `editor/src/Pipeline.h` — generate routing for `vbnet`, `vb`, `vb.net`
|
||||
- `editor/CMakeLists.txt` — `step408_test` target
|
||||
|
||||
**Verification run:**
|
||||
- `step408_test` — PASS (12/12) new step coverage
|
||||
- `step407_test` — PASS (12/12) regression coverage
|
||||
- `step406_test` — PASS (12/12) regression coverage
|
||||
|
||||
**Architecture gate check:**
|
||||
- `editor/src/ast/VBNetGenerator.h` within header-size limit (`261` <= `600`)
|
||||
- `editor/tests/step408_test.cpp` within test-file size guidance (`186` lines)
|
||||
- `editor/src/Pipeline.h` within header-size limit (`247` <= `600`)
|
||||
- Legacy oversized headers persist:
|
||||
- `editor/src/MCPServer.h` (`1679` > `600`)
|
||||
- `editor/src/HeadlessAgentRPCHandler.h` (`2623` > `600`)
|
||||
|
||||
# Roadmap Planning — Sprints 12-25+
|
||||
|
||||
## Status: Planning Complete (Sprints 12-19 detailed, 20-25 in roadmap.md)
|
||||
|
||||
Reference in New Issue
Block a user