lowleveljs
Version:
1. 使用`@babel/parser`解析出js代码的语法树 2. 把所有的功能语句编译成最基础的操作指令列表 3. 编写解释器来运行这些基础操作指令
65 lines (59 loc) • 2.05 kB
JavaScript
// lljs --mask 123456 --compile-es5 test.js --out test.bin
// lljs --mask 123456 --run test.bin
const p=process.argv.slice(2)
let opts={}
for(let i=0; i<p.length; i++) {
if(p[i]==='--version') {
console.log('version: '+require(__dirname+'/package.json').version)
process.exit()
}
if(p[i]==='--mask') opts.mask=p[++i]
if(p[i]==='--run') opts.run=p[++i]
if(p[i]==='--compile-es5') opts.compileFilename=p[++i]
if(p[i]==='--out') opts.out=p[++i]
if(p[i]==='--params') {
const node=process.argv[0]
process.argv.splice(0, i+3)
process.argv.unshift(node, opts.run)
break
}
// 以下为实验参数,不展示在README.md中
// * 1. 特定前缀表达式转换为随机变量名字
if(p[i]==='--replace-prefix') opts.repVars=p[++i]
// * 2. 文件内容读取之后,先转换成es5语法
if(p[i]==='--transform') opts.transform=1
// * 3. 使用uglifyjs混淆源码
if(p[i]==='--use-uglifyjs') opts.uglifyjs=1
}
const fl=(...a)=>require('fs').readFileSync(...a)
const {compile, run, _compile}=require(__dirname)
if(opts.run) {
run(opts.mask, opts.run)
}else if(opts.compileFilename) {
if(!opts.out) {
console.log('必须指定输出文件名:--out 文件名')
process.exit(1)
}
let sourceCode=fl(opts.compileFilename, 'utf8')
const {TXT, MEM, GVARS, SEQ, BIN}=_compile(sourceCode, opts)
console.log('预编译结果 <数字(表示MEM的下标,或者该指令的特殊用法) 和 变量名称>:')
console.log(TXT)
console.log('='.repeat(32))
console.log('内存常量:')
console.log(MEM)
console.log('='.repeat(32))
console.log('全局变量:')
console.log(GVARS)
console.log('='.repeat(32))
console.log('打包后的结果:')
console.log(BIN)
console.log('='.repeat(32))
require('fs').writeFileSync(opts.out, Buffer.from(BIN))
console.log('保存完成')
}else{
console.log('不支持此用法,请查看README.md')
console.log()
console.log(require('fs').readFileSync(__dirname+'/README.md', 'utf8'))
process.exit()
}