Files
whetstone_DSL/editor/src/ast/JavaGenerator.h
2026-02-09 18:54:52 -07:00

632 lines
21 KiB
C++

#pragma once
#include "ProjectionGenerator.h"
#include "Import.h"
#include <map>
#include <unordered_map>
class JavaGenerator : public ProjectionGenerator {
public:
std::string generate(const ASTNode* node) override {
return dispatchGenerate(this, node, "// Unknown concept: ");
}
std::string visitModule(const Module* module) override {
std::ostringstream oss;
auto imports = module->getChildren("imports");
for (const auto* impNode : imports) {
if (impNode->conceptType != "Import") continue;
oss << emitImport(static_cast<const Import*>(impNode)) << "\n";
}
if (!imports.empty()) oss << "\n";
// Group functions and variables by class prefix.
std::map<std::string, std::vector<const Function*>> classMethods;
std::map<std::string, std::vector<const Variable*>> classFields;
std::vector<const Function*> topLevelMethods;
std::vector<const Variable*> topLevelFields;
auto functions = module->getChildren("functions");
for (const auto* fnNode : functions) {
if (fnNode->conceptType != "Function") continue;
const Function* fn = static_cast<const Function*>(fnNode);
auto pos = fn->name.find('.');
if (pos != std::string::npos && pos > 0 && pos + 1 < fn->name.size()) {
std::string className = fn->name.substr(0, pos);
classMethods[className].push_back(fn);
} else {
topLevelMethods.push_back(fn);
}
}
auto variables = module->getChildren("variables");
for (const auto* varNode : variables) {
if (varNode->conceptType != "Variable") continue;
const Variable* var = static_cast<const Variable*>(varNode);
auto pos = var->name.find('.');
if (pos != std::string::npos && pos > 0 && pos + 1 < var->name.size()) {
std::string className = var->name.substr(0, pos);
classFields[className].push_back(var);
} else {
topLevelFields.push_back(var);
}
}
std::string moduleClass = module->name.empty() ? "Main" : module->name;
if (!topLevelMethods.empty() || !topLevelFields.empty()) {
emitClass(oss, moduleClass, topLevelFields, topLevelMethods);
if (!classMethods.empty() || !classFields.empty()) oss << "\n";
}
for (const auto& [className, methods] : classMethods) {
std::vector<const Variable*> fields;
auto it = classFields.find(className);
if (it != classFields.end()) fields = it->second;
emitClass(oss, className, fields, methods);
oss << "\n";
}
if (!classFields.empty() && classMethods.empty()) {
for (const auto& [className, fields] : classFields) {
emitClass(oss, className, fields, {});
oss << "\n";
}
}
return oss.str();
}
std::string visitFunction(const Function* function) override {
std::ostringstream oss;
emitAnnotations(oss, function->getChildren("annotations"), "");
std::string methodName = function->name;
std::string returnType = "void";
auto retType = function->getChild("returnType");
if (retType) returnType = generate(retType);
oss << returnType << " " << methodName << "(";
emitParameters(oss, function->getChildren("parameters"));
oss << ") {\n";
emitBody(oss, function->getChildren("body"), " ");
oss << "}\n";
return oss.str();
}
std::string visitVariable(const Variable* variable) override {
std::ostringstream oss;
emitAnnotations(oss, variable->getChildren("annotations"), "");
std::string typeStr = "Object";
auto type = variable->getChild("type");
if (type) typeStr = generate(type);
std::string name = stripClassPrefix(variable->name);
oss << typeStr << " " << name;
auto initializer = variable->getChild("initializer");
if (initializer) {
oss << " = " << generate(initializer);
}
oss << ";";
return oss.str();
}
std::string visitParameter(const Parameter* parameter) override {
std::ostringstream oss;
std::string typeStr = "Object";
auto type = parameter->getChild("type");
if (type) typeStr = generate(type);
oss << typeStr << " " << parameter->name;
return oss.str();
}
std::string visitAssignment(const Assignment* assignment) override {
std::ostringstream oss;
auto target = assignment->getChild("target");
auto value = assignment->getChild("value");
if (target) {
oss << generate(target);
} else {
oss << "/* missing target */";
}
oss << " = ";
if (value) {
oss << generate(value);
} else {
oss << "null";
}
oss << ";";
return oss.str();
}
std::string visitReturn(const Return* ret) override {
std::ostringstream oss;
oss << "return";
auto value = ret->getChild("value");
if (value) {
oss << " " << generate(value);
}
oss << ";";
return oss.str();
}
std::string visitBinaryOperation(const BinaryOperation* binOp) override {
std::ostringstream oss;
auto left = binOp->getChild("left");
auto right = binOp->getChild("right");
if (left) {
oss << generate(left);
} else {
oss << "/* missing left */";
}
oss << " " << binOp->op << " ";
if (right) {
oss << generate(right);
} else {
oss << "/* missing right */";
}
return oss.str();
}
std::string visitVariableReference(const VariableReference* varRef) override {
return varRef->variableName;
}
std::string visitIntegerLiteral(const IntegerLiteral* lit) override {
return std::to_string(lit->value);
}
std::string visitFloatLiteral(const FloatLiteral* lit) override {
return lit->value;
}
std::string visitStringLiteral(const StringLiteral* lit) override {
if (isQuotedLiteral(lit->value)) return lit->value;
return "\"" + lit->value + "\"";
}
std::string visitBooleanLiteral(const BooleanLiteral* lit) override {
return lit->value ? "true" : "false";
}
std::string visitNullLiteral(const NullLiteral*) override {
return "null";
}
std::string visitIfStatement(const IfStatement* stmt) override {
std::ostringstream oss;
auto condition = stmt->getChild("condition");
auto thenBranch = stmt->getChildren("thenBranch");
auto elseBranch = stmt->getChildren("elseBranch");
oss << "if (";
if (condition) {
oss << generate(condition);
} else {
oss << "true";
}
oss << ") {\n";
emitBody(oss, thenBranch, " ");
oss << "}";
if (!elseBranch.empty()) {
oss << " else {\n";
emitBody(oss, elseBranch, " ");
oss << "}";
}
return oss.str();
}
std::string visitWhileLoop(const WhileLoop* loop) override {
std::ostringstream oss;
auto condition = loop->getChild("condition");
auto body = loop->getChildren("body");
oss << "while (";
if (condition) {
oss << generate(condition);
} else {
oss << "true";
}
oss << ") {\n";
emitBody(oss, body, " ");
oss << "}";
return oss.str();
}
std::string visitForLoop(const ForLoop* loop) override {
std::ostringstream oss;
auto iterable = loop->getChild("iterable");
auto body = loop->getChildren("body");
std::string iterName = loop->iteratorName.empty() ? "item" : loop->iteratorName;
oss << "for (var " << iterName << " : ";
if (iterable) {
oss << generate(iterable);
} else {
oss << "java.util.List.of()";
}
oss << ") {\n";
emitBody(oss, body, " ");
oss << "}";
return oss.str();
}
std::string visitExpressionStatement(const ExpressionStatement* stmt) override {
std::ostringstream oss;
auto expr = stmt->getChild("expression");
if (expr) {
oss << generate(expr);
}
oss << ";";
return oss.str();
}
std::string visitUnaryOperation(const UnaryOperation* unOp) override {
std::ostringstream oss;
std::string op = unOp->op;
bool wordOp = !op.empty() && std::isalpha(static_cast<unsigned char>(op[0]));
oss << op;
if (wordOp) oss << " ";
auto operand = unOp->getChild("operand");
if (operand) {
oss << generate(operand);
} else {
oss << "null";
}
return oss.str();
}
std::string visitFunctionCall(const FunctionCall* call) override {
std::ostringstream oss;
oss << call->functionName << "(";
auto arguments = call->getChildren("arguments");
for (size_t i = 0; i < arguments.size(); ++i) {
if (i > 0) oss << ", ";
oss << generate(arguments[i]);
}
oss << ")";
return oss.str();
}
std::string visitBlock(const Block* block) override {
std::ostringstream oss;
auto statements = block->getChildren("statements");
oss << "{\n";
emitBody(oss, statements, " ");
oss << "}";
return oss.str();
}
std::string visitListLiteral(const ListLiteral* lit) override {
std::ostringstream oss;
oss << "java.util.List.of(";
auto elements = lit->getChildren("elements");
for (size_t i = 0; i < elements.size(); ++i) {
if (i > 0) oss << ", ";
oss << generate(elements[i]);
}
oss << ")";
return oss.str();
}
std::string visitIndexAccess(const IndexAccess* access) override {
std::ostringstream oss;
auto target = access->getChild("target");
auto index = access->getChild("index");
if (target) {
oss << generate(target);
} else {
oss << "/* missing target */";
}
oss << "[";
if (index) {
oss << generate(index);
} else {
oss << "0";
}
oss << "]";
return oss.str();
}
std::string visitMemberAccess(const MemberAccess* access) override {
std::ostringstream oss;
auto target = access->getChild("target");
if (target) {
oss << generate(target);
} else {
oss << "/* missing target */";
}
oss << "." << access->memberName;
return oss.str();
}
std::string visitPrimitiveType(const PrimitiveType* type) override {
std::string kind = type->kind;
if (kind == "string") return "String";
if (kind == "bool") return "boolean";
if (kind == "float") return "float";
if (kind == "double") return "double";
if (kind == "int" || kind == "long" || kind == "short" || kind == "byte") return kind;
if (kind == "char") return "char";
if (kind == "void") return "void";
return kind;
}
std::string visitListType(const ListType* type) override {
std::ostringstream oss;
oss << "java.util.List<";
auto elementType = type->getChild("elementType");
if (elementType) {
oss << generate(elementType);
} else {
oss << "Object";
}
oss << ">";
return oss.str();
}
std::string visitSetType(const SetType* type) override {
std::ostringstream oss;
oss << "java.util.Set<";
auto elementType = type->getChild("elementType");
if (elementType) {
oss << generate(elementType);
} else {
oss << "Object";
}
oss << ">";
return oss.str();
}
std::string visitMapType(const MapType* type) override {
std::ostringstream oss;
oss << "java.util.Map<";
auto keyType = type->getChild("keyType");
auto valueType = type->getChild("valueType");
if (keyType) {
oss << generate(keyType);
} else {
oss << "Object";
}
oss << ", ";
if (valueType) {
oss << generate(valueType);
} else {
oss << "Object";
}
oss << ">";
return oss.str();
}
std::string visitTupleType(const TupleType* type) override {
std::ostringstream oss;
oss << "java.util.List<";
auto elementTypes = type->getChildren("elementTypes");
if (!elementTypes.empty()) {
oss << generate(elementTypes[0]);
} else {
oss << "Object";
}
oss << ">";
return oss.str();
}
std::string visitArrayType(const ArrayType* type) override {
std::ostringstream oss;
auto elementType = type->getChild("elementType");
if (elementType) {
oss << generate(elementType);
} else {
oss << "Object";
}
oss << "[]";
return oss.str();
}
std::string visitOptionalType(const OptionalType* type) override {
std::ostringstream oss;
oss << "java.util.Optional<";
auto inner = type->getChild("innerType");
if (inner) {
oss << generate(inner);
} else {
oss << "Object";
}
oss << ">";
return oss.str();
}
std::string visitCustomType(const CustomType* type) override {
return type->typeName;
}
std::string visitDerefStrategy(const DerefStrategy* annotation) override {
return "// @deref(" + annotation->strategy + ")";
}
std::string visitOptimizationLock(const OptimizationLock* annotation) override {
return "// @lock(" + annotation->lockedBy + ") - " + annotation->lockReason;
}
std::string visitLangSpecific(const LangSpecific* annotation) override {
if (annotation->language == "java" && !annotation->rawSyntax.empty()) {
return "// " + annotation->rawSyntax;
}
return "// @lang_specific(" + annotation->language + ", " + annotation->idiomType + ")";
}
std::string visitDeallocateAnnotation(const DeallocateAnnotation* annotation) override {
return "// @dealloc(" + annotation->strategy + ")";
}
std::string visitLifetimeAnnotation(const LifetimeAnnotation* annotation) override {
return "// @lifetime(" + annotation->strategy + ")";
}
std::string visitReclaimAnnotation(const ReclaimAnnotation* annotation) override {
return "// @reclaim(" + annotation->strategy + ") - GC-managed";
}
std::string visitOwnerAnnotation(const OwnerAnnotation* annotation) override {
if (annotation->strategy == "Single") {
return "// @owner(Single) - AutoCloseable/try-with-resources";
}
return "// @owner(" + annotation->strategy + ")";
}
std::string visitAllocateAnnotation(const AllocateAnnotation* annotation) override {
return "// @allocate(" + annotation->strategy + ")";
}
std::string visitHotColdAnnotation(const HotColdAnnotation* annotation) override {
return "// @" + annotation->hint;
}
std::string visitInlineAnnotation(const InlineAnnotation* annotation) override {
return "// @inline(" + annotation->mode + ")";
}
std::string visitPureAnnotation(const PureAnnotation*) override {
return "// @pure";
}
std::string visitConstExprAnnotation(const ConstExprAnnotation*) override {
return "// @constexpr";
}
private:
static std::string emitImport(const Import* imp) {
std::string moduleName = imp->moduleName.empty() ? "module" : imp->moduleName;
if (imp->importKind == "require") {
return "// require " + moduleName;
}
return "import " + moduleName + ";";
}
static void emitAnnotations(std::ostringstream& oss,
const std::vector<ASTNode*>& annotations,
const std::string& indent) {
for (const auto* annotation : annotations) {
if (!annotation) continue;
std::string code;
if (annotation->conceptType == "LangSpecific") {
auto* lang = static_cast<const LangSpecific*>(annotation);
if (lang->language == "java" && !lang->rawSyntax.empty()) {
code = "// " + lang->rawSyntax;
}
}
if (code.empty()) {
JavaGenerator gen;
code = gen.generate(annotation);
}
if (!code.empty()) {
oss << indent << code << "\n";
}
}
}
void emitParameters(std::ostringstream& oss,
const std::vector<ASTNode*>& params) {
for (size_t i = 0; i < params.size(); ++i) {
if (i > 0) oss << ", ";
oss << visitParameter(static_cast<const Parameter*>(params[i]));
}
}
void emitBody(std::ostringstream& oss,
const std::vector<ASTNode*>& body,
const std::string& indent) {
if (body.empty()) {
oss << indent << "// TODO: implement\n";
return;
}
for (const auto* stmt : body) {
std::string stmtCode = generate(stmt);
appendIndented(oss, stmtCode, indent);
oss << "\n";
}
}
void emitClass(std::ostringstream& oss,
const std::string& className,
const std::vector<const Variable*>& fields,
const std::vector<const Function*>& methods) {
oss << "class " << className << " {\n";
for (const auto* field : fields) {
oss << " " << visitVariable(field) << "\n";
}
if (!fields.empty() && !methods.empty()) oss << "\n";
for (const auto* method : methods) {
emitMethod(oss, className, method);
oss << "\n";
}
oss << "}";
}
void emitMethod(std::ostringstream& oss,
const std::string& className,
const Function* method) {
std::string methodName = methodNameFromQualified(method->name, className);
bool isConstructor = (methodName == "constructor" || methodName == className);
emitAnnotations(oss, method->getChildren("annotations"), " ");
oss << " ";
if (!isConstructor) {
std::string returnType = "void";
auto retType = method->getChild("returnType");
if (retType) returnType = generate(retType);
oss << returnType << " ";
oss << methodName;
} else {
oss << className;
}
oss << "(";
emitParameters(oss, method->getChildren("parameters"));
oss << ") {\n";
emitBody(oss, method->getChildren("body"), " ");
oss << " }";
}
static void appendIndented(std::ostringstream& oss,
const std::string& code,
const std::string& indent) {
size_t pos = 0;
while (pos < code.length()) {
size_t newlinePos = code.find('\n', pos);
if (newlinePos == std::string::npos) {
oss << indent << code.substr(pos);
break;
}
oss << indent << code.substr(pos, newlinePos - pos) << "\n";
pos = newlinePos + 1;
if (pos >= code.length()) break;
}
}
static std::string methodNameFromQualified(const std::string& name,
const std::string& className) {
if (name.rfind(className + ".", 0) == 0) {
return name.substr(className.size() + 1);
}
auto pos = name.find('.');
if (pos != std::string::npos && pos + 1 < name.size()) {
return name.substr(pos + 1);
}
return name;
}
static std::string stripClassPrefix(const std::string& name) {
auto pos = name.find('.');
if (pos != std::string::npos && pos + 1 < name.size()) {
return name.substr(pos + 1);
}
return name;
}
static bool isQuotedLiteral(const std::string& text) {
if (text.size() < 2) return false;
char first = text.front();
char last = text.back();
if ((first == '\'' && last == '\'') || (first == '"' && last == '"')) {
return true;
}
return false;
}
};