AeThex-OS/packages/aethex-cli/lib/compiler/LuaGenerator.js

212 lines
No EOL
7.6 KiB
JavaScript

"use strict";
/**
* AeThex Compiler - Lua Code Generator (for Roblox)
* Generates Lua code from AST
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.LuaGenerator = void 0;
class LuaGenerator {
constructor() {
this.indent = 0;
}
generate(ast) {
const lines = [];
// Runtime header
lines.push('-- Generated by AeThex Compiler v1.0.0');
lines.push('-- Target: Roblox (Lua)');
lines.push('');
// Generate imports (convert to Lua require)
for (const node of ast.body) {
if (node.type === 'Import') {
lines.push(this.generateImport(node));
}
}
if (ast.body.some(n => n.type === 'Import')) {
lines.push('');
}
// Generate realities
for (const node of ast.body) {
if (node.type === 'Reality') {
lines.push(this.generateReality(node));
lines.push('');
}
}
// Generate journeys
for (const node of ast.body) {
if (node.type === 'Journey') {
lines.push(this.generateJourney(node));
lines.push('');
}
}
return lines.join('\n');
}
generateImport(node) {
// Convert @aethex.os/core to Roblox module path
const luaPath = node.source.replace('@aethex.os/', 'ReplicatedStorage.AeThex.');
return `local AeThex = require(game.${luaPath})`;
}
generateReality(node) {
const lines = [];
lines.push(`local ${node.name} = {`);
for (const [key, value] of Object.entries(node.properties)) {
if (Array.isArray(value)) {
const arr = value.map(v => `"${v}"`).join(', ');
lines.push(` ${key} = {${arr}},`);
}
else if (typeof value === 'string') {
lines.push(` ${key} = "${value}",`);
}
else {
lines.push(` ${key} = ${value},`);
}
}
lines.push('}');
return lines.join('\n');
}
generateJourney(node) {
const lines = [];
const params = node.params.join(', ');
lines.push(`local function ${node.name}(${params})`);
this.indent++;
for (const stmt of node.body) {
const generated = this.generateStatement(stmt);
if (generated) {
lines.push(this.indentLine(generated));
}
}
this.indent--;
lines.push('end');
return lines.join('\n');
}
generateStatement(stmt) {
switch (stmt.type) {
case 'LetStatement':
return this.generateLetStatement(stmt);
case 'WhenStatement':
return this.generateWhenStatement(stmt);
case 'NotifyStatement':
return this.generateNotifyStatement(stmt);
case 'RevealStatement':
return this.generateRevealStatement(stmt);
case 'SyncStatement':
return this.generateSyncStatement(stmt);
case 'ReturnStatement':
return 'return';
case 'ExpressionStatement':
return this.generateExpression(stmt.expression);
default:
return '';
}
}
generateLetStatement(stmt) {
const value = this.generateExpression(stmt.value);
return `local ${stmt.identifier} = ${value}`;
}
generateWhenStatement(stmt) {
const lines = [];
const condition = this.generateExpression(stmt.condition);
lines.push(`if ${condition} then`);
this.indent++;
for (const s of stmt.consequent) {
lines.push(this.indentLine(this.generateStatement(s)));
}
this.indent--;
if (stmt.alternate && stmt.alternate.length > 0) {
lines.push(this.indentLine('else'));
this.indent++;
for (const s of stmt.alternate) {
lines.push(this.indentLine(this.generateStatement(s)));
}
this.indent--;
}
lines.push(this.indentLine('end'));
return lines.join('\n');
}
generateNotifyStatement(stmt) {
const message = this.generateExpression(stmt.message);
return `print(${message})`;
}
generateRevealStatement(stmt) {
const value = this.generateExpression(stmt.value);
return `return ${value}`;
}
generateSyncStatement(stmt) {
const target = this.generateExpression(stmt.target);
const platforms = `{${stmt.platforms.map(p => `"${p}"`).join(', ')}}`;
return `AeThex.DataSync.sync(${target}, ${platforms})`;
}
generateExpression(expr) {
switch (expr.type) {
case 'BinaryExpression':
return this.generateBinaryExpression(expr);
case 'UnaryExpression':
return this.generateUnaryExpression(expr);
case 'CallExpression':
return this.generateCallExpression(expr);
case 'MemberExpression':
return this.generateMemberExpression(expr);
case 'Identifier':
return expr.name;
case 'Literal':
return typeof expr.value === 'string' ? `"${expr.value}"` : String(expr.value);
case 'ArrayExpression':
return this.generateArrayExpression(expr);
case 'ObjectExpression':
return this.generateObjectExpression(expr);
case 'NewExpression':
return this.generateNewExpression(expr);
default:
return '';
}
}
generateBinaryExpression(expr) {
const left = this.generateExpression(expr.left);
const right = this.generateExpression(expr.right);
// Lua uses ~= instead of !=
const operator = expr.operator === '!=' ? '~=' :
expr.operator === '==' ? '==' :
expr.operator;
// Lua string concatenation uses ..
if (expr.operator === '+' && this.isStringExpression(expr.left)) {
return `(${left} .. ${right})`;
}
return `(${left} ${operator} ${right})`;
}
generateUnaryExpression(expr) {
const operand = this.generateExpression(expr.operand);
// Lua uses 'not' instead of '!'
const operator = expr.operator === '!' ? 'not ' : expr.operator;
return `(${operator}${operand})`;
}
generateCallExpression(expr) {
const callee = this.generateExpression(expr.callee);
const args = expr.arguments.map(arg => this.generateExpression(arg)).join(', ');
return `${callee}(${args})`;
}
generateMemberExpression(expr) {
const object = this.generateExpression(expr.object);
return `${object}.${expr.property.name}`;
}
generateArrayExpression(expr) {
const elements = expr.elements.map(el => this.generateExpression(el)).join(', ');
return `{${elements}}`;
}
generateObjectExpression(expr) {
const properties = expr.properties
.map(prop => `${prop.key} = ${this.generateExpression(prop.value)}`)
.join(', ');
return `{ ${properties} }`;
}
generateNewExpression(expr) {
const args = expr.arguments.map(arg => this.generateExpression(arg)).join(', ');
return `AeThex.${expr.callee.name}.new(${args})`;
}
isStringExpression(expr) {
return expr.type === 'Literal' && typeof expr.value === 'string';
}
indentLine(line) {
return ' '.repeat(this.indent) + line;
}
}
exports.LuaGenerator = LuaGenerator;
//# sourceMappingURL=LuaGenerator.js.map