#pragma once #include "ProjectionGenerator.h" class ElispGenerator : 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; oss << "; Module: " << module->name << "\n\n"; // Process variables first auto variables = module->getChildren("variables"); for (const auto* var : variables) { oss << visitVariable(static_cast(var)) << "\n"; } if (!variables.empty()) { oss << "\n"; } // Process functions auto functions = module->getChildren("functions"); for (size_t i = 0; i < functions.size(); ++i) { if (i > 0) oss << "\n"; // Add blank line between functions oss << visitFunction(static_cast(functions[i])); } return oss.str(); } std::string visitFunction(const Function* function) override { std::ostringstream oss; // Process annotations first auto annotations = function->getChildren("annotations"); for (const auto* annotation : annotations) { std::string annotationCode = generate(annotation); if (!annotationCode.empty()) { oss << annotationCode << "\n"; } } // Generate function definition in Elisp oss << "(defun " << function->name << " ("; auto parameters = function->getChildren("parameters"); for (size_t i = 0; i < parameters.size(); ++i) { if (i > 0) oss << " "; oss << visitParameter(static_cast(parameters[i])); } oss << ")\n"; // Process function body auto body = function->getChildren("body"); if (body.empty()) { oss << " nil)\n"; // Return nil if no body } else { for (const auto* stmt : body) { std::string stmtCode = generate(stmt); // Indent each line of the statement size_t pos = 0; while (pos < stmtCode.length()) { size_t newlinePos = stmtCode.find('\n', pos); if (newlinePos == std::string::npos) { oss << " " << stmtCode.substr(pos) << "\n"; break; } else { oss << " " << stmtCode.substr(pos, newlinePos - pos) << "\n"; pos = newlinePos + 1; if (pos >= stmtCode.length()) break; } } } oss << ")\n"; // Close the function } return oss.str(); } std::string visitVariable(const Variable* variable) override { std::ostringstream oss; oss << "(defvar " << variable->name << " "; auto initializer = variable->getChild("initializer"); if (initializer) { oss << generate(initializer); } else { oss << "nil"; } oss << ") ; Variable declaration\n"; return oss.str(); } std::string visitParameter(const Parameter* parameter) override { // In Elisp, parameters are just symbols return parameter->name; } std::string visitAssignment(const Assignment* assignment) override { std::ostringstream oss; auto target = assignment->getChild("target"); auto value = assignment->getChild("value"); if (target && value) { oss << "(setq " << generate(target) << " " << generate(value) << ")"; } else if (target) { oss << "(setq " << generate(target) << " nil)"; } else { oss << "nil"; } return oss.str(); } std::string visitReturn(const Return* ret) override { // In Elisp, the last expression in a function is the return value // So we just return the value expression auto value = ret->getChild("value"); if (value) { return generate(value); } else { return "nil"; } } std::string visitBinaryOperation(const BinaryOperation* binOp) override { std::ostringstream oss; auto left = binOp->getChild("left"); auto right = binOp->getChild("right"); // Map operators to Elisp equivalents std::string op = binOp->op; if (op == "+") op = "+"; else if (op == "-") op = "-"; else if (op == "*") op = "*"; else if (op == "/") op = "/"; else if (op == "==") op = "="; else if (op == "!=") op = "/="; else if (op == "<") op = "<"; else if (op == ">") op = ">"; else if (op == "<=") op = "<="; else if (op == ">=") op = ">="; else if (op == "and") op = "and"; else if (op == "or") op = "or"; oss << "(" << op << " "; if (left) { oss << generate(left); } else { oss << "nil"; } oss << " "; if (right) { oss << generate(right); } else { oss << "nil"; } oss << ")"; 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 { // In Elisp, strings are enclosed in double quotes return "\"" + lit->value + "\""; } std::string visitBooleanLiteral(const BooleanLiteral* lit) override { return lit->value ? "t" : "nil"; } std::string visitNullLiteral(const NullLiteral* lit) override { return "nil"; } 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 << "nil"; // fallback } oss << "\n"; // Then branch if (!thenBranch.empty()) { for (size_t i = 0; i < thenBranch.size(); ++i) { if (i > 0) oss << "\n"; oss << " " << generate(thenBranch[i]); } } else { oss << " nil"; } // Else branch if (!elseBranch.empty()) { oss << "\n"; for (size_t i = 0; i < elseBranch.size(); ++i) { if (i > 0) oss << "\n"; oss << " " << generate(elseBranch[i]); } } else { oss << "\n nil"; } 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 << "t"; // fallback to infinite loop } oss << "\n"; for (size_t i = 0; i < body.size(); ++i) { if (i > 0) oss << "\n"; oss << " " << generate(body[i]); } 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 iterator = loop->iteratorName.empty() ? "item" : loop->iteratorName; oss << "(dolist (" << iterator << " "; if (iterable) { oss << generate(iterable); } else { oss << "nil"; // fallback } oss << ")\n"; for (size_t i = 0; i < body.size(); ++i) { if (i > 0) oss << "\n"; oss << " " << generate(body[i]); } oss << ")"; return oss.str(); } std::string visitExpressionStatement(const ExpressionStatement* stmt) override { std::ostringstream oss; auto expr = stmt->getChild("expression"); if (expr) { oss << generate(expr); } else { oss << "nil"; } return oss.str(); } std::string visitUnaryOperation(const UnaryOperation* unOp) override { std::ostringstream oss; auto operand = unOp->getChild("operand"); std::string op = unOp->op; // Map unary operators to Elisp equivalents if (op == "!") op = "not"; else if (op == "-") op = "-"; else if (op == "+") op = "+"; oss << "(" << op << " "; if (operand) { oss << generate(operand); } else { oss << "nil"; } oss << ")"; return oss.str(); } std::string visitFunctionCall(const FunctionCall* call) override { std::ostringstream oss; oss << "(" << call->functionName; auto arguments = call->getChildren("arguments"); for (const auto* arg : arguments) { oss << " " << generate(arg); } oss << ")"; return oss.str(); } std::string visitBlock(const Block* block) override { std::ostringstream oss; auto statements = block->getChildren("statements"); if (statements.empty()) { oss << "nil"; } else { oss << "(progn\n"; for (size_t i = 0; i < statements.size(); ++i) { oss << " " << generate(statements[i]); if (i < statements.size() - 1) oss << "\n"; } oss << ")"; } return oss.str(); } std::string visitListLiteral(const ListLiteral* lit) override { std::ostringstream oss; oss << "(list"; auto elements = lit->getChildren("elements"); for (const auto* elem : elements) { oss << " " << generate(elem); } 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 && index) { // In Elisp, accessing list/array elements oss << "(nth " << generate(index) << " " << generate(target) << ")"; } else if (target) { oss << generate(target); } else { oss << "nil"; } return oss.str(); } std::string visitMemberAccess(const MemberAccess* access) override { std::ostringstream oss; auto target = access->getChild("target"); if (target) { // In Elisp, member access depends on the data structure // For now, we'll represent it as a function call oss << "(." << access->memberName << " " << generate(target) << ")"; } else { oss << access->memberName; } return oss.str(); } std::string visitPrimitiveType(const PrimitiveType* type) override { // In Elisp, types are more dynamic, but we can represent them as symbols std::string kind = type->kind; if (kind == "int") return "integer"; if (kind == "float") return "float"; if (kind == "string") return "string"; if (kind == "bool") return "boolean"; if (kind == "char") return "character"; if (kind == "double") return "float"; if (kind == "long") return "integer"; if (kind == "short") return "integer"; if (kind == "byte") return "integer"; if (kind == "void") return "null"; return kind; // Return as-is if not a common type } std::string visitListType(const ListType* type) override { std::ostringstream oss; oss << "(list "; auto elementType = type->getChild("elementType"); if (elementType) { oss << generate(elementType); } else { oss << "t"; // t means any type in Elisp } oss << ")"; return oss.str(); } std::string visitSetType(const SetType* type) override { std::ostringstream oss; oss << "(hash-table :test 'equal)"; return oss.str(); // Represent sets as hash tables with equal test } std::string visitMapType(const MapType* type) override { std::ostringstream oss; oss << "(hash-table :test 'equal)"; return oss.str(); // Represent maps as hash tables } std::string visitTupleType(const TupleType* type) override { std::ostringstream oss; oss << "(vector"; // Represent tuples as vectors auto elementTypes = type->getChildren("elementTypes"); for (const auto* elemType : elementTypes) { oss << " " << generate(elemType); } oss << ")"; return oss.str(); } std::string visitArrayType(const ArrayType* type) override { std::ostringstream oss; oss << "(vector "; auto elementType = type->getChild("elementType"); if (elementType) { oss << generate(elementType); } else { oss << "t"; } oss << ")"; return oss.str(); } std::string visitOptionalType(const OptionalType* type) override { std::ostringstream oss; oss << "(or null "; auto innerType = type->getChild("innerType"); if (innerType) { oss << generate(innerType); } else { oss << "t"; } oss << ")"; return oss.str(); } std::string visitCustomType(const CustomType* type) override { return type->typeName; } std::string visitDerefStrategy(const DerefStrategy* annotation) override { // Convert deref strategy to Elisp annotation/comment if (annotation->strategy == "batched") { return "; @deref(batched) - Process in batches for efficiency"; } else if (annotation->strategy == "streamed") { return "; @deref(streamed) - Stream processing"; } else if (annotation->strategy == "manual") { return "; @deref(manual) - Manual memory management"; } else { return "; @deref(" + annotation->strategy + ") - Memory dereference strategy"; } } std::string visitOptimizationLock(const OptimizationLock* annotation) override { return "; @lock(" + annotation->lockedBy + ") - Optimization locked by " + annotation->lockedBy; } std::string visitLangSpecific(const LangSpecific* annotation) override { 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 + ")"; } std::string visitOwnerAnnotation(const OwnerAnnotation* annotation) override { 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 + " - Optimization hint"; } std::string visitInlineAnnotation(const InlineAnnotation* annotation) override { return "; @inline(" + annotation->mode + ")"; } std::string visitPureAnnotation(const PureAnnotation*) override { return "; @pure - No side effects"; } std::string visitConstExprAnnotation(const ConstExprAnnotation*) override { return "; @constexpr - Compile-time evaluable"; } };