uppaal-to-tchecker
Version:
JavaScript implementation of Uppaal to TChecker translator - convert Uppaal timed automata models to TChecker format
181 lines (146 loc) ⢠6.63 kB
JavaScript
/**
* Usage demonstration for uppaal-to-tchecker JavaScript API
* This script shows various ways to use the translator
*/
const UppaalToTChecker = require('../src/index');
const fs = require('fs').promises;
const path = require('path');
const demoModel = `
// Demo Uppaal model - Train Gate Controller
clock x, y;
int trains = 0;
bool gate_open = true;
chan approach, exit, lower, raise;
process Train(const int id) {
state far, near, crossing;
init far;
trans far -> near { sync approach!; },
near -> crossing { guard !gate_open; assign x = 0; },
crossing -> far { guard x >= 1; sync exit!; };
}
process Controller() {
state idle, lowering, raised, raising;
init idle;
trans idle -> lowering { sync approach?; assign trains++, y = 0; },
lowering -> raised { guard y >= 2; sync lower!; assign gate_open = false; },
raised -> raising { sync exit?; assign trains--; guard trains == 0; assign y = 0; },
raising -> idle { guard y >= 2; sync raise!; assign gate_open = true; };
}
// Instantiate two trains
T1 := Train(1);
T2 := Train(2);
system T1, T2, Controller;
`;
async function demonstrateAPI() {
console.log('š Uppaal-to-TChecker JavaScript API Demo\n');
const translator = new UppaalToTChecker();
try {
// Demo 1: Basic translation
console.log('š Demo 1: Basic Translation');
console.log('ā'.repeat(50));
const result1 = await translator.translate(demoModel, {
format: 'xta',
systemName: 'TrainGateSystem'
});
console.log('Input: Uppaal XTA model (Train Gate Controller)');
console.log('Output preview:');
console.log(result1.split('\n').slice(0, 10).join('\n') + '\n...\n');
// Demo 2: Translation with options
console.log('š Demo 2: Translation with Options');
console.log('ā'.repeat(50));
translator.setVerbose(1);
translator.setDebug(false);
const result2 = await translator.translate(demoModel, {
format: 'xta',
language: 'xta',
systemName: 'VerboseSystem',
verbose: 1
});
console.log('Used options: verbose=1, systemName=VerboseSystem');
console.log('System line:', result2.split('\n').find(line => line.startsWith('system:')));
console.log();
// Demo 3: File-based translation
console.log('š Demo 3: File-based Translation');
console.log('ā'.repeat(50));
const tempInput = path.join(__dirname, 'temp-demo.xta');
const tempOutput = path.join(__dirname, 'temp-demo.tck');
await fs.writeFile(tempInput, demoModel);
const result3 = await translator.translateFile(tempInput, tempOutput, {
systemName: 'FileBasedSystem'
});
const outputContent = await fs.readFile(tempOutput, 'utf8');
console.log(`Created files: ${tempInput} -> ${tempOutput}`);
console.log(`Output file size: ${outputContent.length} characters`);
console.log(`Number of processes: ${(outputContent.match(/^process:/gm) || []).length}`);
console.log();
// Demo 4: Format detection
console.log('š Demo 4: Format Detection');
console.log('ā'.repeat(50));
const xmlExample = '<?xml version="1.0"?><nta><template><name>Test</name></template></nta>';
console.log('XTA format detected:', translator.detectFormat(demoModel));
console.log('XML format detected:', translator.detectFormat(xmlExample));
console.log('From extension .xta:', translator.detectFormatFromExtension('model.xta'));
console.log('From extension .xml:', translator.detectFormatFromExtension('model.xml'));
console.log();
// Demo 5: Error handling
console.log('š Demo 5: Error Handling');
console.log('ā'.repeat(50));
try {
await translator.translate('invalid uppaal syntax');
} catch (error) {
console.log('Caught expected error:', error.constructor.name);
console.log('Error message:', error.message);
}
console.log();
// Demo 6: Analysis of translation result
console.log('š Demo 6: Translation Analysis');
console.log('ā'.repeat(50));
const lines = result1.split('\n');
const systemLine = lines.find(line => line.startsWith('system:'));
const processLines = lines.filter(line => line.startsWith('process:'));
const locationLines = lines.filter(line => line.startsWith('location:'));
const edgeLines = lines.filter(line => line.startsWith('edge:'));
const syncLines = lines.filter(line => line.startsWith('sync:'));
const clockLines = lines.filter(line => line.startsWith('clock:'));
const intLines = lines.filter(line => line.startsWith('int:'));
console.log(`System: ${systemLine}`);
console.log(`Processes: ${processLines.length}`);
console.log(`Locations: ${locationLines.length}`);
console.log(`Edges: ${edgeLines.length}`);
console.log(`Synchronizations: ${syncLines.length}`);
console.log(`Clocks: ${clockLines.length}`);
console.log(`Integer variables: ${intLines.length}`);
console.log();
console.log('Process names:');
processLines.forEach(line => {
const processName = line.split(':')[1];
console.log(` - ${processName}`);
});
console.log();
// Cleanup
try {
await fs.unlink(tempInput);
await fs.unlink(tempOutput);
} catch (e) {
// Ignore cleanup errors
}
console.log('ā
Demo completed successfully!');
console.log('\nš Next steps:');
console.log(' - Check README.md for complete documentation');
console.log(' - See examples/ for more sample models');
console.log(' - Use USAGE_COMPARISON.md to compare with C++ version');
console.log(' - Run tests with: npm test');
} catch (error) {
console.error('ā Demo failed:', error.message);
if (translator.debug) {
console.error(error.stack);
}
process.exit(1);
}
}
// Run demo if called directly
if (require.main === module) {
demonstrateAPI();
}
module.exports = { demonstrateAPI };