UNPKG

watr

Version:

Light & fast WAT compiler – WebAssembly Text to binary, parse, print, transform

136 lines (117 loc) 4.21 kB
#!/usr/bin/env node /** * watr CLI - WebAssembly Text Format compiler * * Usage: * watr input.wat # compile to input.wasm * watr input.wat -o output.wasm # compile to output.wasm * watr input.wat --print # pretty-print WAT * watr input.wat --minify # minify WAT * watr input.wat --polyfill # polyfill newer features to MVP * watr --help # show help * * @module watr/bin */ import { readFileSync, writeFileSync } from 'fs' import { basename } from 'path' import compile from '../src/compile.js' import print from '../src/print.js' import polyfill from '../src/polyfill.js' import optimize from '../src/optimize.js' import parse from '../src/parse.js' const args = process.argv.slice(2) // Parse polyfill option first (to exclude feature arg from files) let polyfillOpts = null const polyfillIdx = args.findIndex(a => a === '--polyfill') let polyfillFeatureArg = null if (polyfillIdx !== -1) { // Check if next arg is feature list (not a flag or file) const next = args[polyfillIdx + 1] if (next && !next.startsWith('-') && !next.includes('.') && next !== '-') { polyfillOpts = next polyfillFeatureArg = next } else { polyfillOpts = true } } // Parse optimize option let optimizeOpts = null const optimizeIdx = args.findIndex(a => a === '-O' || a === '--optimize') let optimizeFeatureArg = null if (optimizeIdx !== -1) { const next = args[optimizeIdx + 1] if (next && !next.startsWith('-') && !next.includes('.') && next !== '-') { optimizeOpts = next optimizeFeatureArg = next } else { optimizeOpts = true } } // Parse -o output arg const outIdx = args.findIndex(a => a === '-o' || a === '--output') const outArg = outIdx !== -1 ? args[outIdx + 1] : null const flags = new Set(args.filter(a => a.startsWith('-') && a !== '-')) const files = args.filter(a => (!a.startsWith('-') || a === '-') && a !== polyfillFeatureArg && a !== optimizeFeatureArg && a !== outArg) // Help if (flags.has('-h') || flags.has('--help') || !files.length) { console.log(` watr - Light & fast WAT compiler Usage: watr <input.wat> [options] Options: -o, --output <file> Output file (default: input.wasm) -p, --print Pretty-print WAT to stdout -m, --minify Minify WAT to stdout -O, --optimize [opts] Optimize AST (default: all) Options: fold identity strength branch propagate inline deadcode locals treeshake --polyfill [features] Polyfill newer features to MVP (default: all) Features: funcref sign_ext nontrapping bulk_memory return_call i31ref extended_const multi_value -h, --help Show this help Examples: watr add.wat # → add.wasm watr add.wat -o lib/add.wasm # → lib/add.wasm watr add.wat --print # pretty-print watr add.wat -O # optimize all watr add.wat -O treeshake # optimize specific watr add.wat --polyfill # polyfill all features watr add.wat --polyfill funcref # polyfill specific features cat add.wat | watr - # stdin → stdout (binary) ॐ `) process.exit(flags.has('-h') || flags.has('--help') ? 0 : 1) } // Input const input = files[0] const src = input === '-' ? readFileSync(0, 'utf8') : readFileSync(input, 'utf8') // Parse and transform let ast = parse(src) if (polyfillOpts) ast = polyfill(ast, polyfillOpts) if (optimizeOpts) ast = optimize(ast, optimizeOpts) // Print mode if (flags.has('-p') || flags.has('--print')) { console.log(print(ast, { indent: ' ', newline: '\n' })) process.exit(0) } // Minify mode if (flags.has('-m') || flags.has('--minify')) { console.log(print(ast, { indent: '', newline: '' })) process.exit(0) } // Compile mode const binary = compile(ast) // Output const output = outIdx !== -1 && args[outIdx + 1] ? args[outIdx + 1] : input === '-' ? null : input.replace(/\.wat$/, '') + '.wasm' if (output) { writeFileSync(output, binary) console.error(`✓ ${basename(output)} (${binary.length} bytes)`) } else { process.stdout.write(binary) }