Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions src/commands/normalize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2022-2025 Objectionary.com
* SPDX-License-Identifier: MIT
*/

const fs = require('fs');
const path = require('path');
const { spawnSync } = require('child_process');
const parse = require('./parse');
const print = require('./print');

module.exports = async function normalize(opts) {
const target = path.resolve(opts.target || '.');
const eocDir = path.join(target, '.eoc');
const normalizedDir = path.join(eocDir, 'normalized');

if (!fs.existsSync(eocDir)) {
throw new Error(`No .eoc/ directory found at ${eocDir}. Run "eoc parse" first.`);
}

// Step 1: parse EO files to XMIR
await parse({ target });

// Step 2: make sure .eoc/normalized exists
if (!fs.existsSync(normalizedDir)) {
fs.mkdirSync(normalizedDir, { recursive: true });
}

// Step 3: process all .xmir files
const files = fs.readdirSync(eocDir).filter(f => f.endsWith('.xmir'));
for (const file of files) {
const base = path.basename(file, '.xmir');
const inputXmir = path.join(eocDir, file);
const phi = path.join(eocDir, `${base}.phi`);
const normalizedPhi = path.join(eocDir, `${base}.norm.phi`);
const normalizedXmir = path.join(normalizedDir, `${base}.xmir`);

// xmir -> phi
runPhino(['translate', inputXmir], phi);

// phi -> normalized.phi
runPhino(['rewrite', '--normalize', phi], normalizedPhi);

// normalized.phi -> xmir
runPhino(['translate', '--reverse', normalizedPhi], normalizedXmir);
}

// Step 4: print .xmir -> .eo
await print({
target,
printInput: '.eoc/normalized',
printOutput: '.eoc/normalized'
});

console.info(`Normalized EO sources saved to ${path.relative(process.cwd(), normalizedDir)}`);
};

function runPhino(args, outputFilePath) {
const phinoJar = path.resolve(__dirname, '../../phino.jar'); // ← путь до JAR-файла Phino
const javaArgs = ['-jar', phinoJar].concat(args);
const result = spawnSync('java', javaArgs, { encoding: 'utf-8' });

if (result.status !== 0) {
throw new Error(`Phino failed:\n${result.stderr}`);
}

fs.writeFileSync(outputFilePath, result.stdout);
}
17 changes: 16 additions & 1 deletion src/eoc.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const {program} = require('commander'),
generate_comments: require('./commands/generate_comments'),
jeo_disassemble: require('./commands/jeo/disassemble'),
jeo_assemble: require('./commands/jeo/assemble'),
normalize: require('./commands/normalize'),
latex: require('./commands/latex')
},
commands = {
Expand All @@ -58,7 +59,7 @@ const {program} = require('commander'),
}
}
};

if (process.argv.includes('--verbose')) {
tinted.enable('debug');
console.debug('Debug output is turned ON');
Expand Down Expand Up @@ -112,6 +113,20 @@ program.command('audit')
coms().audit(program.opts());
});

program.command('normalize')
.description('Normalize EO programs by rewriting their .phi representation')
.action((str, opts) => {
clear(str);
if (program.opts().alone === undefined) {
coms().register(program.opts())
.then(() => coms().parse(program.opts()))
.then(() => coms().normalize({...program.opts(), ...str}));
} else {
coms().normalize({...program.opts(), ...str});
}
});


program.command('foreign')
.description('Inspect and print the list of foreign objects')
.action((str, opts) => {
Expand Down