UNPKG

meld

Version:

Meld: A template language for LLM prompts

283 lines (226 loc) 8.5 kB
#!/usr/bin/env node /** * Simple script to create test cases for comparing meld-ast versions */ const fs = require('fs'); const path = require('path'); const { execSync } = require('child_process'); const COMPARISON_DIR = path.join(process.cwd(), 'meld-ast-comparison'); const CASES_DIR = path.join(COMPARISON_DIR, 'specific-cases'); // Define test cases for array notation and other issues const TEST_CASES = [ { name: 'array-notation-simple', description: 'Tests simple array access notation', content: ` @data fruits = ["apple", "banana", "cherry"] Bracket notation: {{fruits[0]}}, {{fruits[1]}}, {{fruits[2]}} ` }, { name: 'array-notation-nested', description: 'Tests nested array access notation', content: ` @data users = [ { name: "Alice", hobbies: ["reading", "hiking"] }, { name: "Bob", hobbies: ["gaming", "cooking"] } ] User 1: {{users[0].name}} - {{users[0].hobbies[0]}} User 2: {{users[1].name}} - {{users[1].hobbies[1]}} ` }, { name: 'array-variable-index', description: 'Tests array access with variable index', content: ` @data fruits = ["apple", "banana", "cherry"] @data index = 1 Using variable index: {{fruits[index]}} ` } ]; // Create directory structure function ensureDirExists(dir) { if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } } // Create a version analyzer script function createAnalyzerScript(version) { const content = ` #!/usr/bin/env node const { parse } = require('meld-ast'); const fs = require('fs'); const path = require('path'); // Read in all test case files in the directory const testCasesDir = path.join('${CASES_DIR}'); const files = fs.readdirSync(testCasesDir) .filter(file => file.endsWith('.meld')); async function run() { console.log(\`Analyzing meld-ast \${process.argv[2] || 'current version'}...\`); for (const file of files) { const filePath = path.join(testCasesDir, file); const basename = path.basename(file, '.meld'); const content = fs.readFileSync(filePath, 'utf8'); try { console.log(\`Processing \${basename}...\`); const result = await parse(content, { preserveCodeFences: true, failFast: false, trackLocations: true, validateNodes: true }); // Save AST as JSON fs.writeFileSync( path.join('${CASES_DIR}', '${version}', \`\${basename}-ast.json\`), JSON.stringify(result, null, 2) ); console.log(\`Saved AST for \${basename}\`); } catch (error) { console.error(\`Error processing \${basename}:\`, error); fs.writeFileSync( path.join('${CASES_DIR}', '${version}', \`\${basename}-error.log\`), error.toString() ); } } } run().catch(console.error); `; const scriptPath = path.join(CASES_DIR, version, 'analyze.js'); fs.writeFileSync(scriptPath, content); try { execSync(`chmod +x ${scriptPath}`); } catch (error) { console.warn('Could not make script executable:', error); } } // Main function function main() { // Create directories ensureDirExists(COMPARISON_DIR); ensureDirExists(CASES_DIR); ensureDirExists(path.join(CASES_DIR, '3.0.1')); ensureDirExists(path.join(CASES_DIR, '3.3.0')); // Create test case files for (const testCase of TEST_CASES) { const filePath = path.join(CASES_DIR, `${testCase.name}.meld`); fs.writeFileSync(filePath, testCase.content); console.log(`Created test case: ${testCase.name}`); } // Create README with test case descriptions let readme = '# Specific Test Cases\n\n'; readme += 'This directory contains test cases designed to highlight specific differences between meld-ast 3.0.1 and 3.3.0.\n\n'; for (const testCase of TEST_CASES) { readme += `## ${testCase.name}\n\n`; readme += `${testCase.description}\n\n`; readme += '```meld\n' + testCase.content + '\n```\n\n'; } fs.writeFileSync(path.join(CASES_DIR, 'README.md'), readme); // Create analyzer scripts for each version createAnalyzerScript('3.0.1'); createAnalyzerScript('3.3.0'); // Create a script to compare results const compareScript = ` #!/usr/bin/env node const fs = require('fs'); const path = require('path'); const CASES_DIR = path.join(process.cwd(), 'meld-ast-comparison', 'specific-cases'); // Get all test case files const testFiles = fs.readdirSync(CASES_DIR) .filter(file => file.endsWith('.meld')) .map(file => path.basename(file, '.meld')); // Generate a comparison report let report = '# AST Comparison Report\\n\\n'; report += 'Comparison of meld-ast 3.0.1 vs 3.3.0 for specific test cases\\n\\n'; for (const testName of testFiles) { report += \`## \${testName}\\n\\n\`; const ast301Path = path.join(CASES_DIR, '3.0.1', \`\${testName}-ast.json\`); const ast330Path = path.join(CASES_DIR, '3.3.0', \`\${testName}-ast.json\`); if (!fs.existsSync(ast301Path) || !fs.existsSync(ast330Path)) { report += \`Could not compare ASTs - one or both files missing.\\n\\n\`; continue; } try { const ast301 = JSON.parse(fs.readFileSync(ast301Path, 'utf8')); const ast330 = JSON.parse(fs.readFileSync(ast330Path, 'utf8')); // Simple comparison focusing on array notation const arrayNotationDiffs = findArrayNotationDiffs(ast301, ast330); if (arrayNotationDiffs.length > 0) { report += \`### Array Notation Differences\\n\\n\`; arrayNotationDiffs.forEach(diff => { report += \`- \${diff}\\n\`; }); } else { report += \`No significant array notation differences detected.\\n\`; } } catch (error) { report += \`Error comparing ASTs: \${error.message}\\n\`; } report += \`\\n---\\n\\n\`; } fs.writeFileSync(path.join(CASES_DIR, 'comparison-report.md'), report); console.log('Generated comparison report'); // Find differences in array notation function findArrayNotationDiffs(ast1, ast2) { const diffs = []; // Helper to find all array accesses function findArrayAccesses(ast) { const results = []; function traverse(node, path = '') { if (!node || typeof node !== 'object') return; // Check if this is an array access node if ((node.type === 'MemberExpression' && node.computed === true) || node.type === 'ComputedMemberExpression') { results.push({ node, path }); } // Traverse children for (const key in node) { if (Array.isArray(node[key])) { node[key].forEach((child, i) => traverse(child, \`\${path}.\${key}[\${i}]\`)); } else if (node[key] && typeof node[key] === 'object') { traverse(node[key], \`\${path}.\${key}\`); } } } if (ast.ast) { ast.ast.forEach((node, i) => traverse(node, \`ast[\${i}]\`)); } return results; } const accesses1 = findArrayAccesses(ast1); const accesses2 = findArrayAccesses(ast2); // Compare counts if (accesses1.length !== accesses2.length) { diffs.push(\`Number of array access expressions differs: \${accesses1.length} vs \${accesses2.length}\`); } // Check for type differences in array accesses const minLength = Math.min(accesses1.length, accesses2.length); for (let i = 0; i < minLength; i++) { const access1 = accesses1[i].node; const access2 = accesses2[i].node; if (access1.type !== access2.type) { diffs.push(\`Array access type changed from \${access1.type} to \${access2.type}\`); } if (access1.property && access2.property && access1.property.type !== access2.property.type) { diffs.push(\`Array property type changed from \${access1.property.type} to \${access2.property.type}\`); } } return diffs; } `; const compareScriptPath = path.join(CASES_DIR, 'compare-results.js'); fs.writeFileSync(compareScriptPath, compareScript); try { execSync(`chmod +x ${compareScriptPath}`); } catch (error) { console.warn('Could not make script executable:', error); } console.log('\nTest cases and scripts created successfully.'); console.log('\nNow you can:'); console.log('1. Install meld-ast@3.0.1 and run node meld-ast-comparison/specific-cases/3.0.1/analyze.js'); console.log('2. Install meld-ast@3.3.0 and run node meld-ast-comparison/specific-cases/3.3.0/analyze.js'); console.log('3. Run node meld-ast-comparison/specific-cases/compare-results.js to generate a comparison report'); } main();