UNPKG

python2ib

Version:

Convert Python code to IB Pseudocode format

328 lines 10.2 kB
/** * Main emitter for converting IR to IB Pseudocode text */ import { IndentManager, IndentUtils } from '../utils/indent.js'; /** Main emitter class for IR to IB Pseudocode conversion */ export class IBPseudocodeEmitter { indentManager; config; output = []; constructor(config) { this.config = config; this.indentManager = new IndentManager(config.indentStyle, config.indentSize); } /** Main emit method */ emit(ir) { this.output = []; this.emitNode(ir); let result = this.output.join('\n'); // Apply post-processing if (this.config.normalizeIndentation) { result = IndentUtils.normalize(result, this.config.indentStyle, this.config.indentSize); } // Ensure proper line endings result = result.replace(/\r\n/g, '\n').replace(/\r/g, '\n'); // Remove trailing newlines for single statements result = result.replace(/\n+$/, ''); return result; } /** Emit a single IR node */ emitNode(node) { switch (node.kind) { case 'program': this.emitProgram(node); break; case 'assign': this.emitAssign(node); break; case 'output': this.emitOutput(node); break; case 'input': this.emitInput(node); break; case 'if': this.emitIf(node); break; case 'endif': this.emitEndif(node); break; case 'elseif': this.emitElseif(node); break; case 'else': this.emitElse(node); break; case 'while': this.emitWhile(node); break; case 'until': this.emitUntil(node); break; case 'endwhile': this.emitEndwhile(node); break; case 'for': this.emitFor(node); break; case 'next': this.emitNext(node); break; case 'function': this.emitFunction(node); break; case 'endfunction': this.emitEndfunction(node); break; case 'procedure': this.emitProcedure(node); break; case 'endprocedure': this.emitEndprocedure(node); break; case 'return': this.emitReturn(node); break; case 'comment': this.emitComment(node); break; case 'expression': this.emitExpression(node); break; case 'block': this.emitBlock(node); break; case 'sequence': this.emitSequence(node); break; default: this.emitUnsupported(node); break; } } /** Emit block */ emitBlock(node) { for (const child of node.children) { this.emitNode(child); } } /** Emit sequence */ emitSequence(node) { for (const child of node.children) { this.emitNode(child); } } /** Emit program (root) */ emitProgram(node) { for (const child of node.children) { this.emitNode(child); } } /** Emit assignment */ emitAssign(node) { const line = this.indentManager.current + node.text; this.output.push(line); } /** Emit output statement */ emitOutput(node) { const line = this.indentManager.current + node.text; this.output.push(line); } /** Emit input statement */ emitInput(node) { const line = this.indentManager.current + node.text; this.output.push(line); } /** Emit if statement */ emitIf(node) { const line = this.indentManager.current + node.text; this.output.push(line); // Increase indent for body this.indentManager.increase(); // Emit children for (const child of node.children) { this.emitNode(child); } } /** Emit endif */ emitEndif(node) { // Decrease indent before emitting ENDIF this.indentManager.decrease(); const line = this.indentManager.current + node.text; this.output.push(line); } /** Emit elseif */ emitElseif(node) { // Temporarily decrease indent for ELSEIF this.indentManager.decrease(); const line = this.indentManager.current + node.text; this.output.push(line); this.indentManager.increase(); // Emit children for (const child of node.children) { this.emitNode(child); } } /** Emit else */ emitElse(node) { // Temporarily decrease indent for ELSE this.indentManager.decrease(); const line = this.indentManager.current + node.text; this.output.push(line); this.indentManager.increase(); // Emit children for (const child of node.children) { this.emitNode(child); } } /** Emit while loop */ emitWhile(node) { const line = this.indentManager.current + node.text; this.output.push(line); // Increase indent for body this.indentManager.increase(); // Emit children for (const child of node.children) { this.emitNode(child); } } /** Emit until loop */ emitUntil(node) { const line = this.indentManager.current + node.text; this.output.push(line); // Increase indent for body this.indentManager.increase(); // Emit children for (const child of node.children) { this.emitNode(child); } } /** Emit endwhile */ emitEndwhile(node) { // Decrease indent before emitting ENDWHILE this.indentManager.decrease(); const line = this.indentManager.current + node.text; this.output.push(line); } /** Emit for loop */ emitFor(node) { const line = this.indentManager.current + node.text; this.output.push(line); // Increase indent for body this.indentManager.increase(); // Emit children for (const child of node.children) { this.emitNode(child); } } /** Emit next (end of for loop) */ emitNext(node) { // Decrease indent before emitting NEXT this.indentManager.decrease(); const line = this.indentManager.current + node.text; this.output.push(line); } /** Emit function definition */ emitFunction(node) { const line = this.indentManager.current + node.text; this.output.push(line); // Increase indent for body this.indentManager.increase(); // Emit children for (const child of node.children) { this.emitNode(child); } } /** Emit endfunction */ emitEndfunction(node) { // Decrease indent before emitting ENDFUNCTION this.indentManager.decrease(); const line = this.indentManager.current + node.text; this.output.push(line); } /** Emit procedure definition */ emitProcedure(node) { const line = this.indentManager.current + node.text; this.output.push(line); // Increase indent for body this.indentManager.increase(); // Emit children for (const child of node.children) { this.emitNode(child); } } /** Emit endprocedure */ emitEndprocedure(node) { // Decrease indent before emitting ENDPROCEDURE this.indentManager.decrease(); const line = this.indentManager.current + node.text; this.output.push(line); } /** Emit return statement */ emitReturn(node) { const line = this.indentManager.current + node.text; this.output.push(line); } /** Emit comment */ emitComment(node) { const line = this.indentManager.current + node.text; this.output.push(line); } /** Emit expression */ emitExpression(node) { const line = this.indentManager.current + node.text; this.output.push(line); } /** Emit unsupported node */ emitUnsupported(node) { const unsupportedComment = `// UNSUPPORTED: ${node.kind} - ${node.text}`; const line = this.indentManager.current + unsupportedComment; this.output.push(line); } /** Get current indentation level */ getCurrentIndentLevel() { return this.indentManager.getLevel(); } /** Reset emitter state */ reset() { this.output = []; this.indentManager.reset(); } } /** Convenience function for emitting IR to IB Pseudocode */ export function emitIBPseudocode(ir, config) { const emitter = new IBPseudocodeEmitter(config); return emitter.emit(ir); } /** Convenience function with default config */ export function emitIBPseudocodeDefault(ir) { const defaultConfig = { format: 'plain', indentStyle: 'spaces', indentSize: 4, includeLineNumbers: false, includeOriginalCode: false, validateSyntax: true, preserveEmptyLines: true, variableMapping: {}, functionMapping: {}, strictMode: false, normalizeIndentation: false, preserveComments: true, customOperators: {}, customKeywords: {}, outputOptions: { includeLineNumbers: false, includeComments: true, wrapInCodeBlock: false }, conversionRules: { forceExplicitTypes: false, convertFStrings: true, expandCompoundAssignments: true, simplifyExpressions: false } }; return emitIBPseudocode(ir, defaultConfig); } //# sourceMappingURL=index.js.map