大家可以用这个语言念诗了(大雾)。
function asc2rb(asc) {
let rb = rblib;
let prevfun = "";
let curlvl = 0;
let strayvar = 0;
let lambdaList = [];
let methodIndex = 0;
asc = lowerAllPinYinAndMakeItGlobal(asc);
// console.log("START!",asc)
function getval(x) {
if (!x) return "";
if (x[0] == "ans") {
strayvar = 0;
return currTmpVar();
}
if (x[0] == "iden") return rename(x[1]);
if (x[1] == undefined) return "nil";
return x[1];
}
for (let i = 0; i < asc.length; i++) {
let a = asc[i];
if (a.args) console.log(a.args, a, "+++++++=======++++_____");
if (a.op == "var") {
for (let j = 0; j < a.count; j++) {
if (a.values[j] == undefined) {
a.values[j] = [];
}
let name = a.names[j];
if (a.type == "fun") {
prevfun = name;
continue;
}
let value = getval(a.values[j]);
if (name == undefined) {
name = nextTmpVar();
strayvar++;
}
if ([undefined, "nil"].includes(value)) {
if (a.type == "arr") {
value = "Ctnr.new";
} else if (a.type == "num") {
value = "0";
} else if (a.type == "str") {
value = `""`;
} else if (a.type == "bol") {
value = "false";
}
}
rb += "\t".repeat(curlvl);
rb += `${name}=${value}\n`;
}
} else if (a.op == "print") {
rb += "\t".repeat(curlvl);
rb += `p([`;
for (let j = 0; j < strayvar; j++) {
rb += `${prevTmpVar(strayvar - j)}.to_s`;
if (j != strayvar - 1) {
rb += ",";
}
}
rb += "].join)\n";
strayvar = 0;
} else if (a.op == "fun") {
rb += "\t".repeat(curlvl);
let argsStr = a.args.map(arg => arg.name).join(",");
if (methodIndex == 0) {
rb += `def ${prevfun}(${argsStr})`;
} else {
lambdaList.push(prevfun);
rb += `${prevfun} = proc {|${argsStr}|`;
}
methodIndex++;
} else if (a.op == "funbody") {
rb += "\t".repeat(curlvl);
if (asc[i - 1].op != "fun") {
if (methodIndex == 0) {
rb += `def ${prevfun}()`;
} else {
lambdaList.push(prevfun);
rb += `${prevfun} = proc {|_|`;
}
methodIndex++;
}
rb += "\n";
curlvl++;
} else if (a.op == "funend") {
curlvl--;
methodIndex--;
if (methodIndex == 0) {
rb += `${"\t".repeat(curlvl)}end\n`;
} else {
rb += `${"\t".repeat(curlvl)}}`;
}
rb += "\n";
} else if (a.op == "end") {
curlvl--;
rb += `${"\t".repeat(curlvl)}end \n`;
} else if (a.op == "if") {
rb += "\t".repeat(curlvl);
rb += "if ";
let j = 0;
while (j < a.test.length) {
if (a.test[j][0] == "cmp") {
rb += a.test[j][1];
} else if (a.test[j][0] == "ctnr") {
if (a.test[j][1] == "subs") {
if (a.test[j + 1][1] == "rest") {
rb += ".slice(1)";
} else {
if (a.test[j + 1][0] == "lit") {
rb += "[" + a.test[j + 1][1] + "]";
} else {
rb += "[" + a.test[j + 1][1] + "-1]";
}
}
j++;
} else if (a.test[j][1] == "len") {
rb += ".length";
}
} else {
rb += a.test[j][1];
}
j++;
}
rb += "\n";
curlvl++;
} else if (a.op == "else") {
rb += "\t".repeat(curlvl - 1);
rb += "else\n";
} else if (a.op == "return") {
rb += "\t".repeat(curlvl);
rb += `return ${getval(a.value)}\n`;
} else if (a.op.startsWith("op")) {
rb += "\t".repeat(curlvl);
let lhs = getval(a.lhs);
let rhs = getval(a.rhs);
let op = a.op.slice(2);
if (op in lop) {
op = lop[op];
}
rb += `${nextTmpVar()}=${lhs}${op}${rhs}\n`;
strayvar++;
} else if (a.op == "name") {
for (let j = 0; j < a.names.length; j++) {
rb += "\t".repeat(curlvl);
rb += `${a.names[j]}=${prevTmpVar(strayvar - j)}\n`;
}
strayvar -= a.names.length;
} else if (a.op == "call") {
rb += "\t".repeat(curlvl);
let functionCallStr = `${a.fun}(${a.args.map(x => getval(x)).join(",")})`;
if (lambdaList.includes(a.fun)) {
functionCallStr = `${a.fun}.call(${a.args
.map(x => getval(x))
.join(",")})`;
}
rb += `${nextTmpVar()}=${functionCallStr}\n`;
strayvar++;
} else if (a.op == "subscript") {
rb += "\t".repeat(curlvl);
let idx = getval(a.value);
if (idx == "rest") {
rb += `${nextTmpVar()}=${a.container}.slice(1)\n`;
strayvar++;
} else {
rb += `${nextTmpVar()}=${a.container}[${idx}${
a.value[0] == "lit" ? "" : "-1"
}]\n`;
strayvar++;
}
} else if (a.op == "cat") {
rb += "\t".repeat(curlvl);
rb +=
`${nextTmpVar()}=${a.containers[0]}.concat(` +
a.containers.slice(1).join(").concat(") +
")\n";
strayvar++;
} else if (a.op == "push") {
rb += "\t".repeat(curlvl);
rb += `${a.container}.push(${a.values.map(x => getval(x)).join(",")})\n`;
} else if (a.op == "for") {
rb += "\t".repeat(curlvl);
rb += `${a.container}.each do |${a.iterator.toLowerCase()}|\n`;
curlvl++;
} else if (a.op == "whiletrue") {
rb += "\t".repeat(curlvl);
rb += "while true do\n";
curlvl++;
} else if (a.op == "whilen") {
rb += "\t".repeat(curlvl);
let v = randVar();
rb += `${getval(a.value)}.times do |${v}|\n`;
curlvl++;
} else if (a.op == "break") {
rb += "\t".repeat(curlvl);
rb += "break\n";
} else if (a.op == "not") {
rb += "\t".repeat(curlvl);
let v = getval(a.value);
rb += `${nextTmpVar()}=!${v}\n`;
strayvar++;
} else if (a.op == "reassign") {
rb += "\t".repeat(curlvl);
let rhs = getval(a.rhs);
let lhs = getval(a.lhs);
if (a.lhssubs) {
lhs += `[${a.lhssubs[1]}${a.lhssubs[0] == "lit" ? "" : "-1"}]`;
}
rb += `${lhs}=${rhs}\n`;
} else if (a.op == "discard") {
strayvar = 0;
} else if (a.op == "length") {
rb += `${nextTmpVar()}=${a.container}.length;`;
strayvar++;
} else if (a.op == "comment") {
rb += "\t".repeat(curlvl);
rb += `# ${getval(a.value)}\n`;
rb += "\t".repeat(curlvl);
} else {
// console.log(a.op)
}
}
return rb;
}
这块要重构,另一份分支做了每个操作符的切分重构。抽象每个 operator 然后上单元测试,在作者之前的代码基础上加 Rust 支持的时候就挺麻烦,所以并行了重构分支和 Rust support 分支。