Files
whetstone_DSL/editor/tests/step406_test.cpp

206 lines
6.5 KiB
C++

// Step 406: F# Generator Tests (12 tests)
#include "ast/FSharpGenerator.h"
#include "ast/Module.h"
#include "ast/Function.h"
#include "ast/Variable.h"
#include "ast/Parameter.h"
#include "ast/Expression.h"
#include "ast/Statement.h"
#include "ast/EnumNamespaceNodes.h"
#include "ast/ClassDeclaration.h"
#include "ast/Type.h"
#include "ast/Annotation.h"
#include "ast/AsyncNodes.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_let_function() {
TEST(generate_let_function);
Function fn("fn1", "add");
fn.addChild("parameters", new Parameter("p1", "x"));
fn.addChild("parameters", new Parameter("p2", "y"));
auto* ret = new Return();
ret->id = "ret1";
ret->setChild("value", new BinaryOperation("b1", "+"));
fn.addChild("body", ret);
FSharpGenerator gen;
std::string out = gen.generate(&fn);
CHECK(out.find("let add x y =") != std::string::npos, "expected let function signature");
PASS();
}
void test_generate_mutable_variable() {
TEST(generate_mutable_variable);
Variable v("v1", "counter");
auto* mut = new MutAnnotation();
mut->id = "m1";
v.addChild("annotations", mut);
FSharpGenerator gen;
std::string out = gen.generate(&v);
CHECK(out.find("let mutable counter") != std::string::npos, "expected mutable variable");
PASS();
}
void test_generate_discriminated_union() {
TEST(generate_discriminated_union);
EnumDeclaration en("e1", "Shape");
en.addChild("members", new EnumMember("c1", "Circle"));
en.addChild("members", new EnumMember("c2", "Rectangle"));
FSharpGenerator gen;
std::string out = gen.generate(&en);
CHECK(out.find("type Shape =") != std::string::npos, "expected type declaration");
CHECK(out.find("| Circle") != std::string::npos, "expected Circle case");
CHECK(out.find("| Rectangle") != std::string::npos, "expected Rectangle case");
PASS();
}
void test_generate_record_class() {
TEST(generate_record_class);
ClassDeclaration cls("c1", "Person");
cls.addChild("fields", new Variable("f1", "name"));
cls.addChild("fields", new Variable("f2", "age"));
FSharpGenerator gen;
std::string out = gen.generate(&cls);
CHECK(out.find("type Person = {") != std::string::npos, "expected record type");
CHECK(out.find("name: obj") != std::string::npos, "expected name field");
CHECK(out.find("age: obj") != std::string::npos, "expected age field");
PASS();
}
void test_generate_async_function() {
TEST(generate_async_function);
AsyncFunction fn("a1", "fetchData");
fn.addChild("body", new Return());
FSharpGenerator gen;
std::string out = gen.generate(&fn);
CHECK(out.find("let fetchData = async {") != std::string::npos, "expected async function form");
PASS();
}
void test_generate_module_namespace() {
TEST(generate_module_namespace);
NamespaceDeclaration ns("n1", "MyApp.Core");
FSharpGenerator gen;
std::string out = gen.generate(&ns);
CHECK(out == "module MyApp.Core", "expected module declaration");
PASS();
}
void test_generate_if_statement() {
TEST(generate_if_statement);
IfStatement ifs;
ifs.id = "if1";
ifs.setChild("condition", new BooleanLiteral("b1", true));
auto* thenRet = new Return();
thenRet->id = "ret1";
thenRet->setChild("value", new StringLiteral("s1", "yes"));
ifs.addChild("thenBranch", thenRet);
FSharpGenerator gen;
std::string out = gen.generate(&ifs);
CHECK(out.find("if true then") != std::string::npos, "expected if then");
PASS();
}
void test_generate_pipeline_call_marker() {
TEST(generate_pipeline_call_marker);
FunctionCall call;
call.id = "call1";
call.functionName = "pipeline";
FSharpGenerator gen;
std::string out = gen.generate(&call);
CHECK(out.find("|>") != std::string::npos, "expected pipeline operator");
PASS();
}
void test_type_mapping() {
TEST(type_mapping);
PrimitiveType i("t1", "int");
PrimitiveType s("t2", "string");
PrimitiveType v("t3", "void");
OptionalType opt;
opt.id = "opt1";
opt.setChild("innerType", new CustomType("ct1", "result"));
FSharpGenerator gen;
CHECK(gen.generate(&i) == "int", "int mapping");
CHECK(gen.generate(&s) == "string", "string mapping");
CHECK(gen.generate(&v) == "unit", "void->unit mapping");
CHECK(gen.generate(&opt) == "result option", "optional mapping");
PASS();
}
void test_comment_prefix() {
TEST(comment_prefix);
FSharpGenerator gen;
CHECK(gen.commentPrefix() == "// ", "expected // comment prefix");
PASS();
}
void test_semanno_annotation_output() {
TEST(semanno_annotation_output);
Function fn("f1", "compute");
auto* c = new ComplexityAnnotation();
c->id = "a1";
c->timeComplexity = "O(n)";
fn.addChild("annotations", c);
FSharpGenerator gen;
std::string out = gen.generate(&fn);
CHECK(out.find("@semanno:complexity") != std::string::npos, "expected semanno complexity output");
PASS();
}
void test_pipeline_generate_routing() {
TEST(pipeline_generate_routing);
Module mod;
mod.id = "m1";
mod.name = "demo";
auto* fn = new Function("f1", "run");
mod.addChild("functions", fn);
Pipeline p;
std::string o1 = p.generate(&mod, "fsharp");
std::string o2 = p.generate(&mod, "f#");
std::string o3 = p.generate(&mod, "fs");
CHECK(o1.find("let run") != std::string::npos, "fsharp route");
CHECK(o2.find("let run") != std::string::npos, "f# route");
CHECK(o3.find("let run") != std::string::npos, "fs route");
PASS();
}
int main() {
std::cout << "Step 406: F# Generator Tests\n";
test_generate_let_function(); // 1
test_generate_mutable_variable(); // 2
test_generate_discriminated_union();// 3
test_generate_record_class(); // 4
test_generate_async_function(); // 5
test_generate_module_namespace(); // 6
test_generate_if_statement(); // 7
test_generate_pipeline_call_marker();// 8
test_type_mapping(); // 9
test_comment_prefix(); // 10
test_semanno_annotation_output(); // 11
test_pipeline_generate_routing(); // 12
std::cout << "\nResults: " << passed << "/" << (passed + failed)
<< " passed\n";
return failed == 0 ? 0 : 1;
}