分享 文言文編程語言 现已支持 Ruby

chrishyman · 2019年12月20日 · 最后由 zzz6519003 回复于 2019年12月23日 · 4751 次阅读

大家可以用这个语言念诗了(大雾)。

https://github.com/LingDong-/wenyan-lang

吾有一數。曰三。名之曰「甲」

gwq 回复

jia3 = 3 LOL

看这项目的 issue,也是人才辈出

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;
}

做这个东西不知道有什么意义,感觉很丑

zzz6519003 回复

这块要重构,另一份分支做了每个操作符的切分重构。抽象每个 operator 然后上单元测试,在作者之前的代码基础上加 Rust 支持的时候就挺麻烦,所以并行了重构分支和 Rust support 分支。

chrishyman 回复

有测试就好了 加油!

需要 登录 后方可回复, 如果你还没有账号请 注册新账号