zignet
Version:
MCP server for Zig — AI-powered code analysis, validation, and documentation with fine-tuned LLM
458 lines (456 loc) • 11.9 kB
JavaScript
//#region src/codegen.ts
/**
* Default options
*/
const DEFAULT_OPTIONS = {
indentSize: 4,
useTabs: false,
newlineBeforeBrace: false,
trailingComma: false
};
/**
* Code Generator class
*/
var CodeGenerator = class {
options;
indentLevel = 0;
output = [];
constructor(options = {}) {
this.options = {
...DEFAULT_OPTIONS,
...options
};
}
/**
* Generate code from AST
*/
generate(program) {
this.output = [];
this.indentLevel = 0;
for (let i = 0; i < program.body.length; i++) {
this.generateDeclaration(program.body[i]);
if (i < program.body.length - 1) this.output.push("");
}
return this.output.join("\n");
}
/**
* Generate declaration
*/
generateDeclaration(declaration) {
switch (declaration.type) {
case "FunctionDeclaration":
this.generateFunctionDeclaration(declaration);
break;
case "VariableDeclaration":
this.generateVariableDeclaration(declaration);
break;
case "StructDeclaration":
this.generateStructDeclaration(declaration);
break;
default: break;
}
}
/**
* Generate function declaration
*/
generateFunctionDeclaration(fn) {
let line = "";
if (fn.isInline) line += "inline ";
if (fn.isComptime) line += "comptime ";
line += `fn ${fn.name}(`;
const params = fn.parameters.map((param) => this.generateParameter(param));
line += params.join(", ");
line += ") ";
if (fn.errorUnion) line += "!";
line += this.generateTypeAnnotation(fn.returnType);
if (this.options.newlineBeforeBrace) {
this.writeLine(line);
this.writeLine("{");
} else {
line += " {";
this.writeLine(line);
}
this.indent();
this.generateBlockStatements(fn.body.statements);
this.dedent();
this.writeLine("}");
}
/**
* Generate parameter
*/
generateParameter(param) {
let result = "";
if (param.isComptime) result += "comptime ";
result += param.name;
result += ": ";
result += this.generateTypeAnnotation(param.typeAnnotation);
return result;
}
/**
* Generate variable declaration
*/
generateVariableDeclaration(varDecl) {
let line = varDecl.isConst ? "const " : "var ";
line += varDecl.name;
if (varDecl.typeAnnotation) {
line += ": ";
line += this.generateTypeAnnotation(varDecl.typeAnnotation);
}
if (varDecl.initializer) {
line += " = ";
line += this.generateExpression(varDecl.initializer);
}
line += ";";
this.writeLine(line);
}
/**
* Generate struct declaration
*/
generateStructDeclaration(struct) {
let line = `const ${struct.name} = struct {`;
this.writeLine(line);
this.indent();
for (const field of struct.fields) this.generateStructField(field);
this.dedent();
this.writeLine("};");
}
/**
* Generate struct field
*/
generateStructField(field) {
let line = field.name;
line += ": ";
line += this.generateTypeAnnotation(field.typeAnnotation);
line += ",";
this.writeLine(line);
}
/**
* Generate type annotation
*/
generateTypeAnnotation(typeAnnotation) {
switch (typeAnnotation.type) {
case "PrimitiveType":
case "IdentifierType": return typeAnnotation.name;
case "PointerType": return "*" + this.generateTypeAnnotation(typeAnnotation.pointeeType);
case "ArrayType": return `[${typeAnnotation.size !== void 0 ? typeAnnotation.size.toString() : ""}]${this.generateTypeAnnotation(typeAnnotation.elementType)}`;
case "ErrorUnionType": return "!" + this.generateTypeAnnotation(typeAnnotation.valueType);
case "OptionalType": return "?" + this.generateTypeAnnotation(typeAnnotation.valueType);
default: return "unknown";
}
}
/**
* Generate block statements
*/
generateBlockStatements(statements) {
for (const stmt of statements) this.generateStatement(stmt);
}
/**
* Generate statement
*/
generateStatement(stmt) {
switch (stmt.type) {
case "VariableDeclaration":
this.generateVariableDeclaration(stmt);
break;
case "ReturnStatement":
this.generateReturnStatement(stmt);
break;
case "IfStatement":
this.generateIfStatement(stmt);
break;
case "WhileStatement":
this.generateWhileStatement(stmt);
break;
case "ForStatement":
this.generateForStatement(stmt);
break;
case "BreakStatement":
this.writeLine("break;");
break;
case "ContinueStatement":
this.writeLine("continue;");
break;
case "BlockStatement":
this.generateBlockStatement(stmt);
break;
case "ExpressionStatement":
this.generateExpressionStatement(stmt);
break;
case "ComptimeStatement":
this.generateComptimeStatement(stmt);
break;
}
}
/**
* Generate return statement
*/
generateReturnStatement(stmt) {
let line = "return";
if (stmt.value) {
line += " ";
line += this.generateExpression(stmt.value);
}
line += ";";
this.writeLine(line);
}
/**
* Generate if statement
*/
generateIfStatement(stmt) {
let line = "if (";
line += this.generateExpression(stmt.condition);
line += ") ";
if (stmt.consequent.type === "BlockStatement") {
line += "{";
this.writeLine(line);
this.indent();
this.generateBlockStatements(stmt.consequent.statements);
this.dedent();
this.write("}");
} else {
this.writeLine(line);
this.indent();
this.generateStatement(stmt.consequent);
this.dedent();
}
if (stmt.alternate) {
if (stmt.consequent.type === "BlockStatement") this.output[this.output.length - 1] += " else ";
else this.write("else ");
if (stmt.alternate.type === "IfStatement") this.generateIfStatement(stmt.alternate);
else if (stmt.alternate.type === "BlockStatement") {
this.output[this.output.length - 1] += "{";
this.writeLine("");
this.indent();
this.generateBlockStatements(stmt.alternate.statements);
this.dedent();
this.writeLine("}");
} else {
this.writeLine("");
this.indent();
this.generateStatement(stmt.alternate);
this.dedent();
}
} else if (stmt.consequent.type === "BlockStatement") {
this.output[this.output.length - 1] += "";
this.writeLine("");
}
}
/**
* Generate while statement
*/
generateWhileStatement(stmt) {
let line = "while (";
line += this.generateExpression(stmt.condition);
line += ") ";
if (stmt.body.type === "BlockStatement") {
line += "{";
this.writeLine(line);
this.indent();
this.generateBlockStatements(stmt.body.statements);
this.dedent();
this.writeLine("}");
} else {
this.writeLine(line);
this.indent();
this.generateStatement(stmt.body);
this.dedent();
}
}
/**
* Generate for statement
*/
generateForStatement(stmt) {
let line = "for (";
if (stmt.initializer) if (stmt.initializer.type === "VariableDeclaration") {
const varDecl = stmt.initializer;
line += varDecl.isConst ? "const " : "var ";
line += varDecl.name;
if (varDecl.typeAnnotation) line += ": " + this.generateTypeAnnotation(varDecl.typeAnnotation);
if (varDecl.initializer) line += " = " + this.generateExpression(varDecl.initializer);
} else line += this.generateExpression(stmt.initializer);
line += "; ";
if (stmt.condition) line += this.generateExpression(stmt.condition);
line += "; ";
if (stmt.increment) line += this.generateExpression(stmt.increment);
line += ") ";
if (stmt.body.type === "BlockStatement") {
line += "{";
this.writeLine(line);
this.indent();
this.generateBlockStatements(stmt.body.statements);
this.dedent();
this.writeLine("}");
} else {
this.writeLine(line);
this.indent();
this.generateStatement(stmt.body);
this.dedent();
}
}
/**
* Generate block statement
*/
generateBlockStatement(stmt) {
this.writeLine("{");
this.indent();
this.generateBlockStatements(stmt.statements);
this.dedent();
this.writeLine("}");
}
/**
* Generate expression statement
*/
generateExpressionStatement(stmt) {
const line = this.generateExpression(stmt.expression) + ";";
this.writeLine(line);
}
/**
* Generate comptime statement
*/
generateComptimeStatement(stmt) {
this.writeLine("comptime {");
this.indent();
this.generateBlockStatements(stmt.body.statements);
this.dedent();
this.writeLine("}");
}
/**
* Generate expression
*/
generateExpression(expr) {
switch (expr.type) {
case "NumberLiteral": return this.generateNumberLiteral(expr);
case "StringLiteral": return this.generateStringLiteral(expr);
case "BooleanLiteral": return this.generateBooleanLiteral(expr);
case "Identifier": return this.generateIdentifier(expr);
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 "IndexExpression": return this.generateIndexExpression(expr);
case "AssignmentExpression": return this.generateAssignmentExpression(expr);
case "StructLiteral": return this.generateStructLiteral(expr);
case "ArrayLiteral": return this.generateArrayLiteral(expr);
default: return "unknown";
}
}
/**
* Generate number literal
*/
generateNumberLiteral(expr) {
return expr.value.toString();
}
/**
* Generate string literal
*/
generateStringLiteral(expr) {
return `"${expr.value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t")}"`;
}
/**
* Generate boolean literal
*/
generateBooleanLiteral(expr) {
return expr.value ? "true" : "false";
}
/**
* Generate identifier
*/
generateIdentifier(expr) {
return expr.name;
}
/**
* Generate binary expression
*/
generateBinaryExpression(expr) {
const left = this.generateExpression(expr.left);
const right = this.generateExpression(expr.right);
return `${left} ${expr.operator} ${right}`;
}
/**
* Generate unary expression
*/
generateUnaryExpression(expr) {
const operand = this.generateExpression(expr.operand);
return `${expr.operator}${operand}`;
}
/**
* Generate call expression
*/
generateCallExpression(expr) {
return `${this.generateExpression(expr.callee)}(${expr.arguments.map((arg) => this.generateExpression(arg)).join(", ")})`;
}
/**
* Generate member expression
*/
generateMemberExpression(expr) {
return `${this.generateExpression(expr.object)}.${expr.property}`;
}
/**
* Generate index expression
*/
generateIndexExpression(expr) {
return `${this.generateExpression(expr.object)}[${this.generateExpression(expr.index)}]`;
}
/**
* Generate assignment expression
*/
generateAssignmentExpression(expr) {
const left = this.generateExpression(expr.left);
const right = this.generateExpression(expr.right);
return `${left} ${expr.operator} ${right}`;
}
/**
* Generate struct literal
*/
generateStructLiteral(expr) {
let result = expr.typeName + "{ ";
const fields = expr.fields.map((field) => {
return `.${field.name} = ${this.generateExpression(field.value)}`;
});
result += fields.join(", ");
result += " }";
return result;
}
/**
* Generate array literal
*/
generateArrayLiteral(expr) {
return `[_]{ ${expr.elements.map((elem) => this.generateExpression(elem)).join(", ")} }`;
}
/**
* Write a line with proper indentation
*/
writeLine(text) {
if (text === "") this.output.push("");
else this.output.push(this.getIndent() + text);
}
/**
* Write without newline
*/
write(text) {
if (this.output.length === 0) this.output.push(this.getIndent() + text);
else this.output[this.output.length - 1] += text;
}
/**
* Get current indentation string
*/
getIndent() {
if (this.options.useTabs) return " ".repeat(this.indentLevel);
return " ".repeat(this.indentLevel * this.options.indentSize);
}
/**
* Increase indentation level
*/
indent() {
this.indentLevel++;
}
/**
* Decrease indentation level
*/
dedent() {
if (this.indentLevel > 0) this.indentLevel--;
}
};
//#endregion
exports.CodeGenerator = CodeGenerator;
//# sourceMappingURL=codegen.cjs.map