/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/

var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJS = (cb, mod) => function __require() {
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// node_modules/readline-sync/lib/readline-sync.js
var require_readline_sync = __commonJS({
  "node_modules/readline-sync/lib/readline-sync.js"(exports) {
    "use strict";
    var IS_WIN = process.platform === "win32";
    var ALGORITHM_CIPHER = "aes-256-cbc";
    var ALGORITHM_HASH = "sha256";
    var DEFAULT_ERR_MSG = "The current environment doesn't support interactive reading from TTY.";
    var fs3 = require("fs");
    var TTY = process.binding("tty_wrap").TTY;
    var childProc = require("child_process");
    var pathUtil = require("path");
    var defaultOptions = {
      prompt: "> ",
      hideEchoBack: false,
      mask: "*",
      limit: [],
      limitMessage: "Input another, please.$<( [)limit(])>",
      defaultInput: "",
      trueValue: [],
      falseValue: [],
      caseSensitive: false,
      keepWhitespace: false,
      encoding: "utf8",
      bufferSize: 1024,
      print: void 0,
      history: true,
      cd: false,
      phContent: void 0,
      preCheck: void 0
    };
    var fdR = "none";
    var fdW;
    var ttyR;
    var isRawMode = false;
    var extHostPath;
    var extHostArgs;
    var tempdir;
    var salt = 0;
    var lastInput = "";
    var inputHistory = [];
    var rawInput;
    var _DBG_useExt = false;
    var _DBG_checkOptions = false;
    var _DBG_checkMethod = false;
    function getHostArgs(options) {
      function encodeArg(arg) {
        return arg.replace(/[^\w\u0080-\uFFFF]/g, function(chr) {
          return "#" + chr.charCodeAt(0) + ";";
        });
      }
      return extHostArgs.concat(function(conf) {
        var args = [];
        Object.keys(conf).forEach(function(optionName) {
          if (conf[optionName] === "boolean") {
            if (options[optionName]) {
              args.push("--" + optionName);
            }
          } else if (conf[optionName] === "string") {
            if (options[optionName]) {
              args.push("--" + optionName, encodeArg(options[optionName]));
            }
          }
        });
        return args;
      }({
        display: "string",
        displayOnly: "boolean",
        keyIn: "boolean",
        hideEchoBack: "boolean",
        mask: "string",
        limit: "string",
        caseSensitive: "boolean"
      }));
    }
    function _execFileSync(options, execOptions) {
      function getTempfile(name) {
        var filepath, suffix = "", fd;
        tempdir = tempdir || require("os").tmpdir();
        while (true) {
          filepath = pathUtil.join(tempdir, name + suffix);
          try {
            fd = fs3.openSync(filepath, "wx");
          } catch (e) {
            if (e.code === "EEXIST") {
              suffix++;
              continue;
            } else {
              throw e;
            }
          }
          fs3.closeSync(fd);
          break;
        }
        return filepath;
      }
      var hostArgs, shellPath, shellArgs, res = {}, exitCode, extMessage, pathStdout = getTempfile("readline-sync.stdout"), pathStderr = getTempfile("readline-sync.stderr"), pathExit = getTempfile("readline-sync.exit"), pathDone = getTempfile("readline-sync.done"), crypto = require("crypto"), shasum, decipher, password;
      shasum = crypto.createHash(ALGORITHM_HASH);
      shasum.update("" + process.pid + salt++ + Math.random());
      password = shasum.digest("hex");
      decipher = crypto.createDecipher(ALGORITHM_CIPHER, password);
      hostArgs = getHostArgs(options);
      if (IS_WIN) {
        shellPath = process.env.ComSpec || "cmd.exe";
        process.env.Q = '"';
        shellArgs = [
          "/V:ON",
          "/S",
          "/C",
          "(%Q%" + shellPath + "%Q% /V:ON /S /C %Q%%Q%" + extHostPath + "%Q%" + hostArgs.map(function(arg) {
            return " %Q%" + arg + "%Q%";
          }).join("") + " & (echo !ERRORLEVEL!)>%Q%" + pathExit + "%Q%%Q%) 2>%Q%" + pathStderr + "%Q% |%Q%" + process.execPath + "%Q% %Q%" + __dirname + "\\encrypt.js%Q% %Q%" + ALGORITHM_CIPHER + "%Q% %Q%" + password + "%Q% >%Q%" + pathStdout + "%Q% & (echo 1)>%Q%" + pathDone + "%Q%"
        ];
      } else {
        shellPath = "/bin/sh";
        shellArgs = [
          "-c",
          '("' + extHostPath + '"' + hostArgs.map(function(arg) {
            return " '" + arg.replace(/'/g, "'\\''") + "'";
          }).join("") + '; echo $?>"' + pathExit + '") 2>"' + pathStderr + '" |"' + process.execPath + '" "' + __dirname + '/encrypt.js" "' + ALGORITHM_CIPHER + '" "' + password + '" >"' + pathStdout + '"; echo 1 >"' + pathDone + '"'
        ];
      }
      if (_DBG_checkMethod) {
        _DBG_checkMethod("_execFileSync", hostArgs);
      }
      try {
        childProc.spawn(shellPath, shellArgs, execOptions);
      } catch (e) {
        res.error = new Error(e.message);
        res.error.method = "_execFileSync - spawn";
        res.error.program = shellPath;
        res.error.args = shellArgs;
      }
      while (fs3.readFileSync(pathDone, { encoding: options.encoding }).trim() !== "1") {
      }
      if ((exitCode = fs3.readFileSync(pathExit, { encoding: options.encoding }).trim()) === "0") {
        res.input = decipher.update(
          fs3.readFileSync(pathStdout, { encoding: "binary" }),
          "hex",
          options.encoding
        ) + decipher.final(options.encoding);
      } else {
        extMessage = fs3.readFileSync(pathStderr, { encoding: options.encoding }).trim();
        res.error = new Error(DEFAULT_ERR_MSG + (extMessage ? "\n" + extMessage : ""));
        res.error.method = "_execFileSync";
        res.error.program = shellPath;
        res.error.args = shellArgs;
        res.error.extMessage = extMessage;
        res.error.exitCode = +exitCode;
      }
      fs3.unlinkSync(pathStdout);
      fs3.unlinkSync(pathStderr);
      fs3.unlinkSync(pathExit);
      fs3.unlinkSync(pathDone);
      return res;
    }
    function readlineExt(options) {
      var hostArgs, res = {}, extMessage, execOptions = { env: process.env, encoding: options.encoding };
      if (!extHostPath) {
        if (IS_WIN) {
          if (process.env.PSModulePath) {
            extHostPath = "powershell.exe";
            extHostArgs = ["-ExecutionPolicy", "Bypass", "-File", __dirname + "\\read.ps1"];
          } else {
            extHostPath = "cscript.exe";
            extHostArgs = ["//nologo", __dirname + "\\read.cs.js"];
          }
        } else {
          extHostPath = "/bin/sh";
          extHostArgs = [__dirname + "/read.sh"];
        }
      }
      if (IS_WIN && !process.env.PSModulePath) {
        execOptions.stdio = [process.stdin];
      }
      if (childProc.execFileSync) {
        hostArgs = getHostArgs(options);
        if (_DBG_checkMethod) {
          _DBG_checkMethod("execFileSync", hostArgs);
        }
        try {
          res.input = childProc.execFileSync(extHostPath, hostArgs, execOptions);
        } catch (e) {
          extMessage = e.stderr ? (e.stderr + "").trim() : "";
          res.error = new Error(DEFAULT_ERR_MSG + (extMessage ? "\n" + extMessage : ""));
          res.error.method = "execFileSync";
          res.error.program = extHostPath;
          res.error.args = hostArgs;
          res.error.extMessage = extMessage;
          res.error.exitCode = e.status;
          res.error.code = e.code;
          res.error.signal = e.signal;
        }
      } else {
        res = _execFileSync(options, execOptions);
      }
      if (!res.error) {
        res.input = res.input.replace(/^\s*'|'\s*$/g, "");
        options.display = "";
      }
      return res;
    }
    function _readlineSync(options) {
      var input = "", displaySave = options.display, silent = !options.display && options.keyIn && options.hideEchoBack && !options.mask;
      function tryExt() {
        var res = readlineExt(options);
        if (res.error) {
          throw res.error;
        }
        return res.input;
      }
      if (_DBG_checkOptions) {
        _DBG_checkOptions(options);
      }
      (function() {
        var fsB, constants, verNum;
        function getFsB() {
          if (!fsB) {
            fsB = process.binding("fs");
            constants = process.binding("constants");
          }
          return fsB;
        }
        if (typeof fdR !== "string") {
          return;
        }
        fdR = null;
        if (IS_WIN) {
          verNum = function(ver) {
            var nums = ver.replace(/^\D+/, "").split(".");
            var verNum2 = 0;
            if (nums[0] = +nums[0]) {
              verNum2 += nums[0] * 1e4;
            }
            if (nums[1] = +nums[1]) {
              verNum2 += nums[1] * 100;
            }
            if (nums[2] = +nums[2]) {
              verNum2 += nums[2];
            }
            return verNum2;
          }(process.version);
          if (!(verNum >= 20302 && verNum < 40204 || verNum >= 5e4 && verNum < 50100 || verNum >= 50600 && verNum < 60200) && process.stdin.isTTY) {
            process.stdin.pause();
            fdR = process.stdin.fd;
            ttyR = process.stdin._handle;
          } else {
            try {
              fdR = getFsB().open("CONIN$", constants.O_RDWR, parseInt("0666", 8));
              ttyR = new TTY(fdR, true);
            } catch (e) {
            }
          }
          if (process.stdout.isTTY) {
            fdW = process.stdout.fd;
          } else {
            try {
              fdW = fs3.openSync("\\\\.\\CON", "w");
            } catch (e) {
            }
            if (typeof fdW !== "number") {
              try {
                fdW = getFsB().open("CONOUT$", constants.O_RDWR, parseInt("0666", 8));
              } catch (e) {
              }
            }
          }
        } else {
          if (process.stdin.isTTY) {
            process.stdin.pause();
            try {
              fdR = fs3.openSync("/dev/tty", "r");
              ttyR = process.stdin._handle;
            } catch (e) {
            }
          } else {
            try {
              fdR = fs3.openSync("/dev/tty", "r");
              ttyR = new TTY(fdR, false);
            } catch (e) {
            }
          }
          if (process.stdout.isTTY) {
            fdW = process.stdout.fd;
          } else {
            try {
              fdW = fs3.openSync("/dev/tty", "w");
            } catch (e) {
            }
          }
        }
      })();
      (function() {
        var atEol, limit, isCooked = !options.hideEchoBack && !options.keyIn, buffer, reqSize, readSize, chunk, line;
        rawInput = "";
        function setRawMode(mode) {
          if (mode === isRawMode) {
            return true;
          }
          if (ttyR.setRawMode(mode) !== 0) {
            return false;
          }
          isRawMode = mode;
          return true;
        }
        if (_DBG_useExt || !ttyR || typeof fdW !== "number" && (options.display || !isCooked)) {
          input = tryExt();
          return;
        }
        if (options.display) {
          fs3.writeSync(fdW, options.display);
          options.display = "";
        }
        if (options.displayOnly) {
          return;
        }
        if (!setRawMode(!isCooked)) {
          input = tryExt();
          return;
        }
        reqSize = options.keyIn ? 1 : options.bufferSize;
        buffer = Buffer.allocUnsafe && Buffer.alloc ? Buffer.alloc(reqSize) : new Buffer(reqSize);
        if (options.keyIn && options.limit) {
          limit = new RegExp(
            "[^" + options.limit + "]",
            "g" + (options.caseSensitive ? "" : "i")
          );
        }
        while (true) {
          readSize = 0;
          try {
            readSize = fs3.readSync(fdR, buffer, 0, reqSize);
          } catch (e) {
            if (e.code !== "EOF") {
              setRawMode(false);
              input += tryExt();
              return;
            }
          }
          if (readSize > 0) {
            chunk = buffer.toString(options.encoding, 0, readSize);
            rawInput += chunk;
          } else {
            chunk = "\n";
            rawInput += String.fromCharCode(0);
          }
          if (chunk && typeof (line = (chunk.match(/^(.*?)[\r\n]/) || [])[1]) === "string") {
            chunk = line;
            atEol = true;
          }
          if (chunk) {
            chunk = chunk.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "");
          }
          if (chunk && limit) {
            chunk = chunk.replace(limit, "");
          }
          if (chunk) {
            if (!isCooked) {
              if (!options.hideEchoBack) {
                fs3.writeSync(fdW, chunk);
              } else if (options.mask) {
                fs3.writeSync(fdW, new Array(chunk.length + 1).join(options.mask));
              }
            }
            input += chunk;
          }
          if (!options.keyIn && atEol || options.keyIn && input.length >= reqSize) {
            break;
          }
        }
        if (!isCooked && !silent) {
          fs3.writeSync(fdW, "\n");
        }
        setRawMode(false);
      })();
      if (options.print && !silent) {
        options.print(
          displaySave + (options.displayOnly ? "" : (options.hideEchoBack ? new Array(input.length + 1).join(options.mask) : input) + "\n"),
          options.encoding
        );
      }
      return options.displayOnly ? "" : lastInput = options.keepWhitespace || options.keyIn ? input : input.trim();
    }
    function flattenArray(array, validator) {
      var flatArray = [];
      function _flattenArray(array2) {
        if (array2 == null) {
          return;
        } else if (Array.isArray(array2)) {
          array2.forEach(_flattenArray);
        } else if (!validator || validator(array2)) {
          flatArray.push(array2);
        }
      }
      _flattenArray(array);
      return flatArray;
    }
    function escapePattern(pattern) {
      return pattern.replace(
        /[\x00-\x7f]/g,
        function(s) {
          return "\\x" + ("00" + s.charCodeAt().toString(16)).substr(-2);
        }
      );
    }
    function margeOptions() {
      var optionsList = Array.prototype.slice.call(arguments), optionNames, fromDefault;
      if (optionsList.length && typeof optionsList[0] === "boolean") {
        fromDefault = optionsList.shift();
        if (fromDefault) {
          optionNames = Object.keys(defaultOptions);
          optionsList.unshift(defaultOptions);
        }
      }
      return optionsList.reduce(function(options, optionsPart) {
        if (optionsPart == null) {
          return options;
        }
        if (optionsPart.hasOwnProperty("noEchoBack") && !optionsPart.hasOwnProperty("hideEchoBack")) {
          optionsPart.hideEchoBack = optionsPart.noEchoBack;
          delete optionsPart.noEchoBack;
        }
        if (optionsPart.hasOwnProperty("noTrim") && !optionsPart.hasOwnProperty("keepWhitespace")) {
          optionsPart.keepWhitespace = optionsPart.noTrim;
          delete optionsPart.noTrim;
        }
        if (!fromDefault) {
          optionNames = Object.keys(optionsPart);
        }
        optionNames.forEach(function(optionName) {
          var value;
          if (!optionsPart.hasOwnProperty(optionName)) {
            return;
          }
          value = optionsPart[optionName];
          switch (optionName) {
            case "mask":
            case "limitMessage":
            case "defaultInput":
            case "encoding":
              value = value != null ? value + "" : "";
              if (value && optionName !== "limitMessage") {
                value = value.replace(/[\r\n]/g, "");
              }
              options[optionName] = value;
              break;
            case "bufferSize":
              if (!isNaN(value = parseInt(value, 10)) && typeof value === "number") {
                options[optionName] = value;
              }
              break;
            case "displayOnly":
            case "keyIn":
            case "hideEchoBack":
            case "caseSensitive":
            case "keepWhitespace":
            case "history":
            case "cd":
              options[optionName] = !!value;
              break;
            case "limit":
            case "trueValue":
            case "falseValue":
              options[optionName] = flattenArray(value, function(value2) {
                var type = typeof value2;
                return type === "string" || type === "number" || type === "function" || value2 instanceof RegExp;
              }).map(function(value2) {
                return typeof value2 === "string" ? value2.replace(/[\r\n]/g, "") : value2;
              });
              break;
            case "print":
            case "phContent":
            case "preCheck":
              options[optionName] = typeof value === "function" ? value : void 0;
              break;
            case "prompt":
            case "display":
              options[optionName] = value != null ? value : "";
              break;
          }
        });
        return options;
      }, {});
    }
    function isMatched(res, comps, caseSensitive) {
      return comps.some(function(comp) {
        var type = typeof comp;
        return type === "string" ? caseSensitive ? res === comp : res.toLowerCase() === comp.toLowerCase() : type === "number" ? parseFloat(res) === comp : type === "function" ? comp(res) : comp instanceof RegExp ? comp.test(res) : false;
      });
    }
    function replaceHomePath(path6, expand) {
      var homePath = pathUtil.normalize(
        IS_WIN ? (process.env.HOMEDRIVE || "") + (process.env.HOMEPATH || "") : process.env.HOME || ""
      ).replace(/[\/\\]+$/, "");
      path6 = pathUtil.normalize(path6);
      return expand ? path6.replace(/^~(?=\/|\\|$)/, homePath) : path6.replace(new RegExp("^" + escapePattern(homePath) + "(?=\\/|\\\\|$)", IS_WIN ? "i" : ""), "~");
    }
    function replacePlaceholder(text, generator) {
      var PTN_INNER = "(?:\\(([\\s\\S]*?)\\))?(\\w+|.-.)(?:\\(([\\s\\S]*?)\\))?", rePlaceholder = new RegExp("(\\$)?(\\$<" + PTN_INNER + ">)", "g"), rePlaceholderCompat = new RegExp("(\\$)?(\\$\\{" + PTN_INNER + "\\})", "g");
      function getPlaceholderText(s, escape2, placeholder, pre, param, post) {
        var text2;
        return escape2 || typeof (text2 = generator(param)) !== "string" ? placeholder : text2 ? (pre || "") + text2 + (post || "") : "";
      }
      return text.replace(rePlaceholder, getPlaceholderText).replace(rePlaceholderCompat, getPlaceholderText);
    }
    function array2charlist(array, caseSensitive, collectSymbols) {
      var values, group3 = [], groupClass = -1, charCode = 0, symbols = "", suppressed;
      function addGroup(groups, group4) {
        if (group4.length > 3) {
          groups.push(group4[0] + "..." + group4[group4.length - 1]);
          suppressed = true;
        } else if (group4.length) {
          groups = groups.concat(group4);
        }
        return groups;
      }
      values = array.reduce(
        function(chars, value) {
          return chars.concat((value + "").split(""));
        },
        []
      ).reduce(function(groups, curChar) {
        var curGroupClass, curCharCode;
        if (!caseSensitive) {
          curChar = curChar.toLowerCase();
        }
        curGroupClass = /^\d$/.test(curChar) ? 1 : /^[A-Z]$/.test(curChar) ? 2 : /^[a-z]$/.test(curChar) ? 3 : 0;
        if (collectSymbols && curGroupClass === 0) {
          symbols += curChar;
        } else {
          curCharCode = curChar.charCodeAt(0);
          if (curGroupClass && curGroupClass === groupClass && curCharCode === charCode + 1) {
            group3.push(curChar);
          } else {
            groups = addGroup(groups, group3);
            group3 = [curChar];
            groupClass = curGroupClass;
          }
          charCode = curCharCode;
        }
        return groups;
      }, []);
      values = addGroup(values, group3);
      if (symbols) {
        values.push(symbols);
        suppressed = true;
      }
      return { values, suppressed };
    }
    function joinChunks(chunks, suppressed) {
      return chunks.join(chunks.length > 2 ? ", " : suppressed ? " / " : "/");
    }
    function getPhContent(param, options) {
      var text, values, resCharlist = {}, arg;
      if (options.phContent) {
        text = options.phContent(param, options);
      }
      if (typeof text !== "string") {
        switch (param) {
          case "hideEchoBack":
          case "mask":
          case "defaultInput":
          case "caseSensitive":
          case "keepWhitespace":
          case "encoding":
          case "bufferSize":
          case "history":
          case "cd":
            text = !options.hasOwnProperty(param) ? "" : typeof options[param] === "boolean" ? options[param] ? "on" : "off" : options[param] + "";
            break;
          case "limit":
          case "trueValue":
          case "falseValue":
            values = options[options.hasOwnProperty(param + "Src") ? param + "Src" : param];
            if (options.keyIn) {
              resCharlist = array2charlist(values, options.caseSensitive);
              values = resCharlist.values;
            } else {
              values = values.filter(function(value) {
                var type = typeof value;
                return type === "string" || type === "number";
              });
            }
            text = joinChunks(values, resCharlist.suppressed);
            break;
          case "limitCount":
          case "limitCountNotZero":
            text = options[options.hasOwnProperty("limitSrc") ? "limitSrc" : "limit"].length;
            text = text || param !== "limitCountNotZero" ? text + "" : "";
            break;
          case "lastInput":
            text = lastInput;
            break;
          case "cwd":
          case "CWD":
          case "cwdHome":
            text = process.cwd();
            if (param === "CWD") {
              text = pathUtil.basename(text);
            } else if (param === "cwdHome") {
              text = replaceHomePath(text);
            }
            break;
          case "date":
          case "time":
          case "localeDate":
          case "localeTime":
            text = new Date()["to" + param.replace(/^./, function(str) {
              return str.toUpperCase();
            }) + "String"]();
            break;
          default:
            if (typeof (arg = (param.match(/^history_m(\d+)$/) || [])[1]) === "string") {
              text = inputHistory[inputHistory.length - arg] || "";
            }
        }
      }
      return text;
    }
    function getPhCharlist(param) {
      var matches = /^(.)-(.)$/.exec(param), text = "", from, to, code, step;
      if (!matches) {
        return null;
      }
      from = matches[1].charCodeAt(0);
      to = matches[2].charCodeAt(0);
      step = from < to ? 1 : -1;
      for (code = from; code !== to + step; code += step) {
        text += String.fromCharCode(code);
      }
      return text;
    }
    function parseCl(cl) {
      var reToken = new RegExp(/(\s*)(?:("|')(.*?)(?:\2|$)|(\S+))/g), matches, taken = "", args = [], part;
      cl = cl.trim();
      while (matches = reToken.exec(cl)) {
        part = matches[3] || matches[4] || "";
        if (matches[1]) {
          args.push(taken);
          taken = "";
        }
        taken += part;
      }
      if (taken) {
        args.push(taken);
      }
      return args;
    }
    function toBool(res, options) {
      return options.trueValue.length && isMatched(res, options.trueValue, options.caseSensitive) ? true : options.falseValue.length && isMatched(res, options.falseValue, options.caseSensitive) ? false : res;
    }
    function getValidLine(options) {
      var res, forceNext, limitMessage, matches, histInput, args, resCheck;
      function _getPhContent(param) {
        return getPhContent(param, options);
      }
      function addDisplay(text) {
        options.display += (/[^\r\n]$/.test(options.display) ? "\n" : "") + text;
      }
      options.limitSrc = options.limit;
      options.displaySrc = options.display;
      options.limit = "";
      options.display = replacePlaceholder(options.display + "", _getPhContent);
      while (true) {
        res = _readlineSync(options);
        forceNext = false;
        limitMessage = "";
        if (options.defaultInput && !res) {
          res = options.defaultInput;
        }
        if (options.history) {
          if (matches = /^\s*\!(?:\!|-1)(:p)?\s*$/.exec(res)) {
            histInput = inputHistory[0] || "";
            if (matches[1]) {
              forceNext = true;
            } else {
              res = histInput;
            }
            addDisplay(histInput + "\n");
            if (!forceNext) {
              options.displayOnly = true;
              _readlineSync(options);
              options.displayOnly = false;
            }
          } else if (res && res !== inputHistory[inputHistory.length - 1]) {
            inputHistory = [res];
          }
        }
        if (!forceNext && options.cd && res) {
          args = parseCl(res);
          switch (args[0].toLowerCase()) {
            case "cd":
              if (args[1]) {
                try {
                  process.chdir(replaceHomePath(args[1], true));
                } catch (e) {
                  addDisplay(e + "");
                }
              }
              forceNext = true;
              break;
            case "pwd":
              addDisplay(process.cwd());
              forceNext = true;
              break;
          }
        }
        if (!forceNext && options.preCheck) {
          resCheck = options.preCheck(res, options);
          res = resCheck.res;
          if (resCheck.forceNext) {
            forceNext = true;
          }
        }
        if (!forceNext) {
          if (!options.limitSrc.length || isMatched(res, options.limitSrc, options.caseSensitive)) {
            break;
          }
          if (options.limitMessage) {
            limitMessage = replacePlaceholder(options.limitMessage, _getPhContent);
          }
        }
        addDisplay((limitMessage ? limitMessage + "\n" : "") + replacePlaceholder(options.displaySrc + "", _getPhContent));
      }
      return toBool(res, options);
    }
    exports._DBG_set_useExt = function(val) {
      _DBG_useExt = val;
    };
    exports._DBG_set_checkOptions = function(val) {
      _DBG_checkOptions = val;
    };
    exports._DBG_set_checkMethod = function(val) {
      _DBG_checkMethod = val;
    };
    exports._DBG_clearHistory = function() {
      lastInput = "";
      inputHistory = [];
    };
    exports.setDefaultOptions = function(options) {
      defaultOptions = margeOptions(true, options);
      return margeOptions(true);
    };
    exports.question = function(query, options) {
      return getValidLine(margeOptions(margeOptions(true, options), {
        display: query
      }));
    };
    exports.prompt = function(options) {
      var readOptions = margeOptions(true, options);
      readOptions.display = readOptions.prompt;
      return getValidLine(readOptions);
    };
    exports.keyIn = function(query, options) {
      var readOptions = margeOptions(margeOptions(true, options), {
        display: query,
        keyIn: true,
        keepWhitespace: true
      });
      readOptions.limitSrc = readOptions.limit.filter(function(value) {
        var type = typeof value;
        return type === "string" || type === "number";
      }).map(function(text) {
        return replacePlaceholder(text + "", getPhCharlist);
      });
      readOptions.limit = escapePattern(readOptions.limitSrc.join(""));
      ["trueValue", "falseValue"].forEach(function(optionName) {
        readOptions[optionName] = readOptions[optionName].reduce(function(comps, comp) {
          var type = typeof comp;
          if (type === "string" || type === "number") {
            comps = comps.concat((comp + "").split(""));
          } else {
            comps.push(comp);
          }
          return comps;
        }, []);
      });
      readOptions.display = replacePlaceholder(
        readOptions.display + "",
        function(param) {
          return getPhContent(param, readOptions);
        }
      );
      return toBool(_readlineSync(readOptions), readOptions);
    };
    exports.questionEMail = function(query, options) {
      if (query == null) {
        query = "Input e-mail address: ";
      }
      return exports.question(query, margeOptions({
        hideEchoBack: false,
        limit: /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/,
        limitMessage: "Input valid e-mail address, please.",
        trueValue: null,
        falseValue: null
      }, options, {
        keepWhitespace: false,
        cd: false
      }));
    };
    exports.questionNewPassword = function(query, options) {
      var resCharlist, min, max, readOptions = margeOptions({
        hideEchoBack: true,
        mask: "*",
        limitMessage: "It can include: $<charlist>\nAnd the length must be: $<length>",
        trueValue: null,
        falseValue: null,
        caseSensitive: true
      }, options, {
        history: false,
        cd: false,
        phContent: function(param) {
          return param === "charlist" ? resCharlist.text : param === "length" ? min + "..." + max : null;
        }
      }), charlist, confirmMessage, unmatchMessage, limit, limitMessage, res1, res2;
      options = options || {};
      charlist = replacePlaceholder(
        options.charlist ? options.charlist + "" : "$<!-~>",
        getPhCharlist
      );
      if (isNaN(min = parseInt(options.min, 10)) || typeof min !== "number") {
        min = 12;
      }
      if (isNaN(max = parseInt(options.max, 10)) || typeof max !== "number") {
        max = 24;
      }
      limit = new RegExp("^[" + escapePattern(charlist) + "]{" + min + "," + max + "}$");
      resCharlist = array2charlist([charlist], readOptions.caseSensitive, true);
      resCharlist.text = joinChunks(resCharlist.values, resCharlist.suppressed);
      confirmMessage = options.confirmMessage != null ? options.confirmMessage : "Reinput a same one to confirm it: ";
      unmatchMessage = options.unmatchMessage != null ? options.unmatchMessage : "It differs from first one. Hit only the Enter key if you want to retry from first one.";
      if (query == null) {
        query = "Input new password: ";
      }
      limitMessage = readOptions.limitMessage;
      while (!res2) {
        readOptions.limit = limit;
        readOptions.limitMessage = limitMessage;
        res1 = exports.question(query, readOptions);
        readOptions.limit = [res1, ""];
        readOptions.limitMessage = unmatchMessage;
        res2 = exports.question(confirmMessage, readOptions);
      }
      return res1;
    };
    function _questionNum(query, options, parser) {
      var validValue;
      function getValidValue(value) {
        validValue = parser(value);
        return !isNaN(validValue) && typeof validValue === "number";
      }
      exports.question(query, margeOptions({
        limitMessage: "Input valid number, please."
      }, options, {
        limit: getValidValue,
        cd: false
      }));
      return validValue;
    }
    exports.questionInt = function(query, options) {
      return _questionNum(query, options, function(value) {
        return parseInt(value, 10);
      });
    };
    exports.questionFloat = function(query, options) {
      return _questionNum(query, options, parseFloat);
    };
    exports.questionPath = function(query, options) {
      var validPath, error = "", readOptions = margeOptions({
        hideEchoBack: false,
        limitMessage: "$<error(\n)>Input valid path, please.$<( Min:)min>$<( Max:)max>",
        history: true,
        cd: true
      }, options, {
        keepWhitespace: false,
        limit: function(value) {
          var exists, stat, res;
          value = replaceHomePath(value, true);
          error = "";
          function mkdirParents(dirPath) {
            dirPath.split(/\/|\\/).reduce(function(parents, dir) {
              var path6 = pathUtil.resolve(parents += dir + pathUtil.sep);
              if (!fs3.existsSync(path6)) {
                fs3.mkdirSync(path6);
              } else if (!fs3.statSync(path6).isDirectory()) {
                throw new Error("Non directory already exists: " + path6);
              }
              return parents;
            }, "");
          }
          try {
            exists = fs3.existsSync(value);
            validPath = exists ? fs3.realpathSync(value) : pathUtil.resolve(value);
            if (!options.hasOwnProperty("exists") && !exists || typeof options.exists === "boolean" && options.exists !== exists) {
              error = (exists ? "Already exists" : "No such file or directory") + ": " + validPath;
              return false;
            }
            if (!exists && options.create) {
              if (options.isDirectory) {
                mkdirParents(validPath);
              } else {
                mkdirParents(pathUtil.dirname(validPath));
                fs3.closeSync(fs3.openSync(validPath, "w"));
              }
              validPath = fs3.realpathSync(validPath);
            }
            if (exists && (options.min || options.max || options.isFile || options.isDirectory)) {
              stat = fs3.statSync(validPath);
              if (options.isFile && !stat.isFile()) {
                error = "Not file: " + validPath;
                return false;
              } else if (options.isDirectory && !stat.isDirectory()) {
                error = "Not directory: " + validPath;
                return false;
              } else if (options.min && stat.size < +options.min || options.max && stat.size > +options.max) {
                error = "Size " + stat.size + " is out of range: " + validPath;
                return false;
              }
            }
            if (typeof options.validate === "function" && (res = options.validate(validPath)) !== true) {
              if (typeof res === "string") {
                error = res;
              }
              return false;
            }
          } catch (e) {
            error = e + "";
            return false;
          }
          return true;
        },
        phContent: function(param) {
          return param === "error" ? error : param !== "min" && param !== "max" ? null : options.hasOwnProperty(param) ? options[param] + "" : "";
        }
      });
      options = options || {};
      if (query == null) {
        query = 'Input path (you can "cd" and "pwd"): ';
      }
      exports.question(query, readOptions);
      return validPath;
    };
    function getClHandler(commandHandler, options) {
      var clHandler = {}, hIndex = {};
      if (typeof commandHandler === "object") {
        Object.keys(commandHandler).forEach(function(cmd) {
          if (typeof commandHandler[cmd] === "function") {
            hIndex[options.caseSensitive ? cmd : cmd.toLowerCase()] = commandHandler[cmd];
          }
        });
        clHandler.preCheck = function(res) {
          var cmdKey;
          clHandler.args = parseCl(res);
          cmdKey = clHandler.args[0] || "";
          if (!options.caseSensitive) {
            cmdKey = cmdKey.toLowerCase();
          }
          clHandler.hRes = cmdKey !== "_" && hIndex.hasOwnProperty(cmdKey) ? hIndex[cmdKey].apply(res, clHandler.args.slice(1)) : hIndex.hasOwnProperty("_") ? hIndex._.apply(res, clHandler.args) : null;
          return { res, forceNext: false };
        };
        if (!hIndex.hasOwnProperty("_")) {
          clHandler.limit = function() {
            var cmdKey = clHandler.args[0] || "";
            if (!options.caseSensitive) {
              cmdKey = cmdKey.toLowerCase();
            }
            return hIndex.hasOwnProperty(cmdKey);
          };
        }
      } else {
        clHandler.preCheck = function(res) {
          clHandler.args = parseCl(res);
          clHandler.hRes = typeof commandHandler === "function" ? commandHandler.apply(res, clHandler.args) : true;
          return { res, forceNext: false };
        };
      }
      return clHandler;
    }
    exports.promptCL = function(commandHandler, options) {
      var readOptions = margeOptions({
        hideEchoBack: false,
        limitMessage: "Requested command is not available.",
        caseSensitive: false,
        history: true
      }, options), clHandler = getClHandler(commandHandler, readOptions);
      readOptions.limit = clHandler.limit;
      readOptions.preCheck = clHandler.preCheck;
      exports.prompt(readOptions);
      return clHandler.args;
    };
    exports.promptLoop = function(inputHandler, options) {
      var readOptions = margeOptions({
        hideEchoBack: false,
        trueValue: null,
        falseValue: null,
        caseSensitive: false,
        history: true
      }, options);
      while (true) {
        if (inputHandler(exports.prompt(readOptions))) {
          break;
        }
      }
      return;
    };
    exports.promptCLLoop = function(commandHandler, options) {
      var readOptions = margeOptions({
        hideEchoBack: false,
        limitMessage: "Requested command is not available.",
        caseSensitive: false,
        history: true
      }, options), clHandler = getClHandler(commandHandler, readOptions);
      readOptions.limit = clHandler.limit;
      readOptions.preCheck = clHandler.preCheck;
      while (true) {
        exports.prompt(readOptions);
        if (clHandler.hRes) {
          break;
        }
      }
      return;
    };
    exports.promptSimShell = function(options) {
      return exports.prompt(margeOptions({
        hideEchoBack: false,
        history: true
      }, options, {
        prompt: function() {
          return IS_WIN ? "$<cwd>>" : (process.env.USER || "") + (process.env.HOSTNAME ? "@" + process.env.HOSTNAME.replace(/\..*$/, "") : "") + ":$<cwdHome>$ ";
        }()
      }));
    };
    function _keyInYN(query, options, limit) {
      var res;
      if (query == null) {
        query = "Are you sure? ";
      }
      if ((!options || options.guide !== false) && (query += "")) {
        query = query.replace(/\s*:?\s*$/, "") + " [y/n]: ";
      }
      res = exports.keyIn(query, margeOptions(options, {
        hideEchoBack: false,
        limit,
        trueValue: "y",
        falseValue: "n",
        caseSensitive: false
      }));
      return typeof res === "boolean" ? res : "";
    }
    exports.keyInYN = function(query, options) {
      return _keyInYN(query, options);
    };
    exports.keyInYNStrict = function(query, options) {
      return _keyInYN(query, options, "yn");
    };
    exports.keyInPause = function(query, options) {
      if (query == null) {
        query = "Continue...";
      }
      if ((!options || options.guide !== false) && (query += "")) {
        query = query.replace(/\s+$/, "") + " (Hit any key)";
      }
      exports.keyIn(query, margeOptions({
        limit: null
      }, options, {
        hideEchoBack: true,
        mask: ""
      }));
      return;
    };
    exports.keyInSelect = function(items, query, options) {
      var readOptions = margeOptions({
        hideEchoBack: false
      }, options, {
        trueValue: null,
        falseValue: null,
        caseSensitive: false,
        phContent: function(param) {
          return param === "itemsCount" ? items.length + "" : param === "firstItem" ? (items[0] + "").trim() : param === "lastItem" ? (items[items.length - 1] + "").trim() : null;
        }
      }), keylist = "", key2i = {}, charCode = 49, display = "\n";
      if (!Array.isArray(items) || !items.length || items.length > 35) {
        throw "`items` must be Array (max length: 35).";
      }
      items.forEach(function(item, i2) {
        var key = String.fromCharCode(charCode);
        keylist += key;
        key2i[key] = i2;
        display += "[" + key + "] " + (item + "").trim() + "\n";
        charCode = charCode === 57 ? 97 : charCode + 1;
      });
      if (!options || options.cancel !== false) {
        keylist += "0";
        key2i["0"] = -1;
        display += "[0] " + (options && options.cancel != null && typeof options.cancel !== "boolean" ? (options.cancel + "").trim() : "CANCEL") + "\n";
      }
      readOptions.limit = keylist;
      display += "\n";
      if (query == null) {
        query = "Choose one from list: ";
      }
      if (query += "") {
        if (!options || options.guide !== false) {
          query = query.replace(/\s*:?\s*$/, "") + " [$<limit>]: ";
        }
        display += query;
      }
      return key2i[exports.keyIn(display, readOptions).toLowerCase()];
    };
    exports.getRawInput = function() {
      return rawInput;
    };
    function _setOption(optionName, args) {
      var options;
      if (args.length) {
        options = {};
        options[optionName] = args[0];
      }
      return exports.setDefaultOptions(options)[optionName];
    }
    exports.setPrint = function() {
      return _setOption("print", arguments);
    };
    exports.setPrompt = function() {
      return _setOption("prompt", arguments);
    };
    exports.setEncoding = function() {
      return _setOption("encoding", arguments);
    };
    exports.setMask = function() {
      return _setOption("mask", arguments);
    };
    exports.setBufferSize = function() {
      return _setOption("bufferSize", arguments);
    };
  }
});

// node_modules/tau-prolog/modules/core.js
var require_core = __commonJS({
  "node_modules/tau-prolog/modules/core.js"(exports, module2) {
    (function() {
      var version = { major: 0, minor: 3, patch: 4, status: "beta" };
      function TauFile(name, type, parent, text) {
        text = text === void 0 ? "" : text;
        this.name = name;
        this.type = type;
        this.parent = parent;
        this.text = text;
        this.created = Date.now() / 1e3;
        this.modified = this.created;
      }
      TauFile.prototype.get = function(length, position) {
        if (position === this.text.length) {
          return "end_of_stream";
        } else if (position > this.text.length) {
          return "end_of_stream";
        } else {
          return this.text.substring(position, position + length);
        }
      };
      TauFile.prototype.eof = function(position) {
        return position === this.text.length;
      };
      TauFile.prototype.put = function(text, position) {
        if (position === "end_of_stream") {
          this.text += text;
          return true;
        } else if (position === "past_end_of_stream") {
          return null;
        } else {
          this.text = this.text.substring(0, position) + text + this.text.substring(position + text.length);
          return true;
        }
      };
      TauFile.prototype.get_byte = function(position) {
        if (position === "end_of_stream")
          return -1;
        var index = Math.floor(position / 2);
        if (this.text.length <= index)
          return -1;
        var code = codePointAt(this.text[Math.floor(position / 2)], 0);
        if (position % 2 === 0)
          return code & 255;
        else
          return code / 256 >>> 0;
      };
      TauFile.prototype.put_byte = function(byte, position) {
        var index = position === "end_of_stream" ? this.text.length : Math.floor(position / 2);
        if (this.text.length < index)
          return null;
        var code = this.text.length === index ? -1 : codePointAt(this.text[Math.floor(position / 2)], 0);
        if (position % 2 === 0) {
          code = code / 256 >>> 0;
          code = (code & 255) << 8 | byte & 255;
        } else {
          code = code & 255;
          code = (byte & 255) << 8 | code & 255;
        }
        if (this.text.length === index)
          this.text += fromCodePoint(code);
        else
          this.text = this.text.substring(0, index) + fromCodePoint(code) + this.text.substring(index + 1);
        return true;
      };
      TauFile.prototype.flush = function() {
        return true;
      };
      TauFile.prototype.close = function() {
        this.modified = Date.now() / 1e3;
        return true;
      };
      TauFile.prototype.size = function() {
        return this.text.length;
      };
      function TauDirectory(name, parent) {
        this.name = name;
        this.parent = parent;
        this.files = {};
        this.length = 0;
        this.created = Date.now() / 1e3;
        this.modified = this.created;
      }
      TauDirectory.prototype.lookup = function(file) {
        if (this.files.hasOwnProperty(file))
          return this.files[file];
        return null;
      };
      TauDirectory.prototype.push = function(name, file) {
        if (!this.files.hasOwnProperty(name))
          this.length++;
        this.files[name] = file;
        this.modified = Date.now() / 1e3;
      };
      TauDirectory.prototype.remove = function(name) {
        if (this.files.hasOwnProperty(name)) {
          this.length--;
          delete this.files[name];
          this.modified = Date.now() / 1e3;
        }
      };
      TauDirectory.prototype.empty = function() {
        return this.length === 0;
      };
      TauDirectory.prototype.size = function() {
        return 4096;
      };
      tau_file_system = {
        files: new TauDirectory("/", "/", null),
        open: function(path6, type, mode) {
          var dirs = path6.replace(/\/$/, "").split("/");
          var dir = tau_file_system.files;
          var name = dirs[dirs.length - 1];
          for (var i2 = 1; i2 < dirs.length - 1; i2++) {
            dir = dir.lookup(dirs[i2]);
            if (!pl.type.is_directory(dir))
              return null;
          }
          var file = dir.lookup(name);
          if (file === null) {
            if (mode === "read")
              return null;
            file = new TauFile(name, type, dir);
            dir.push(name, file);
          } else if (!pl.type.is_file(file)) {
            return null;
          }
          if (mode === "write")
            file.text = "";
          return file;
        },
        get: function(path6) {
          var dirs = path6.replace(/\/$/, "").split("/");
          var file = tau_file_system.files;
          for (var i2 = 1; i2 < dirs.length; i2++)
            if (pl.type.is_directory(file))
              file = file.lookup(dirs[i2]);
            else
              return null;
          return file;
        }
      };
      tau_user_input = {
        buffer: "",
        get: function(length, _) {
          var text;
          while (tau_user_input.buffer.length < length) {
            text = window.prompt();
            if (text.length === 0)
              return "end_of_stream";
            if (text) {
              tau_user_input.buffer += text;
            }
          }
          text = tau_user_input.buffer.substr(0, length);
          tau_user_input.buffer = tau_user_input.buffer.substr(length);
          return text;
        },
        eof: function(_) {
          return false;
        }
      };
      tau_user_output = {
        put: function(text, _) {
          console.log(text);
          return true;
        },
        flush: function() {
          return true;
        }
      };
      tau_user_error = {
        put: function(text, _) {
          (console.error || console.log)(text);
          return true;
        },
        flush: function() {
          return true;
        }
      };
      nodejs_file_system = {
        open: function(path6, type, mode) {
          var fd, fs3 = require("fs");
          if (mode === "read" && !fs3.existsSync(path6))
            return null;
          try {
            fd = fs3.openSync(path6, mode[0]);
          } catch (ex) {
            return false;
          }
          return {
            get: function(length, position) {
              var buffer = new Buffer(length);
              fs3.readSync(fd, buffer, 0, length, position);
              var end_of_file = true;
              var text = buffer.toString();
              for (var i2 = 0; i2 < length && end_of_file; i2++)
                end_of_file = text[i2] === "\0";
              return end_of_file ? "end_of_stream" : buffer.toString();
            },
            eof: function(position) {
              var stats = fs3.statSync(path6);
              return position === stats["size"];
            },
            put: function(text, position) {
              var buffer = Buffer.from(text);
              if (position === "end_of_stream")
                fs3.writeSync(fd, buffer);
              else if (position === "past_end_of_stream")
                return null;
              else
                fs3.writeSync(fd, buffer, 0, buffer.length, position);
              return true;
            },
            get_byte: function(position) {
              try {
                var buffer = Buffer.alloc(1);
                var bytesRead = fs3.readSync(fd, buffer, 0, 1, position);
                var end_of_file = bytesRead < 1;
                return end_of_file ? "end_of_stream" : buffer.readUInt8(0);
              } catch (ex) {
                return "end_of_stream";
              }
            },
            put_byte: function(byte, position) {
              var buffer = Buffer.from([byte]);
              if (position === "end_of_stream")
                fs3.writeSync(fd, buffer);
              else if (position === "past_end_of_stream")
                return null;
              else
                fs3.writeSync(fd, buffer, 0, buffer.length, position);
              return true;
            },
            flush: function() {
              return true;
            },
            close: function() {
              fs3.closeSync(fd);
              return true;
            }
          };
        }
      };
      nodejs_user_input = {
        buffer: "",
        get: function(length, _) {
          var text;
          var readlineSync = require_readline_sync();
          while (nodejs_user_input.buffer.length < length)
            nodejs_user_input.buffer += readlineSync.question("", { keepWhitespace: true }) + "\n";
          text = nodejs_user_input.buffer.substr(0, length);
          nodejs_user_input.buffer = nodejs_user_input.buffer.substr(length);
          return text;
        },
        eof: function(length) {
          return false;
        }
      };
      nodejs_user_output = {
        put: function(text, _) {
          process.stdout.write(text);
          return true;
        },
        flush: function() {
          return true;
        }
      };
      nodejs_user_error = {
        put: function(text, _) {
          process.stderr.write(text);
          return true;
        },
        flush: function() {
          return true;
        }
      };
      var indexOf;
      if (!Array.prototype.indexOf) {
        indexOf = function(array, elem) {
          var len = array.length;
          for (var i2 = 0; i2 < len; i2++) {
            if (elem === array[i2])
              return i2;
          }
          return -1;
        };
      } else {
        indexOf = function(array, elem) {
          return array.indexOf(elem);
        };
      }
      var reduce = function(array, fn) {
        if (array.length === 0)
          return void 0;
        var elem = array[0];
        var len = array.length;
        for (var i2 = 1; i2 < len; i2++) {
          elem = fn(elem, array[i2]);
        }
        return elem;
      };
      var map;
      if (!Array.prototype.map) {
        map = function(array, fn) {
          var a = [];
          var len = array.length;
          for (var i2 = 0; i2 < len; i2++) {
            a.push(fn(array[i2]));
          }
          return a;
        };
      } else {
        map = function(array, fn) {
          return array.map(fn);
        };
      }
      var filter;
      if (!Array.prototype.filter) {
        filter = function(array, fn) {
          var a = [];
          var len = array.length;
          for (var i2 = 0; i2 < len; i2++) {
            if (fn(array[i2]))
              a.push(array[i2]);
          }
          return a;
        };
      } else {
        filter = function(array, fn) {
          return array.filter(fn);
        };
      }
      var codePointAt;
      if (!String.prototype.codePointAt) {
        codePointAt = function(str, i2) {
          return str.charCodeAt(i2);
        };
      } else {
        codePointAt = function(str, i2) {
          return str.codePointAt(i2);
        };
      }
      var fromCodePoint;
      if (!String.fromCodePoint) {
        fromCodePoint = function() {
          return String.fromCharCode.apply(null, arguments);
        };
      } else {
        fromCodePoint = function() {
          return String.fromCodePoint.apply(null, arguments);
        };
      }
      var stringLength;
      var regexAstralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
      if (Array.from)
        stringLength = function(str) {
          return Array.from(str).length;
        };
      else
        stringLength = function(str) {
          return str.replace(regexAstralSymbols, "_").length;
        };
      var ERROR = 0;
      var SUCCESS = 1;
      var regex_escape = /(\\a)|(\\b)|(\\d)|(\\e)|(\\f)|(\\n)|(\\r)|(\\s)|(\\t)|(\\v)|\\x([0-9a-fA-F]+)\\|\\([0-7]+)\\|(\\\\)|(\\')|('')|(\\")|(\\`)|(\\.)|(.)/g;
      var escape_map = { "\\a": 7, "\\b": 8, "\\d": 127, "\\e": 27, "\\f": 12, "\\n": 10, "\\r": 13, "\\s": 32, "\\t": 9, "\\v": 11 };
      function escape2(str) {
        var stack = [];
        var _error = false;
        str.replace(regex_escape, function(match, a, b, d, e, f, n, r, s, t, v, hex, octal, back, single, dsingle, double, backquote, error, char) {
          switch (true) {
            case hex !== void 0:
              stack.push(parseInt(hex, 16));
              return "";
            case octal !== void 0:
              stack.push(parseInt(octal, 8));
              return "";
            case back !== void 0:
            case single !== void 0:
            case dsingle !== void 0:
            case double !== void 0:
            case backquote !== void 0:
              stack.push(codePointAt(match.substr(1), 0));
              return "";
            case char !== void 0:
              stack.push(codePointAt(char, 0));
              return "";
            case error !== void 0:
              _error = true;
            default:
              stack.push(escape_map[match]);
              return "";
          }
        });
        if (_error)
          return null;
        return stack;
      }
      function escapeAtom(str, quote) {
        var atom = "";
        if (str === "\\")
          return null;
        if (str.length < 2)
          return str;
        try {
          str = str.replace(/((?:\\\\)+)|\\([0-7]+)\\/g, function(match, g1, g2) {
            return g1 || fromCodePoint(parseInt(g2, 8));
          });
          str = str.replace(/((?:\\\\)+)|\\x([0-9a-fA-F]+)\\/g, function(match, g1, g2) {
            return g1 || fromCodePoint(parseInt(g2, 16));
          });
          str = str.replace(/((?:\\\\)+)|\\u([0-9a-fA-F]{4})/g, function(match, g1, g2) {
            return g1 || fromCodePoint(parseInt(g2, 16));
          });
        } catch (error) {
          return null;
        }
        for (var i2 = 0; i2 < str.length; i2++) {
          var a = str.charAt(i2);
          var b = str.charAt(i2 + 1);
          if (a === quote && b === quote) {
            i2++;
            atom += quote;
          } else if (a === "\\") {
            if (["a", "b", "f", "n", "r", "t", "v", "'", '"', "\\", "a", "\b", "\f", "\n", "\r", "	", "\v"].indexOf(b) !== -1) {
              i2 += 1;
              switch (b) {
                case "a":
                  atom += "a";
                  break;
                case "b":
                  atom += "\b";
                  break;
                case "f":
                  atom += "\f";
                  break;
                case "n":
                  atom += "\n";
                  break;
                case "r":
                  atom += "\r";
                  break;
                case "t":
                  atom += "	";
                  break;
                case "v":
                  atom += "\v";
                  break;
                case "'":
                  atom += "'";
                  break;
                case '"':
                  atom += '"';
                  break;
                case "\\":
                  atom += "\\";
                  break;
              }
            } else {
              return null;
            }
          } else {
            atom += a;
          }
        }
        return atom;
      }
      function redoEscape(str) {
        var atom = "";
        for (var i2 = 0; i2 < str.length; i2++) {
          switch (str.charAt(i2)) {
            case "'":
              atom += "\\'";
              break;
            case "\\":
              atom += "\\\\";
              break;
            case "\b":
              atom += "\\b";
              break;
            case "\f":
              atom += "\\f";
              break;
            case "\n":
              atom += "\\n";
              break;
            case "\r":
              atom += "\\r";
              break;
            case "	":
              atom += "\\t";
              break;
            case "\v":
              atom += "\\v";
              break;
            default:
              atom += str.charAt(i2);
              break;
          }
        }
        return atom;
      }
      function convertNum(num) {
        var n = num.substr(2);
        switch (num.substr(0, 2).toLowerCase()) {
          case "0x":
            return parseInt(n, 16);
          case "0b":
            return parseInt(n, 2);
          case "0o":
            return parseInt(n, 8);
          case "0'":
            return escape2(n)[0];
          default:
            return parseFloat(num);
        }
      }
      function is_graphic_token(string) {
        return /^[#\$\&\*\+\-\.\/\:\<\=\>\?\@\^\~\\]+/.test(string);
      }
      var rules = {
        whitespace: /^\s*(?:(?:%.*)|(?:\/\*(?:\n|\r|.)*?(?:\*\/|$))|(?:\s+))\s*/,
        variable: /^(?:[A-Z_][a-zA-Z0-9_]*)/,
        atom: /^(\!|,|;|[a-z][0-9a-zA-Z_]*|[#\$\&\*\+\-\.\/\:\<\=\>\?\@\^\~\\]+|'(?:(?:'')|(?:\\\\)|(?:\\')|[^'])*')/,
        number: /^(?:0o[0-7]+|0x[0-9a-fA-F]+|0b[01]+|0'(?:''|\\[abdefnrstv\\'"`]|\\x?\d+\\|[^\\])|\d+(?:\.\d+(?:[eE][+-]?\d+)?)?)/,
        string: /^(?:"([^"]|""|\\")*"|`([^`]|``|\\`)*`)/,
        l_brace: /^(?:\[)/,
        r_brace: /^(?:\])/,
        l_bracket: /^(?:\{)/,
        r_bracket: /^(?:\})/,
        bar: /^(?:\|)/,
        l_paren: /^(?:\()/,
        r_paren: /^(?:\))/
      };
      function replace(thread, text) {
        if (thread.get_flag("char_conversion").id === "on") {
          return text.replace(/./g, function(char) {
            return thread.get_char_conversion(char);
          });
        }
        return text;
      }
      function Tokenizer(thread) {
        this.thread = thread;
        this.text = "";
        this.tokens = [];
      }
      Tokenizer.prototype.set_last_tokens = function(tokens) {
        return this.tokens = tokens;
      };
      Tokenizer.prototype.new_text = function(text) {
        this.text = text;
        this.tokens = [];
      };
      Tokenizer.prototype.get_tokens = function(init) {
        var text;
        var len = 0;
        var line = 0;
        var start = 0;
        var tokens = [];
        var last_is_blank;
        if (init) {
          var token = this.tokens[init - 1];
          len = token.len;
          text = replace(this.thread, this.text.substr(token.len));
          line = token.line;
          start = token.start;
        } else
          text = this.text;
        if (/^\s*$/.test(text))
          return null;
        while (text !== "") {
          var matches = [];
          last_is_blank = false;
          if (/^\n/.exec(text) !== null) {
            line++;
            start = 0;
            len++;
            text = text.replace(/\n/, "");
            last_is_blank = true;
            continue;
          }
          for (var rule in rules) {
            if (rules.hasOwnProperty(rule)) {
              var matchs = rules[rule].exec(text);
              if (matchs) {
                matches.push({
                  value: matchs[0],
                  name: rule,
                  matches: matchs
                });
              }
            }
          }
          if (!matches.length)
            return this.set_last_tokens([{ value: text, matches: [], name: "lexical", line, start }]);
          var token = reduce(matches, function(a, b) {
            return a.value.length >= b.value.length ? a : b;
          });
          token.start = start;
          token.line = line;
          text = text.replace(token.value, "");
          start += token.value.length;
          len += token.value.length;
          var nl = (token.value.match(/\n/g) || []).length;
          line += nl;
          if (nl > 0)
            start = token.value.length - token.value.lastIndexOf("\n") - 1;
          token.line_count = line;
          token.line_position = start;
          switch (token.name) {
            case "atom":
              token.raw = token.value;
              if (token.value.charAt(0) === "'") {
                token.value = escapeAtom(token.value.substring(1, token.value.length - 1), "'");
                if (token.value === null) {
                  token.name = "lexical";
                  token.value = token.raw;
                  token.error = "unknown_escape_sequence";
                }
              }
              break;
            case "number":
              var substr = token.value.substring(0, 2);
              token.raw = token.value;
              token.float = substr !== "0x" && substr !== "0'" && token.value.match(/[.eE]/) !== null;
              token.value = convertNum(token.value);
              token.blank = last_is_blank;
              if (!token.float && pl.flag.bounded.value.indicator === "true/0" && token.value > pl.flag.max_integer.value.value) {
                token.name = "lexical";
                token.value = token.raw;
                token.error = "int_overflow";
              }
              break;
            case "string":
              var del = token.value.charAt(0);
              token.raw = token.value;
              token.value = escapeAtom(token.value.substring(1, token.value.length - 1), del);
              if (token.value === null) {
                token.name = "lexical";
                token.value = token.raw;
                token.error = "unknown_escape_sequence";
              }
              break;
            case "whitespace":
              var last = tokens[tokens.length - 1];
              if (last)
                last.space = true;
              last_is_blank = true;
              continue;
            case "r_bracket":
              if (tokens.length > 0 && tokens[tokens.length - 1].name === "l_bracket") {
                token = tokens.pop();
                token.name = "atom";
                token.value = "{}";
                token.raw = "{}";
                token.space = false;
              }
              break;
            case "r_brace":
              if (tokens.length > 0 && tokens[tokens.length - 1].name === "l_brace") {
                token = tokens.pop();
                token.name = "atom";
                token.value = "[]";
                token.raw = "[]";
                token.space = false;
              }
              break;
          }
          token.len = len;
          tokens.push(token);
          last_is_blank = false;
        }
        var t = this.set_last_tokens(tokens);
        return t.length === 0 ? null : t;
      };
      function parseExpr(thread, tokens, start, priority, toplevel) {
        if (!tokens[start])
          return { type: ERROR, value: pl.error.syntax(tokens[start - 1], "expression expected", true) };
        var error;
        if (priority === "0") {
          var token = tokens[start];
          switch (token.name) {
            case "number":
              return { type: SUCCESS, len: start + 1, value: new pl.type.Num(token.value, token.float) };
            case "variable":
              return { type: SUCCESS, len: start + 1, value: new pl.type.Var(token.value) };
            case "string":
              var str;
              switch (thread.get_flag("double_quotes").id) {
                case "atom":
                  ;
                  str = new Term(token.value, []);
                  break;
                case "codes":
                  str = new Term("[]", []);
                  for (var i2 = token.value.length - 1; i2 >= 0; i2--)
                    str = new Term(".", [new pl.type.Num(codePointAt(token.value, i2), false), str]);
                  break;
                case "chars":
                  str = new Term("[]", []);
                  for (var i2 = token.value.length - 1; i2 >= 0; i2--)
                    str = new Term(".", [new pl.type.Term(token.value.charAt(i2), []), str]);
                  break;
              }
              return { type: SUCCESS, len: start + 1, value: str };
            case "l_paren":
              var expr = parseExpr(thread, tokens, start + 1, thread.__get_max_priority(), true);
              if (expr.type !== SUCCESS)
                return expr;
              if (tokens[expr.len] && tokens[expr.len].name === "r_paren") {
                expr.len++;
                return expr;
              }
              return { type: ERROR, derived: true, value: pl.error.syntax(tokens[expr.len] ? tokens[expr.len] : tokens[expr.len - 1], ") or operator expected", !tokens[expr.len]) };
            case "l_bracket":
              var expr = parseExpr(thread, tokens, start + 1, thread.__get_max_priority(), true);
              if (expr.type !== SUCCESS)
                return expr;
              if (tokens[expr.len] && tokens[expr.len].name === "r_bracket") {
                expr.len++;
                expr.value = new Term("{}", [expr.value]);
                return expr;
              }
              return { type: ERROR, derived: true, value: pl.error.syntax(tokens[expr.len] ? tokens[expr.len] : tokens[expr.len - 1], "} or operator expected", !tokens[expr.len]) };
          }
          var result = parseTerm(thread, tokens, start, toplevel);
          if (result.type === SUCCESS || result.derived)
            return result;
          result = parseList(thread, tokens, start);
          if (result.type === SUCCESS || result.derived)
            return result;
          return { type: ERROR, derived: false, value: pl.error.syntax(tokens[start], token.error || "unexpected token") };
        }
        var max_priority = thread.__get_max_priority();
        var next_priority = thread.__get_next_priority(priority);
        var aux_start = start;
        if (tokens[start].name === "atom" && tokens[start + 1] && (tokens[start].space || tokens[start + 1].name !== "l_paren")) {
          var token = tokens[start++];
          var classes = thread.__lookup_operator_classes(priority, token.value);
          if (classes && classes.indexOf("fy") > -1) {
            var expr = parseExpr(thread, tokens, start, priority, toplevel);
            if (expr.type !== ERROR) {
              if (token.value === "-" && !token.space && pl.type.is_number(expr.value)) {
                return {
                  value: new pl.type.Num(-expr.value.value, expr.value.is_float),
                  len: expr.len,
                  type: SUCCESS
                };
              } else {
                return {
                  value: new pl.type.Term(token.value, [expr.value]),
                  len: expr.len,
                  type: SUCCESS
                };
              }
            } else {
              error = expr;
            }
          } else if (classes && classes.indexOf("fx") > -1) {
            var expr = parseExpr(thread, tokens, start, next_priority, toplevel);
            if (expr.type !== ERROR) {
              return {
                value: new pl.type.Term(token.value, [expr.value]),
                len: expr.len,
                type: SUCCESS
              };
            } else {
              error = expr;
            }
          }
        }
        start = aux_start;
        var expr = parseExpr(thread, tokens, start, next_priority, toplevel);
        if (expr.type === SUCCESS) {
          start = expr.len;
          var token = tokens[start];
          if (tokens[start] && (tokens[start].name === "atom" && thread.__lookup_operator_classes(priority, token.value) || tokens[start].name === "bar" && thread.__lookup_operator_classes(priority, "|"))) {
            var next_priority_lt = next_priority;
            var next_priority_eq = priority;
            var classes = thread.__lookup_operator_classes(priority, token.value);
            if (classes.indexOf("xf") > -1) {
              return {
                value: new pl.type.Term(token.value, [expr.value]),
                len: ++expr.len,
                type: SUCCESS
              };
            } else if (classes.indexOf("xfx") > -1) {
              var expr2 = parseExpr(thread, tokens, start + 1, next_priority_lt, toplevel);
              if (expr2.type === SUCCESS) {
                return {
                  value: new pl.type.Term(token.value, [expr.value, expr2.value]),
                  len: expr2.len,
                  type: SUCCESS
                };
              } else {
                expr2.derived = true;
                return expr2;
              }
            } else if (classes.indexOf("xfy") > -1) {
              var expr2 = parseExpr(thread, tokens, start + 1, next_priority_eq, toplevel);
              if (expr2.type === SUCCESS) {
                return {
                  value: new pl.type.Term(token.value, [expr.value, expr2.value]),
                  len: expr2.len,
                  type: SUCCESS
                };
              } else {
                expr2.derived = true;
                return expr2;
              }
            } else if (expr.type !== ERROR) {
              while (true) {
                start = expr.len;
                var token = tokens[start];
                if (token && token.name === "atom" && thread.__lookup_operator_classes(priority, token.value)) {
                  var classes = thread.__lookup_operator_classes(priority, token.value);
                  if (classes.indexOf("yf") > -1) {
                    expr = {
                      value: new pl.type.Term(token.value, [expr.value]),
                      len: ++start,
                      type: SUCCESS
                    };
                  } else if (classes.indexOf("yfx") > -1) {
                    var expr2 = parseExpr(thread, tokens, ++start, next_priority_lt, toplevel);
                    if (expr2.type === ERROR) {
                      expr2.derived = true;
                      return expr2;
                    }
                    start = expr2.len;
                    expr = {
                      value: new pl.type.Term(token.value, [expr.value, expr2.value]),
                      len: start,
                      type: SUCCESS
                    };
                  } else {
                    break;
                  }
                } else {
                  break;
                }
              }
            }
          } else {
            error = { type: ERROR, value: pl.error.syntax(tokens[expr.len - 1], "operator expected") };
          }
          return expr;
        }
        return expr;
      }
      function parseTerm(thread, tokens, start, toplevel) {
        if (!tokens[start] || tokens[start].name === "atom" && tokens[start].raw === "." && !toplevel && (tokens[start].space || !tokens[start + 1] || tokens[start + 1].name !== "l_paren"))
          return { type: ERROR, derived: false, value: pl.error.syntax(tokens[start - 1], "unfounded token") };
        var atom = tokens[start];
        var exprs = [];
        if (tokens[start].name === "atom" && tokens[start].raw !== ",") {
          start++;
          if (tokens[start - 1].space)
            return { type: SUCCESS, len: start, value: new pl.type.Term(atom.value, exprs) };
          if (tokens[start] && tokens[start].name === "l_paren") {
            if (tokens[start + 1] && tokens[start + 1].name === "r_paren")
              return { type: ERROR, derived: true, value: pl.error.syntax(tokens[start + 1], "argument expected") };
            var expr = parseExpr(thread, tokens, ++start, "999", true);
            if (expr.type === ERROR) {
              if (expr.derived)
                return expr;
              else
                return { type: ERROR, derived: true, value: pl.error.syntax(tokens[start] ? tokens[start] : tokens[start - 1], "argument expected", !tokens[start]) };
            }
            exprs.push(expr.value);
            start = expr.len;
            while (tokens[start] && tokens[start].name === "atom" && tokens[start].value === ",") {
              expr = parseExpr(thread, tokens, start + 1, "999", true);
              if (expr.type === ERROR) {
                if (expr.derived)
                  return expr;
                else
                  return { type: ERROR, derived: true, value: pl.error.syntax(tokens[start + 1] ? tokens[start + 1] : tokens[start], "argument expected", !tokens[start + 1]) };
              }
              exprs.push(expr.value);
              start = expr.len;
            }
            if (tokens[start] && tokens[start].name === "r_paren")
              start++;
            else
              return { type: ERROR, derived: true, value: pl.error.syntax(tokens[start] ? tokens[start] : tokens[start - 1], ", or ) expected", !tokens[start]) };
          }
          return { type: SUCCESS, len: start, value: new pl.type.Term(atom.value, exprs) };
        }
        return { type: ERROR, derived: false, value: pl.error.syntax(tokens[start], "term expected") };
      }
      function parseList(thread, tokens, start) {
        if (!tokens[start])
          return { type: ERROR, derived: false, value: pl.error.syntax(tokens[start - 1], "[ expected") };
        if (tokens[start] && tokens[start].name === "l_brace") {
          var expr = parseExpr(thread, tokens, ++start, "999", true);
          var exprs = [expr.value];
          var cons = void 0;
          if (expr.type === ERROR) {
            if (tokens[start] && tokens[start].name === "r_brace") {
              return { type: SUCCESS, len: start + 1, value: new pl.type.Term("[]", []) };
            }
            return { type: ERROR, derived: true, value: pl.error.syntax(tokens[start], "] expected") };
          }
          start = expr.len;
          while (tokens[start] && tokens[start].name === "atom" && tokens[start].value === ",") {
            expr = parseExpr(thread, tokens, start + 1, "999", true);
            if (expr.type === ERROR) {
              if (expr.derived)
                return expr;
              else
                return { type: ERROR, derived: true, value: pl.error.syntax(tokens[start + 1] ? tokens[start + 1] : tokens[start], "argument expected", !tokens[start + 1]) };
            }
            exprs.push(expr.value);
            start = expr.len;
          }
          var bar = false;
          if (tokens[start] && tokens[start].name === "bar") {
            bar = true;
            expr = parseExpr(thread, tokens, start + 1, "999", true);
            if (expr.type === ERROR) {
              if (expr.derived)
                return expr;
              else
                return { type: ERROR, derived: true, value: pl.error.syntax(tokens[start + 1] ? tokens[start + 1] : tokens[start], "argument expected", !tokens[start + 1]) };
            }
            cons = expr.value;
            start = expr.len;
          }
          if (tokens[start] && tokens[start].name === "r_brace")
            return { type: SUCCESS, len: start + 1, value: arrayToList(exprs, cons) };
          else
            return { type: ERROR, derived: true, value: pl.error.syntax(tokens[start] ? tokens[start] : tokens[start - 1], bar ? "] expected" : ", or | or ] expected", !tokens[start]) };
        }
        return { type: ERROR, derived: false, value: pl.error.syntax(tokens[start], "list expected") };
      }
      function parseRule(thread, tokens, start) {
        var line = tokens[start].line;
        var expr = parseExpr(thread, tokens, start, thread.__get_max_priority(), false);
        var rule = null;
        var obj;
        if (expr.type !== ERROR) {
          start = expr.len;
          if (tokens[start] && tokens[start].name === "atom" && tokens[start].raw === ".") {
            start++;
            if (pl.type.is_term(expr.value)) {
              if (expr.value.indicator === ":-/2") {
                rule = new pl.type.Rule(expr.value.args[0], body_conversion(expr.value.args[1]));
                obj = {
                  value: rule,
                  len: start,
                  type: SUCCESS
                };
              } else if (expr.value.indicator === "-->/2") {
                rule = new pl.type.Rule(expr.value.args[0], body_conversion(expr.value.args[1]));
                rule = rule_to_dcg(rule, thread);
                rule.body = body_conversion(rule.body);
                if (!pl.type.is_rule(rule))
                  return {
                    value: rule,
                    len: start,
                    type: ERROR
                  };
                obj = {
                  value: rule,
                  len: start,
                  type: pl.type.is_rule(rule) ? SUCCESS : ERROR
                };
              } else {
                rule = new pl.type.Rule(expr.value, null);
                obj = {
                  value: rule,
                  len: start,
                  type: SUCCESS
                };
              }
              if (rule) {
                var singleton = rule.singleton_variables();
                if (singleton.length > 0)
                  thread.throw_warning(pl.warning.singleton(singleton, rule.head.indicator, line));
              }
              return obj;
            } else {
              return { type: ERROR, value: pl.error.syntax(tokens[start], "callable expected") };
            }
          } else {
            return { type: ERROR, value: pl.error.syntax(tokens[start] ? tokens[start] : tokens[start - 1], ". or operator expected") };
          }
        }
        return expr;
      }
      function parseProgram(thread, string, options) {
        var opts = {};
        options = options ? options : {};
        opts.success = options.success ? options.success : function() {
        };
        opts.error = options.error ? options.error : function() {
        };
        opts.from = options.from ? options.from : "$tau-js";
        opts.reconsult = options.reconsult !== void 0 ? options.reconsult : true;
        opts.reconsulted = options.reconsulted === void 0 ? {} : options.reconsulted;
        opts.context_module = options.context_module === void 0 ? "user" : options.context_module;
        opts.initialization = options.initialization === void 0 ? [] : options.initialization;
        opts.current_token = options.current_token === void 0 ? 0 : options.current_token;
        opts.tokenizer = options.tokenizer === void 0 ? null : options.tokenizer;
        opts.tokens = options.tokens === void 0 ? null : options.tokens;
        opts.string = string;
        opts.term_expansion = false;
        var reconsulted = opts.reconsulted;
        var tokenizer = opts.tokenizer;
        var tokens = opts.tokens;
        if (tokenizer === null) {
          tokenizer = new Tokenizer(thread);
          tokenizer.new_text(string);
          opts.tokenizer = tokenizer;
          tokens = tokenizer.get_tokens(0);
          opts.tokens = tokens;
        }
        var n = opts.current_token;
        while (tokens !== null && tokens[n]) {
          var expr = parseRule(thread, tokens, n);
          opts.current_token = expr.len;
          if (expr.type === ERROR) {
            if (opts.error !== void 0)
              opts.error(new Term("throw", [expr.value]));
            return;
          } else {
            var context_module = opts.context_module;
            var term_expansion = thread.session.modules[context_module].rules["term_expansion/2"];
            if (term_expansion && term_expansion.length > 0) {
              opts.term_expansion = true;
              var n_thread = new Thread(thread.session);
              var term = expr.value.body ? new Term(":-", [expr.value.head, expr.value.body]) : expr.value.head;
              thread.session.renamed_variables = {};
              term = term.rename(thread.session);
              n_thread.query(context_module + ":term_expansion(" + term.toString({ quoted: true }) + ", X).");
              n_thread.answer(function(thread2, opts2, reconsulted2, expr2) {
                return function(answer) {
                  if (answer && !pl.type.is_error(answer) && pl.type.is_term(answer.links["X"])) {
                    var term2 = answer.links["X"];
                    var rule = term2.indicator === ":-/2" ? new Rule(term2.args[0], term2.args[1]) : new Rule(term2, null);
                    parseProgramExpansion(thread2, opts2, reconsulted2, { value: rule, len: expr2.len, type: expr2.type });
                  } else {
                    parseProgramExpansion(thread2, opts2, reconsulted2, expr2);
                  }
                };
              }(thread, opts, reconsulted, expr));
              return;
            } else {
              opts.term_expansion = false;
              var async = parseProgramExpansion(thread, opts, reconsulted, expr);
              if (async)
                return;
              n = expr.len;
            }
          }
        }
        var callback = opts.success;
        var nthread = new Thread(thread.session);
        for (var i2 = opts.initialization.length - 1; i2 > 0; i2--) {
          var next_callback = function(init, callback2) {
            return function(answer) {
              if (answer === null) {
                nthread.answer();
              } else if (pl.type.is_error(answer)) {
                opts.error(answer);
              } else {
                nthread.add_goal(init);
                nthread.answer(callback2);
              }
            };
          }(opts.initialization[i2], callback);
          callback = next_callback;
        }
        if (opts.initialization.length > 0) {
          nthread.add_goal(opts.initialization[0]);
          nthread.answer(callback);
        } else {
          callback();
        }
      }
      function parseGoalExpansion(thread, options, expr) {
        var n_thread = new Thread(thread.session);
        n_thread.__goal_expansion = true;
        var varterm = thread.next_free_variable();
        var varhead = thread.next_free_variable();
        var goal = varhead + " = " + expr.value.head + ", goal_expansion(" + expr.value.body.toString({
          quoted: true
        }) + ", " + varterm.toString({
          quoted: true
        }) + ").";
        n_thread.query(goal);
        n_thread.answer(function(answer) {
          if (answer && !pl.type.is_error(answer) && answer.links[varterm]) {
            expr.value.head = answer.links[varhead];
            expr.value.body = body_conversion(answer.links[varterm]);
            parseGoalExpansion(thread, options, expr);
          } else {
            thread.add_rule(expr.value, options);
            parseProgram(thread, options.string, options);
          }
        });
      }
      function parseQueryExpansion(thread, term, options) {
        var n_thread = new Thread(thread.session);
        n_thread.__goal_expansion = true;
        var varterm = thread.next_free_variable();
        var goal = "goal_expansion(" + term.toString({
          quoted: true
        }) + ", " + varterm.toString({
          quoted: true
        }) + ").";
        n_thread.query(goal);
        var variables = n_thread.head_point().substitution.domain();
        n_thread.answer(function(answer) {
          if (answer && !pl.type.is_error(answer) && answer.links[varterm]) {
            for (var i2 = 0; i2 < variables.length; i2++) {
              if (variables[i2] !== varterm.id && answer.links[variables[i2]]) {
                var subs = new Substitution();
                subs.links[answer.links[variables[i2]]] = variables[i2];
                answer.links[varterm] = answer.links[varterm].apply(subs);
              }
            }
            parseQueryExpansion(thread, body_conversion(answer.links[varterm]), options);
          } else {
            thread.add_goal(term);
            options.success(term);
            parseQuery(thread, options.string, options);
          }
        });
      }
      function parseProgramExpansion(thread, options, reconsulted, expr) {
        var async = options.term_expansion === true;
        if (expr.value.body === null && expr.value.head.indicator === "?-/1") {
          async = true;
          var n_thread = new Thread(thread.session);
          n_thread.add_goal(expr.value.head.args[0]);
          n_thread.answer(function(answer) {
            if (pl.type.is_error(answer)) {
              thread.throw_warning(answer.args[0]);
            } else if (answer === false || answer === null) {
              thread.throw_warning(pl.warning.failed_goal(expr.value.head.args[0], expr.len));
            }
            parseProgram(thread, options.string, options);
          });
        } else if (expr.value.body === null && expr.value.head.indicator === ":-/1") {
          var result = thread.run_directive(expr.value.head.args[0], options);
          async = async || result === true;
          if (async)
            parseProgram(thread, options.string, options);
        } else {
          var context_module = options.context_module;
          var indicator2 = expr.value.head.indicator;
          if (expr.value.head.indicator === ":/2") {
            context_module = expr.value.head.args[0].id;
            indicator2 = expr.value.head.args[1].indicator;
          }
          if (!reconsulted.hasOwnProperty(context_module))
            reconsulted[context_module] = {};
          if (options.reconsult !== false && reconsulted[context_module][indicator2] !== true && !thread.is_multifile_predicate(indicator2)) {
            var get_module = thread.session.modules[context_module];
            if (context_module !== "system" && get_module && get_module.rules[indicator2]) {
              get_module.rules[indicator2] = filter(get_module.rules[indicator2], function(rule) {
                return rule.dynamic;
              });
              get_module.update_indices_predicate(indicator2);
            }
            reconsulted[context_module][indicator2] = true;
          }
          var goal_expansion = thread.session.modules.user.rules["goal_expansion/2"];
          if (expr.value.body !== null && goal_expansion && goal_expansion.length > 0) {
            async = true;
            thread.session.renamed_variables = {};
            var origin = {
              head: function() {
                return expr.value.head;
              },
              term: function() {
                return expr.value.body;
              },
              set: function(h, p) {
                expr.value.head = h;
                expr.value.body = p;
              }
            };
            parseGoalExpansion(thread, options, expr, body_conversion(expr.value.body), origin.set, origin);
          } else {
            thread.add_rule(expr.value, options);
            if (async)
              parseProgram(thread, options.string, options);
          }
        }
        return async;
      }
      function parseQuery(thread, string, options) {
        var opts = {};
        var callback = typeof options === "function" ? options : function() {
        };
        options = options === void 0 || typeof options === "function" ? {} : options;
        opts.success = options.success === void 0 ? callback : options.success;
        opts.error = options.error === void 0 ? callback : options.error;
        opts.tokenizer = options.tokenizer === void 0 ? null : options.tokenizer;
        opts.current_token = options.current_token === void 0 ? 0 : options.current_token;
        opts.string = string;
        var tokenizer = opts.tokenizer;
        var n = opts.current_token;
        if (tokenizer === null) {
          tokenizer = new Tokenizer(thread);
          opts.tokenizer = tokenizer;
          tokenizer.new_text(string);
        }
        do {
          var tokens = tokenizer.get_tokens(n);
          if (tokens === null)
            break;
          var expr = parseExpr(thread, tokens, 0, thread.__get_max_priority(), false);
          if (expr.type !== ERROR) {
            var expr_position = expr.len;
            n = expr.len + 1;
            opts.current_token = n;
            if (tokens[expr_position] && tokens[expr_position].name === "atom" && tokens[expr_position].raw === ".") {
              expr.value = body_conversion(expr.value);
              var goal_expansion = thread.session.modules.user.rules["goal_expansion/2"];
              if (!thread.__goal_expansion && goal_expansion && goal_expansion.length > 0) {
                parseQueryExpansion(thread, expr.value, opts);
                return;
              } else {
                thread.add_goal(expr.value);
                opts.success(expr.value);
              }
            } else {
              var token = tokens[expr_position];
              opts.error(
                new Term("throw", [
                  pl.error.syntax(
                    token ? token : tokens[expr_position - 1],
                    token && token.error ? token.error : ". or operator expected",
                    !token
                  )
                ])
              );
              return;
            }
          } else {
            opts.error(new Term("throw", [expr.value]));
            return;
          }
        } while (true);
      }
      function rule_to_dcg(rule, thread) {
        thread.session.renamed_variables = {};
        rule = rule.rename(thread);
        var begin = thread.next_free_variable();
        var dcg = body_to_dcg(rule.body, begin, thread);
        if (dcg.error)
          return dcg.value;
        rule.body = dcg.value;
        if (rule.head.indicator === ",/2") {
          var terminals = rule.head.args[1];
          rule.head = rule.head.args[0];
          var last = thread.next_free_variable();
          var pointer = terminals;
          if (!pl.type.is_list(pointer)) {
            return pl.error.type("list", pointer, "DCG/0");
          }
          if (pointer.indicator === "[]/0") {
            terminals = dcg.variable;
          } else {
            while (pointer.indicator === "./2" && pl.type.is_list(pointer) && pointer.args[1].indicator !== "[]/0") {
              pointer = pointer.args[1];
            }
            if (pl.type.is_variable(pointer))
              return pl.error.instantiation("DCG/0");
            else if (!pl.type.is_list(pointer))
              return pl.error.type("list", terminals, "DCG/0");
            pointer.args[1] = dcg.variable;
          }
          rule.body = new Term(",", [rule.body, new Term("=", [last, terminals])]);
          rule.head = new Term(rule.head.id, rule.head.args.concat([begin, last]));
        } else {
          var first_assign = rule.body;
          if (pl.type.is_term(first_assign) && first_assign.indicator === ",/2")
            first_assign = first_assign.args[0];
          if (pl.type.is_term(first_assign) && first_assign.indicator === "=/2" && pl.type.is_variable(first_assign.args[0]) && first_assign.args[0] === begin) {
            begin = first_assign.args[1];
            rule.body = rule.body.replace(null);
          }
          if (rule.head.indicator === ":/2")
            rule.head = new Term(":", [
              new Term(rule.head.args[0].id, []),
              new Term(rule.head.args[1].id, rule.head.args[1].args.concat([begin, dcg.variable]))
            ]);
          else
            rule.head = new Term(rule.head.id, rule.head.args.concat([begin, dcg.variable]));
        }
        return rule;
      }
      function body_to_dcg(expr, last, thread) {
        var free;
        if (pl.type.is_term(expr) && expr.indicator === "!/0") {
          free = thread.next_free_variable();
          return {
            value: new Term(",", [expr, new Term("=", [last, free])]),
            variable: free,
            error: false
          };
        } else if (pl.type.is_term(expr) && expr.indicator === ":/2") {
          var right = body_to_dcg(expr.args[1], last, thread);
          if (right.error)
            return right;
          return {
            value: new Term(":", [expr.args[0], right.value]),
            variable: right.variable,
            error: false
          };
        } else if (pl.type.is_term(expr) && expr.indicator === "\\+/1") {
          var left = body_to_dcg(expr.args[0], last, thread);
          if (left.error)
            return left;
          free = thread.next_free_variable();
          return {
            value: new Term(",", [new Term(expr.id, [left.value]), new Term("=", [last, free])]),
            variable: free,
            error: false
          };
        } else if (pl.type.is_term(expr) && (expr.indicator === ",/2" || expr.indicator === "->/2")) {
          var left = body_to_dcg(expr.args[0], last, thread);
          if (left.error)
            return left;
          var right = body_to_dcg(expr.args[1], left.variable, thread);
          if (right.error)
            return right;
          return {
            value: new Term(expr.id, [left.value, right.value]),
            variable: right.variable,
            error: false
          };
        } else if (pl.type.is_term(expr) && expr.indicator === ";/2") {
          var left = body_to_dcg(expr.args[0], last, thread);
          if (left.error)
            return left;
          var right = body_to_dcg(expr.args[1], last, thread);
          if (right.error)
            return right;
          return {
            value: new Term(",", [new Term(";", [left.value, right.value]), new Term("=", [left.variable, right.variable])]),
            variable: right.variable,
            error: false
          };
        } else if (pl.type.is_term(expr) && expr.indicator === "{}/1") {
          free = thread.next_free_variable();
          return {
            value: new Term(",", [expr.args[0], new Term("=", [last, free])]),
            variable: free,
            error: false
          };
        } else if (pl.type.is_empty_list(expr)) {
          return {
            value: new Term("true", []),
            variable: last,
            error: false
          };
        } else if (pl.type.is_list(expr)) {
          free = thread.next_free_variable();
          var pointer = expr;
          var prev;
          while (pointer.indicator === "./2") {
            prev = pointer;
            pointer = pointer.args[1];
          }
          if (pl.type.is_variable(pointer)) {
            return {
              value: pl.error.instantiation("DCG/0"),
              variable: last,
              error: true
            };
          } else if (!pl.type.is_empty_list(pointer)) {
            return {
              value: pl.error.type("list", expr, "DCG/0"),
              variable: last,
              error: true
            };
          } else {
            prev.args[1] = free;
            return {
              value: new Term("=", [last, expr]),
              variable: free,
              error: false
            };
          }
        } else if (pl.type.is_callable(expr)) {
          free = thread.next_free_variable();
          expr = new Term(expr.id, expr.args.concat([last, free]));
          return {
            value: expr,
            variable: free,
            error: false
          };
        } else {
          return {
            value: pl.error.type("callable", expr, "DCG/0"),
            variable: last,
            error: true
          };
        }
      }
      function body_conversion(expr) {
        if (pl.type.is_variable(expr))
          return new Term("call", [expr]);
        else if (pl.type.is_term(expr) && [",/2", ";/2", "->/2"].indexOf(expr.indicator) !== -1)
          return new Term(expr.id, [body_conversion(expr.args[0]), body_conversion(expr.args[1])]);
        else if (pl.type.is_term(expr) && expr.indicator === ":/2") {
          var body = body_conversion(expr.args[1]);
          return new Term(":", [expr.args[0], body]);
        }
        return expr;
      }
      function arrayToList(array, cons) {
        var list = cons ? cons : new Term("[]", []);
        for (var i2 = array.length - 1; i2 >= 0; i2--)
          list = new Term(".", [array[i2], list]);
        return list;
      }
      function difference(xs, ys) {
        var zs = [];
        for (var i2 = 0; i2 < xs.length; i2++) {
          if (indexOf(zs, xs[i2]) === -1 && indexOf(ys, xs[i2]) === -1)
            zs.push(xs[i2]);
        }
        return zs;
      }
      function remove(array, element) {
        for (var i2 = array.length - 1; i2 >= 0; i2--) {
          if (array[i2] === element) {
            array.splice(i2, 1);
          }
        }
      }
      function nub(array) {
        var seen = {};
        var unique = [];
        for (var i2 = 0; i2 < array.length; i2++) {
          if (!(array[i2] in seen)) {
            unique.push(array[i2]);
            seen[array[i2]] = true;
          }
        }
        return unique;
      }
      function retract(thread, point, indicator2, rule, get_module) {
        if (get_module.rules[indicator2]) {
          for (var i2 = 0; i2 < get_module.rules[indicator2].length; i2++) {
            if (get_module.rules[indicator2][i2] === rule) {
              get_module.rules[indicator2].splice(i2, 1);
              get_module.update_indices_predicate(indicator2);
              thread.success(point);
              break;
            }
          }
        }
      }
      function callN(n) {
        return function(thread, point, atom) {
          var closure = atom.args[0], args = atom.args.slice(1, n);
          var module_atom;
          if (pl.type.is_term(closure) && closure.indicator === ":/2") {
            if (!pl.type.is_atom(closure.args[0])) {
              thread.throw_error(pl.error.type("module", closure.args[0], atom.indicator));
              return;
            }
            module_atom = closure.args[0];
            closure = closure.args[1];
          }
          if (pl.type.is_variable(closure)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_callable(closure)) {
            thread.throw_error(pl.error.type("callable", closure, atom.indicator));
          } else {
            var goal = body_conversion(new Term(closure.id, closure.args.concat(args)));
            if (!pl.type.is_callable(goal)) {
              thread.throw_error(pl.error.type("callable", goal, atom.indicator));
              return;
            }
            if (module_atom)
              goal = new Term(":", [module_atom, goal]);
            thread.prepend([new State(point.goal.replace(goal), point.substitution, point)]);
          }
        };
      }
      function str_indicator(str) {
        for (var i2 = str.length - 1; i2 >= 0; i2--)
          if (str.charAt(i2) === "/")
            return new Term("/", [new Term(str.substring(0, i2)), new Num(parseInt(str.substring(i2 + 1)), false)]);
      }
      function gcd(a, b) {
        if (b === 0)
          return a;
        return Math.abs(gcd(b, a % b));
      }
      function Var(id) {
        this.id = id;
        this.ground = false;
      }
      function Num(value, is_float) {
        this.is_float = is_float !== void 0 ? is_float : Math.trunc(value) !== value;
        this.value = this.is_float ? value : Math.trunc(value);
        this.index = this.value;
        this.ground = true;
      }
      var term_ref = 0;
      function Term(id, args, ref) {
        term_ref++;
        this.ref = ref || term_ref;
        this.id = id;
        this.args = args || [];
        this.indicator = id + "/" + this.args.length;
        this.index = this.indicator;
        this.ground = true;
        for (var i2 = 0; i2 < this.args.length; i2++) {
          if (this.args[i2].hasOwnProperty("ground") && this.args[i2].ground === false) {
            this.ground = false;
            break;
          }
        }
      }
      var stream_ref = 0;
      function Stream(stream, mode, alias, type, reposition, eof_action) {
        this.id = stream_ref++;
        this.stream = stream;
        this.mode = mode;
        this.alias = alias;
        this.type = type !== void 0 ? type : "text";
        this.reposition = reposition !== void 0 ? reposition : true;
        this.eof_action = eof_action !== void 0 ? eof_action : "eof_code";
        this.position = this.mode === "append" ? "end_of_stream" : 0;
        this.output = this.mode === "write" || this.mode === "append";
        this.input = this.mode === "read";
        this.line_position = 0;
        this.line_count = 1;
        this.char_count = 0;
      }
      function Substitution(links, attrs) {
        links = links || {};
        attrs = attrs || {};
        this.links = links;
        this.attrs = attrs;
      }
      function State(goal, subs, parent) {
        subs = subs || new Substitution();
        parent = parent || null;
        this.goal = goal;
        this.substitution = subs;
        this.parent = parent;
      }
      function Rule(head, body, dynamic) {
        this.head = head;
        this.body = body;
        this.dynamic = dynamic ? dynamic : false;
      }
      function Session(limit) {
        limit = typeof limit === "number" && limit > 0 ? limit : null;
        this.rename = 0;
        this.modules = {};
        this.modules.user = new Module("user", {}, "all", {
          session: this,
          dependencies: ["system"]
        });
        this.modules.system = pl.modules.system;
        this.rules = this.modules.user.rules;
        this.total_threads = 0;
        this.renamed_variables = {};
        this.public_predicates = this.modules.user.public_predicates;
        this.multifile_predicates = this.modules.user.multifile_predicates;
        this.limit = limit;
        this.streams = {
          "user_input": new Stream(
            nodejs_flag ? nodejs_user_input : tau_user_input,
            "read",
            "user_input",
            "text",
            false,
            "reset"
          ),
          "user_output": new Stream(
            nodejs_flag ? nodejs_user_output : tau_user_output,
            "append",
            "user_output",
            "text",
            false,
            "reset"
          ),
          "user_error": new Stream(
            nodejs_flag ? nodejs_user_error : tau_user_error,
            "append",
            "user_error",
            "text",
            false,
            "reset"
          )
        };
        this.file_system = nodejs_flag ? nodejs_file_system : tau_file_system;
        this.standard_input = this.streams["user_input"];
        this.standard_output = this.streams["user_output"];
        this.standard_error = this.streams["user_error"];
        this.current_input = this.streams["user_input"];
        this.current_output = this.streams["user_output"];
        this.working_directory = "/";
        this.format_success = function(state) {
          return state.substitution;
        };
        this.format_error = function(state) {
          return state.goal;
        };
        this.flag = {
          bounded: pl.flag.bounded.value,
          max_integer: pl.flag.max_integer.value,
          min_integer: pl.flag.min_integer.value,
          integer_rounding_function: pl.flag.integer_rounding_function.value,
          char_conversion: pl.flag.char_conversion.value,
          debug: pl.flag.debug.value,
          max_arity: pl.flag.max_arity.value,
          unknown: pl.flag.unknown.value,
          double_quotes: pl.flag.double_quotes.value,
          occurs_check: pl.flag.occurs_check.value,
          dialect: pl.flag.dialect.value,
          version_data: pl.flag.version_data.value,
          nodejs: pl.flag.nodejs.value,
          argv: pl.flag.argv.value
        };
        this.__loaded_modules = [];
        this.__char_conversion = {};
        this.__operators = {
          1200: { ":-": ["fx", "xfx"], "-->": ["xfx"], "?-": ["fx"] },
          1150: { "meta_predicate": ["fx"] },
          1100: { ";": ["xfy"] },
          1050: { "->": ["xfy"], "*->": ["xfy"] },
          1e3: { ",": ["xfy"] },
          900: { "\\+": ["fy"] },
          700: {
            "=": ["xfx"],
            "\\=": ["xfx"],
            "==": ["xfx"],
            "\\==": ["xfx"],
            "@<": ["xfx"],
            "@=<": ["xfx"],
            "@>": ["xfx"],
            "@>=": ["xfx"],
            "=..": ["xfx"],
            "is": ["xfx"],
            "=:=": ["xfx"],
            "=\\=": ["xfx"],
            "<": ["xfx"],
            "=<": ["xfx"],
            ">": ["xfx"],
            ">=": ["xfx"]
          },
          600: { ":": ["xfy"] },
          500: { "+": ["yfx"], "-": ["yfx"], "/\\": ["yfx"], "\\/": ["yfx"] },
          400: {
            "*": ["yfx"],
            "/": ["yfx"],
            "//": ["yfx"],
            "rem": ["yfx"],
            "mod": ["yfx"],
            "<<": ["yfx"],
            ">>": ["yfx"],
            "div": ["yfx"]
          },
          200: { "**": ["xfx"], "^": ["xfy"], "-": ["fy"], "+": ["fy"], "\\": ["fy"] }
        };
        this.thread = new Thread(this);
      }
      function Thread(session) {
        this.epoch = Date.now();
        this.session = session;
        this.session.total_threads++;
        this.format_success = session.format_success;
        this.format_error = session.format_error;
        this.total_steps = 0;
        this.cpu_time = 0;
        this.points = [];
        this.debugger = false;
        this.debugger_states = [];
        this.level = new Term("top_level");
        this.current_limit = this.session.limit;
        this.has_limit = this.session.limit !== null;
        this.warnings = [];
        this.__calls = [];
        this.__goal_expansion = false;
        this.__stacks = {};
      }
      function Module(id, rules2, exports2, options) {
        options = options === void 0 ? {} : options;
        options.public_predicates = options.public_predicates === void 0 ? {} : options.public_predicates;
        options.multifile_predicates = options.multifile_predicates === void 0 ? {} : options.multifile_predicates;
        options.meta_predicates = options.meta_predicates === void 0 ? {} : options.meta_predicates;
        options.session = options.session === void 0 ? null : options.session;
        options.dependencies = options.dependencies === void 0 ? [] : options.dependencies;
        this.id = id;
        this.rules = rules2;
        this.indexed_clauses = {};
        this.non_indexable_clauses = {};
        this.public_predicates = options.public_predicates;
        this.multifile_predicates = options.multifile_predicates;
        this.meta_predicates = options.meta_predicates;
        this.src_predicates = {};
        this.dependencies = options.dependencies;
        this.exports = exports2;
        this.is_library = options.session === null;
        this.modules = {};
        if (options.session) {
          options.session.modules[id] = this;
          for (var i2 = 0; i2 < options.dependencies.length; i2++) {
            var lib = options.dependencies[i2];
            if (!options.session.modules.hasOwnProperty(lib))
              options.session.modules[lib] = pl.modules[lib];
          }
        } else {
          pl.modules[id] = this;
        }
        if (exports2 !== "all") {
          for (var i2 = 0; i2 < exports2.length; i2++) {
            this.public_predicates[exports2[i2]] = options.public_predicates.hasOwnProperty(exports2[i2]) && options.public_predicates[exports2[i2]] === true;
          }
        }
        this.update_indices_clauses();
      }
      Module.prototype.exports_predicate = function(indicator2) {
        return this.exports === "all" || indexOf(this.exports, indicator2) !== -1;
      };
      Module.prototype.is_public_predicate = function(indicator2) {
        return !this.public_predicates.hasOwnProperty(indicator2) || this.public_predicates[indicator2] === true;
      };
      Module.prototype.is_multifile_predicate = function(indicator2) {
        return this.multifile_predicates.hasOwnProperty(indicator2) && this.multifile_predicates[indicator2] === true;
      };
      Module.prototype.is_meta_predicate = function(indicator2) {
        if (this.meta_predicates.hasOwnProperty(indicator2))
          return this.meta_predicates[indicator2];
        return null;
      };
      Module.prototype.update_indices_clauses = function() {
        this.indexed_clauses = {};
        this.non_indexable_clauses = {};
        for (var indicator2 in this.rules)
          this.update_indices_predicate(indicator2);
      };
      Module.prototype.update_indices_predicate = function(indicator2) {
        this.indexed_clauses[indicator2] = {};
        this.non_indexable_clauses[indicator2] = [];
        if (!Array.isArray(this.rules[indicator2]))
          return;
        for (var i2 = 0; i2 < this.rules[indicator2].length; i2++) {
          var clause = this.rules[indicator2][i2];
          this.add_index_predicate(clause);
        }
      };
      Module.prototype.add_index_predicate = function(clause) {
        var indicator2 = clause.head.indicator;
        var index = clause.head.args.length > 0 ? clause.head.args[0].index : void 0;
        if (index) {
          if (!this.indexed_clauses.hasOwnProperty(indicator2))
            this.indexed_clauses[indicator2] = {};
          if (!this.indexed_clauses[indicator2].hasOwnProperty(index)) {
            this.indexed_clauses[indicator2][index] = [];
            if (this.non_indexable_clauses.hasOwnProperty(indicator2))
              for (var j = 0; j < this.non_indexable_clauses[indicator2].length; j++)
                this.indexed_clauses[indicator2][index].push(this.non_indexable_clauses[indicator2][j]);
          }
          this.indexed_clauses[indicator2][index].push(clause);
        } else {
          if (!this.non_indexable_clauses.hasOwnProperty(indicator2))
            this.non_indexable_clauses[indicator2] = [];
          this.non_indexable_clauses[indicator2].push(clause);
          for (var index in this.indexed_clauses[indicator2])
            this.indexed_clauses[indicator2][index].push(clause);
        }
      };
      Var.prototype.unify = function(obj, occurs_check) {
        if (occurs_check && indexOf(obj.variables(), this.id) !== -1 && !pl.type.is_variable(obj))
          return null;
        var links = {};
        links[this.id] = obj;
        return new Substitution(links);
      };
      Num.prototype.unify = function(obj, occurs_check) {
        if (pl.type.is_number(obj) && this.value === obj.value && this.is_float === obj.is_float)
          return new Substitution();
        return null;
      };
      Term.prototype.unify = function(obj, occurs_check) {
        if (!pl.type.is_term(obj) && obj.unify !== void 0) {
          return obj.unify(this, occurs_check);
        } else if (pl.type.is_term(obj) && this.indicator === obj.indicator) {
          var subs = new Substitution();
          for (var i2 = 0; i2 < this.args.length; i2++) {
            var mgu = pl.unify(this.args[i2].apply(subs), obj.args[i2].apply(subs), occurs_check);
            if (mgu === null)
              return null;
            for (var x in mgu.links)
              subs.links[x] = mgu.links[x];
            subs = subs.apply(mgu);
          }
          return subs;
        }
        return null;
      };
      Stream.prototype.unify = function(obj, _occurs_check) {
        if (pl.type.is_stream(obj) && this.id === obj.id)
          return new Substitution();
        return null;
      };
      Stream.prototype.compare = function(obj) {
        if (this.id < obj.id)
          return -1;
        else if (this.id === obj.id)
          return 0;
        else
          return 1;
      };
      Var.prototype.toString = function(options) {
        options = options === void 0 ? {} : options;
        if (options.variable_names) {
          var pointer = options.variable_names;
          while (pl.type.is_term(pointer) && pointer.indicator === "./2") {
            var head = pointer.args[0];
            if (pl.type.is_term(head) && head.indicator === "=/2" && pl.type.is_variable(head.args[1]) && head.args[1].id === this.id && pl.type.is_atom(head.args[0]))
              return head.args[0].id;
            pointer = pointer.args[1];
          }
        }
        return this.id;
      };
      Num.prototype.toString = function(_) {
        var str = this.value.toString();
        var e = str.indexOf("e");
        if (e !== -1) {
          if (str.indexOf(".") !== -1)
            return str;
          else
            return str.replace("e", ".0e");
        }
        return this.is_float && indexOf(str, ".") === -1 ? this.value + ".0" : str;
      };
      Term.prototype.toString = function(options, priority, from) {
        options = !options ? {} : options;
        options.quoted = options.quoted === void 0 ? false : options.quoted;
        options.ignore_ops = options.ignore_ops === void 0 ? false : options.ignore_ops;
        options.numbervars = options.numbervars === void 0 ? false : options.numbervars;
        options.variable_names = options.variable_names === void 0 ? false : options.variable_names;
        priority = priority === void 0 ? { priority: 1200, class: "", indicator: "" } : priority;
        from = from === void 0 ? "" : from;
        var arg_priority = { priority: 999, class: "", indicator: "" };
        if (options.numbervars && this.indicator === "$VAR/1" && pl.type.is_integer(this.args[0]) && this.args[0].value >= 0) {
          var i2 = this.args[0].value;
          var number = Math.floor(i2 / 26);
          var letter = i2 % 26;
          return "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[letter] + (number !== 0 ? number : "");
        }
        switch (this.indicator) {
          case "[]/0":
          case "{}/0":
          case "!/0":
            return this.id;
          case "{}/1":
            if (options.ignore_ops === false) {
              return "{" + this.args[0].toString(options) + "}";
            } else {
              return "{}(" + this.args[0].toString(options) + ")";
            }
          case "./2":
            if (options.ignore_ops === false) {
              var list = "[" + this.args[0].toString(options, arg_priority);
              var pointer = this.args[1];
              while (pointer.indicator === "./2") {
                list += "," + pointer.args[0].toString(options, arg_priority);
                pointer = pointer.args[1];
              }
              if (pointer.indicator !== "[]/0") {
                list += "|" + pointer.toString(options, arg_priority);
              }
              list += "]";
              return list;
            }
          default:
            var id = this.id;
            var operator = options.session ? options.session.lookup_operator(this.id, this.args.length) : null;
            if (options.session === void 0 || options.ignore_ops || operator === null) {
              if (options.quoted && (!/^(!|[a-z][0-9a-zA-Z_]*|[#\$\&\*\+\-\.\/\:\<\=\>\?\@\^\~\\]+)$/.test(id) && id !== "{}" && id !== "[]" || indexOf([".", ",", ";"], id) !== -1 || id.substring(0, 2) === "/*"))
                id = "'" + redoEscape(id) + "'";
              if (this.args.length === 0 && is_graphic_token(this.id) && priority.indicator !== "")
                return "(" + id + ")";
              return id + (this.args.length > 0 ? "(" + map(
                this.args,
                function(x) {
                  return x.toString(options, arg_priority);
                }
              ).join(",") + ")" : "");
            } else {
              var priority_op = parseInt(operator.priority);
              var priority_arg = parseInt(priority.priority);
              var cond = priority_op > priority_arg || priority_op === priority_arg && (operator.class === "xfx" || operator.class === "xfy" && this.indicator !== priority.indicator || operator.class === "yfx" && this.indicator !== priority.indicator || this.indicator === priority.indicator && operator.class === "yfx" && from === "right" || this.indicator === priority.indicator && operator.class === "xfy" && from === "left" || this.indicator === priority.indicator && operator.class === "xf" && from === "left" || this.indicator === priority.indicator && operator.class === "fx" && from === "right");
              operator.indicator = this.indicator;
              var lpar = cond ? "(" : "";
              var rpar = cond ? ")" : "";
              var space = !(is_graphic_token(this.id) || this.id === "," || this.id === ";") || operator.class.length === 2 || operator.class.length === 3 && pl.type.is_number(this.args[1]) && this.args[1].value < 0 ? " " : "";
              if (this.args.length === 0) {
                return lpar + this.id + rpar;
              } else if (["fy", "fx"].indexOf(operator.class) !== -1) {
                return lpar + id + space + this.args[0].toString(options, operator, "right") + rpar;
              } else if (["yf", "xf"].indexOf(operator.class) !== -1) {
                return lpar + this.args[0].toString(options, operator, "left") + space + id + rpar;
              } else {
                return lpar + this.args[0].toString(options, operator, "left") + space + this.id + space + this.args[1].toString(options, operator, "right") + rpar;
              }
            }
        }
      };
      Stream.prototype.toString = function(_) {
        return "<stream>(" + this.id + ")";
      };
      Substitution.prototype.toString = function(options) {
        var str = "{";
        for (var link in this.links) {
          if (!this.links.hasOwnProperty(link))
            continue;
          if (str !== "{") {
            str += ", ";
          }
          str += link + "/" + this.links[link].toString(options);
        }
        str += "}";
        return str;
      };
      State.prototype.toString = function(options) {
        if (this.goal === null) {
          return "<" + this.substitution.toString(options) + ">";
        } else {
          return "<" + this.goal.toString(options) + ", " + this.substitution.toString(options) + ">";
        }
      };
      Rule.prototype.toString = function(options) {
        if (!this.body) {
          return this.head.toString(options) + ".";
        } else {
          return this.head.toString(options, 1200, "left") + " :- " + this.body.toString(options, 1200, "right") + ".";
        }
      };
      Session.prototype.toString = function(options) {
        var str = "";
        for (var prop in this.modules) {
          if (this.modules.hasOwnProperty(prop) && this.modules[prop].is_library)
            str += ":- use_module(library(" + this.modules[prop] + ")).\n";
        }
        str += "\n";
        for (var key in this.modules.user.rules) {
          if (!this.modules.user.rules.hasOwnProperty(key))
            continue;
          for (i = 0; i < this.modules.user.rules[key].length; i++) {
            str += this.modules.user.rules[key][i].toString(options);
            str += "\n";
          }
        }
        return str;
      };
      Var.prototype.clone = function() {
        return new Var(this.id);
      };
      Num.prototype.clone = function() {
        return new Num(this.value, this.is_float);
      };
      Term.prototype.clone = function() {
        var term = new Term(this.id, map(this.args, function(arg) {
          return arg.clone();
        }));
        if (this.definition_module)
          term.definition_module = this.definition_module;
        return term;
      };
      Stream.prototype.clone = function() {
        return new Stream(this.stream, this.mode, this.alias, this.type, this.reposition, this.eof_action);
      };
      Substitution.prototype.clone = function() {
        var links = {};
        var attrs = {};
        for (var link in this.links) {
          if (!this.links.hasOwnProperty(link))
            continue;
          links[link] = this.links[link].clone();
        }
        for (var attr in this.attrs) {
          if (!this.attrs.hasOwnProperty(attrs))
            continue;
          attrs[attr] = {};
          for (var m in this.attrs[attr]) {
            if (!this.attrs[attr].hasOwnProperty(m))
              continue;
            attrs[attr][m] = this.attrs[attr][m].clone();
          }
        }
        return new Substitution(links, attrs);
      };
      State.prototype.clone = function() {
        return new State(this.goal.clone(), this.substitution.clone(), this.parent);
      };
      Rule.prototype.clone = function() {
        return new Rule(this.head.clone(), this.body !== null ? this.body.clone() : null);
      };
      Var.prototype.equals = function(obj) {
        return pl.type.is_variable(obj) && this.id === obj.id;
      };
      Num.prototype.equals = function(obj) {
        return pl.type.is_number(obj) && this.value === obj.value && this.is_float === obj.is_float;
      };
      Term.prototype.equals = function(obj) {
        if (!pl.type.is_term(obj) || this.indicator !== obj.indicator) {
          return false;
        }
        for (var i2 = 0; i2 < this.args.length; i2++) {
          if (!this.args[i2].equals(obj.args[i2])) {
            return false;
          }
        }
        return true;
      };
      Stream.prototype.equals = function(obj) {
        return pl.type.is_stream(obj) && this.id === obj.id;
      };
      Substitution.prototype.equals = function(obj) {
        var link;
        if (!pl.type.is_substitution(obj)) {
          return false;
        }
        for (link in this.links) {
          if (!this.links.hasOwnProperty(link))
            continue;
          if (!obj.links[link] || !this.links[link].equals(obj.links[link])) {
            return false;
          }
        }
        for (link in obj.links) {
          if (!obj.links.hasOwnProperty(link))
            continue;
          if (!this.links[link]) {
            return false;
          }
        }
        return true;
      };
      State.prototype.equals = function(obj) {
        return pl.type.is_state(obj) && this.goal.equals(obj.goal) && this.substitution.equals(obj.substitution) && this.parent === obj.parent;
      };
      Rule.prototype.equals = function(obj) {
        return pl.type.is_rule(obj) && this.head.equals(obj.head) && (this.body === null && obj.body === null || this.body !== null && this.body.equals(obj.body));
      };
      Var.prototype.rename = function(thread) {
        return thread.get_free_variable(this);
      };
      Num.prototype.rename = function(_) {
        return this;
      };
      Term.prototype.rename = function(thread) {
        if (this.ground)
          return new Term(this.id, this.args);
        if (this.indicator === "./2") {
          var arr = [];
          var pointer = this;
          while (pointer.indicator === "./2" && !pointer.ground) {
            var app = pointer.args[0].rename(thread);
            arr.push(app);
            pointer = pointer.args[1];
          }
          var list = pointer.rename(thread);
          for (var i2 = arr.length - 1; i2 >= 0; i2--)
            list = new Term(".", [arr[i2], list]);
          return list;
        }
        var args = [];
        for (var i2 = 0; i2 < this.args.length; i2++) {
          var app = this.args[i2].rename(thread);
          args.push(app);
        }
        return new Term(this.id, args);
      };
      Stream.prototype.rename = function(thread) {
        return this;
      };
      Rule.prototype.rename = function(thread) {
        return new Rule(this.head.rename(thread), this.body !== null ? this.body.rename(thread) : null);
      };
      Var.prototype.is_rename = function(obj, links) {
        links = links || {};
        if (!pl.type.is_variable(obj) || links.hasOwnProperty(this.id) && links[this.id] !== obj.id || links.hasOwnProperty(obj.id) && links[obj.id] !== this.id)
          return false;
        links[this.id] = obj.id;
        links[obj.id] = this.id;
        return true;
      };
      Num.prototype.is_rename = function(obj, _links) {
        return this.equals(obj);
      };
      Term.prototype.is_rename = function(obj, links) {
        links = links || {};
        if (!pl.type.is_term(obj) || this.indicator !== obj.indicator)
          return false;
        for (var i2 = 0; i2 < this.args.length; i2++) {
          if (!pl.is_rename(this.args[i2], obj.args[i2], links))
            return false;
        }
        return true;
      };
      Stream.prototype.is_rename = function(obj, _links) {
        return this.equals(obj);
      };
      Var.prototype.variables = function() {
        return [this.id];
      };
      Num.prototype.variables = function() {
        return [];
      };
      Term.prototype.variables = function() {
        if (this.ground)
          return [];
        return [].concat.apply([], map(this.args, function(arg) {
          return arg.variables();
        }));
      };
      Stream.prototype.variables = function() {
        return [];
      };
      Rule.prototype.variables = function() {
        if (this.body === null) {
          return this.head.variables();
        } else {
          return this.head.variables().concat(this.body.variables());
        }
      };
      Var.prototype.apply = function(subs) {
        if (subs.lookup(this.id)) {
          return subs.lookup(this.id);
        }
        return this;
      };
      Num.prototype.apply = function(_) {
        return this;
      };
      Term.prototype.apply = function(subs) {
        if (this.ground)
          return this;
        if (this.indicator === "./2") {
          var arr = [];
          var pointer = this;
          while (pointer.indicator === "./2" && !pointer.ground) {
            var app = pointer.args[0].apply(subs);
            arr.push(app);
            pointer = pointer.args[1];
          }
          var list = pointer.apply(subs);
          for (var i2 = arr.length - 1; i2 >= 0; i2--)
            list = new Term(".", [arr[i2], list]);
          return list;
        }
        var args = [];
        for (var i2 = 0; i2 < this.args.length; i2++) {
          var app = this.args[i2].apply(subs);
          args.push(app);
        }
        return new Term(this.id, args, this.ref);
      };
      Stream.prototype.apply = function(_) {
        return this;
      };
      Rule.prototype.apply = function(subs) {
        return new Rule(this.head.apply(subs), this.body !== null ? this.body.apply(subs) : null);
      };
      Substitution.prototype.apply = function(subs) {
        var link, links = {}, attr, attrs = {}, m;
        for (link in this.links) {
          if (!this.links.hasOwnProperty(link))
            continue;
          links[link] = this.links[link].apply(subs);
        }
        for (attr in this.attrs) {
          if (!this.attrs.hasOwnProperty(attr))
            continue;
          attrs[attr] = {};
          for (m in this.attrs[attr]) {
            if (!this.attrs[attr].hasOwnProperty(m))
              continue;
            attrs[attr][m] = this.attrs[attr][m].apply(subs);
          }
        }
        return new Substitution(links, attrs);
      };
      Term.prototype.select = function() {
        var pointer = this;
        while (pl.type.is_term(pointer) && pointer.indicator === ",/2")
          pointer = pointer.args[0];
        return pointer;
      };
      Term.prototype.replace = function(expr) {
        if (this.indicator === ",/2") {
          if (this.args[0].indicator === ",/2") {
            return new Term(",", [this.args[0].replace(expr), this.args[1]]);
          } else {
            return expr === null ? this.args[1] : new Term(",", [expr, this.args[1]]);
          }
        } else {
          return expr;
        }
      };
      Term.prototype.search = function(expr) {
        if (this == expr || this.ref === expr.ref)
          return true;
        for (var i2 = 0; i2 < this.args.length; i2++)
          if (pl.type.is_term(this.args[i2]) && this.args[i2].search(expr))
            return true;
        return false;
      };
      Session.prototype.push_global_stack = function(stack, value) {
        return this.thread.push_global_stack(stack, value);
      };
      Thread.prototype.push_global_stack = function(stack, value) {
        if (!this.__stacks.hasOwnProperty(stack))
          this.__stacks[stack] = [];
        this.__stacks[stack].push(value);
      };
      Session.prototype.flush_global_stack = function(stack, tail) {
        return this.thread.push_global_stack(stack, tail);
      };
      Thread.prototype.flush_global_stack = function(stack, tail) {
        var list = tail || new Term("[]", []);
        if (this.__stacks.hasOwnProperty(stack)) {
          while (this.__stacks[stack].length > 0)
            list = new Term(".", [this.__stacks[stack].pop(), list]);
          delete this.__stacks[stack];
        }
        return list;
      };
      Session.prototype.setMaxInferences = function(max) {
        this.limit = typeof max === "number" && max > 0 ? max : null;
      };
      Thread.prototype.setMaxInferences = function(max) {
        this.session.setMaxInferences(max);
        this.current_limit = this.session.limit;
        this.has_limit = this.session.limit !== null;
      };
      Session.prototype.format_answer = function(answer, options) {
        return this.thread.format_answer(answer, options);
      };
      Thread.prototype.format_answer = function(answer, options) {
        return pl.format_answer(answer, this, options);
      };
      Session.prototype.get_current_input = function() {
        return this.current_input;
      };
      Thread.prototype.get_current_input = function() {
        return this.session.get_current_input();
      };
      Session.prototype.get_current_output = function() {
        return this.current_output;
      };
      Thread.prototype.get_current_output = function() {
        return this.session.get_current_output();
      };
      Session.prototype.set_current_input = function(input) {
        this.current_input = input;
      };
      Thread.prototype.set_current_input = function(input) {
        return this.session.set_current_input(input);
      };
      Session.prototype.set_current_output = function(output) {
        this.current_output = output;
      };
      Thread.prototype.set_current_output = function(output) {
        return this.session.set_current_output(output);
      };
      Session.prototype.get_stream_by_alias = function(alias) {
        return this.streams[alias];
      };
      Thread.prototype.get_stream_by_alias = function(alias) {
        return this.session.get_stream_by_alias(alias);
      };
      Session.prototype.file_system_open = function(path6, type, mode) {
        if (this.get_flag("nodejs").indicator === "false/0")
          path6 = this.absolute_file_name(path6);
        return this.file_system.open(path6, type, mode);
      };
      Thread.prototype.file_system_open = function(path6, type, mode) {
        return this.session.file_system_open(path6, type, mode);
      };
      Session.prototype.absolute_file_name = function(filename) {
        var absolute;
        if (this.get_flag("nodejs").indicator === "true/0") {
          var path6 = require("path");
          absolute = filename;
          for (var prop in process.env) {
            if (!process.env.hasOwnProperty(prop))
              continue;
            absolute = absolute.replace(new RegExp("\\$" + prop, "g"), process.env[prop]);
          }
          return path6.resolve(absolute);
        } else {
          var cwd = this.working_directory;
          if (filename[0] === "/")
            absolute = filename;
          else
            absolute = cwd + (cwd[cwd.length - 1] === "/" ? filename : "/" + filename);
          absolute = absolute.replace(/\/\.\//g, "/");
          var dirs = absolute.split("/");
          var dirs2 = [];
          for (var i2 = 0; i2 < dirs.length; i2++) {
            if (dirs[i2] !== "..") {
              dirs2.push(dirs[i2]);
            } else {
              if (dirs2.length !== 0)
                dirs2.pop();
            }
          }
          absolute = dirs2.join("/").replace(/\/\.$/, "/");
        }
        return absolute;
      };
      Thread.prototype.absolute_file_name = function(path6, cwd) {
        return this.session.absolute_file_name(path6, cwd);
      };
      Session.prototype.get_char_conversion = function(char) {
        return this.__char_conversion[char] || char;
      };
      Thread.prototype.get_char_conversion = function(char) {
        return this.session.get_char_conversion(char);
      };
      Session.prototype.parse = function(string) {
        return this.thread.parse(string);
      };
      Thread.prototype.parse = function(string) {
        var tokenizer = new Tokenizer(this);
        tokenizer.new_text(string);
        var tokens = tokenizer.get_tokens();
        if (tokens === null)
          return false;
        var expr = parseExpr(this, tokens, 0, this.__get_max_priority(), false);
        if (expr.len !== tokens.length)
          return false;
        return { value: expr.value, expr, tokens };
      };
      Session.prototype.get_flag = function(flag) {
        return this.flag[flag];
      };
      Thread.prototype.get_flag = function(flag) {
        return this.session.get_flag(flag);
      };
      Session.prototype.add_rule = function(rule, options) {
        return this.thread.add_rule(rule, options);
      };
      Thread.prototype.add_rule = function(rule, options) {
        options = options ? options : {};
        options.from = options.from ? options.from : "$tau-js";
        var module_id, get_module;
        if (pl.type.is_term(rule.head) && rule.head.indicator === ":/2") {
          if (!pl.type.is_atom(rule.head.args[0])) {
            this.throw_warning(pl.error.type("module", rule.head.args[0], "top_level/0"));
            return;
          }
          module_id = rule.head.args[0].id;
          rule.head = rule.head.args[1];
        }
        if (module_id) {
          get_module = this.session.modules[module_id];
          if (!pl.type.is_module(get_module)) {
            get_module = new Module(module_id, {}, "all", { session: this.session });
            this.session.modules[module_id] = get_module;
          }
        } else {
          get_module = this.session.modules[options.context_module];
        }
        get_module.src_predicates[rule.head.indicator] = options.from;
        if (!get_module.rules.hasOwnProperty(rule.head.indicator)) {
          get_module.rules[rule.head.indicator] = [];
        }
        get_module.rules[rule.head.indicator].push(rule);
        if (!get_module.public_predicates.hasOwnProperty(rule.head.indicator))
          get_module.public_predicates[rule.head.indicator] = false;
        get_module.add_index_predicate(rule);
        return true;
      };
      Session.prototype.run_directive = function(directive, options) {
        return this.thread.run_directive(directive, options);
      };
      Thread.prototype.run_directive = function(directive, options) {
        if (pl.type.is_directive(directive)) {
          if (pl.directive[directive.indicator])
            return pl.directive[directive.indicator](this, directive, options);
          else
            return pl.directive[directive.id + "/*"](this, directive, options);
        }
        return false;
      };
      Session.prototype.__get_max_priority = function() {
        return "1200";
      };
      Thread.prototype.__get_max_priority = function() {
        return this.session.__get_max_priority();
      };
      Session.prototype.__get_next_priority = function(priority) {
        var max = 0;
        priority = parseInt(priority);
        for (var key in this.__operators) {
          if (!this.__operators.hasOwnProperty(key))
            continue;
          var n = parseInt(key);
          if (n > max && n < priority)
            max = n;
        }
        return max.toString();
      };
      Thread.prototype.__get_next_priority = function(priority) {
        return this.session.__get_next_priority(priority);
      };
      Session.prototype.__lookup_operator_classes = function(priority, operator) {
        if (this.__operators.hasOwnProperty(priority) && this.__operators[priority][operator] instanceof Array) {
          return this.__operators[priority][operator] || false;
        }
        return false;
      };
      Thread.prototype.__lookup_operator_classes = function(priority, operator) {
        return this.session.__lookup_operator_classes(priority, operator);
      };
      Session.prototype.lookup_operator = function(name, arity) {
        for (var p in this.__operators)
          if (this.__operators[p][name]) {
            for (var i2 = 0; i2 < this.__operators[p][name].length; i2++)
              if (this.__operators[p][name][i2].length === arity + 1)
                return { priority: p, class: this.__operators[p][name][i2] };
          }
        return null;
      };
      Thread.prototype.lookup_operator = function(name, arity) {
        return this.session.lookup_operator(name, arity);
      };
      Session.prototype.throw_warning = function(warning) {
        this.thread.throw_warning(warning);
      };
      Thread.prototype.throw_warning = function(warning) {
        this.warnings.push(warning);
      };
      Session.prototype.get_warnings = function() {
        return this.thread.get_warnings();
      };
      Thread.prototype.get_warnings = function() {
        return this.warnings;
      };
      Session.prototype.add_goal = function(goal, unique) {
        this.thread.add_goal(goal, unique);
      };
      Thread.prototype.add_goal = function(goal, unique, parent) {
        parent = parent ? parent : null;
        if (unique === true)
          this.points = [];
        var vars = goal.variables();
        var links = {};
        for (var i2 = 0; i2 < vars.length; i2++)
          links[vars[i2]] = new Var(vars[i2]);
        this.points.push(new State(goal, new Substitution(links), parent));
      };
      Session.prototype.consult = function(program, options) {
        return this.thread.consult(program, options);
      };
      Thread.prototype.consult = function(program, options) {
        var string = "", success = false;
        var opts = {};
        var callback = typeof options === "function" ? options : function() {
        };
        options = options === void 0 || typeof options === "function" ? {} : options;
        opts.context_module = options.context_module === void 0 ? "user" : options.context_module;
        opts.text = options.text === void 0 ? true : options.text;
        opts.html = options.html === void 0 ? true : options.html;
        opts.url = options.url === void 0 ? true : options.url;
        opts.file = options.file === void 0 ? true : options.file;
        opts.script = options.script === void 0 ? true : options.script;
        opts.success = options.success === void 0 ? callback : options.success;
        opts.error = options.error === void 0 ? callback : options.error;
        if (typeof program === "string") {
          string = program;
          if (opts.script && this.get_flag("nodejs").indicator === "false/0" && program != "" && document.getElementById(string)) {
            var script = document.getElementById(string);
            var type = script.getAttribute("type");
            if (type !== null && type.replace(/ /g, "").toLowerCase() === "text/prolog") {
              string = script.text;
              success = true;
            }
          }
          if (!success && opts.file && this.get_flag("nodejs").indicator === "true/0") {
            var fs3 = require("fs");
            var thread = this;
            fs3.readFile(program, function(error, data) {
              if (error) {
                opts.file = false;
                thread.consult(program, opts);
              } else {
                parseProgram(thread, data.toString(), opts);
              }
            });
            return;
          }
          if (!success && this.get_flag("nodejs").indicator === "false/0" && opts.url && program !== "" && !/\s/.test(program)) {
            try {
              var xhttp = new XMLHttpRequest();
              var thread = this;
              xhttp.onreadystatechange = function() {
                if (this.readyState == 4) {
                  if (this.status == 200) {
                    string = xhttp.responseText;
                    success = true;
                    parseProgram(thread, string, opts);
                  } else {
                    opts.url = false;
                    thread.consult(program, opts);
                  }
                }
              };
              xhttp.open("GET", program, true);
              xhttp.send();
              return;
            } catch (ex) {
              opts.error(ex);
              return;
            }
          }
          if (!success && opts.text) {
            success = true;
          }
        } else if (opts.html && program.nodeName) {
          switch (program.nodeName.toLowerCase()) {
            case "input":
            case "textarea":
              string = program.value;
              success = true;
              break;
            default:
              string = program.innerHTML;
              success = true;
              break;
          }
        } else {
          opts.error(pl.error.existence("source_sink", new Term(string), "top_level/0"));
        }
        this.warnings = [];
        parseProgram(this, string, opts);
      };
      Session.prototype.query = function(string, options) {
        return this.thread.query(string, options);
      };
      Thread.prototype.query = function(string, options) {
        this.points = [];
        this.debugger_states = [];
        this.level = new Term("top_level");
        return parseQuery(this, string, options);
      };
      Session.prototype.head_point = function() {
        return this.thread.head_point();
      };
      Thread.prototype.head_point = function() {
        return this.points[this.points.length - 1];
      };
      Session.prototype.get_free_variable = function(variable) {
        return this.thread.get_free_variable(variable);
      };
      Thread.prototype.get_free_variable = function(variable) {
        var variables = [];
        if (variable.id === "_" || this.session.renamed_variables[variable.id] === void 0) {
          this.session.rename++;
          if (this.current_point)
            variables = this.current_point.substitution.domain();
          while (indexOf(variables, pl.format_variable(this.session.rename, variable.id)) !== -1) {
            this.session.rename++;
          }
          if (variable.id === "_") {
            return new Var(pl.format_variable(this.session.rename, variable.id));
          } else {
            this.session.renamed_variables[variable.id] = pl.format_variable(this.session.rename, variable.id);
          }
        }
        return new Var(this.session.renamed_variables[variable.id]);
      };
      Session.prototype.next_free_variable = function() {
        return this.thread.next_free_variable();
      };
      Thread.prototype.next_free_variable = function() {
        this.session.rename++;
        var variables = [];
        if (this.current_point)
          variables = this.current_point.substitution.domain();
        while (indexOf(variables, pl.format_variable(this.session.rename)) !== -1) {
          this.session.rename++;
        }
        return new Var(pl.format_variable(this.session.rename));
      };
      Session.prototype.is_public_predicate = function(indicator2, module_id) {
        module_id = module_id === void 0 ? "user" : module_id;
        return pl.type.is_module(this.modules[module_id]) && this.modules[module_id].is_public_predicate(indicator2);
      };
      Thread.prototype.is_public_predicate = function(indicator2, module_id) {
        return this.session.is_public_predicate(indicator2, module_id);
      };
      Session.prototype.is_multifile_predicate = function(indicator2, module_id) {
        module_id = module_id === void 0 ? "user" : module_id;
        return pl.type.is_module(this.modules[module_id]) && this.modules[module_id].is_multifile_predicate(indicator2);
      };
      Thread.prototype.is_multifile_predicate = function(indicator2, module_id) {
        return this.session.is_multifile_predicate(indicator2, module_id);
      };
      Session.prototype.is_meta_predicate = function(indicator2, module_id) {
        module_id = module_id === void 0 ? "user" : module_id;
        if (pl.type.is_module(this.modules[module_id]))
          return this.modules[module_id].is_meta_predicate(indicator2);
        return null;
      };
      Thread.prototype.is_meta_predicate = function(indicator2, module_id) {
        return this.session.is_meta_predicate(indicator2, module_id);
      };
      Session.prototype.prepend = function(states) {
        return this.thread.prepend(states);
      };
      Thread.prototype.prepend = function(states) {
        for (var i2 = states.length - 1; i2 >= 0; i2--)
          this.points.push(states[i2]);
      };
      Session.prototype.success = function(point, parent) {
        return this.thread.success(point, parent);
      };
      Thread.prototype.success = function(point, parent) {
        var parent = typeof parent === "undefined" ? point : parent;
        this.prepend([new State(point.goal.replace(null), point.substitution, parent)]);
      };
      Session.prototype.throw_error = function(error) {
        return this.thread.throw_error(error);
      };
      Thread.prototype.throw_error = function(error) {
        if (pl.type.is_variable(error))
          error = pl.error.instantiation(this.level.indicator);
        var state = new State(
          new Term("throw", [error]),
          new Substitution(),
          null
        );
        state.error = true;
        this.prepend([state]);
      };
      Session.prototype.lookup_module = function(atom, context_module) {
        return this.thread.lookup_module(atom, context_module);
      };
      Thread.prototype.lookup_module = function(atom, context_module) {
        var get_module = this.session.modules[context_module];
        if (!pl.type.is_module(get_module))
          get_module = this.session.modules.user;
        if (get_module.rules.hasOwnProperty(atom.indicator) && (get_module.exports_predicate(atom.indicator) || get_module.rules.hasOwnProperty(this.level.indicator) || context_module === get_module.id))
          return get_module;
        get_module.modules.system = pl.modules.system;
        get_module.modules.user = this.session.modules.user;
        for (var prop in get_module.modules) {
          if (!this.session.modules.hasOwnProperty(prop))
            continue;
          var get_module = this.session.modules[prop];
          if (get_module.rules.hasOwnProperty(atom.indicator) && (get_module.exports_predicate(atom.indicator) || get_module.rules.hasOwnProperty(this.level.indicator) || context_module === get_module.id))
            return get_module;
        }
        return null;
      };
      Session.prototype.expand_meta_predicate = function(atom, definition_module, context_module) {
        return this.thread.expand_meta_predicate(atom, definition_module, context_module);
      };
      Thread.prototype.expand_meta_predicate = function(atom, definition_module, context_module) {
        var get_module = this.session.modules[definition_module];
        if (!get_module)
          return;
        var meta = get_module.is_meta_predicate(atom.indicator);
        if (!meta)
          return;
        for (var i2 = 0; i2 < meta.args.length; i2++) {
          if (pl.type.is_integer(meta.args[i2]) || pl.type.is_atom(meta.args[i2]) && indexOf([":"], meta.args[i2].id) !== -1) {
            if (!pl.type.is_term(atom.args[i2]) || atom.args[i2].indicator !== ":/2") {
              atom.args[i2] = new Term(":", [new Term(context_module), atom.args[i2]]);
            }
          } else if (pl.type.is_atom(meta.args[i2]) && meta.args[i2].id === "^") {
            var pointer_last = atom;
            var pointer_index = i2;
            var pointer = atom.args[i2];
            while (pl.type.is_term(pointer) && pointer.indicator === "^/2") {
              pointer_last = pointer;
              pointer_index = 1;
              pointer = pointer.args[1];
            }
            if (!pl.type.is_term(pointer) || pointer.indicator !== ":/2") {
              pointer_last.args[pointer_index] = new Term(":", [new Term(context_module), pointer]);
            }
          }
        }
      };
      Session.prototype.step = function() {
        return this.thread.step();
      };
      Thread.prototype.step = function() {
        if (this.points.length === 0) {
          return;
        }
        var asyn = false;
        var point = this.points.pop();
        this.current_point = point;
        if (this.debugger)
          this.debugger_states.push(point);
        var atom = pl.type.is_term(point.goal) ? point.goal.select() : point.goal;
        if (pl.type.is_term(atom) && (atom.indicator !== ":/2" || pl.type.is_term(atom.args[1]))) {
          var context_module = null;
          var states = [];
          if (atom !== null) {
            this.total_steps++;
            var level = point;
            while (level.parent !== null && level.parent.goal.search(atom))
              level = level.parent;
            if (level.parent === null) {
              this.level = new Term("top_level");
            } else {
              this.level = level.parent.goal.select();
              if (this.level.indicator === ":/2")
                this.level = this.level.args[1];
            }
            if (pl.type.is_term(atom) && atom.indicator === ":/2") {
              context_module = atom.args[0];
              atom = atom.args[1];
              if (!pl.type.is_atom(context_module)) {
                this.throw_error(pl.error.type("module", context_module, this.level.indicator));
                return;
              }
              context_module = context_module.id;
            } else {
              if (this.level.definition_module) {
                context_module = this.level.definition_module;
              } else {
                context_module = "user";
              }
            }
            atom.context_module = context_module;
            if (atom.indicator === ",/2") {
              this.prepend([new State(
                point.goal.replace(new Term(",", [
                  new Term(":", [new Term(context_module), atom.args[0]]),
                  new Term(":", [new Term(context_module), atom.args[1]])
                ])),
                point.substitution,
                point
              )]);
              return;
            }
            this.__call_indicator = atom.indicator;
            var get_module = this.lookup_module(atom, context_module);
            atom.definition_module = pl.type.is_module(get_module) ? get_module.id : "user";
            this.expand_meta_predicate(atom, atom.definition_module, context_module);
            var clauses = null;
            if (get_module && atom.args.length > 0 && atom.args[0].index && get_module.indexed_clauses.hasOwnProperty(atom.indicator) && get_module.indexed_clauses[atom.indicator].hasOwnProperty(atom.args[0].index))
              clauses = get_module.indexed_clauses[atom.indicator][atom.args[0].index];
            else
              clauses = get_module === null ? null : get_module.rules[atom.indicator];
            if (clauses === null) {
              if (!this.session.modules.user.rules.hasOwnProperty(atom.indicator)) {
                if (this.get_flag("unknown").id === "error") {
                  this.throw_error(pl.error.existence("procedure", atom.indicator, this.level.indicator));
                } else if (this.get_flag("unknown").id === "warning") {
                  this.throw_warning("unknown procedure " + atom.indicator + " (from " + this.level.indicator + ")");
                }
              }
            } else if (clauses instanceof Function) {
              asyn = clauses(this, point, atom);
            } else {
              if (this.__goal_expansion && atom.indicator === "goal_expansion/2")
                clauses = clauses.concat(pl.builtin.rules["goal_expansion/2"]);
              for (var i2 = 0; i2 < clauses.length; i2++) {
                this.session.renamed_variables = {};
                var clause = clauses[i2].rename(this);
                var occurs_check = this.get_flag("occurs_check").indicator === "true/0";
                var mgu = pl.unify(atom, clause.head, occurs_check);
                if (mgu !== null) {
                  var state = new State();
                  state.goal = point.goal.replace(clause.body);
                  if (state.goal !== null)
                    state.goal = state.goal.apply(mgu);
                  state.substitution = point.substitution.apply(mgu);
                  state.parent = point;
                  states.push(state);
                }
              }
              this.prepend(states);
            }
          }
        } else {
          var term = pl.type.is_term(atom) && atom.indicator === ":/2" ? atom.args[1] : atom;
          if (pl.type.is_variable(term))
            this.throw_error(pl.error.instantiation(this.level.indicator));
          else
            this.throw_error(pl.error.type("callable", term, this.level.indicator));
        }
        return asyn;
      };
      Session.prototype.answer = function(options) {
        return this.thread.answer(options);
      };
      Thread.prototype.answer = function(options) {
        var opts = {};
        options = options || function() {
        };
        if (typeof options === "function") {
          opts = {
            success: options,
            error: options,
            fail: options,
            limit: options
          };
        } else {
          opts.success = options.success === void 0 ? function() {
          } : options.success;
          opts.error = options.error === void 0 ? function() {
          } : options.error;
          opts.fail = options.fail === void 0 ? function() {
          } : options.fail;
          opts.limit = options.limit === void 0 ? function() {
          } : options.limit;
        }
        this.__calls.push(opts);
        if (this.__calls.length > 1) {
          return;
        }
        this.again();
      };
      Session.prototype.answers = function(callback, max, after) {
        return this.thread.answers(callback, max, after);
      };
      Thread.prototype.answers = function(callback, max, after) {
        var answers = max === void 0 ? 1e3 : max;
        var thread = this;
        if (answers <= 0) {
          if (after)
            after();
          return;
        }
        this.answer(function(answer) {
          callback(answer);
          if (answer !== false) {
            setTimeout(function() {
              thread.answers(callback, answers - 1, after);
            }, 0);
          } else if (after) {
            after();
          }
        });
      };
      Session.prototype.again = function(reset_limit) {
        return this.thread.again(reset_limit);
      };
      Thread.prototype.again = function(reset_limit) {
        while (this.__calls.length > 0) {
          this.warnings = [];
          if (reset_limit !== false)
            this.current_limit = this.session.limit;
          while ((!this.has_limit || this.current_limit > 0) && this.points.length > 0 && this.head_point().goal !== null && !pl.type.is_error_state(this.head_point())) {
            if (this.has_limit)
              this.current_limit--;
            var t0 = Date.now();
            var asyn = this.step();
            var t1 = Date.now();
            this.cpu_time += t1 - t0;
            if (asyn === true)
              return;
          }
          var call = this.__calls.shift();
          if (this.has_limit && this.current_limit <= 0) {
            (function(call2) {
              return setTimeout(function() {
                call2.limit(null);
              }, 0);
            })(call);
          } else if (this.points.length === 0) {
            (function(call2) {
              return setTimeout(function() {
                call2.fail(false);
              }, 0);
            })(call);
          } else if (pl.type.is_error(this.head_point().goal)) {
            var error = this.format_error(this.points.pop());
            this.points = [];
            (function(error2, call2) {
              return setTimeout(function() {
                call2.error(error2);
              }, 0);
            })(error, call);
          } else {
            if (this.debugger)
              this.debugger_states.push(this.head_point());
            var answer = this.format_success(this.points.pop());
            (function(answer2, call2) {
              return setTimeout(function() {
                call2.success(answer2);
              }, 0);
            })(answer, call);
          }
        }
      };
      Session.prototype.unfold = function(rule) {
        if (rule.body === null)
          return false;
        var head = rule.head;
        var body = rule.body;
        var atom = body.select();
        var thread = new Thread(this);
        var unfolded = [];
        thread.add_goal(atom);
        thread.step();
        for (var i2 = thread.points.length - 1; i2 >= 0; i2--) {
          var point = thread.points[i2];
          var head2 = head.apply(point.substitution);
          var body2 = body.replace(point.goal);
          if (body2 !== null)
            body2 = body2.apply(point.substitution);
          unfolded.push(new Rule(head2, body2));
        }
        var rules2 = this.modules.user.rules[head.indicator];
        var index = indexOf(rules2, rule);
        if (unfolded.length > 0 && index !== -1) {
          rules2.splice.apply(rules2, [index, 1].concat(unfolded));
          return true;
        }
        return false;
      };
      Thread.prototype.unfold = function(rule) {
        return this.session.unfold(rule);
      };
      Var.prototype.interpret = function(thread) {
        return pl.error.instantiation(thread.level.indicator);
      };
      Num.prototype.interpret = function(thread) {
        return this;
      };
      Term.prototype.interpret = function(thread) {
        if (pl.type.is_unitary_list(this)) {
          return this.args[0].interpret(thread);
        } else {
          return pl.operate(thread, this);
        }
      };
      Var.prototype.compare = function(obj) {
        if (this.id < obj.id) {
          return -1;
        } else if (this.id > obj.id) {
          return 1;
        } else {
          return 0;
        }
      };
      Num.prototype.compare = function(obj) {
        if (this.value === obj.value && this.is_float === obj.is_float) {
          return 0;
        } else if (this.value < obj.value || this.value === obj.value && this.is_float && !obj.is_float) {
          return -1;
        } else if (this.value > obj.value) {
          return 1;
        }
      };
      Term.prototype.compare = function(obj) {
        if (this.args.length < obj.args.length || this.args.length === obj.args.length && this.id < obj.id) {
          return -1;
        } else if (this.args.length > obj.args.length || this.args.length === obj.args.length && this.id > obj.id) {
          return 1;
        } else {
          for (var i2 = 0; i2 < this.args.length; i2++) {
            var arg = pl.compare(this.args[i2], obj.args[i2]);
            if (arg !== 0) {
              return arg;
            }
          }
          return 0;
        }
      };
      Substitution.prototype.lookup = function(variable) {
        if (this.links[variable]) {
          return this.links[variable];
        } else {
          return null;
        }
      };
      Substitution.prototype.filter = function(predicate) {
        var links = {};
        for (var id in this.links) {
          if (!this.links.hasOwnProperty(id))
            continue;
          var value = this.links[id];
          if (predicate(id, value)) {
            links[id] = value;
          }
        }
        return new Substitution(links, this.attrs);
      };
      Substitution.prototype.exclude = function(variables) {
        var links = {};
        for (var variable in this.links) {
          if (!this.links.hasOwnProperty(variable))
            continue;
          if (indexOf(variables, variable) === -1) {
            links[variable] = this.links[variable];
          }
        }
        return new Substitution(links, this.attrs);
      };
      Substitution.prototype.add = function(variable, value) {
        this.links[variable] = value;
      };
      Substitution.prototype.domain = function(plain) {
        var f = plain === true ? function(x2) {
          return x2;
        } : function(x2) {
          return new Var(x2);
        };
        var vars = [];
        for (var x in this.links)
          vars.push(f(x));
        return vars;
      };
      Substitution.prototype.get_attribute = function(variable, module3) {
        if (this.attrs[variable])
          return this.attrs[variable][module3];
      };
      Substitution.prototype.set_attribute = function(variable, module3, value) {
        var subs = new Substitution(this.links);
        for (var v in this.attrs) {
          if (v === variable) {
            subs.attrs[v] = {};
            for (var m in this.attrs[v]) {
              subs.attrs[v][m] = this.attrs[v][m];
            }
          } else {
            subs.attrs[v] = this.attrs[v];
          }
        }
        if (!subs.attrs[variable]) {
          subs.attrs[variable] = {};
        }
        subs.attrs[variable][module3] = value;
        return subs;
      };
      Substitution.prototype.has_attributes = function(variable) {
        return this.attrs[variable] && this.attrs[variable] !== {};
      };
      Var.prototype.compile = function() {
        return 'new pl.type.Var("' + this.id.toString() + '")';
      };
      Num.prototype.compile = function() {
        return "new pl.type.Num(" + this.value.toString() + ", " + this.is_float.toString() + ")";
      };
      Term.prototype.compile = function() {
        return 'new pl.type.Term("' + this.id.replace(/"/g, '\\"') + '", [' + map(this.args, function(arg) {
          return arg.compile();
        }) + "])";
      };
      Rule.prototype.compile = function() {
        return "new pl.type.Rule(" + this.head.compile() + ", " + (this.body === null ? "null" : this.body.compile()) + ")";
      };
      Session.prototype.compile = function() {
        var str, obj = [], rules2;
        for (var _indicator in this.modules.user.rules) {
          if (!this.modules.user.rules.hasOwnProperty(_indicator))
            continue;
          var indicator2 = this.modules.user.rules[_indicator];
          rules2 = [];
          str = '"' + _indicator + '": [';
          for (var i2 = 0; i2 < indicator2.length; i2++) {
            rules2.push(indicator2[i2].compile());
          }
          str += rules2.join();
          str += "]";
          obj.push(str);
        }
        return "{" + obj.join() + "};";
      };
      Module.prototype.compile = function() {
        var length = 0;
        var dependencies = 0;
        var str = "var pl;\n";
        str += "(function(pl) {\n";
        str += '	var name = "' + this.id + '";\n';
        str += "	var predicates = function() {\n";
        str += "		return {\n";
        for (var prop in this.rules) {
          if (length > 0)
            str += ",\n";
          str += '			"' + prop + '": ';
          if (typeof this.rules[prop] === "function") {
            str += this.rules[prop];
          } else {
            str += "[\n";
            for (var i2 = 0; i2 < this.rules[prop].length; i2++) {
              str += "				" + this.rules[prop][i2].compile();
              if (i2 < this.rules[prop].length - 1)
                str += ",";
              str += "\n";
            }
            str += "			]";
          }
          length++;
        }
        str += "\n		};\n";
        str += "	};\n";
        str += "	var exports = [";
        for (var i2 = 0; i2 < this.exports.length; i2++) {
          if (i2 > 0)
            str += ", ";
          str += '"' + this.exports[i2] + '"';
        }
        str += "];\n";
        str += "	var options = function() {\n";
        str += "		return {\n";
        str += "			dependencies: [";
        for (var prop in this.modules) {
          if (dependencies > 0)
            str += ", ";
          str += '"' + prop + '"';
          dependencies++;
        }
        str += "]\n";
        str += "		};\n";
        str += "};\n";
        str += "	if(typeof module !== 'undefined') {\n";
        str += "		module.exports = function(p) {\n";
        str += "			pl = p;\n";
        str += "			new pl.type.Module(name, predicates(), exports, options());\n";
        str += "		};\n";
        str += "	} else {\n";
        str += "		new pl.type.Module(name, predicates(), exports, options());\n";
        str += "	}\n";
        str += "})(pl);\n";
        return str;
      };
      Var.prototype.toJavaScript = function() {
        return this.toString();
      };
      Num.prototype.toJavaScript = function() {
        return this.value;
      };
      Term.prototype.toJavaScript = function(options) {
        if (this.args.length === 0 && this.indicator !== "[]/0") {
          return this.toString(options);
        } else if (pl.type.is_list(this)) {
          var all_obj = true;
          var arr = [];
          var obj = {};
          var pointer = this;
          var value;
          while (pointer.indicator === "./2") {
            value = pointer.args[0].toJavaScript(options);
            arr.push(value);
            all_obj = all_obj && pl.type.is_term(pointer.args[0]) && pointer.args[0].indicator === "-/2" && pl.type.is_atom(pointer.args[0].args[0]);
            if (all_obj)
              obj[pointer.args[0].args[0].id] = pointer.args[0].args[1].toJavaScript(options);
            pointer = pointer.args[1];
          }
          if (pointer.indicator === "[]/0")
            return all_obj && arr.length > 0 ? obj : arr;
        }
        return this.toString(options);
      };
      Rule.prototype.singleton_variables = function(include_named) {
        include_named = include_named || false;
        var variables = this.head.variables();
        var count = {};
        var singleton = [];
        if (this.body !== null)
          variables = variables.concat(this.body.variables());
        for (var i2 = 0; i2 < variables.length; i2++) {
          if (count[variables[i2]] === void 0)
            count[variables[i2]] = 0;
          count[variables[i2]]++;
        }
        for (var key in count) {
          if (!count.hasOwnProperty(key))
            continue;
          if (count[key] === 1) {
            var charcode = codePointAt(key, 1);
            if (!include_named || key === "_") {
              if (key === "_" || key[0] === "_" && (charcode === 95 || charcode >= 65 && charcode <= 90))
                continue;
            }
            singleton.push(key);
          }
        }
        return singleton;
      };
      var nodejs_flag = typeof process !== "undefined" && !process.browser;
      var nodejs_arguments = nodejs_flag ? arrayToList(map(process.argv.slice(1), function(arg) {
        return new Term(arg);
      })) : new Term("[]", []);
      var pl = {
        __env: nodejs_flag ? global : window,
        modules: {},
        version,
        parser: {
          tokenizer: Tokenizer,
          expression: parseExpr
        },
        utils: {
          str_indicator,
          codePointAt,
          fromCodePoint,
          stringLength
        },
        statistics: {
          getCountTerms: function() {
            return term_ref;
          }
        },
        fromJavaScript: {
          test: {
            boolean: function(obj, tobj) {
              return obj === true || obj === false;
            },
            number: function(obj, tobj) {
              return typeof obj === "number";
            },
            string: function(obj, tobj) {
              return typeof obj === "string";
            },
            list: function(obj, tobj) {
              return obj instanceof Array;
            },
            variable: function(obj, tobj) {
              return obj === void 0;
            },
            object: function(obj, tobj) {
              tobj = tobj === void 0 ? false : tobj;
              return tobj && !(obj instanceof Array) && typeof obj === "object";
            },
            any: function(_, tobj) {
              return true;
            }
          },
          conversion: {
            boolean: function(obj, tobj) {
              return new Term(obj ? "true" : "false", []);
            },
            number: function(obj, tobj) {
              return new Num(obj, obj % 1 !== 0);
            },
            string: function(obj, tobj) {
              return new Term(obj, []);
            },
            list: function(obj, tobj) {
              tobj = tobj === void 0 ? false : tobj;
              var arr = [];
              var elem;
              for (var i2 = 0; i2 < obj.length; i2++) {
                elem = pl.fromJavaScript.apply(obj[i2], tobj);
                if (elem === void 0)
                  return void 0;
                arr.push(elem);
              }
              return arrayToList(arr);
            },
            variable: function(obj, tobj) {
              return new Var("_");
            },
            object: function(obj, tobj) {
              tobj = tobj === void 0 ? false : tobj;
              var list = new Term("[]", []);
              var arr = [];
              for (var prop in obj) {
                if (!obj.hasOwnProperty(prop))
                  continue;
                arr.push(new Term("-", [
                  pl.fromJavaScript.apply(prop, tobj),
                  pl.fromJavaScript.apply(obj[prop], tobj)
                ]));
              }
              return arrayToList(arr);
            },
            any: function(obj, tobj) {
              return void 0;
            }
          },
          apply: function(obj, tobj) {
            tobj = tobj === void 0 ? false : tobj;
            for (var i2 in pl.fromJavaScript.test)
              if (i2 !== "any" && pl.fromJavaScript.test[i2](obj, tobj))
                return pl.fromJavaScript.conversion[i2](obj, tobj);
            return pl.fromJavaScript.conversion.any(obj, tobj);
          }
        },
        type: {
          Var,
          Num,
          Term,
          Rule,
          State,
          Stream,
          Module,
          Thread,
          Session,
          Substitution,
          File: TauFile,
          Directory: TauDirectory,
          order: [Var, Num, Term, Stream],
          compare: function(x, y) {
            var ord_x = indexOf(pl.type.order, x.constructor);
            var ord_y = indexOf(pl.type.order, y.constructor);
            if (ord_x < ord_y) {
              return -1;
            } else if (ord_x > ord_y) {
              return 1;
            } else {
              if (x.constructor === Num) {
                if (x.is_float && y.is_float)
                  return 0;
                else if (x.is_float)
                  return -1;
                else if (y.is_float)
                  return 1;
              }
              return 0;
            }
          },
          is_substitution: function(obj) {
            return obj instanceof Substitution;
          },
          is_state: function(obj) {
            return obj instanceof State;
          },
          is_rule: function(obj) {
            return obj instanceof Rule;
          },
          is_variable: function(obj) {
            return obj instanceof Var;
          },
          is_stream: function(obj) {
            return obj instanceof Stream;
          },
          is_anonymous_var: function(obj) {
            return obj instanceof Var && obj.id === "_";
          },
          is_callable: function(obj) {
            return obj instanceof Term && (indexOf([",/2", ";/2", "->/2"], obj.indicator) === -1 || pl.type.is_callable(obj.args[0]) && pl.type.is_callable(obj.args[1])) || obj instanceof Var;
          },
          is_number: function(obj) {
            return obj instanceof Num;
          },
          is_integer: function(obj) {
            return obj instanceof Num && !obj.is_float;
          },
          is_float: function(obj) {
            return obj instanceof Num && obj.is_float;
          },
          is_term: function(obj) {
            return obj instanceof Term;
          },
          is_atom: function(obj) {
            return obj instanceof Term && obj.args.length === 0;
          },
          is_ground: function(obj) {
            if (obj instanceof Var)
              return false;
            if (obj instanceof Term) {
              for (var i2 = 0; i2 < obj.args.length; i2++)
                if (!pl.type.is_ground(obj.args[i2]))
                  return false;
            }
            return true;
          },
          is_atomic: function(obj) {
            return obj instanceof Term && obj.args.length === 0 || obj instanceof Num;
          },
          is_compound: function(obj) {
            return obj instanceof Term && obj.args.length > 0;
          },
          is_list: function(obj) {
            return obj instanceof Term && (obj.indicator === "[]/0" || obj.indicator === "./2");
          },
          is_empty_list: function(obj) {
            return obj instanceof Term && obj.indicator === "[]/0";
          },
          is_non_empty_list: function(obj) {
            return obj instanceof Term && obj.indicator === "./2";
          },
          is_fully_list: function(obj) {
            while (obj instanceof Term && obj.indicator === "./2") {
              obj = obj.args[1];
            }
            return obj instanceof Var || obj instanceof Term && obj.indicator === "[]/0";
          },
          is_instantiated_list: function(obj) {
            while (obj instanceof Term && obj.indicator === "./2") {
              obj = obj.args[1];
            }
            return obj instanceof Term && obj.indicator === "[]/0";
          },
          is_unitary_list: function(obj) {
            return obj instanceof Term && obj.indicator === "./2" && obj.args[1] instanceof Term && obj.args[1].indicator === "[]/0";
          },
          is_character: function(obj) {
            return obj instanceof Term && obj.args.length === 0 && (obj.id.length === 1 || obj.id.length > 0 && obj.id.length <= 2 && codePointAt(obj.id, 0) >= 65536);
          },
          is_in_character: function(obj) {
            return obj instanceof Term && (obj.indicator === "end_of_file/0" || obj.id.length === 1 || obj.id.length > 0 && obj.id.length <= 2 && codePointAt(obj.id, 0) >= 65536);
          },
          is_character_code: function(obj) {
            return obj instanceof Num && !obj.is_float && obj.value >= 0 && obj.value <= 1114111;
          },
          is_in_character_code: function(obj) {
            return obj instanceof Num && !obj.is_float && obj.value >= -1 && obj.value <= 1114111;
          },
          is_byte: function(obj) {
            return obj instanceof Num && !obj.is_float && obj.value >= 0 && obj.value <= 255;
          },
          is_in_byte: function(obj) {
            return obj instanceof Num && !obj.is_float && obj.value >= -1 && obj.value <= 255;
          },
          is_operator: function(obj) {
            return obj instanceof Term && pl.arithmetic.evaluation[obj.indicator];
          },
          is_directive: function(obj) {
            return obj instanceof Term && (pl.directive[obj.indicator] !== void 0 || pl.directive[obj.id + "/*"] !== void 0);
          },
          is_builtin: function(obj) {
            return obj instanceof Term && pl.builtin.rules.hasOwnProperty(obj.indicator) && obj.indicator !== "goal_expansion/2";
          },
          is_error: function(obj) {
            return obj instanceof Term && obj.indicator === "throw/1";
          },
          is_error_state: function(obj) {
            return pl.type.is_state(obj) && obj.error && obj.error === true;
          },
          is_predicate_indicator: function(obj) {
            return obj instanceof Term && obj.indicator === "//2" && obj.args[0] instanceof Term && obj.args[0].args.length === 0 && obj.args[1] instanceof Num && obj.args[1].is_float === false;
          },
          is_flag: function(obj) {
            return obj instanceof Term && obj.args.length === 0 && pl.flag[obj.id] !== void 0;
          },
          is_value_flag: function(flag, obj) {
            if (!pl.type.is_flag(flag))
              return false;
            for (var value in pl.flag[flag.id].allowed) {
              if (!pl.flag[flag.id].allowed.hasOwnProperty(value))
                continue;
              if (pl.flag[flag.id].allowed[value].equals(obj))
                return true;
            }
            return false;
          },
          is_io_mode: function(obj) {
            return pl.type.is_atom(obj) && ["read", "write", "append"].indexOf(obj.id) !== -1;
          },
          is_stream_option: function(obj) {
            return pl.type.is_term(obj) && (obj.indicator === "alias/1" && pl.type.is_atom(obj.args[0]) || obj.indicator === "reposition/1" && pl.type.is_atom(obj.args[0]) && (obj.args[0].id === "true" || obj.args[0].id === "false") || obj.indicator === "type/1" && pl.type.is_atom(obj.args[0]) && (obj.args[0].id === "text" || obj.args[0].id === "binary") || obj.indicator === "eof_action/1" && pl.type.is_atom(obj.args[0]) && (obj.args[0].id === "error" || obj.args[0].id === "eof_code" || obj.args[0].id === "reset"));
          },
          is_stream_position: function(obj) {
            return pl.type.is_term(obj) && (obj.indicator === "end_of_stream/0" || obj.indicator === "past_end_of_stream/0" || obj.indicator === "position/3" && pl.type.is_integer(obj.args[0]) && pl.type.is_integer(obj.args[1]) && pl.type.is_integer(obj.args[2]));
          },
          is_stream_property: function(obj) {
            return pl.type.is_term(obj) && (obj.indicator === "input/0" || obj.indicator === "output/0" || obj.indicator === "alias/1" && (pl.type.is_variable(obj.args[0]) || pl.type.is_atom(obj.args[0])) || obj.indicator === "file_name/1" && (pl.type.is_variable(obj.args[0]) || pl.type.is_atom(obj.args[0])) || obj.indicator === "reposition/1" && (pl.type.is_variable(obj.args[0]) || pl.type.is_atom(obj.args[0]) && (obj.args[0].id === "true" || obj.args[0].id === "false")) || obj.indicator === "type/1" && (pl.type.is_variable(obj.args[0]) || pl.type.is_atom(obj.args[0]) && (obj.args[0].id === "text" || obj.args[0].id === "binary")) || obj.indicator === "mode/1" && (pl.type.is_variable(obj.args[0]) || pl.type.is_atom(obj.args[0]) && (obj.args[0].id === "read" || obj.args[0].id === "write" || obj.args[0].id === "append")) || obj.indicator === "eof_action/1" && (pl.type.is_variable(obj.args[0]) || pl.type.is_atom(obj.args[0]) && (obj.args[0].id === "error" || obj.args[0].id === "eof_code" || obj.args[0].id === "reset")) || obj.indicator === "end_of_stream/1" && (pl.type.is_variable(obj.args[0]) || pl.type.is_atom(obj.args[0]) && (obj.args[0].id === "at" || obj.args[0].id === "past" || obj.args[0].id === "not")) || obj.indicator === "position/1" && (pl.type.is_variable(obj.args[0]) || pl.type.is_term(obj.args[0]) && obj.args[0].indicator === "position/3" && (pl.type.is_variable(obj.args[0].args[0]) || pl.type.is_integer(obj.args[0].args[0])) && (pl.type.is_variable(obj.args[0].args[1]) || pl.type.is_integer(obj.args[0].args[1])) && (pl.type.is_variable(obj.args[0].args[2]) || pl.type.is_integer(obj.args[0].args[2]))));
          },
          is_streamable: function(obj) {
            return obj.__proto__.stream !== void 0;
          },
          is_read_option: function(obj) {
            return pl.type.is_term(obj) && ["variables/1", "variable_names/1", "singletons/1"].indexOf(obj.indicator) !== -1;
          },
          is_write_option: function(obj) {
            return pl.type.is_term(obj) && (obj.indicator === "quoted/1" && pl.type.is_atom(obj.args[0]) && (obj.args[0].id === "true" || obj.args[0].id === "false") || obj.indicator === "ignore_ops/1" && pl.type.is_atom(obj.args[0]) && (obj.args[0].id === "true" || obj.args[0].id === "false") || obj.indicator === "numbervars/1" && pl.type.is_atom(obj.args[0]) && (obj.args[0].id === "true" || obj.args[0].id === "false") || obj.indicator === "variable_names/1" && pl.type.is_fully_list(obj.args[0]));
          },
          is_close_option: function(obj) {
            return pl.type.is_term(obj) && obj.indicator === "force/1" && pl.type.is_atom(obj.args[0]) && (obj.args[0].id === "true" || obj.args[0].id === "false");
          },
          is_modifiable_flag: function(obj) {
            return pl.type.is_flag(obj) && pl.flag[obj.id].changeable;
          },
          is_module: function(obj) {
            return obj instanceof Module;
          },
          is_file: function(obj) {
            return obj instanceof TauFile;
          },
          is_directory: function(obj) {
            return obj instanceof TauDirectory;
          },
          is_predicate_property: function(obj) {
            return pl.type.is_term(obj) && (obj.indicator === "built_in/0" || obj.indicator === "static/0" || obj.indicator === "dynamic/0" || obj.indicator === "native_code/0" || obj.indicator === "multifile/0" || obj.indicator === "meta_predicate/1");
          },
          is_meta_argument_specifier: function(obj) {
            return pl.type.is_integer(obj) && obj.value >= 0 || pl.type.is_atom(obj) && indexOf(["+", "-", "?", "*", "^", ":", "//"], obj.id) !== -1;
          },
          is_time_property: function(obj) {
            return pl.type.is_term(obj) && obj.args.length === 1 && (pl.type.is_variable(obj.args[0]) || pl.type.is_integer(obj.args[0])) && indexOf(["year", "month", "day", "hours", "minutes", "seconds", "milliseconds", "weekday"], obj.id) !== -1;
          }
        },
        arithmetic: {
          evaluation: {
            "e/0": {
              type_args: null,
              type_result: true,
              fn: function(_) {
                return Math.E;
              }
            },
            "pi/0": {
              type_args: null,
              type_result: true,
              fn: function(_) {
                return Math.PI;
              }
            },
            "tau/0": {
              type_args: null,
              type_result: true,
              fn: function(_) {
                return 2 * Math.PI;
              }
            },
            "epsilon/0": {
              type_args: null,
              type_result: true,
              fn: function(_) {
                return Number.EPSILON;
              }
            },
            "+/1": {
              type_args: null,
              type_result: null,
              fn: function(x, _) {
                return x;
              }
            },
            "-/1": {
              type_args: null,
              type_result: null,
              fn: function(x, _) {
                return -x;
              }
            },
            "\\/1": {
              type_args: false,
              type_result: false,
              fn: function(x, _) {
                return ~x;
              }
            },
            "abs/1": {
              type_args: null,
              type_result: null,
              fn: function(x, _) {
                return Math.abs(x);
              }
            },
            "sign/1": {
              type_args: null,
              type_result: null,
              fn: function(x, _) {
                return Math.sign(x);
              }
            },
            "float_integer_part/1": {
              type_args: true,
              type_result: false,
              fn: function(x, _) {
                return parseInt(x);
              }
            },
            "float_fractional_part/1": {
              type_args: true,
              type_result: true,
              fn: function(x, _) {
                return x - parseInt(x);
              }
            },
            "float/1": {
              type_args: null,
              type_result: true,
              fn: function(x, _) {
                return parseFloat(x);
              }
            },
            "floor/1": {
              type_args: true,
              type_result: false,
              fn: function(x, _) {
                return Math.floor(x);
              }
            },
            "truncate/1": {
              type_args: true,
              type_result: false,
              fn: function(x, _) {
                return parseInt(x);
              }
            },
            "round/1": {
              type_args: true,
              type_result: false,
              fn: function(x, _) {
                return Math.round(x);
              }
            },
            "ceiling/1": {
              type_args: true,
              type_result: false,
              fn: function(x, _) {
                return Math.ceil(x);
              }
            },
            "sin/1": {
              type_args: null,
              type_result: true,
              fn: function(x, _) {
                return Math.sin(x);
              }
            },
            "cos/1": {
              type_args: null,
              type_result: true,
              fn: function(x, _) {
                return Math.cos(x);
              }
            },
            "tan/1": {
              type_args: null,
              type_result: true,
              fn: function(x, _) {
                return Math.tan(x);
              }
            },
            "asin/1": {
              type_args: null,
              type_result: true,
              fn: function(x, thread) {
                return Math.abs(x) <= 1 ? Math.asin(x) : pl.error.evaluation("undefined", thread.__call_indicator);
              }
            },
            "acos/1": {
              type_args: null,
              type_result: true,
              fn: function(x, thread) {
                return Math.abs(x) <= 1 ? Math.acos(x) : pl.error.evaluation("undefined", thread.__call_indicator);
              }
            },
            "atan/1": {
              type_args: null,
              type_result: true,
              fn: function(x, _) {
                return Math.atan(x);
              }
            },
            "atan2/2": {
              type_args: null,
              type_result: true,
              fn: function(x, y, thread) {
                return x === 0 && y === 0 ? pl.error.evaluation("undefined", thread.__call_indicator) : Math.atan2(x, y);
              }
            },
            "acosh/1": {
              type_args: null,
              type_result: true,
              fn: function(x, thread) {
                return x >= 1 ? Math.acosh(x) : pl.error.evaluation("undefined", thread.__call_indicator);
              }
            },
            "asinh/1": {
              type_args: null,
              type_result: true,
              fn: function(x, _) {
                return Math.asinh(x);
              }
            },
            "atanh/1": {
              type_args: null,
              type_result: true,
              fn: function(x, thread) {
                return Math.abs(x) < 1 ? Math.atanh(x) : pl.error.evaluation("undefined", thread.__call_indicator);
              }
            },
            "cosh/1": {
              type_args: null,
              type_result: true,
              fn: function(x, _) {
                return Math.cosh(x);
              }
            },
            "sinh/1": {
              type_args: null,
              type_result: true,
              fn: function(x, _) {
                return Math.sinh(x);
              }
            },
            "tanh/1": {
              type_args: null,
              type_result: true,
              fn: function(x, _) {
                return Math.tanh(x);
              }
            },
            "exp/1": {
              type_args: null,
              type_result: true,
              fn: function(x, _) {
                return Math.exp(x);
              }
            },
            "sqrt/1": {
              type_args: null,
              type_result: true,
              fn: function(x, thread) {
                return x >= 0 ? Math.sqrt(x) : pl.error.evaluation("undefined", thread.__call_indicator);
              }
            },
            "log/1": {
              type_args: null,
              type_result: true,
              fn: function(x, thread) {
                return x > 0 ? Math.log(x) : pl.error.evaluation("undefined", thread.__call_indicator);
              }
            },
            "log/2": {
              type_args: null,
              type_result: true,
              fn: function(x, y, thread) {
                return x > 0 && y > 0 ? Math.log(y) / Math.log(x) : pl.error.evaluation("undefined", thread.__call_indicator);
              }
            },
            "log10/1": {
              type_args: null,
              type_result: true,
              fn: function(x, thread) {
                return x > 0 ? Math.log(x) / Math.log(10) : pl.error.evaluation("undefined", thread.__call_indicator);
              }
            },
            "+/2": {
              type_args: null,
              type_result: null,
              fn: function(x, y, _) {
                return x + y;
              }
            },
            "-/2": {
              type_args: null,
              type_result: null,
              fn: function(x, y, _) {
                return x - y;
              }
            },
            "*/2": {
              type_args: null,
              type_result: null,
              fn: function(x, y, _) {
                return x * y;
              }
            },
            "//2": {
              type_args: null,
              type_result: true,
              fn: function(x, y, thread) {
                return y ? x / y : pl.error.evaluation("zero_divisor", thread.__call_indicator);
              }
            },
            "///2": {
              type_args: false,
              type_result: false,
              fn: function(x, y, thread) {
                return y ? Math.trunc(x / y) : pl.error.evaluation("zero_divisor", thread.__call_indicator);
              }
            },
            "div/2": {
              type_args: false,
              type_result: false,
              fn: function(x, y, thread) {
                return y ? Math.floor(x / y) : pl.error.evaluation("zero_divisor", thread.__call_indicator);
              }
            },
            "**/2": {
              type_args: null,
              type_result: true,
              fn: function(x, y, thread) {
                return x == 0 && y < 0 ? pl.error.evaluation("zero_divisor", thread.__call_indicator) : Math.pow(x, y);
              }
            },
            "^/2": {
              type_args: null,
              type_result: null,
              fn: function(x, y, thread) {
                return x == 0 && y < 0 ? pl.error.evaluation("zero_divisor", thread.__call_indicator) : Math.pow(x, y);
              }
            },
            "<</2": {
              type_args: false,
              type_result: false,
              fn: function(x, y, _) {
                return x << y;
              }
            },
            ">>/2": {
              type_args: false,
              type_result: false,
              fn: function(x, y, _) {
                return x >> y;
              }
            },
            "/\\/2": {
              type_args: false,
              type_result: false,
              fn: function(x, y, _) {
                return x & y;
              }
            },
            "\\//2": {
              type_args: false,
              type_result: false,
              fn: function(x, y, _) {
                return x | y;
              }
            },
            "xor/2": {
              type_args: false,
              type_result: false,
              fn: function(x, y, _) {
                return x ^ y;
              }
            },
            "rem/2": {
              type_args: false,
              type_result: false,
              fn: function(x, y, thread) {
                return y ? x % y : pl.error.evaluation("zero_divisor", thread.__call_indicator);
              }
            },
            "mod/2": {
              type_args: false,
              type_result: false,
              fn: function(x, y, thread) {
                return y ? x - Math.floor(x / y) * y : pl.error.evaluation("zero_divisor", thread.__call_indicator);
              }
            },
            "max/2": {
              type_args: null,
              type_result: null,
              fn: function(x, y, _) {
                return Math.max(x, y);
              }
            },
            "min/2": {
              type_args: null,
              type_result: null,
              fn: function(x, y, _) {
                return Math.min(x, y);
              }
            },
            "gcd/2": {
              type_args: false,
              type_result: false,
              fn: function(x, y, _) {
                return gcd(x, y);
              }
            }
          }
        },
        directive: {
          "dynamic/1": function(thread, atom, options) {
            var indicators = atom.args[0];
            if (!pl.type.is_list(indicators))
              indicators = arrayToList([indicators]);
            var pointer = indicators;
            while (pl.type.is_term(pointer) && pointer.indicator === "./2") {
              indicator = pointer.args[0];
              if (pl.type.is_variable(indicator)) {
                thread.throw_warning(pl.error.instantiation(atom.indicator));
              } else if (!pl.type.is_compound(indicator) || indicator.indicator !== "//2") {
                thread.throw_warning(pl.error.type("predicate_indicator", indicator, atom.indicator));
              } else if (pl.type.is_variable(indicator.args[0]) || pl.type.is_variable(indicator.args[1])) {
                thread.throw_warning(pl.error.instantiation(atom.indicator));
              } else if (!pl.type.is_atom(indicator.args[0])) {
                thread.throw_warning(pl.error.type("atom", indicator.args[0], atom.indicator));
              } else if (!pl.type.is_integer(indicator.args[1])) {
                thread.throw_warning(pl.error.type("integer", indicator.args[1], atom.indicator));
              } else {
                var key = indicator.args[0].id + "/" + indicator.args[1].value;
                var get_module = thread.session.modules[options.context_module];
                get_module.public_predicates[key] = true;
                if (!get_module.rules[key])
                  get_module.rules[key] = [];
              }
              pointer = pointer.args[1];
            }
            if (pl.type.is_variable(pointer)) {
              thread.throw_warning(pl.error.instantiation(atom.indicator));
            } else if (!pl.type.is_term(pointer) || pointer.indicator !== "[]/0") {
              thread.throw_warning(pl.error.type("predicate_indicator", indicator, atom.indicator));
            }
          },
          "dynamic/*": function(thread, atom) {
            for (var i2 = 0; i2 < atom.args.length; i2++) {
              pl.directive["dynamic/1"](thread, new Term("dynamic", [atom.args[i2]]));
            }
          },
          "multifile/1": function(thread, atom, options) {
            var indicator2 = atom.args[0];
            if (pl.type.is_variable(indicator2)) {
              thread.throw_warning(pl.error.instantiation(atom.indicator));
            } else if (!pl.type.is_compound(indicator2) || indicator2.indicator !== "//2") {
              thread.throw_warning(pl.error.type("predicate_indicator", indicator2, atom.indicator));
            } else if (pl.type.is_variable(indicator2.args[0]) || pl.type.is_variable(indicator2.args[1])) {
              thread.throw_warning(pl.error.instantiation(atom.indicator));
            } else if (!pl.type.is_atom(indicator2.args[0])) {
              thread.throw_warning(pl.error.type("atom", indicator2.args[0], atom.indicator));
            } else if (!pl.type.is_integer(indicator2.args[1])) {
              thread.throw_warning(pl.error.type("integer", indicator2.args[1], atom.indicator));
            } else {
              var predicate_indicator = atom.args[0].args[0].id + "/" + atom.args[0].args[1].value;
              var get_module = thread.session.modules[options.context_module];
              get_module.multifile_predicates[predicate_indicator] = true;
              if (!get_module.rules.hasOwnProperty(predicate_indicator)) {
                get_module.rules[predicate_indicator] = [];
                get_module.public_predicates[predicate_indicator] = false;
              }
            }
          },
          "meta_predicate/1": function(thread, atom, options) {
            var options = options === void 0 ? {} : options;
            var head = atom.args[0];
            if (pl.type.is_variable(head)) {
              thread.throw_warning(pl.error.instantiation(atom.indicator));
            } else if (!pl.type.is_callable(head)) {
              thread.throw_warning(pl.error.type("callable", head, atom.indicator));
            } else {
              for (var i2 = 0; i2 < head.args.length; i2++) {
                var arg = head.args[i2];
                if (!pl.type.is_meta_argument_specifier(arg)) {
                  thread.throw_warning(pl.error.type("meta_argument_specifier", arg, atom.indicator));
                  return;
                }
              }
              thread.session.modules[options.context_module].meta_predicates[head.indicator] = head;
            }
          },
          "set_prolog_flag/2": function(thread, atom) {
            var flag = atom.args[0], value = atom.args[1];
            if (pl.type.is_variable(flag) || pl.type.is_variable(value)) {
              thread.throw_warning(pl.error.instantiation(atom.indicator));
            } else if (!pl.type.is_atom(flag)) {
              thread.throw_warning(pl.error.type("atom", flag, atom.indicator));
            } else if (!pl.type.is_flag(flag)) {
              thread.throw_warning(pl.error.domain("prolog_flag", flag, atom.indicator));
            } else if (!pl.type.is_modifiable_flag(flag)) {
              thread.throw_warning(pl.error.permission("modify", "flag", flag, atom.indicator));
            } else if (!pl.type.is_value_flag(flag, value)) {
              thread.throw_warning(pl.error.domain("flag_value", new Term("+", [flag, value]), atom.indicator));
            } else {
              thread.session.flag[flag.id] = value;
            }
          },
          "module/2": function(thread, atom, options) {
            var options = options === void 0 ? {} : options;
            options.context_module = options.context_module === void 0 ? "user" : options.context_module;
            var module_id = atom.args[0], exports2 = atom.args[1];
            if (pl.type.is_variable(module_id) || pl.type.is_variable(exports2)) {
              thread.throw_warning(pl.error.instantiation(atom.indicator));
            } else if (!pl.type.is_atom(module_id)) {
              thread.throw_warning(pl.error.type("atom", module_id, atom.indicator));
            } else if (!pl.type.is_list(exports2)) {
              thread.throw_warning(pl.error.type("list", exports2, atom.indicator));
            } else {
              if (!pl.type.is_module(thread.session.modules[module_id.indicator])) {
                var pointer = exports2;
                var indicators = [];
                while (pl.type.is_term(pointer) && pointer.indicator === "./2") {
                  var predicate = pointer.args[0];
                  if (!pl.type.is_predicate_indicator(predicate)) {
                    thread.throw_warning(pl.error.type("predicate_indicator", predicate, atom.indicator));
                  } else {
                    indicators.push(predicate.args[0].id + "/" + predicate.args[1].value);
                  }
                  pointer = pointer.args[1];
                }
                if (pl.type.is_variable(pointer)) {
                  thread.throw_warning(pl.error.instantiation(atom.indicator));
                } else if (!pl.type.is_empty_list(pointer)) {
                  thread.throw_warning(pl.error.type("list", exports2, atom.indicator));
                }
                var new_module = new Module(module_id.id, {}, indicators, {
                  session: thread.session
                });
                thread.session.modules[module_id.id] = new_module;
                thread.session.modules[options.context_module].modules[module_id.id] = new_module;
                options.context_module = module_id.id;
              } else {
                thread.throw_warning(pl.error.permission("create", "module", module_id, atom.indicator));
              }
            }
          },
          "use_module/1": function(thread, atom, options) {
            var options = options === void 0 ? {} : options;
            options.context_module = options.context_module === void 0 ? "user" : options.context_module;
            var module_id = atom.args[0];
            if (pl.type.is_variable(module_id)) {
              thread.throw_warning(pl.error.instantiation(atom.indicator));
            } else if (!pl.type.is_term(module_id)) {
              thread.throw_warning(pl.error.type("term", module_id, atom.indicator));
            } else {
              if (module_id.indicator === "library/1") {
                var name = module_id.args[0].id;
                var get_module = pl.modules[name];
                if (pl.type.is_module(get_module)) {
                  if (!thread.session.modules[options.context_module].modules.hasOwnProperty(name)) {
                    thread.session.modules[name] = get_module;
                    thread.session.modules[options.context_module].modules[name] = get_module;
                    for (var i2 = 0; i2 < get_module.dependencies.length; i2++) {
                      var term = new Term("use_module", [new Term("library", [new Term(get_module.dependencies[i2])])]);
                      pl.directive["use_module/1"](thread, term, {
                        context_module: name
                      });
                    }
                  }
                } else {
                  thread.throw_warning(pl.error.existence("module", module_id, atom.indicator));
                }
              } else {
                var name = module_id.id;
                thread.consult(name, {
                  context_module: options.context_module,
                  text: false,
                  success: function() {
                    parseProgram(thread, options.string, options);
                  },
                  error: function() {
                    options.error(pl.error.existence("module", module_id, atom.indicator));
                  }
                });
                return true;
              }
            }
          },
          "char_conversion/2": function(thread, atom, options) {
            var inchar = atom.args[0], outchar = atom.args[1];
            if (pl.type.is_variable(inchar) || pl.type.is_variable(outchar)) {
              thread.throw_warning(pl.error.instantiation(atom.indicator));
            } else if (!pl.type.is_character(inchar)) {
              thread.throw_warning(pl.error.type("character", inchar, atom.indicator));
            } else if (!pl.type.is_character(outchar)) {
              thread.throw_warning(pl.error.type("character", outchar, atom.indicator));
            } else {
              if (inchar.id === outchar.id) {
                delete thread.session.__char_conversion[inchar.id];
              } else {
                thread.session.__char_conversion[inchar.id] = outchar.id;
              }
              options.tokens = options.tokenizer.get_tokens(options.current_token);
              options.current_token = 0;
              return true;
            }
          },
          "op/3": function(thread, atom) {
            var priority = atom.args[0], type = atom.args[1], operators = atom.args[2];
            if (pl.type.is_atom(operators))
              operators = new Term(".", [operators, new Term("[]")]);
            if (pl.type.is_variable(priority) || pl.type.is_variable(type) || pl.type.is_variable(operators)) {
              thread.throw_warning(pl.error.instantiation(atom.indicator));
            } else if (!pl.type.is_integer(priority)) {
              thread.throw_warning(pl.error.type("integer", priority, atom.indicator));
            } else if (!pl.type.is_atom(type)) {
              thread.throw_warning(pl.error.type("atom", type, atom.indicator));
            } else if (!pl.type.is_list(operators)) {
              thread.throw_warning(pl.error.type("list", operators, atom.indicator));
            } else if (pl.type.is_empty_list(operators)) {
              thread.throw_warning(pl.error.permission("create", "operator", operators, atom.indicator));
            } else {
              var pointer = operators;
              while (pl.type.is_term(pointer) && pointer.indicator === "./2") {
                var operator = pointer.args[0];
                pointer = pointer.args[1];
                if (pl.type.is_variable(operator)) {
                  thread.throw_warning(pl.error.instantiation(atom.indicator));
                } else if (!pl.type.is_atom(operator)) {
                  thread.throw_warning(pl.error.type("atom", operator, atom.indicator));
                } else if (priority.value < 0 || priority.value > 1200) {
                  thread.throw_warning(pl.error.domain("operator_priority", priority, atom.indicator));
                } else if (operator.id === ",") {
                  thread.throw_error(pl.error.permission("modify", "operator", operator, atom.indicator));
                } else if (operator.id === "{}") {
                  thread.throw_warning(pl.error.permission("create", "operator", operator, atom.indicator));
                } else if (operator.id === "[]") {
                  thread.throw_warning(pl.error.permission("create", "operator", operator, atom.indicator));
                } else if (operator.id === "|" && priority.value !== 0 && (priority.value < 1001 || type.id.length !== 3)) {
                  thread.throw_warning(pl.error.permission("create", "operator", operator, atom.indicator));
                } else if (["fy", "fx", "yf", "xf", "xfx", "yfx", "xfy"].indexOf(type.id) === -1) {
                  thread.throw_warning(pl.error.domain("operator_specifier", type, atom.indicator));
                } else {
                  var fix = { prefix: null, infix: null, postfix: null };
                  for (var p in thread.session.__operators) {
                    if (!thread.session.__operators.hasOwnProperty(p))
                      continue;
                    var classes = thread.session.__operators[p][operator.id];
                    if (classes) {
                      if (indexOf(classes, "fx") !== -1) {
                        fix.prefix = { priority: p, type: "fx" };
                      }
                      if (indexOf(classes, "fy") !== -1) {
                        fix.prefix = { priority: p, type: "fy" };
                      }
                      if (indexOf(classes, "xf") !== -1) {
                        fix.postfix = { priority: p, type: "xf" };
                      }
                      if (indexOf(classes, "yf") !== -1) {
                        fix.postfix = { priority: p, type: "yf" };
                      }
                      if (indexOf(classes, "xfx") !== -1) {
                        fix.infix = { priority: p, type: "xfx" };
                      }
                      if (indexOf(classes, "xfy") !== -1) {
                        fix.infix = { priority: p, type: "xfy" };
                      }
                      if (indexOf(classes, "yfx") !== -1) {
                        fix.infix = { priority: p, type: "yfx" };
                      }
                    }
                  }
                  var current_class;
                  switch (type.id) {
                    case "fy":
                    case "fx":
                      current_class = "prefix";
                      break;
                    case "yf":
                    case "xf":
                      current_class = "postfix";
                      break;
                    default:
                      current_class = "infix";
                      break;
                  }
                  if (fix.infix && current_class === "postfix" || fix.postfix && current_class === "infix") {
                    thread.throw_warning(pl.error.permission("create", "operator", operator, atom.indicator));
                  } else {
                    if (fix[current_class]) {
                      remove(thread.session.__operators[fix[current_class].priority][operator.id], fix[current_class].type);
                      if (thread.session.__operators[fix[current_class].priority][operator.id].length === 0) {
                        delete thread.session.__operators[fix[current_class].priority][operator.id];
                      }
                    }
                    if (priority.value > 0) {
                      if (!thread.session.__operators[priority.value])
                        thread.session.__operators[priority.value.toString()] = {};
                      if (!thread.session.__operators[priority.value][operator.id])
                        thread.session.__operators[priority.value][operator.id] = [];
                      thread.session.__operators[priority.value][operator.id].push(type.id);
                    }
                  }
                }
              }
              if (pl.type.is_variable(pointer)) {
                thread.throw_warning(pl.error.instantiation(atom.indicator));
                return;
              } else if (!pl.type.is_term(pointer) || pointer.indicator !== "[]/0") {
                thread.throw_warning(pl.error.type("list", operators, atom.indicator));
                return;
              }
            }
          },
          "initialization/1": function(thread, atom, options) {
            var goal = atom.args[0];
            options.initialization.push(goal);
          }
        },
        flag: {
          bounded: {
            allowed: [new Term("true"), new Term("false")],
            value: new Term("true"),
            changeable: false
          },
          max_integer: {
            allowed: [new Num(Number.MAX_SAFE_INTEGER)],
            value: new Num(Number.MAX_SAFE_INTEGER),
            changeable: false
          },
          min_integer: {
            allowed: [new Num(Number.MIN_SAFE_INTEGER)],
            value: new Num(Number.MIN_SAFE_INTEGER),
            changeable: false
          },
          integer_rounding_function: {
            allowed: [new Term("down"), new Term("toward_zero")],
            value: new Term("toward_zero"),
            changeable: false
          },
          char_conversion: {
            allowed: [new Term("on"), new Term("off")],
            value: new Term("on"),
            changeable: true
          },
          debug: {
            allowed: [new Term("on"), new Term("off")],
            value: new Term("off"),
            changeable: true
          },
          max_arity: {
            allowed: [new Term("unbounded")],
            value: new Term("unbounded"),
            changeable: false
          },
          unknown: {
            allowed: [new Term("error"), new Term("fail"), new Term("warning")],
            value: new Term("error"),
            changeable: true
          },
          double_quotes: {
            allowed: [new Term("chars"), new Term("codes"), new Term("atom")],
            value: new Term("chars"),
            changeable: true
          },
          occurs_check: {
            allowed: [new Term("false"), new Term("true")],
            value: new Term("false"),
            changeable: true
          },
          dialect: {
            allowed: [new Term("tau")],
            value: new Term("tau"),
            changeable: false
          },
          version_data: {
            allowed: [new Term("tau", [new Num(version.major, false), new Num(version.minor, false), new Num(version.patch, false), new Term(version.status)])],
            value: new Term("tau", [new Num(version.major, false), new Num(version.minor, false), new Num(version.patch, false), new Term(version.status)]),
            changeable: false
          },
          nodejs: {
            allowed: [new Term("true"), new Term("false")],
            value: new Term(nodejs_flag ? "true" : "false"),
            changeable: false
          },
          argv: {
            allowed: [nodejs_arguments],
            value: nodejs_arguments,
            changeble: false
          }
        },
        unify: function(t1, t2, occurs_check) {
          occurs_check = occurs_check === void 0 ? false : occurs_check;
          var left = Array.isArray(t1) ? t1 : [t1];
          var right = Array.isArray(t2) ? t2 : [t2];
          if (left.length !== right.length)
            return null;
          var subs = new Substitution();
          while (left.length > 0) {
            var s = left.pop();
            var t = right.pop();
            if (pl.type.is_variable(s))
              s = s.apply(subs);
            if (pl.type.is_variable(t))
              t = t.apply(subs);
            if (s == t)
              continue;
            if (pl.type.is_term(s) && pl.type.is_term(t)) {
              if (s.indicator !== t.indicator)
                return null;
              for (var i2 = s.args.length - 1; i2 >= 0; i2--) {
                left.push(s.args[i2]);
                right.push(t.args[i2]);
              }
            } else if (pl.type.is_number(s) && pl.type.is_number(t)) {
              if (s.value !== t.value || s.is_float !== t.is_float)
                return null;
            } else if (pl.type.is_variable(s)) {
              t = t.apply(subs);
              if (pl.type.is_variable(t) && s.id === t.id)
                continue;
              if (occurs_check === true && indexOf(t.variables(), s.id) !== -1)
                return null;
              if (s.id !== "_")
                subs.add(s.id, t);
            } else if (pl.type.is_variable(t)) {
              left.push(t);
              right.push(s);
            } else if (s.unify !== void 0) {
              var user_subs = s.apply(subs).unify(t.apply(subs), occurs_check);
              if (user_subs == null)
                return null;
              for (var i2 in user_subs.links)
                subs.add(i2, user_subs.links[i2]);
            } else {
              return null;
            }
          }
          return subs.apply(subs);
        },
        is_rename: function(obj1, obj2, links) {
          links = links || {};
          if (obj1.is_rename && obj2.is_rename)
            return obj1.is_rename(obj2, links);
          else if (obj1.equals && obj2.equals)
            return obj1.equals(obj2);
          else
            return false;
        },
        compare: function(obj1, obj2) {
          var type = pl.type.compare(obj1, obj2);
          return type !== 0 ? type : obj1.compare(obj2);
        },
        arithmetic_compare: function(thread, obj1, obj2) {
          var expr1 = obj1.interpret(thread);
          if (!pl.type.is_number(expr1)) {
            return expr1;
          } else {
            var expr2 = obj2.interpret(thread);
            if (!pl.type.is_number(expr2)) {
              return expr2;
            } else {
              return expr1.value < expr2.value ? -1 : expr1.value > expr2.value ? 1 : 0;
            }
          }
        },
        operate: function(thread, obj) {
          if (pl.type.is_operator(obj)) {
            var op = pl.type.is_operator(obj);
            var args = [], value;
            var type = false;
            for (var i2 = 0; i2 < obj.args.length; i2++) {
              value = obj.args[i2].interpret(thread);
              if (!pl.type.is_number(value)) {
                return value;
              } else if (op.type_args !== null && value.is_float !== op.type_args) {
                return pl.error.type(op.type_args ? "float" : "integer", value, thread.__call_indicator);
              } else {
                args.push(value.value);
              }
              type = type || value.is_float;
            }
            args.push(thread);
            value = pl.arithmetic.evaluation[obj.indicator].fn.apply(this, args);
            if (obj.indicator === "^/2" && !type && value !== parseInt(value, 10))
              return pl.error.type("float", new Num(args[0], false), thread.__call_indicator);
            type = op.type_result === null ? type : op.type_result;
            if (pl.type.is_term(value)) {
              return value;
            } else if (value === Number.POSITIVE_INFINITY || value === Number.NEGATIVE_INFINITY) {
              return pl.error.evaluation("float_overflow", thread.__call_indicator);
            } else if (type === false && thread.get_flag("bounded").id === "true" && (value > thread.get_flag("max_integer").value || value < thread.get_flag("min_integer").value)) {
              return pl.error.evaluation("int_overflow", thread.__call_indicator);
            } else {
              return new Num(value, type);
            }
          } else {
            return pl.error.type("evaluable", str_indicator(obj.indicator), thread.__call_indicator);
          }
        },
        error: {
          existence: function(type, object, indicator2) {
            if (typeof object === "string")
              object = str_indicator(object);
            return new Term("error", [new Term("existence_error", [new Term(type), object]), str_indicator(indicator2)]);
          },
          type: function(expected, found, indicator2) {
            return new Term("error", [new Term("type_error", [new Term(expected), found]), str_indicator(indicator2)]);
          },
          instantiation: function(indicator2) {
            return new Term("error", [new Term("instantiation_error"), str_indicator(indicator2)]);
          },
          uninstantiation: function(found, indicator2) {
            return new Term("error", [new Term("uninstantiation_error", [new Term(found)]), str_indicator(indicator2)]);
          },
          domain: function(expected, found, indicator2) {
            return new Term("error", [new Term("domain_error", [new Term(expected), found]), str_indicator(indicator2)]);
          },
          representation: function(flag, indicator2) {
            return new Term("error", [new Term("representation_error", [new Term(flag)]), str_indicator(indicator2)]);
          },
          permission: function(operation, type, found, indicator2) {
            return new Term("error", [new Term("permission_error", [new Term(operation), new Term(type), found]), str_indicator(indicator2)]);
          },
          evaluation: function(error, indicator2) {
            return new Term("error", [new Term("evaluation_error", [new Term(error)]), str_indicator(indicator2)]);
          },
          syntax: function(token, expected, last) {
            token = token || { value: "", line: 0, column: 0, matches: [""], start: 0 };
            var position = last && token.matches.length > 0 ? token.start + token.matches[0].length : token.start;
            var found = last ? new Term("token_not_found") : new Term("found", [new Term(token.value.toString())]);
            var info = new Term(".", [new Term("line", [new Num(token.line + 1)]), new Term(".", [new Term("column", [new Num(position)]), new Term(".", [found, new Term("[]", [])])])]);
            return new Term("error", [new Term("syntax_error", [new Term(expected)]), info]);
          },
          syntax_by_predicate: function(expected, indicator2) {
            return new Term("error", [new Term("syntax_error", [new Term(expected)]), str_indicator(indicator2)]);
          }
        },
        warning: {
          singleton: function(variables, rule, line) {
            var list = new Term("[]");
            for (var i2 = variables.length - 1; i2 >= 0; i2--)
              list = new Term(".", [new Var(variables[i2]), list]);
            return new Term("warning", [new Term("singleton_variables", [list, str_indicator(rule)]), new Term(".", [new Term("line", [new Num(line, false)]), new Term("[]")])]);
          },
          failed_goal: function(goal, line) {
            return new Term("warning", [new Term("failed_goal", [goal]), new Term(".", [new Term("line", [new Num(line, false)]), new Term("[]")])]);
          }
        },
        format_variable: function(id, variable) {
          var charcode = variable && variable.length > 0 ? codePointAt(variable, 1) : 0;
          if (variable === "_" || variable && variable[0] === "_" && (charcode === 95 || charcode >= 65 && charcode <= 90))
            return "__" + id;
          return "_" + id;
        },
        format_answer: function(answer, thread, options) {
          if (thread instanceof Session)
            thread = thread.thread;
          var options = options ? options : {};
          options.session = thread ? thread.session : void 0;
          if (pl.type.is_error(answer)) {
            return "uncaught exception: " + answer.args[0].toString(options);
          } else if (answer === false) {
            return "false";
          } else if (answer === null) {
            return "limit exceeded";
          } else {
            var i2 = 0;
            var str = "";
            if (pl.type.is_substitution(answer)) {
              var dom = answer.domain(true);
              for (var link in answer.links) {
                if (!answer.links.hasOwnProperty(link))
                  continue;
                if (pl.type.is_variable(answer.links[link])) {
                  var links = {};
                  links[answer.links[link].id] = new Var(link);
                  answer = answer.apply(new Substitution(links));
                }
              }
              answer = answer.filter(function(id, value) {
                return !pl.type.is_variable(value) || pl.type.is_variable(value) && answer.has_attributes(id) || indexOf(dom, value.id) !== -1 && id !== value.id;
              });
            }
            for (var link in answer.links) {
              if (!answer.links.hasOwnProperty(link))
                continue;
              if (pl.type.is_variable(answer.links[link]) && link === answer.links[link].id) {
                var attrs = answer.attrs[link];
                for (var module3 in attrs) {
                  if (!attrs.hasOwnProperty(module3))
                    continue;
                  i2++;
                  if (str !== "")
                    str += ", ";
                  str += "put_attr(" + link + ", " + module3 + ", " + attrs[module3].toString(options) + ")";
                }
              } else {
                i2++;
                if (str !== "")
                  str += ", ";
                str += link.toString(options) + " = " + answer.links[link].toString(options, { priority: "700", class: "xfx", indicator: "=/2" }, "right");
              }
            }
            if (i2 === 0) {
              return "true";
            } else {
              return str;
            }
          }
        },
        flatten_error: function(error) {
          if (!pl.type.is_error(error))
            return null;
          error = error.args[0];
          var obj = {};
          obj.type = error.args[0].id;
          obj.thrown = obj.type === "syntax_error" ? null : error.args[1].id;
          obj.expected = null;
          obj.found = null;
          obj.representation = null;
          obj.existence = null;
          obj.existence_type = null;
          obj.line = null;
          obj.column = null;
          obj.permission_operation = null;
          obj.permission_type = null;
          obj.evaluation_type = null;
          if (obj.type === "type_error" || obj.type === "domain_error") {
            obj.expected = error.args[0].args[0].id;
            obj.found = error.args[0].args[1].toString();
          } else if (obj.type === "syntax_error") {
            if (error.args[1].indicator === "./2") {
              obj.expected = error.args[0].args[0].id;
              obj.found = error.args[1].args[1].args[1].args[0];
              obj.found = obj.found.id === "token_not_found" ? obj.found.id : obj.found.args[0].id;
              obj.line = error.args[1].args[0].args[0].value;
              obj.column = error.args[1].args[1].args[0].args[0].value;
            } else {
              obj.thrown = error.args[1].id;
            }
          } else if (obj.type === "permission_error") {
            obj.found = error.args[0].args[2].toString();
            obj.permission_operation = error.args[0].args[0].id;
            obj.permission_type = error.args[0].args[1].id;
          } else if (obj.type === "evaluation_error") {
            obj.evaluation_type = error.args[0].args[0].id;
          } else if (obj.type === "representation_error") {
            obj.representation = error.args[0].args[0].id;
          } else if (obj.type === "existence_error") {
            obj.existence = error.args[0].args[1].toString();
            obj.existence_type = error.args[0].args[0].id;
          }
          return obj;
        },
        create: function(limit) {
          return new pl.type.Session(limit);
        }
      };
      pl.builtin = new Module("system", {
        "goal_expansion/2": [
          new Rule(new Term("goal_expansion", [new Term(",", [new Var("X"), new Var("Y")]), new Term(",", [new Var("X_"), new Var("Y_")])]), new Term(";", [new Term(",", [new Term("goal_expansion", [new Var("X"), new Var("X_")]), new Term(";", [new Term("goal_expansion", [new Var("Y"), new Var("Y_")]), new Term("=", [new Var("Y_"), new Var("Y")])])]), new Term(",", [new Term("=", [new Var("X"), new Var("X_")]), new Term("goal_expansion", [new Var("Y"), new Var("Y_")])])])),
          new Rule(new Term("goal_expansion", [new Term(";", [new Var("X"), new Var("Y")]), new Term(";", [new Var("X_"), new Var("Y_")])]), new Term(";", [new Term(",", [new Term("goal_expansion", [new Var("X"), new Var("X_")]), new Term(";", [new Term("goal_expansion", [new Var("Y"), new Var("Y_")]), new Term("=", [new Var("Y_"), new Var("Y")])])]), new Term(",", [new Term("=", [new Var("X"), new Var("X_")]), new Term("goal_expansion", [new Var("Y"), new Var("Y_")])])])),
          new Rule(new Term("goal_expansion", [new Term("->", [new Var("X"), new Var("Y")]), new Term("->", [new Var("X_"), new Var("Y_")])]), new Term(";", [new Term(",", [new Term("goal_expansion", [new Var("X"), new Var("X_")]), new Term(";", [new Term("goal_expansion", [new Var("Y"), new Var("Y_")]), new Term("=", [new Var("Y_"), new Var("Y")])])]), new Term(",", [new Term("=", [new Var("X"), new Var("X_")]), new Term("goal_expansion", [new Var("Y"), new Var("Y_")])])])),
          new Rule(new Term("goal_expansion", [new Term("catch", [new Var("X"), new Var("Y"), new Var("Z")]), new Term("catch", [new Var("X_"), new Var("Y"), new Var("Z_")])]), new Term(";", [new Term(",", [new Term("goal_expansion", [new Var("X"), new Var("X_")]), new Term(";", [new Term("goal_expansion", [new Var("Z"), new Var("Z_")]), new Term("=", [new Var("Z_"), new Var("Z")])])]), new Term(",", [new Term("=", [new Var("X_"), new Var("X")]), new Term("goal_expansion", [new Var("Z"), new Var("Z_")])])])),
          new Rule(new Term("goal_expansion", [new Term("\\+", [new Var("X")]), new Term("\\+", [new Var("X_")])]), new Term(",", [new Term("nonvar", [new Var("X")]), new Term("goal_expansion", [new Var("X"), new Var("X_")])])),
          new Rule(new Term("goal_expansion", [new Term("once", [new Var("X")]), new Term("once", [new Var("X_")])]), new Term(",", [new Term("nonvar", [new Var("X")]), new Term("goal_expansion", [new Var("X"), new Var("X_")])])),
          new Rule(new Term("goal_expansion", [new Term("findall", [new Var("X"), new Var("Y"), new Var("Z")]), new Term("findall", [new Var("X"), new Var("Y_"), new Var("Z")])]), new Term("goal_expansion", [new Var("Y"), new Var("Y_")])),
          new Rule(new Term("goal_expansion", [new Term("setof", [new Var("X"), new Var("Y"), new Var("Z")]), new Term("findall", [new Var("X"), new Var("Y_"), new Var("Z")])]), new Term("goal_expansion", [new Var("Y"), new Var("Y_")])),
          new Rule(new Term("goal_expansion", [new Term("bagof", [new Var("X"), new Var("Y"), new Var("Z")]), new Term("findall", [new Var("X"), new Var("Y_"), new Var("Z")])]), new Term("goal_expansion", [new Var("Y"), new Var("Y_")])),
          new Rule(new Term("goal_expansion", [new Term("call", [new Var("X")]), new Term("call", [new Var("X_")])]), new Term(",", [new Term("nonvar", [new Var("X")]), new Term("goal_expansion", [new Var("X"), new Var("X_")])])),
          new Rule(new Term("goal_expansion", [new Term("call", [new Var("X"), new Var("A1")]), new Term("call", [new Var("F_")])]), new Term(",", [new Term("=..", [new Var("F"), new Term(".", [new Var("X"), new Term(".", [new Var("A1"), new Term("[]", [])])])]), new Term("goal_expansion", [new Var("F"), new Var("F_")])])),
          new Rule(new Term("goal_expansion", [new Term("call", [new Var("X"), new Var("A1"), new Var("A2")]), new Term("call", [new Var("F_")])]), new Term(",", [new Term("=..", [new Var("F"), new Term(".", [new Var("X"), new Term(".", [new Var("A1"), new Term(".", [new Var("A2"), new Term("[]", [])])])])]), new Term("goal_expansion", [new Var("F"), new Var("F_")])])),
          new Rule(new Term("goal_expansion", [new Term("call", [new Var("X"), new Var("A1"), new Var("A2"), new Var("A3")]), new Term("call", [new Var("F_")])]), new Term(",", [new Term("=..", [new Var("F"), new Term(".", [new Var("X"), new Term(".", [new Var("A1"), new Term(".", [new Var("A2"), new Term(".", [new Var("A3"), new Term("[]", [])])])])])]), new Term("goal_expansion", [new Var("F"), new Var("F_")])])),
          new Rule(new Term("goal_expansion", [new Term("call", [new Var("X"), new Var("A1"), new Var("A2"), new Var("A3"), new Var("A4")]), new Term("call", [new Var("F_")])]), new Term(",", [new Term("=..", [new Var("F"), new Term(".", [new Var("X"), new Term(".", [new Var("A1"), new Term(".", [new Var("A2"), new Term(".", [new Var("A3"), new Term(".", [new Var("A4"), new Term("[]", [])])])])])])]), new Term("goal_expansion", [new Var("F"), new Var("F_")])])),
          new Rule(new Term("goal_expansion", [new Term("call", [new Var("X"), new Var("A1"), new Var("A2"), new Var("A3"), new Var("A4"), new Var("A5")]), new Term("call", [new Var("F_")])]), new Term(",", [new Term("=..", [new Var("F"), new Term(".", [new Var("X"), new Term(".", [new Var("A1"), new Term(".", [new Var("A2"), new Term(".", [new Var("A3"), new Term(".", [new Var("A4"), new Term(".", [new Var("A5"), new Term("[]", [])])])])])])])]), new Term("goal_expansion", [new Var("F"), new Var("F_")])])),
          new Rule(new Term("goal_expansion", [new Term("call", [new Var("X"), new Var("A1"), new Var("A2"), new Var("A3"), new Var("A4"), new Var("A5"), new Var("A6")]), new Term("call", [new Var("F_")])]), new Term(",", [new Term("=..", [new Var("F"), new Term(".", [new Var("X"), new Term(".", [new Var("A1"), new Term(".", [new Var("A2"), new Term(".", [new Var("A3"), new Term(".", [new Var("A4"), new Term(".", [new Var("A5"), new Term(".", [new Var("A6"), new Term("[]", [])])])])])])])])]), new Term("goal_expansion", [new Var("F"), new Var("F_")])])),
          new Rule(new Term("goal_expansion", [new Term("call", [new Var("X"), new Var("A1"), new Var("A2"), new Var("A3"), new Var("A4"), new Var("A5"), new Var("A6"), new Var("A7")]), new Term("call", [new Var("F_")])]), new Term(",", [new Term("=..", [new Var("F"), new Term(".", [new Var("X"), new Term(".", [new Var("A1"), new Term(".", [new Var("A2"), new Term(".", [new Var("A3"), new Term(".", [new Var("A4"), new Term(".", [new Var("A5"), new Term(".", [new Var("A6"), new Term(".", [new Var("A7"), new Term("[]", [])])])])])])])])])]), new Term("goal_expansion", [new Var("F"), new Var("F_")])]))
        ],
        "$push_global_stack/2": function(thread, point, atom) {
          var stack = atom.args[0], value = atom.args[1];
          if (!pl.type.is_variable(stack)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else {
            thread.push_global_stack(stack.id, value);
            thread.success(point);
          }
        },
        "$flush_global_stack/3": function(thread, point, atom) {
          var stack = atom.args[0], list = atom.args[1], tail = atom.args[2];
          if (!pl.type.is_variable(stack)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else {
            var values = thread.flush_global_stack(stack.id, tail);
            thread.prepend([new State(
              point.goal.replace(new Term("=", [list, values])),
              point.substitution,
              point
            )]);
          }
        },
        "$free_variable_set/3": function(thread, point, atom) {
          var goal_in = atom.args[0], goal_out = atom.args[1], vars = atom.args[2];
          var bv = [];
          var pointer = goal_in;
          while (pl.type.is_term(pointer) && pointer.indicator === "^/2") {
            bv = bv.concat(pointer.args[0].variables());
            pointer = pointer.args[1];
          }
          var gv = pointer.variables();
          var fv = arrayToList(map(difference(gv, bv), function(v) {
            return new Var(v);
          }));
          thread.prepend([
            new State(
              point.goal.replace(new Term(",", [
                new Term("=", [goal_out, pointer]),
                new Term("=", [vars, fv])
              ])),
              point.substitution,
              point
            )
          ]);
        },
        "$member/2": [
          new pl.type.Rule(new pl.type.Term("$member", [new pl.type.Var("X"), new pl.type.Term(".", [new pl.type.Var("X"), new pl.type.Var("_")])]), null),
          new pl.type.Rule(new pl.type.Term("$member", [new pl.type.Var("X"), new pl.type.Term(".", [new pl.type.Var("_"), new pl.type.Var("Xs")])]), new pl.type.Term("$member", [new pl.type.Var("X"), new pl.type.Var("Xs")]))
        ],
        "$bind_bagof_keys/2": [
          new pl.type.Rule(new pl.type.Term("$bind_bagof_keys", [new pl.type.Term("[]", []), new pl.type.Var("_")]), null),
          new pl.type.Rule(new pl.type.Term("$bind_bagof_keys", [new pl.type.Term(".", [new pl.type.Term("-", [new pl.type.Var("Key"), new pl.type.Var("_")]), new pl.type.Var("Bag")]), new pl.type.Var("Vars")]), new pl.type.Term(",", [new pl.type.Term("term_variables", [new pl.type.Var("Key"), new pl.type.Var("Vars"), new pl.type.Var("_")]), new pl.type.Term("$bind_bagof_keys", [new pl.type.Var("Bag"), new pl.type.Var("Vars")])]))
        ],
        "$findall/4": [
          new pl.type.Rule(new pl.type.Term("$findall", [new pl.type.Var("Template0"), new pl.type.Var("Goal0"), new pl.type.Var("Instances"), new pl.type.Var("Tail")]), new pl.type.Term(";", [new pl.type.Term(",", [new pl.type.Term("copy_term", [new pl.type.Term("-", [new pl.type.Var("Template0"), new pl.type.Var("Goal0")]), new pl.type.Term("-", [new pl.type.Var("Template1"), new pl.type.Var("Goal1")])]), new pl.type.Term(",", [new pl.type.Term("call", [new pl.type.Var("Goal1")]), new pl.type.Term(",", [new pl.type.Term("copy_term", [new pl.type.Var("Template1"), new pl.type.Var("Template2")]), new pl.type.Term(",", [new pl.type.Term("$push_global_stack", [new pl.type.Var("Var"), new pl.type.Var("Template2")]), new pl.type.Term("false", [])])])])]), new pl.type.Term("$flush_global_stack", [new pl.type.Var("Var"), new pl.type.Var("Instances"), new pl.type.Var("Tail")])]))
        ],
        "$bagof/3": [
          new pl.type.Rule(new pl.type.Term("$bagof", [new pl.type.Var("Template"), new pl.type.Var("Goal0"), new pl.type.Var("Answer")]), new pl.type.Term(",", [new pl.type.Term("$free_variable_set", [new pl.type.Term("^", [new pl.type.Var("Template"), new pl.type.Var("Goal0")]), new pl.type.Var("Goal1"), new pl.type.Var("FV")]), new pl.type.Term(",", [new pl.type.Term("findall", [new pl.type.Term("-", [new pl.type.Var("FV"), new pl.type.Var("Template")]), new pl.type.Var("Goal1"), new pl.type.Var("Answers"), new pl.type.Term("[]", [])]), new pl.type.Term(",", [new pl.type.Term("$bind_bagof_keys", [new pl.type.Var("Answers"), new pl.type.Var("_")]), new pl.type.Term(",", [new pl.type.Term("keygroup", [new pl.type.Var("Answers"), new pl.type.Var("KeyGroups")]), new pl.type.Term(",", [new pl.type.Term("keysort", [new pl.type.Var("KeyGroups"), new pl.type.Var("KeySorted")]), new pl.type.Term("$member", [new pl.type.Term("-", [new pl.type.Var("FV"), new pl.type.Var("Answer")]), new pl.type.Var("KeySorted")])])])])])]))
        ],
        "$setof/3": [
          new pl.type.Rule(new pl.type.Term("$setof", [new pl.type.Var("Template"), new pl.type.Var("Goal0"), new pl.type.Var("Answer")]), new pl.type.Term(",", [new pl.type.Term("$free_variable_set", [new pl.type.Term("^", [new pl.type.Var("Template"), new pl.type.Var("Goal0")]), new pl.type.Var("Goal1"), new pl.type.Var("FV")]), new pl.type.Term(",", [new pl.type.Term("findall", [new pl.type.Term("-", [new pl.type.Var("FV"), new pl.type.Var("Template")]), new pl.type.Var("Goal1"), new pl.type.Var("Answers"), new pl.type.Term("[]", [])]), new pl.type.Term(",", [new pl.type.Term("$bind_bagof_keys", [new pl.type.Var("Answers"), new pl.type.Var("_")]), new pl.type.Term(",", [new pl.type.Term("keygroup", [new pl.type.Var("Answers"), new pl.type.Var("KeyGroups")]), new pl.type.Term(",", [new pl.type.Term("keysort", [new pl.type.Var("KeyGroups"), new pl.type.Var("KeySorted")]), new pl.type.Term(",", [new pl.type.Term("$member", [new pl.type.Term("-", [new pl.type.Var("FV"), new pl.type.Var("Unsorted")]), new pl.type.Var("KeySorted")]), new pl.type.Term("sort", [new pl.type.Var("Unsorted"), new pl.type.Var("Answer")])])])])])])]))
        ],
        "$if/3": [
          new pl.type.Rule(new pl.type.Term("$if", [new pl.type.Var("If"), new pl.type.Var("Then"), new pl.type.Var("Else")]), new pl.type.Term(";", [new pl.type.Term(",", [new pl.type.Term("call", [new pl.type.Var("If")]), new pl.type.Term(",", [new pl.type.Term("$push_global_stack", [new pl.type.Var("Stack"), new pl.type.Var("_")]), new pl.type.Term("call", [new pl.type.Var("Then")])])]), new pl.type.Term(",", [new pl.type.Term("$flush_global_stack", [new pl.type.Var("Stack"), new pl.type.Term("[]", []), new pl.type.Term("[]", [])]), new pl.type.Term("call", [new pl.type.Var("Else")])])]))
        ],
        "put_attr/3": function(thread, point, atom) {
          var variable = atom.args[0], module3 = atom.args[1], value = atom.args[2];
          if (!pl.type.is_variable(variable)) {
            thread.throw_error(pl.error.type("variable", variable, atom.indicator));
          } else if (!pl.type.is_atom(module3)) {
            thread.throw_error(pl.error.type("atom", module3, atom.indicator));
          } else {
            var subs = point.substitution.set_attribute(variable.id, module3, value);
            thread.prepend([new State(point.goal.replace(null), subs, point)]);
          }
        },
        "get_attr/3": function(thread, point, atom) {
          var variable = atom.args[0], module3 = atom.args[1], value = atom.args[2];
          if (!pl.type.is_variable(variable)) {
            thread.throw_error(pl.error.type("variable", variable, atom.indicator));
          } else if (!pl.type.is_atom(module3)) {
            thread.throw_error(pl.error.type("atom", module3, atom.indicator));
          } else {
            var attr = point.substitution.get_attribute(variable.id, module3);
            if (attr) {
              thread.prepend([new State(
                point.goal.replace(new Term("=", [value, attr])),
                point.substitution,
                point
              )]);
            }
          }
        },
        "op/3": function(thread, point, atom) {
          var priority = atom.args[0], type = atom.args[1], operators = atom.args[2];
          if (pl.type.is_atom(operators))
            operators = new Term(".", [operators, new Term("[]")]);
          if (pl.type.is_variable(priority) || pl.type.is_variable(type) || pl.type.is_variable(operators)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_integer(priority)) {
            thread.throw_error(pl.error.type("integer", priority, atom.indicator));
          } else if (!pl.type.is_atom(type)) {
            thread.throw_error(pl.error.type("atom", type, atom.indicator));
          } else if (!pl.type.is_list(operators)) {
            thread.throw_error(pl.error.type("list", operators, atom.indicator));
          } else if (pl.type.is_empty_list(operators)) {
            thread.throw_error(pl.error.permission("create", "operator", operators, atom.indicator));
          } else {
            var pointer = operators;
            while (pl.type.is_term(pointer) && pointer.indicator === "./2") {
              var operator = pointer.args[0];
              pointer = pointer.args[1];
              if (pl.type.is_variable(operator)) {
                thread.throw_error(pl.error.instantiation(atom.indicator));
                return;
              } else if (!pl.type.is_atom(operator)) {
                thread.throw_error(pl.error.type("atom", operator, atom.indicator));
                return;
              } else if (priority.value < 0 || priority.value > 1200) {
                thread.throw_error(pl.error.domain("operator_priority", priority, atom.indicator));
                return;
              } else if (operator.id === ",") {
                thread.throw_error(pl.error.permission("modify", "operator", operator, atom.indicator));
                return;
              } else if (operator.id === "{}") {
                thread.throw_error(pl.error.permission("create", "operator", operator, atom.indicator));
                return;
              } else if (operator.id === "[]") {
                thread.throw_error(pl.error.permission("create", "operator", operator, atom.indicator));
                return;
              } else if (operator.id === "|" && priority.value !== 0 && (priority.value < 1001 || type.id.length !== 3)) {
                thread.throw_error(pl.error.permission("create", "operator", operator, atom.indicator));
                return;
              } else if (["fy", "fx", "yf", "xf", "xfx", "yfx", "xfy"].indexOf(type.id) === -1) {
                thread.throw_error(pl.error.domain("operator_specifier", type, atom.indicator));
                return;
              } else {
                var fix = { prefix: null, infix: null, postfix: null };
                for (var p in thread.session.__operators) {
                  if (!thread.session.__operators.hasOwnProperty(p))
                    continue;
                  var classes = thread.session.__operators[p][operator.id];
                  if (classes) {
                    if (indexOf(classes, "fx") !== -1) {
                      fix.prefix = { priority: p, type: "fx" };
                    }
                    if (indexOf(classes, "fy") !== -1) {
                      fix.prefix = { priority: p, type: "fy" };
                    }
                    if (indexOf(classes, "xf") !== -1) {
                      fix.postfix = { priority: p, type: "xf" };
                    }
                    if (indexOf(classes, "yf") !== -1) {
                      fix.postfix = { priority: p, type: "yf" };
                    }
                    if (indexOf(classes, "xfx") !== -1) {
                      fix.infix = { priority: p, type: "xfx" };
                    }
                    if (indexOf(classes, "xfy") !== -1) {
                      fix.infix = { priority: p, type: "xfy" };
                    }
                    if (indexOf(classes, "yfx") !== -1) {
                      fix.infix = { priority: p, type: "yfx" };
                    }
                  }
                }
                var current_class;
                switch (type.id) {
                  case "fy":
                  case "fx":
                    current_class = "prefix";
                    break;
                  case "yf":
                  case "xf":
                    current_class = "postfix";
                    break;
                  default:
                    current_class = "infix";
                    break;
                }
                if (fix.infix && current_class === "postfix" || fix.postfix && current_class === "infix") {
                  thread.throw_error(pl.error.permission("create", "operator", operator, atom.indicator));
                  return;
                } else {
                  if (fix[current_class]) {
                    remove(thread.session.__operators[fix[current_class].priority][operator.id], fix[current_class].type);
                    if (thread.session.__operators[fix[current_class].priority][operator.id].length === 0) {
                      delete thread.session.__operators[fix[current_class].priority][operator.id];
                    }
                  }
                  if (priority.value > 0) {
                    if (!thread.session.__operators[priority.value])
                      thread.session.__operators[priority.value.toString()] = {};
                    if (!thread.session.__operators[priority.value][operator.id])
                      thread.session.__operators[priority.value][operator.id] = [];
                    thread.session.__operators[priority.value][operator.id].push(type.id);
                  }
                }
              }
            }
            if (pl.type.is_variable(pointer)) {
              thread.throw_error(pl.error.instantiation(atom.indicator));
              return;
            } else if (!pl.type.is_term(pointer) || pointer.indicator !== "[]/0") {
              thread.throw_error(pl.error.type("list", operators, atom.indicator));
              return;
            } else {
              thread.success(point);
            }
          }
        },
        "current_op/3": function(thread, point, atom) {
          var priority = atom.args[0], specifier = atom.args[1], operator = atom.args[2];
          var points = [];
          if (!pl.type.is_variable(priority) && !pl.type.is_integer(priority)) {
            thread.throw_error(pl.error.type("integer", priority, atom.indicator));
          } else if (pl.type.is_integer(priority) && (priority.value < 0 || priority.value > 1200)) {
            thread.throw_error(pl.error.domain("operator_priority", priority, atom.indicator));
          } else if (!pl.type.is_variable(specifier) && !pl.type.is_atom(specifier)) {
            thread.throw_error(pl.error.type("atom", specifier, atom.indicator));
          } else if (pl.type.is_atom(specifier) && indexOf(["fy", "fx", "yf", "xf", "xfx", "yfx", "xfy"], specifier.id) === -1) {
            thread.throw_error(pl.error.domain("operator_specifier", specifier, atom.indicator));
          } else if (!pl.type.is_variable(operator) && !pl.type.is_atom(operator)) {
            thread.throw_error(pl.error.type("atom", operator, atom.indicator));
          } else {
            for (var p in thread.session.__operators)
              for (var o in thread.session.__operators[p])
                for (var i2 = 0; i2 < thread.session.__operators[p][o].length; i2++)
                  points.push(new State(
                    point.goal.replace(
                      new Term(",", [
                        new Term("=", [new Num(p, false), priority]),
                        new Term(",", [
                          new Term("=", [new Term(thread.session.__operators[p][o][i2], []), specifier]),
                          new Term("=", [new Term(o, []), operator])
                        ])
                      ])
                    ),
                    point.substitution,
                    point
                  ));
            thread.prepend(points);
          }
        },
        ";/2": function(thread, point, atom) {
          var left = atom.args[0], right = atom.args[1];
          var context_left = left.args[0];
          var free_left = left.indicator === ":/2" ? left.args[1] : left;
          if (pl.type.is_term(free_left) && free_left.indicator === "->/2") {
            var cond = left.indicator === ":/2" ? new Term(":", [context_left, new Term("call", [free_left.args[0]])]) : free_left.args[0];
            var then = left.indicator === ":/2" ? new Term(":", [context_left, free_left.args[1]]) : free_left.args[1];
            var otherwise = right;
            var goal_fst = point.goal.replace(new Term(",", [cond, new Term(",", [new Term("!"), then])]));
            var goal_snd = point.goal.replace(new Term(",", [new Term("!"), otherwise]));
            thread.prepend([
              new State(goal_fst, point.substitution, point),
              new State(goal_snd, point.substitution, point)
            ]);
          } else if (pl.type.is_term(free_left) && free_left.indicator === "*->/2") {
            var cond = left.indicator === ":/2" ? new Term(":", [context_left, free_left.args[0]]) : free_left.args[0];
            var then = left.indicator === ":/2" ? new Term(":", [context_left, free_left.args[1]]) : free_left.args[1];
            var otherwise = right;
            thread.prepend([new State(
              point.goal.replace(new Term("$if", [cond, then, otherwise])),
              point.substitution,
              point
            )]);
          } else {
            thread.prepend([
              new State(point.goal.replace(left), point.substitution, point),
              new State(point.goal.replace(right), point.substitution, point)
            ]);
          }
        },
        "!/0": function(thread, point, atom) {
          var parent_cut, last_cut, states = [];
          parent_cut = point;
          last_cut = null;
          while (parent_cut.parent !== null && parent_cut.parent.goal.search(atom)) {
            last_cut = parent_cut;
            parent_cut = parent_cut.parent;
            if (parent_cut.goal !== null) {
              var selected = parent_cut.goal.select();
              if (selected && selected.indicator === ":/2")
                selected = selected.args[1];
              if (selected && selected.id === "call" && selected.search(atom)) {
                parent_cut = last_cut;
                break;
              }
            }
          }
          var setup_call_cleanup = null;
          for (var i2 = thread.points.length - 1; i2 >= 0; i2--) {
            var state = thread.points[i2];
            var node = state.parent;
            while (node !== null && node !== parent_cut.parent) {
              node = node.parent;
            }
            if (node === null && node !== parent_cut.parent)
              states.push(state);
            else if (state.setup_call_cleanup_goal)
              setup_call_cleanup = state.setup_call_cleanup_goal;
          }
          thread.points = states.reverse();
          thread.prepend([new State(
            point.goal.replace(setup_call_cleanup),
            point.substitution,
            point
          )]);
        },
        "\\+/1": function(thread, point, atom) {
          var goal = atom.args[0];
          if (pl.type.is_variable(goal)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_callable(goal)) {
            thread.throw_error(pl.error.type("callable", goal, atom.indicator));
          } else {
            thread.prepend([
              new State(point.goal.replace(new Term(",", [new Term(",", [new Term("call", [goal]), new Term("!", [])]), new Term("fail", [])])), point.substitution, point),
              new State(point.goal.replace(null), point.substitution, point)
            ]);
          }
        },
        "->/2": function(thread, point, atom) {
          var cond = atom.args[0], then = atom.args[1];
          var goal = point.goal.replace(new Term(",", [
            new Term("call", [cond]),
            new Term(",", [new Term("!"), then])
          ]));
          thread.prepend([new State(goal, point.substitution, point)]);
        },
        "*->/2": function(thread, point, atom) {
          var cond = atom.args[0], then = atom.args[1];
          var goal = point.goal.replace(new Term(",", [
            new Term("call", [cond]),
            then
          ]));
          thread.prepend([new State(goal, point.substitution, point)]);
        },
        "fail/0": function(_1, _2, _3) {
        },
        "false/0": function(_1, _2, _3) {
        },
        "true/0": function(thread, point, _) {
          thread.success(point);
        },
        "call/1": callN(1),
        "call/2": callN(2),
        "call/3": callN(3),
        "call/4": callN(4),
        "call/5": callN(5),
        "call/6": callN(6),
        "call/7": callN(7),
        "call/8": callN(8),
        "once/1": function(thread, point, atom) {
          var goal = atom.args[0];
          thread.prepend([new State(point.goal.replace(new Term(",", [new Term("call", [goal]), new Term("!", [])])), point.substitution, point)]);
        },
        "forall/2": function(thread, point, atom) {
          var generate = atom.args[0], test = atom.args[1];
          thread.prepend([new State(point.goal.replace(new Term("\\+", [new Term(",", [new Term("call", [generate]), new Term("\\+", [new Term("call", [test])])])])), point.substitution, point)]);
        },
        "repeat/0": function(thread, point, _) {
          thread.prepend([new State(point.goal.replace(null), point.substitution, point), point]);
        },
        "throw/1": function(thread, point, atom) {
          var error = atom.args[0];
          if (pl.type.is_variable(error)) {
            thread.throw_error(pl.error.instantiation(thread.level.indicator));
          } else {
            for (var i2 = 0; i2 < thread.points.length; i2++) {
              var state = thread.points[i2];
              if (state.setup_call_cleanup_catch) {
                thread.points = [new State(
                  new Term(",", [
                    new Term("catch", [
                      state.setup_call_cleanup_catch,
                      new Var("_"),
                      new Term("throw", [error])
                    ]),
                    new Term("throw", [error])
                  ]),
                  point.substitution,
                  point
                )];
                return;
              }
            }
            thread.throw_error(error);
          }
        },
        "catch/3": function(thread, point, atom) {
          var goal = atom.args[0], catcher = atom.args[1], recover = atom.args[2];
          var nthread;
          if (!point.catch) {
            nthread = new Thread(thread.session);
            nthread.debugger = thread.debugger;
            nthread.format_success = function(state) {
              return state.substitution;
            };
            nthread.format_error = function(state) {
              return state.goal;
            };
            nthread.add_goal(goal, true, point);
            point.catch = nthread;
          } else {
            nthread = point.catch;
          }
          var callback = function(answer) {
            if (pl.type.is_error(answer)) {
              var occurs_check = thread.get_flag("occurs_check").indicator === "true/0";
              var state = new State();
              var mgu = pl.unify(answer.args[0], catcher, occurs_check);
              if (mgu !== null) {
                state.substitution = point.substitution.apply(mgu);
                state.goal = point.goal.replace(recover).apply(mgu);
                state.parent = point;
                thread.prepend([state]);
              } else {
                thread.throw_error(answer.args[0]);
              }
            } else if (answer !== false && answer !== null) {
              var state = answer === null ? [] : new State(
                point.goal.apply(answer).replace(null),
                point.substitution.apply(answer),
                point
              );
              thread.prepend([state, point]);
            } else if (answer === null) {
              thread.prepend([point]);
              if (thread.has_limit)
                thread.current_limit = 0;
            }
            thread.again(answer !== null);
          };
          nthread.answer(callback);
          return true;
        },
        "call_cleanup/2": function(thread, point, atom) {
          var call = atom.args[0], cleanup = atom.args[1];
          if (pl.type.is_variable(call) || pl.type.is_variable(cleanup)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_callable(call)) {
            thread.throw_error(pl.error.type("callable", call, atom.indicator));
          } else if (!pl.type.is_callable(cleanup)) {
            thread.throw_error(pl.error.type("callable", cleanup, atom.indicator));
          } else {
            var nthread, callback;
            if (point.hasOwnProperty("setup_call_cleanup_thread")) {
              nthread = point.setup_call_cleanup_thread;
              callback = point.setup_call_cleanup_callback;
            } else {
              var goal = new Term("call", [call]);
              nthread = new Thread(thread.session);
              nthread.add_goal(goal, true, point);
              callback = function(answer) {
                if (answer === null) {
                  var state = new State(
                    point.goal,
                    point.substitution,
                    point
                  );
                  state.setup_call_cleanup_thread = nthread;
                  state.setup_call_cleanup_callback = callback;
                  thread.prepend([state]);
                } else if (answer === false) {
                  var cleanup_and_fail = new Term(",", [
                    new Term("call", [cleanup]),
                    new Term("fail")
                  ]);
                  var state = new State(
                    point.goal.replace(cleanup_and_fail),
                    point.substitution,
                    point
                  );
                  thread.prepend([state]);
                } else if (pl.type.is_error(answer)) {
                  var cleanup_and_throw = new Term(",", [
                    new Term("call", [cleanup]),
                    answer
                  ]);
                  var state = new State(
                    point.goal.replace(cleanup_and_throw),
                    point.substitution,
                    point
                  );
                  thread.prepend([state]);
                } else {
                  if (nthread.points.length === 0) {
                    var state = new State(
                      point.goal.replace(
                        new Term("call", [cleanup])
                      ).apply(answer),
                      point.substitution.apply(answer),
                      point
                    );
                    thread.prepend([state]);
                  } else {
                    var state1 = new State(
                      point.goal.apply(answer).replace(null),
                      point.substitution.apply(answer),
                      point
                    );
                    var state2 = new State(
                      point.goal,
                      point.substitution,
                      point
                    );
                    state2.setup_call_cleanup_thread = nthread;
                    state2.setup_call_cleanup_callback = callback;
                    state2.setup_call_cleanup_goal = cleanup.apply(answer);
                    state2.setup_call_cleanup_catch = cleanup;
                    thread.prepend([state1, state2]);
                  }
                }
                thread.again();
              };
            }
            nthread.answer(callback);
            return true;
          }
        },
        "setup_call_cleanup/3": function(thread, point, atom) {
          var setup = atom.args[0], call = atom.args[1], cleanup = atom.args[2];
          if (pl.type.is_variable(setup) || pl.type.is_variable(call) || pl.type.is_variable(cleanup)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_callable(setup)) {
            thread.throw_error(pl.error.type("callable", setup, atom.indicator));
          } else if (!pl.type.is_callable(call)) {
            thread.throw_error(pl.error.type("callable", call, atom.indicator));
          } else if (!pl.type.is_callable(cleanup)) {
            thread.throw_error(pl.error.type("callable", cleanup, atom.indicator));
          } else {
            thread.prepend([new State(
              point.goal.replace(new Term(",", [
                new Term("once", [setup]),
                new Term("call_cleanup", [call, cleanup])
              ])),
              point.substitution,
              point
            )]);
          }
        },
        "=/2": function(thread, point, atom) {
          var occurs_check = thread.get_flag("occurs_check").indicator === "true/0";
          var state = new State();
          var mgu = pl.unify(atom.args[0], atom.args[1], occurs_check);
          if (mgu !== null) {
            state.goal = point.goal.apply(mgu).replace(null);
            state.substitution = point.substitution.apply(mgu);
            state.parent = point;
            thread.prepend([state]);
          }
        },
        "unify_with_occurs_check/2": function(thread, point, atom) {
          var state = new State();
          var mgu = pl.unify(atom.args[0], atom.args[1], true);
          if (mgu !== null) {
            state.goal = point.goal.apply(mgu).replace(null);
            state.substitution = point.substitution.apply(mgu);
            state.parent = point;
            thread.prepend([state]);
          }
        },
        "\\=/2": function(thread, point, atom) {
          var occurs_check = thread.get_flag("occurs_check").indicator === "true/0";
          var mgu = pl.unify(atom.args[0], atom.args[1], occurs_check);
          if (mgu === null) {
            thread.success(point);
          }
        },
        "subsumes_term/2": function(thread, point, atom) {
          var general = atom.args[0], specific = atom.args[1];
          var vars1 = thread.next_free_variable();
          var vars2 = thread.next_free_variable();
          thread.prepend([new State(
            point.goal.replace(new Term("\\+", [
              new Term("\\+", [
                new Term(",", [
                  new Term("term_variables", [specific, vars1]),
                  new Term(",", [
                    new Term("unify_with_occurs_check", [general, specific]),
                    new Term(",", [
                      new Term("term_variables", [vars1, vars2]),
                      new Term("==", [vars1, vars2])
                    ])
                  ])
                ])
              ])
            ])),
            point.substitution,
            point
          )]);
        },
        "findall/3": function(thread, point, atom) {
          var template = atom.args[0], goal = atom.args[1], instances = atom.args[2];
          var tail = new Term("[]", []);
          thread.prepend([new State(
            point.goal.replace(new Term("findall", [template, goal, instances, tail])),
            point.substitution,
            point
          )]);
        },
        "findall/4": function(thread, point, atom) {
          var template = atom.args[0], goal = atom.args[1], instances = atom.args[2], tail = atom.args[3];
          var proper_goal = goal;
          if (pl.type.is_term(goal) && goal.indicator === ":/2")
            proper_goal = goal.args[1];
          if (pl.type.is_variable(proper_goal)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_callable(proper_goal)) {
            thread.throw_error(pl.error.type("callable", goal, atom.indicator));
          } else if (!pl.type.is_variable(instances) && !pl.type.is_list(instances)) {
            thread.throw_error(pl.error.type("list", instances, atom.indicator));
          } else if (!pl.type.is_variable(tail) && !pl.type.is_list(tail)) {
            thread.throw_error(pl.error.type("list", tail, atom.indicator));
          } else {
            thread.prepend([new State(
              point.goal.replace(new Term("$findall", [template, goal, instances, tail])),
              point.substitution,
              point
            )]);
          }
        },
        "bagof/3": function(thread, point, atom) {
          var template = atom.args[0], goal = atom.args[1], instances = atom.args[2];
          if (pl.type.is_variable(goal)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_callable(goal)) {
            thread.throw_error(pl.error.type("callable", goal, atom.indicator));
          } else if (!pl.type.is_variable(instances) && !pl.type.is_list(instances)) {
            thread.throw_error(pl.error.type("list", instances, atom.indicator));
          } else {
            thread.prepend([new State(
              point.goal.replace(new Term("$bagof", [template, goal, instances])),
              point.substitution,
              point
            )]);
          }
        },
        "setof/3": function(thread, point, atom) {
          var template = atom.args[0], goal = atom.args[1], instances = atom.args[2];
          if (pl.type.is_variable(goal)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_callable(goal)) {
            thread.throw_error(pl.error.type("callable", goal, atom.indicator));
          } else if (!pl.type.is_variable(instances) && !pl.type.is_list(instances)) {
            thread.throw_error(pl.error.type("list", instances, atom.indicator));
          } else {
            thread.prepend([new State(
              point.goal.replace(new Term("$setof", [template, goal, instances])),
              point.substitution,
              point
            )]);
          }
        },
        "functor/3": function(thread, point, atom) {
          var subs;
          var term = atom.args[0], name = atom.args[1], arity = atom.args[2];
          if (pl.type.is_variable(term) && (pl.type.is_variable(name) || pl.type.is_variable(arity))) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(arity) && !pl.type.is_integer(arity)) {
            thread.throw_error(pl.error.type("integer", atom.args[2], atom.indicator));
          } else if (!pl.type.is_variable(name) && !pl.type.is_atomic(name)) {
            thread.throw_error(pl.error.type("atomic", atom.args[1], atom.indicator));
          } else if (pl.type.is_variable(term) && !pl.type.is_atom(name) && pl.type.is_integer(arity) && arity.value > 0) {
            thread.throw_error(pl.error.type("atom", atom.args[1], atom.indicator));
          } else if (pl.type.is_variable(term) && pl.type.is_integer(arity) && arity.value < 0) {
            thread.throw_error(pl.error.domain("not_less_than_zero", atom.args[2], atom.indicator));
          } else if (pl.type.is_variable(term)) {
            if (atom.args[2].value >= 0) {
              var args = [];
              for (var i2 = 0; i2 < arity.value; i2++)
                args.push(thread.next_free_variable());
              var functor = pl.type.is_number(name) ? name : new Term(name.id, args);
              thread.prepend([new State(point.goal.replace(new Term("=", [term, functor])), point.substitution, point)]);
            }
          } else {
            var id = pl.type.is_number(term) ? term : new Term(term.id, []);
            var length = pl.type.is_number(term) ? new Num(0, false) : new Num(term.args.length, false);
            var goal = new Term(",", [new Term("=", [id, name]), new Term("=", [length, arity])]);
            thread.prepend([new State(point.goal.replace(goal), point.substitution, point)]);
          }
        },
        "arg/3": function(thread, point, atom) {
          if (pl.type.is_variable(atom.args[0]) || pl.type.is_variable(atom.args[1])) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_integer(atom.args[0])) {
            thread.throw_error(pl.error.type("integer", atom.args[0], atom.indicator));
          } else if (atom.args[0].value < 0) {
            thread.throw_error(pl.error.domain("not_less_than_zero", atom.args[0], atom.indicator));
          } else if (!pl.type.is_compound(atom.args[1])) {
            thread.throw_error(pl.error.type("compound", atom.args[1], atom.indicator));
          } else {
            var n = atom.args[0].value;
            if (n > 0 && n <= atom.args[1].args.length) {
              var goal = new Term("=", [atom.args[1].args[n - 1], atom.args[2]]);
              thread.prepend([new State(point.goal.replace(goal), point.substitution, point)]);
            }
          }
        },
        "=../2": function(thread, point, atom) {
          var list;
          if (pl.type.is_variable(atom.args[0]) && (pl.type.is_variable(atom.args[1]) || pl.type.is_non_empty_list(atom.args[1]) && pl.type.is_variable(atom.args[1].args[0]))) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_fully_list(atom.args[1])) {
            thread.throw_error(pl.error.type("list", atom.args[1], atom.indicator));
          } else if (pl.type.is_variable(atom.args[0]) && pl.type.is_empty_list(atom.args[1])) {
            thread.throw_error(pl.error.domain("non_empty_list", atom.args[1], atom.indicator));
          } else if (!pl.type.is_variable(atom.args[0])) {
            if (pl.type.is_term(atom.args[0]) && atom.args[0].args.length > 0) {
              list = new Term("[]");
              for (var i2 = atom.args[0].args.length - 1; i2 >= 0; i2--) {
                list = new Term(".", [atom.args[0].args[i2], list]);
              }
              list = new Term(".", [new Term(atom.args[0].id), list]);
            } else {
              list = new Term(".", [atom.args[0], new Term("[]")]);
            }
            thread.prepend([new State(point.goal.replace(new Term("=", [list, atom.args[1]])), point.substitution, point)]);
          } else if (!pl.type.is_variable(atom.args[1])) {
            var args = [];
            list = atom.args[1].args[1];
            while (list.indicator === "./2") {
              args.push(list.args[0]);
              list = list.args[1];
            }
            if (pl.type.is_variable(atom.args[0]) && pl.type.is_variable(list)) {
              thread.throw_error(pl.error.instantiation(atom.indicator));
            } else if (args.length === 0 && pl.type.is_compound(atom.args[1].args[0])) {
              thread.throw_error(pl.error.type("atomic", atom.args[1].args[0], atom.indicator));
            } else if (args.length > 0 && (pl.type.is_compound(atom.args[1].args[0]) || pl.type.is_number(atom.args[1].args[0]))) {
              thread.throw_error(pl.error.type("atom", atom.args[1].args[0], atom.indicator));
            } else {
              if (args.length === 0) {
                thread.prepend([new State(point.goal.replace(new Term("=", [atom.args[1].args[0], atom.args[0]], point)), point.substitution, point)]);
              } else {
                thread.prepend([new State(point.goal.replace(new Term("=", [new Term(atom.args[1].args[0].id, args), atom.args[0]])), point.substitution, point)]);
              }
            }
          }
        },
        "copy_term/2": function(thread, point, atom) {
          var original_term = atom.args[0], renamed_term = atom.args[1];
          thread.session.renamed_variables = {};
          var new_term = original_term.rename(thread);
          thread.session.renamed_variables = {};
          thread.prepend(
            [
              new State(
                point.goal.replace(new Term("=", [renamed_term, new_term])),
                point.substitution,
                point
              )
            ]
          );
        },
        "term_variables/2": [
          new pl.type.Rule(new pl.type.Term("term_variables", [new pl.type.Var("Term"), new pl.type.Var("Vars")]), new pl.type.Term("term_variables", [new pl.type.Var("Term"), new pl.type.Var("Vars"), new pl.type.Term("[]", [])]))
        ],
        "term_variables/3": function(thread, point, atom) {
          var term = atom.args[0], vars = atom.args[1], tail = atom.args[2];
          if (!pl.type.is_fully_list(vars)) {
            thread.throw_error(pl.error.type("list", vars, atom.indicator));
          } else {
            var list = arrayToList(map(nub(term.variables()), function(v) {
              return new Var(v);
            }), tail);
            thread.prepend([new State(
              point.goal.replace(new Term("=", [vars, list])),
              point.substitution,
              point
            )]);
          }
        },
        "numbervars/3": function(thread, point, atom) {
          var term = atom.args[0], start = atom.args[1], end = atom.args[2];
          if (pl.type.is_variable(start)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_integer(start)) {
            thread.throw_error(pl.error.type("integer", start, atom.indicator));
          } else if (!pl.type.is_variable(end) && !pl.type.is_integer(end)) {
            thread.throw_error(pl.error.type("integer", end, atom.indicator));
          } else {
            var variables = nub(term.variables());
            var value = start.value;
            var unif_body = new Term("true");
            for (var i2 = 0; i2 < variables.length; i2++) {
              unif_body = new Term(",", [
                new Term("=", [
                  new Var(variables[i2]),
                  new Term("$VAR", [new Num(value, false)])
                ]),
                unif_body
              ]);
              value++;
            }
            var unif_end = new Term("=", [end, new Num(value, false)]);
            if (pl.type.is_variable(end) || end.value === value) {
              thread.prepend([new State(
                point.goal.replace(new Term(",", [unif_body, unif_end])),
                point.substitution,
                point
              )]);
            }
          }
        },
        "clause/2": function(thread, point, atom) {
          var head = atom.args[0], body = atom.args[1];
          var module_id = "user";
          if (pl.type.is_term(head) && head.indicator === ":/2") {
            if (!pl.type.is_atom(head.args[0])) {
              thread.throw_error(pl.error.type("module", head.args[0], atom.indicator));
              return;
            }
            module_id = head.args[0].id;
            head = head.args[1];
          }
          var get_module = thread.session.modules[module_id];
          if (pl.type.is_variable(head)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_callable(head)) {
            thread.throw_error(pl.error.type("callable", head, atom.indicator));
          } else if (!pl.type.is_variable(body) && !pl.type.is_callable(body)) {
            thread.throw_error(pl.error.type("callable", body, atom.indicator));
          } else if (head.indicator === ",/2" || thread.session.modules.system.rules.hasOwnProperty(head.indicator)) {
            thread.throw_error(pl.error.permission("access", "private_procedure", str_indicator(head.indicator), atom.indicator));
          } else if (pl.type.is_module(get_module) && get_module.rules[head.indicator]) {
            if (get_module.is_public_predicate(head.indicator)) {
              var states = [];
              if (typeof get_module.rules[head.indicator] === "function") {
                thread.throw_error(pl.error.permission("modify", "static_procedure", str_indicator(head.indicator), atom.indicator));
                return;
              }
              for (var i2 = 0; i2 < get_module.rules[head.indicator].length; i2++) {
                var rule = get_module.rules[head.indicator][i2];
                thread.session.renamed_variables = {};
                rule = rule.rename(thread);
                if (rule.body === null)
                  rule.body = new Term("true");
                var goal = new Term(",", [
                  new Term("=", [rule.head, head]),
                  new Term("=", [rule.body, body])
                ]);
                states.push(new State(point.goal.replace(goal), point.substitution, point));
              }
              thread.prepend(states);
            } else {
              thread.throw_error(pl.error.permission("access", "private_procedure", str_indicator(head.indicator), atom.indicator));
            }
          }
        },
        "current_predicate/1": function(thread, point, atom) {
          var indicator2 = atom.args[0];
          var module_id;
          if (pl.type.is_term(indicator2) && indicator2.indicator === ":/2") {
            if (!pl.type.is_atom(indicator2.args[0])) {
              thread.throw_error(pl.error.type("module", indicator2.args[0], atom.indicator));
              return;
            }
            module_id = indicator2.args[0].id;
            indicator2 = indicator2.args[1];
          } else {
            module_id = "user";
          }
          if (!pl.type.is_variable(indicator2) && (!pl.type.is_compound(indicator2) || indicator2.indicator !== "//2")) {
            thread.throw_error(pl.error.type("predicate_indicator", indicator2, atom.indicator));
          } else if (!pl.type.is_variable(indicator2) && !pl.type.is_variable(indicator2.args[0]) && !pl.type.is_atom(indicator2.args[0])) {
            thread.throw_error(pl.error.type("atom", indicator2.args[0], atom.indicator));
          } else if (!pl.type.is_variable(indicator2) && !pl.type.is_variable(indicator2.args[1]) && !pl.type.is_integer(indicator2.args[1])) {
            thread.throw_error(pl.error.type("integer", indicator2.args[1], atom.indicator));
          } else if (!pl.type.is_variable(indicator2) && pl.type.is_integer(indicator2.args[1]) && indicator2.args[1].value < 0) {
            thread.throw_error(pl.error.domain("not_less_than_zero", indicator2.args[1], atom.indicator));
          } else {
            var states = [];
            var get_module = thread.session.modules[module_id];
            if (pl.type.is_module(get_module)) {
              for (var prop in get_module.rules) {
                if (!get_module.rules.hasOwnProperty(prop))
                  continue;
                var predicate = str_indicator(prop);
                var goal = new Term("=", [predicate, indicator2]);
                states.push(new State(point.goal.replace(goal), point.substitution, point));
              }
              thread.prepend(states);
            }
          }
        },
        "current_module/1": function(thread, point, atom) {
          var module_id = atom.args[0];
          if (!pl.type.is_variable(module_id) && !pl.type.is_atom(module_id)) {
            thread.throw_error(pl.error.type("atom", module_id, atom.indicator));
          } else {
            if (pl.type.is_variable(module_id)) {
              var states = [];
              for (var prop in thread.session.modules) {
                if (!thread.session.modules.hasOwnProperty(prop))
                  continue;
                states.push(new State(
                  point.goal.replace(new Term("=", [module_id, new Term(prop)])),
                  point.substitution,
                  point
                ));
              }
              thread.prepend(states);
            } else {
              if (thread.session.modules.hasOwnProperty(module_id.id))
                thread.success(point);
            }
          }
        },
        "predicate_property/2": function(thread, point, atom) {
          var head = atom.args[0], property = atom.args[1];
          var module_id;
          if (pl.type.is_term(head) && head.indicator === ":/2") {
            if (!pl.type.is_atom(head.args[0])) {
              thread.throw_error(pl.error.type("module", head.args[0], atom.indicator));
              return;
            }
            module_id = head.args[0].id;
            head = head.args[1];
          }
          if (!pl.type.is_variable(head) && !pl.type.is_callable(head)) {
            thread.throw_error(pl.error.type("callable", head, atom.indicator));
          } else if (!pl.type.is_variable(property) && !pl.type.is_predicate_property(property)) {
            thread.throw_error(pl.error.domain("predicate_property", property, atom.indicator));
          } else {
            var get_module = module_id ? thread.session.modules[module_id] : thread.session.modules.user;
            var points = [];
            if (pl.type.is_variable(head)) {
              if (!module_id) {
                for (var prop in pl.builtin.rules) {
                  if (!pl.builtin.rules.hasOwnProperty(prop))
                    continue;
                  var indicator2 = str_indicator(prop);
                  var args = [];
                  for (var i2 = 0; i2 < indicator2.args[1].value; i2++)
                    args.push(thread.next_free_variable());
                  var unif_head = new Term(indicator2.args[0].id, args);
                  var current_properties = [
                    new Term("static"),
                    new Term("built_in"),
                    new Term("native_code")
                  ];
                  if (pl.builtin.meta_predicates.hasOwnProperty(prop))
                    current_properties.push(new Term("meta_predicate", [
                      pl.builtin.meta_predicates[prop]
                    ]));
                  for (var i2 = 0; i2 < current_properties.length; i2++) {
                    if (pl.type.is_variable(property) || current_properties[i2].indicator === property.indicator) {
                      points.push(new State(
                        point.goal.replace(new Term(",", [
                          new Term("=", [head, unif_head]),
                          new Term("=", [property, current_properties[i2]])
                        ])),
                        point.substitution,
                        point
                      ));
                    }
                  }
                }
              }
              if (pl.type.is_module(get_module)) {
                for (var prop in get_module.rules) {
                  if (!get_module.rules.hasOwnProperty(prop))
                    continue;
                  var indicator2 = str_indicator(prop);
                  var args = [];
                  for (var i2 = 0; i2 < indicator2.args[1].value; i2++)
                    args.push(thread.next_free_variable());
                  var unif_head = new Term(indicator2.args[0].id, args);
                  var current_properties = [];
                  if (thread.is_public_predicate(prop, module_id))
                    current_properties.push(new Term("dynamic"));
                  else
                    current_properties.push(new Term("static"));
                  if (get_module.rules[prop] instanceof Function)
                    current_properties.push(new Term("native_code"));
                  if (thread.is_multifile_predicate(prop, module_id))
                    current_properties.push(new Term("multifile"));
                  if (get_module.meta_predicates.hasOwnProperty(prop))
                    current_properties.push(new Term("meta_predicate", [
                      get_module.meta_predicates[prop]
                    ]));
                  for (var i2 = 0; i2 < current_properties.length; i2++) {
                    if (pl.type.is_variable(property) || current_properties[i2].indicator === property.indicator) {
                      points.push(new State(
                        point.goal.replace(new Term(",", [
                          new Term("=", [head, unif_head]),
                          new Term("=", [property, current_properties[i2]])
                        ])),
                        point.substitution,
                        point
                      ));
                    }
                  }
                }
              }
            } else {
              var builtin = !module_id && pl.type.is_builtin(head);
              var predicate = builtin ? pl.builtin.rules[head.indicator] : get_module.rules[head.indicator];
              get_module = builtin ? pl.builtin : get_module;
              if (predicate) {
                var current_properties;
                if (builtin) {
                  current_properties = [
                    new Term("static"),
                    new Term("built_in"),
                    new Term("native_code")
                  ];
                } else {
                  current_properties = [];
                  if (thread.is_public_predicate(head.indicator, module_id))
                    current_properties.push(new Term("dynamic"));
                  else
                    current_properties.push(new Term("static"));
                  if (predicate instanceof Function)
                    current_properties.push(new Term("native_code"));
                  if (thread.is_multifile_predicate(head.indicator, module_id))
                    current_properties.push(new Term("multifile"));
                }
                if (get_module.meta_predicates.hasOwnProperty(head.indicator))
                  current_properties.push(new Term("meta_predicate", [
                    get_module.meta_predicates[head.indicator]
                  ]));
                var args = [];
                for (var i2 = 0; i2 < head.args.length; i2++)
                  args.push(thread.next_free_variable());
                var unif_head = new Term(head.id, args);
                for (var i2 = 0; i2 < current_properties.length; i2++) {
                  if (pl.type.is_variable(property) || current_properties[i2].indicator === property.indicator) {
                    points.push(new State(
                      point.goal.replace(new Term(",", [
                        new Term("=", [head, unif_head]),
                        new Term("=", [property, current_properties[i2]])
                      ])),
                      point.substitution,
                      point
                    ));
                  }
                }
              }
            }
            thread.prepend(points);
          }
        },
        "listing/0": function(thread, point, atom) {
          var context_module = atom.context_module ? atom.context_module : "user";
          var rules2 = {};
          if (pl.type.is_module(thread.session.modules[context_module])) {
            rules2 = thread.session.modules[context_module].rules;
          }
          var str = "";
          for (var indicator2 in rules2) {
            if (!rules2.hasOwnProperty(indicator2))
              continue;
            var predicate = rules2[indicator2];
            str += "% " + indicator2 + "\n";
            if (predicate instanceof Array) {
              for (var i2 = 0; i2 < predicate.length; i2++)
                str += predicate[i2].toString({ session: thread.session }) + "\n";
            } else {
              str += "/*\n" + predicate.toString() + "\n*/";
            }
            str += "\n";
          }
          thread.prepend([new State(
            point.goal.replace(new Term("write", [new Term(str, [])])),
            point.substitution,
            point
          )]);
        },
        "listing/1": function(thread, point, atom) {
          var indicator2 = atom.args[0];
          var context_module = "user";
          if (indicator2.indicator === ":/2") {
            context_module = indicator2.args[0].id;
            indicator2 = indicator2.args[1];
          }
          if (pl.type.is_variable(indicator2)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_predicate_indicator(indicator2)) {
            thread.throw_error(pl.error.type("predicate_indicator", indicator2, atom.indicator));
          } else {
            var rules2 = {};
            if (pl.type.is_module(thread.session.modules[context_module])) {
              rules2 = thread.session.modules[context_module].rules;
            }
            var str = "";
            var str_indicator2 = indicator2.args[0].id + "/" + indicator2.args[1].value;
            if (rules2.hasOwnProperty(str_indicator2)) {
              var predicate = rules2[str_indicator2];
              if (predicate instanceof Array) {
                for (var i2 = 0; i2 < predicate.length; i2++)
                  str += predicate[i2].toString({ session: thread.session }) + "\n";
              } else {
                str += "/*\n" + predicate.toString() + "\n*/";
              }
              str += "\n";
            }
            thread.prepend([new State(
              point.goal.replace(new Term("write", [new Term(str, [])])),
              point.substitution,
              point
            )]);
          }
        },
        "sort/2": function(thread, point, atom) {
          var list = atom.args[0], expected = atom.args[1];
          if (pl.type.is_variable(list)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(expected) && !pl.type.is_fully_list(expected)) {
            thread.throw_error(pl.error.type("list", expected, atom.indicator));
          } else {
            var arr = [];
            var pointer = list;
            while (pointer.indicator === "./2") {
              arr.push(pointer.args[0]);
              pointer = pointer.args[1];
            }
            if (pl.type.is_variable(pointer)) {
              thread.throw_error(pl.error.instantiation(atom.indicator));
            } else if (!pl.type.is_empty_list(pointer)) {
              thread.throw_error(pl.error.type("list", list, atom.indicator));
            } else {
              var sorted_arr = arr.sort(pl.compare);
              for (var i2 = sorted_arr.length - 1; i2 > 0; i2--) {
                if (sorted_arr[i2].equals(sorted_arr[i2 - 1]))
                  sorted_arr.splice(i2, 1);
              }
              var sorted_list = new Term("[]");
              for (var i2 = sorted_arr.length - 1; i2 >= 0; i2--) {
                sorted_list = new Term(".", [sorted_arr[i2], sorted_list]);
              }
              thread.prepend([new State(point.goal.replace(new Term("=", [sorted_list, expected])), point.substitution, point)]);
            }
          }
        },
        "keysort/2": function(thread, point, atom) {
          var list = atom.args[0], expected = atom.args[1];
          if (pl.type.is_variable(list)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(expected) && !pl.type.is_fully_list(expected)) {
            thread.throw_error(pl.error.type("list", expected, atom.indicator));
          } else {
            var arr = [];
            var elem;
            var pointer = list;
            while (pointer.indicator === "./2") {
              elem = pointer.args[0];
              if (pl.type.is_variable(elem)) {
                thread.throw_error(pl.error.instantiation(atom.indicator));
                return;
              } else if (!pl.type.is_term(elem) || elem.indicator !== "-/2") {
                thread.throw_error(pl.error.type("pair", elem, atom.indicator));
                return;
              }
              elem.args[0].pair = elem.args[1];
              arr.push(elem.args[0]);
              pointer = pointer.args[1];
            }
            if (pl.type.is_variable(pointer)) {
              thread.throw_error(pl.error.instantiation(atom.indicator));
            } else if (!pl.type.is_empty_list(pointer)) {
              thread.throw_error(pl.error.type("list", list, atom.indicator));
            } else {
              if (!pl.type.is_variable(expected)) {
                var pointer = expected;
                while (pl.type.is_term(pointer) && pointer.indicator === "./2") {
                  var head = pointer.args[0];
                  if (!pl.type.is_variable(head) && (!pl.type.is_term(head) || head.indicator !== "-/2")) {
                    thread.throw_error(pl.error.type("pair", head, atom.indicator));
                    return;
                  }
                  pointer = pointer.args[1];
                }
                if (!pl.type.is_variable(pointer) && !pl.type.is_empty_list(pointer)) {
                  thread.throw_error(pl.error.type("list", expected, atom.indicator));
                  return;
                }
              }
              var sorted_arr = arr.sort(pl.compare);
              var sorted_list = new pl.type.Term("[]");
              for (var i2 = sorted_arr.length - 1; i2 >= 0; i2--) {
                sorted_list = new pl.type.Term(".", [new pl.type.Term("-", [sorted_arr[i2], sorted_arr[i2].pair]), sorted_list]);
                delete sorted_arr[i2].pair;
              }
              thread.prepend([new pl.type.State(point.goal.replace(new pl.type.Term("=", [sorted_list, expected])), point.substitution, point)]);
            }
          }
        },
        "keygroup/2": function(thread, point, atom) {
          var list = atom.args[0], expected = atom.args[1];
          if (pl.type.is_variable(list)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(expected) && !pl.type.is_fully_list(expected)) {
            thread.throw_error(pl.error.type("list", expected, atom.indicator));
          } else {
            var keys = [];
            var values = [];
            var pointer = list;
            while (pl.type.is_term(pointer) && pointer.indicator === "./2") {
              var elem = pointer.args[0];
              if (pl.type.is_variable(elem)) {
                thread.throw_error(pl.error.instantiation(atom.indicator));
                return;
              } else if (!pl.type.is_term(elem) || elem.indicator !== "-/2") {
                thread.throw_error(pl.error.type("pair", elem, atom.indicator));
                return;
              }
              var key = elem.args[0], value = elem.args[1];
              var index = -1;
              for (var i2 = 0; i2 < keys.length; i2++) {
                if (pl.compare(key, keys[i2]) === 0) {
                  index = i2;
                  break;
                }
              }
              if (index === -1) {
                index = keys.length;
                keys.push(key);
                values.push([]);
              }
              values[index].push(value);
              pointer = pointer.args[1];
            }
            if (pl.type.is_variable(pointer)) {
              thread.throw_error(pl.error.instantiation(atom.indicator));
            } else if (!pl.type.is_empty_list(pointer)) {
              thread.throw_error(pl.error.type("list", list, atom.indicator));
            } else {
              if (!pl.type.is_variable(expected)) {
                var pointer = expected;
                while (pl.type.is_term(pointer) && pointer.indicator === "./2") {
                  var head = pointer.args[0];
                  if (!pl.type.is_variable(head) && (!pl.type.is_term(head) || head.indicator !== "-/2")) {
                    thread.throw_error(pl.error.type("pair", head, atom.indicator));
                    return;
                  }
                  pointer = pointer.args[1];
                }
                if (!pl.type.is_variable(pointer) && !pl.type.is_empty_list(pointer)) {
                  thread.throw_error(pl.error.type("list", expected, atom.indicator));
                  return;
                }
              }
              group = new Term("[]", []);
              for (var i2 = keys.length - 1; i2 >= 0; i2--)
                group = new Term(".", [new Term("-", [keys[i2], arrayToList(values[i2])]), group]);
              thread.prepend([
                new State(
                  point.goal.replace(new pl.type.Term("=", [expected, group])),
                  point.substitution,
                  point
                )
              ]);
            }
          }
        },
        "asserta/1": function(thread, point, atom) {
          var clause = atom.args[0];
          var module_id = "user";
          if (pl.type.is_term(clause) && clause.indicator === ":/2") {
            module_id = clause.args[0].id;
            clause = clause.args[1];
          }
          if (pl.type.is_variable(clause)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_callable(clause)) {
            thread.throw_error(pl.error.type("callable", clause, atom.indicator));
          } else {
            var head, body, get_module;
            if (clause.indicator === ":-/2") {
              head = clause.args[0];
              body = body_conversion(clause.args[1]);
            } else {
              head = clause;
              body = null;
            }
            if (pl.type.is_variable(head)) {
              thread.throw_error(pl.error.instantiation(atom.indicator));
            } else if (!pl.type.is_callable(head)) {
              thread.throw_error(pl.error.type("callable", head, atom.indicator));
            } else if (body !== null && !pl.type.is_callable(body)) {
              thread.throw_error(pl.error.type("callable", body, atom.indicator));
            } else if ((!pl.type.is_module(thread.session.modules[module_id]) || thread.is_public_predicate(head.indicator, module_id)) && head.indicator !== ",/2" && !thread.session.modules.system.rules.hasOwnProperty(head.indicator)) {
              if (!pl.type.is_module(thread.session.modules[module_id])) {
                get_module = new Module(module_id, {}, "all", { session: thread.session });
                thread.session.modules[module_id] = get_module;
              } else {
                get_module = thread.session.modules[module_id];
              }
              if (get_module.rules[head.indicator] === void 0)
                get_module.rules[head.indicator] = [];
              get_module.public_predicates[head.indicator] = true;
              get_module.rules[head.indicator] = [new Rule(head, body, true)].concat(get_module.rules[head.indicator]);
              get_module.update_indices_predicate(head.indicator);
              thread.success(point);
            } else {
              thread.throw_error(pl.error.permission("modify", "static_procedure", str_indicator(head.indicator), atom.indicator));
            }
          }
        },
        "assertz/1": function(thread, point, atom) {
          var clause = atom.args[0];
          var module_id = "user";
          if (pl.type.is_term(clause) && clause.indicator === ":/2") {
            module_id = clause.args[0].id;
            clause = clause.args[1];
          }
          if (pl.type.is_variable(clause)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_callable(clause)) {
            thread.throw_error(pl.error.type("callable", clause, atom.indicator));
          } else {
            var head, body, get_module;
            if (clause.indicator === ":-/2") {
              head = clause.args[0];
              body = body_conversion(clause.args[1]);
            } else {
              head = clause;
              body = null;
            }
            if (pl.type.is_variable(head)) {
              thread.throw_error(pl.error.instantiation(atom.indicator));
            } else if (!pl.type.is_callable(head)) {
              thread.throw_error(pl.error.type("callable", head, atom.indicator));
            } else if (body !== null && !pl.type.is_callable(body)) {
              thread.throw_error(pl.error.type("callable", body, atom.indicator));
            } else if ((!pl.type.is_module(thread.session.modules[module_id]) || thread.is_public_predicate(head.indicator, module_id)) && head.indicator !== ",/2" && !thread.session.modules.system.rules.hasOwnProperty(head.indicator)) {
              if (!pl.type.is_module(thread.session.modules[module_id])) {
                get_module = new Module(module_id, {}, "all", { session: thread.session });
                thread.session.modules[module_id] = get_module;
              } else {
                get_module = thread.session.modules[module_id];
              }
              if (get_module.rules[head.indicator] === void 0)
                get_module.rules[head.indicator] = [];
              get_module.public_predicates[head.indicator] = true;
              get_module.rules[head.indicator].push(new Rule(head, body, true));
              get_module.update_indices_predicate(head.indicator);
              thread.success(point);
            } else {
              thread.throw_error(pl.error.permission("modify", "static_procedure", str_indicator(head.indicator), atom.indicator));
            }
          }
        },
        "retract/1": function(thread, point, atom) {
          var clause = atom.args[0];
          if (pl.type.is_variable(clause)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_callable(clause)) {
            thread.throw_error(pl.error.type("callable", clause, atom.indicator));
          } else {
            var head, body, module_atom, module_id;
            if (clause.indicator === ":/2") {
              module_atom = clause.args[0];
              clause = clause.args[1];
              if (!pl.type.is_atom(module_atom)) {
                thread.throw_error(pl.error.type("module", module_atom, atom.indicator));
                return;
              }
            } else {
              module_atom = new Term("user");
            }
            if (clause.indicator === ":-/2") {
              head = clause.args[0];
              body = clause.args[1];
            } else {
              head = clause;
              body = new Term("true");
            }
            if (pl.type.is_variable(head)) {
              thread.throw_error(pl.error.instantiation(atom.indicator));
              return;
            } else if (!pl.type.is_callable(head)) {
              thread.throw_error(pl.error.type("callable", head, atom.indicator));
              return;
            }
            module_id = module_atom.id;
            var get_module = thread.session.modules[module_id];
            if (!pl.type.is_module(get_module))
              return;
            if (!point.retract) {
              if (thread.is_public_predicate(head.indicator, module_id) && head.indicator !== ",/2" && !thread.session.modules.system.rules.hasOwnProperty(head.indicator)) {
                if (get_module.rules[head.indicator] !== void 0) {
                  var states = [];
                  if (typeof get_module.rules[head.indicator] === "function") {
                    thread.throw_error(pl.error.permission("modify", "static_procedure", str_indicator(head.indicator), atom.indicator));
                    return;
                  }
                  for (var i2 = 0; i2 < get_module.rules[head.indicator].length; i2++) {
                    thread.session.renamed_variables = {};
                    var orule = get_module.rules[head.indicator][i2];
                    var rule = orule.rename(thread);
                    if (rule.body === null)
                      rule.body = new Term("true", []);
                    var occurs_check = thread.get_flag("occurs_check").indicator === "true/0";
                    var mgu = pl.unify(new Term(",", [head, body]), new Term(",", [rule.head, rule.body]), occurs_check);
                    if (mgu !== null) {
                      var state = new State(
                        point.goal.replace(new Term(",", [
                          new Term(":", [
                            module_atom,
                            new Term("retract", [new Term(":-", [head, body])])
                          ]),
                          new Term(",", [
                            new Term("=", [head, rule.head]),
                            new Term("=", [body, rule.body])
                          ])
                        ])),
                        point.substitution,
                        point
                      );
                      state.retract = orule;
                      states.push(state);
                    }
                  }
                  thread.prepend(states);
                }
              } else {
                thread.throw_error(pl.error.permission("modify", "static_procedure", str_indicator(head.indicator), atom.indicator));
              }
            } else {
              retract(thread, point, head.indicator, point.retract, get_module);
            }
          }
        },
        "retractall/1": function(thread, point, atom) {
          var head = atom.args[0];
          var context_module = "user";
          if (pl.type.is_term(head) && head.indicator === ":/2") {
            context_module = head.args[0].id;
            head = head.args[1];
          }
          if (pl.type.is_variable(head)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_callable(head)) {
            thread.throw_error(pl.error.type("callable", head, atom.indicator));
          } else if (!thread.is_public_predicate(head.indicator, context_module) || head.indicator === ",/2" || thread.session.modules.system.rules.hasOwnProperty(head.indicator)) {
            thread.throw_error(pl.error.permission("modify", "static_procedure", str_indicator(head.indicator), atom.indicator));
          } else {
            thread.prepend([
              new State(point.goal.replace(new Term(",", [
                new Term(":", [
                  new Term(context_module),
                  new Term("retract", [new pl.type.Term(":-", [head, new Var("_")])])
                ]),
                new Term("fail", [])
              ])), point.substitution, point),
              new State(point.goal.replace(null), point.substitution, point)
            ]);
          }
        },
        "abolish/1": function(thread, point, atom) {
          var predicate = atom.args[0];
          var module_id;
          if (pl.type.is_term(predicate) && predicate.indicator === ":/2") {
            if (!pl.type.is_atom(predicate.args[0])) {
              thread.throw_error(pl.error.type("module", predicate.args[0], atom.indicator));
              return;
            }
            module_id = predicate.args[0].id;
            predicate = predicate.args[1];
          } else {
            module_id = "user";
          }
          if (pl.type.is_variable(predicate) || pl.type.is_term(predicate) && predicate.indicator === "//2" && (pl.type.is_variable(predicate.args[0]) || pl.type.is_variable(predicate.args[1]))) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_term(predicate) || predicate.indicator !== "//2") {
            thread.throw_error(pl.error.type("predicate_indicator", predicate, atom.indicator));
          } else if (!pl.type.is_atom(predicate.args[0])) {
            thread.throw_error(pl.error.type("atom", predicate.args[0], atom.indicator));
          } else if (!pl.type.is_integer(predicate.args[1])) {
            thread.throw_error(pl.error.type("integer", predicate.args[1], atom.indicator));
          } else if (predicate.args[1].value < 0) {
            thread.throw_error(pl.error.domain("not_less_than_zero", predicate.args[1], atom.indicator));
          } else if (pl.type.is_number(thread.get_flag("max_arity")) && predicate.args[1].value > thread.get_flag("max_arity").value) {
            thread.throw_error(pl.error.representation("max_arity", atom.indicator));
          } else {
            var get_module = thread.session.modules[module_id];
            if (pl.type.is_module(get_module)) {
              var indicator2 = predicate.args[0].id + "/" + predicate.args[1].value;
              if (thread.is_public_predicate(indicator2, module_id) && indicator2 !== ",/2" && !thread.session.modules.system.rules.hasOwnProperty(indicator2)) {
                delete get_module.rules[indicator2];
                delete get_module.indexed_clauses[indicator2];
                delete get_module.non_indexable_clauses[indicator2];
                delete get_module.public_predicates[indicator2];
                delete get_module.multifile_predicates[indicator2];
                thread.success(point);
              } else {
                thread.throw_error(pl.error.permission("modify", "static_procedure", atom.args[0], atom.indicator));
              }
            } else {
              thread.success(point);
            }
          }
        },
        "atom_length/2": function(thread, point, atom) {
          if (pl.type.is_variable(atom.args[0])) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_atom(atom.args[0])) {
            thread.throw_error(pl.error.type("atom", atom.args[0], atom.indicator));
          } else if (!pl.type.is_variable(atom.args[1]) && !pl.type.is_integer(atom.args[1])) {
            thread.throw_error(pl.error.type("integer", atom.args[1], atom.indicator));
          } else if (pl.type.is_integer(atom.args[1]) && atom.args[1].value < 0) {
            thread.throw_error(pl.error.domain("not_less_than_zero", atom.args[1], atom.indicator));
          } else {
            var length = new Num(stringLength(atom.args[0].id), false);
            thread.prepend([new State(point.goal.replace(new Term("=", [length, atom.args[1]])), point.substitution, point)]);
          }
        },
        "atom_concat/3": function(thread, point, atom) {
          var str, goal, start = atom.args[0], end = atom.args[1], whole = atom.args[2];
          if (pl.type.is_variable(whole) && (pl.type.is_variable(start) || pl.type.is_variable(end))) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(start) && !pl.type.is_atom(start)) {
            thread.throw_error(pl.error.type("atom", start, atom.indicator));
          } else if (!pl.type.is_variable(end) && !pl.type.is_atom(end)) {
            thread.throw_error(pl.error.type("atom", end, atom.indicator));
          } else if (!pl.type.is_variable(whole) && !pl.type.is_atom(whole)) {
            thread.throw_error(pl.error.type("atom", whole, atom.indicator));
          } else {
            var v1 = pl.type.is_variable(start);
            var v2 = pl.type.is_variable(end);
            if (!v1 && !v2) {
              goal = new Term("=", [whole, new Term(start.id + end.id)]);
              thread.prepend([new State(point.goal.replace(goal), point.substitution, point)]);
            } else if (v1 && !v2) {
              str = whole.id.substr(0, whole.id.length - end.id.length);
              if (str + end.id === whole.id) {
                goal = new Term("=", [start, new Term(str)]);
                thread.prepend([new State(point.goal.replace(goal), point.substitution, point)]);
              }
            } else if (v2 && !v1) {
              str = whole.id.substr(start.id.length);
              if (start.id + str === whole.id) {
                goal = new Term("=", [end, new Term(str)]);
                thread.prepend([new State(point.goal.replace(goal), point.substitution, point)]);
              }
            } else {
              var states = [];
              for (var i2 = 0; i2 <= whole.id.length; i2++) {
                var atom1 = new Term(whole.id.substr(0, i2));
                var atom2 = new Term(whole.id.substr(i2));
                goal = new Term(",", [new Term("=", [atom1, start]), new Term("=", [atom2, end])]);
                states.push(new State(point.goal.replace(goal), point.substitution, point));
              }
              thread.prepend(states);
            }
          }
        },
        "sub_atom/5": function(thread, point, atom) {
          var i2, atom1 = atom.args[0], before = atom.args[1], length = atom.args[2], after = atom.args[3], subatom = atom.args[4];
          if (pl.type.is_variable(atom1)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_atom(atom1)) {
            thread.throw_error(pl.error.type("atom", atom1, atom.indicator));
          } else if (!pl.type.is_variable(before) && !pl.type.is_integer(before)) {
            thread.throw_error(pl.error.type("integer", before, atom.indicator));
          } else if (!pl.type.is_variable(length) && !pl.type.is_integer(length)) {
            thread.throw_error(pl.error.type("integer", length, atom.indicator));
          } else if (!pl.type.is_variable(after) && !pl.type.is_integer(after)) {
            thread.throw_error(pl.error.type("integer", after, atom.indicator));
          } else if (pl.type.is_integer(before) && before.value < 0) {
            thread.throw_error(pl.error.domain("not_less_than_zero", before, atom.indicator));
          } else if (pl.type.is_integer(length) && length.value < 0) {
            thread.throw_error(pl.error.domain("not_less_than_zero", length, atom.indicator));
          } else if (pl.type.is_integer(after) && after.value < 0) {
            thread.throw_error(pl.error.domain("not_less_than_zero", after, atom.indicator));
          } else if (!pl.type.is_variable(subatom) && !pl.type.is_atom(subatom)) {
            thread.throw_error(pl.error.type("atom", subatom, atom.indicator));
          } else {
            var bs = [], ls = [], as = [];
            if (pl.type.is_variable(before)) {
              for (i2 = 0; i2 <= atom1.id.length; i2++) {
                bs.push(i2);
              }
            } else {
              bs.push(before.value);
            }
            if (pl.type.is_variable(length)) {
              for (i2 = 0; i2 <= atom1.id.length; i2++) {
                ls.push(i2);
              }
            } else {
              ls.push(length.value);
            }
            if (pl.type.is_variable(after)) {
              for (i2 = 0; i2 <= atom1.id.length; i2++) {
                as.push(i2);
              }
            } else {
              as.push(after.value);
            }
            var states = [];
            for (var _i in bs) {
              if (!bs.hasOwnProperty(_i))
                continue;
              i2 = bs[_i];
              for (var _j in ls) {
                if (!ls.hasOwnProperty(_j))
                  continue;
                var j = ls[_j];
                var k = atom1.id.length - i2 - j;
                if (indexOf(as, k) !== -1) {
                  if (i2 + j + k === atom1.id.length) {
                    var str = atom1.id.substr(i2, j);
                    if (atom1.id === atom1.id.substr(0, i2) + str + atom1.id.substr(i2 + j, k)) {
                      var pl1 = new Term("=", [new Term(str), subatom]);
                      var pl2 = new Term("=", [before, new Num(i2)]);
                      var pl3 = new Term("=", [length, new Num(j)]);
                      var pl4 = new Term("=", [after, new Num(k)]);
                      var goal = new Term(",", [new Term(",", [new Term(",", [pl2, pl3]), pl4]), pl1]);
                      states.push(new State(point.goal.replace(goal), point.substitution, point));
                    }
                  }
                }
              }
            }
            thread.prepend(states);
          }
        },
        "atom_chars/2": function(thread, point, atom) {
          var atom1 = atom.args[0], list = atom.args[1];
          if (pl.type.is_variable(atom1) && pl.type.is_variable(list)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(atom1) && !pl.type.is_atom(atom1)) {
            thread.throw_error(pl.error.type("atom", atom1, atom.indicator));
          } else {
            if (!pl.type.is_variable(atom1)) {
              if (!pl.type.is_variable(list)) {
                var pointer = list;
                while (pl.type.is_term(pointer) && pointer.indicator === "./2") {
                  if (!pl.type.is_character(pointer.args[0]) && !pl.type.is_variable(pointer.args[0])) {
                    thread.throw_error(pl.error.type("character", pointer.args[0], atom.indicator));
                    return;
                  }
                  pointer = pointer.args[1];
                }
              }
              var list1 = new Term("[]");
              var unilen = stringLength(atom1.id);
              for (var i2 = unilen - 1; i2 >= 0; i2--) {
                list1 = new Term(".", [new Term(atom1.id.charAt(i2)), list1]);
              }
              thread.prepend([new State(point.goal.replace(new Term("=", [list, list1])), point.substitution, point)]);
            } else {
              var pointer = list;
              var v = pl.type.is_variable(atom1);
              var str = "";
              while (pointer.indicator === "./2") {
                if (!pl.type.is_character(pointer.args[0])) {
                  if (pl.type.is_variable(pointer.args[0]) && v) {
                    thread.throw_error(pl.error.instantiation(atom.indicator));
                    return;
                  } else if (!pl.type.is_variable(pointer.args[0])) {
                    thread.throw_error(pl.error.type("character", pointer.args[0], atom.indicator));
                    return;
                  }
                } else {
                  str += pointer.args[0].id;
                }
                pointer = pointer.args[1];
              }
              if (pl.type.is_variable(pointer) && v) {
                thread.throw_error(pl.error.instantiation(atom.indicator));
              } else if (!pl.type.is_empty_list(pointer) && !pl.type.is_variable(pointer)) {
                thread.throw_error(pl.error.type("list", list, atom.indicator));
              } else {
                thread.prepend([new State(point.goal.replace(new Term("=", [new Term(str), atom1])), point.substitution, point)]);
              }
            }
          }
        },
        "atom_codes/2": function(thread, point, atom) {
          var atom1 = atom.args[0], list = atom.args[1];
          if (pl.type.is_variable(atom1) && pl.type.is_variable(list)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(atom1) && !pl.type.is_atom(atom1)) {
            thread.throw_error(pl.error.type("atom", atom1, atom.indicator));
          } else {
            if (!pl.type.is_variable(atom1)) {
              if (!pl.type.is_variable(list)) {
                var pointer = list;
                while (pl.type.is_term(pointer) && pointer.indicator === "./2") {
                  if (!pl.type.is_character_code(pointer.args[0]) && !pl.type.is_variable(pointer.args[0])) {
                    thread.throw_error(pl.error.type("integer", pointer.args[0], atom.indicator));
                    return;
                  }
                  pointer = pointer.args[1];
                }
              }
              var list1 = new Term("[]");
              var unilen = stringLength(atom1.id);
              for (var i2 = unilen - 1; i2 >= 0; i2--) {
                list1 = new Term(".", [new Num(codePointAt(atom1.id, i2), false), list1]);
              }
              thread.prepend([new State(point.goal.replace(new Term("=", [list, list1])), point.substitution, point)]);
            } else {
              var pointer = list;
              var v = pl.type.is_variable(atom1);
              var str = "";
              while (pointer.indicator === "./2") {
                if (!pl.type.is_character_code(pointer.args[0])) {
                  if (pl.type.is_variable(pointer.args[0]) && v) {
                    thread.throw_error(pl.error.instantiation(atom.indicator));
                    return;
                  } else if (!pl.type.is_variable(pointer.args[0])) {
                    thread.throw_error(pl.error.representation("character_code", atom.indicator));
                    return;
                  }
                } else {
                  str += fromCodePoint(pointer.args[0].value);
                }
                pointer = pointer.args[1];
              }
              if (pl.type.is_variable(pointer) && v) {
                thread.throw_error(pl.error.instantiation(atom.indicator));
              } else if (!pl.type.is_empty_list(pointer) && !pl.type.is_variable(pointer)) {
                thread.throw_error(pl.error.type("list", list, atom.indicator));
              } else {
                thread.prepend([new State(point.goal.replace(new Term("=", [new Term(str), atom1])), point.substitution, point)]);
              }
            }
          }
        },
        "char_code/2": function(thread, point, atom) {
          var char = atom.args[0], code = atom.args[1];
          if (pl.type.is_variable(char) && pl.type.is_variable(code)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(char) && !pl.type.is_character(char)) {
            thread.throw_error(pl.error.type("character", char, atom.indicator));
          } else if (!pl.type.is_variable(code) && !pl.type.is_integer(code)) {
            thread.throw_error(pl.error.type("integer", code, atom.indicator));
          } else if (!pl.type.is_variable(code) && !pl.type.is_character_code(code)) {
            thread.throw_error(pl.error.representation("character_code", atom.indicator));
          } else {
            if (pl.type.is_variable(code)) {
              var code1 = new Num(codePointAt(char.id, 0), false);
              thread.prepend([new State(point.goal.replace(new Term("=", [code1, code])), point.substitution, point)]);
            } else {
              var char1 = new Term(fromCodePoint(code.value));
              thread.prepend([new State(point.goal.replace(new Term("=", [char1, char])), point.substitution, point)]);
            }
          }
        },
        "number_chars/2": function(thread, point, atom) {
          var str, num = atom.args[0], list = atom.args[1];
          if (pl.type.is_variable(num) && pl.type.is_variable(list)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(num) && !pl.type.is_number(num)) {
            thread.throw_error(pl.error.type("number", num, atom.indicator));
          } else if (!pl.type.is_variable(list) && !pl.type.is_list(list)) {
            thread.throw_error(pl.error.type("list", list, atom.indicator));
          } else {
            var isvar = pl.type.is_variable(num);
            if (!pl.type.is_variable(list)) {
              var pointer = list;
              var total = true;
              str = "";
              while (pointer.indicator === "./2") {
                if (!pl.type.is_character(pointer.args[0])) {
                  if (pl.type.is_variable(pointer.args[0])) {
                    total = false;
                  } else if (!pl.type.is_variable(pointer.args[0])) {
                    thread.throw_error(pl.error.type("character", pointer.args[0], atom.indicator));
                    return;
                  }
                } else {
                  str += pointer.args[0].id;
                }
                pointer = pointer.args[1];
              }
              total = total && pl.type.is_empty_list(pointer);
              if (!pl.type.is_empty_list(pointer) && !pl.type.is_variable(pointer)) {
                thread.throw_error(pl.error.type("list", list, atom.indicator));
                return;
              }
              if (!total && isvar) {
                thread.throw_error(pl.error.instantiation(atom.indicator));
                return;
              } else if (total) {
                if (pl.type.is_variable(pointer) && isvar) {
                  thread.throw_error(pl.error.instantiation(atom.indicator));
                  return;
                } else {
                  var expr = thread.parse(str);
                  var num2 = expr.value;
                  if (!pl.type.is_number(num2) || expr.tokens[expr.tokens.length - 1].space) {
                    thread.throw_error(pl.error.syntax_by_predicate("parseable_number", atom.indicator));
                  } else {
                    thread.prepend([new State(point.goal.replace(new Term("=", [num, num2])), point.substitution, point)]);
                  }
                  return;
                }
              }
            }
            if (!isvar) {
              str = num.toString();
              var list2 = new Term("[]");
              for (var i2 = str.length - 1; i2 >= 0; i2--) {
                list2 = new Term(".", [new Term(str.charAt(i2)), list2]);
              }
              thread.prepend([new State(point.goal.replace(new Term("=", [list, list2])), point.substitution, point)]);
            }
          }
        },
        "number_codes/2": function(thread, point, atom) {
          var str, num = atom.args[0], list = atom.args[1];
          if (pl.type.is_variable(num) && pl.type.is_variable(list)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(num) && !pl.type.is_number(num)) {
            thread.throw_error(pl.error.type("number", num, atom.indicator));
          } else if (!pl.type.is_variable(list) && !pl.type.is_list(list)) {
            thread.throw_error(pl.error.type("list", list, atom.indicator));
          } else {
            var isvar = pl.type.is_variable(num);
            if (!pl.type.is_variable(list)) {
              var pointer = list;
              var total = true;
              str = "";
              while (pointer.indicator === "./2") {
                if (!pl.type.is_character_code(pointer.args[0])) {
                  if (pl.type.is_variable(pointer.args[0])) {
                    total = false;
                  } else if (!pl.type.is_variable(pointer.args[0])) {
                    thread.throw_error(pl.error.representation("character_code", atom.indicator));
                    return;
                  }
                } else {
                  str += fromCodePoint(pointer.args[0].value);
                }
                pointer = pointer.args[1];
              }
              total = total && pl.type.is_empty_list(pointer);
              if (!pl.type.is_empty_list(pointer) && !pl.type.is_variable(pointer)) {
                thread.throw_error(pl.error.type("list", list, atom.indicator));
                return;
              }
              if (!total && isvar) {
                thread.throw_error(pl.error.instantiation(atom.indicator));
                return;
              } else if (total) {
                if (pl.type.is_variable(pointer) && isvar) {
                  thread.throw_error(pl.error.instantiation(atom.indicator));
                  return;
                } else {
                  var expr = thread.parse(str);
                  var num2 = expr.value;
                  if (!pl.type.is_number(num2) || expr.tokens[expr.tokens.length - 1].space) {
                    thread.throw_error(pl.error.syntax_by_predicate("parseable_number", atom.indicator));
                  } else {
                    thread.prepend([new State(point.goal.replace(new Term("=", [num, num2])), point.substitution, point)]);
                  }
                  return;
                }
              }
            }
            if (!isvar) {
              str = num.toString();
              var list2 = new Term("[]");
              for (var i2 = str.length - 1; i2 >= 0; i2--) {
                list2 = new Term(".", [new Num(codePointAt(str, i2), false), list2]);
              }
              thread.prepend([new State(point.goal.replace(new Term("=", [list, list2])), point.substitution, point)]);
            }
          }
        },
        "upcase_atom/2": function(thread, point, atom) {
          var original = atom.args[0], upcase = atom.args[1];
          if (pl.type.is_variable(original)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_atom(original)) {
            thread.throw_error(pl.error.type("atom", original, atom.indicator));
          } else if (!pl.type.is_variable(upcase) && !pl.type.is_atom(upcase)) {
            thread.throw_error(pl.error.type("atom", upcase, atom.indicator));
          } else {
            thread.prepend([new State(point.goal.replace(new Term("=", [upcase, new Term(original.id.toUpperCase(), [])])), point.substitution, point)]);
          }
        },
        "downcase_atom/2": function(thread, point, atom) {
          var original = atom.args[0], downcase = atom.args[1];
          if (pl.type.is_variable(original)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_atom(original)) {
            thread.throw_error(pl.error.type("atom", original, atom.indicator));
          } else if (!pl.type.is_variable(downcase) && !pl.type.is_atom(downcase)) {
            thread.throw_error(pl.error.type("atom", downcase, atom.indicator));
          } else {
            thread.prepend([new State(point.goal.replace(new Term("=", [downcase, new Term(original.id.toLowerCase(), [])])), point.substitution, point)]);
          }
        },
        "atomic_concat/3": function(thread, point, atom) {
          var atomic1 = atom.args[0], atomic2 = atom.args[1], concat2 = atom.args[2];
          if (pl.type.is_variable(atomic1) || pl.type.is_variable(atomic2)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_atomic(atomic1)) {
            thread.throw_error(pl.error.type("atomic", atomic1, atom.indicator));
          } else if (!pl.type.is_atomic(atomic2)) {
            thread.throw_error(pl.error.type("atomic", atomic2, atom.indicator));
          } else if (!pl.type.is_variable(concat2) && !pl.type.is_atom(concat2)) {
            thread.throw_error(pl.error.type("atom", concat2, atom.indicator));
          } else {
            var id = "";
            if (pl.type.is_atom(atomic1)) {
              id += atomic1.id;
            } else {
              id += "" + atomic1.value;
            }
            if (pl.type.is_atom(atomic2)) {
              id += atomic2.id;
            } else {
              id += "" + atomic2.value;
            }
            var atom = new Term(id, []);
            thread.prepend([new State(point.goal.replace(new Term("=", [atom, concat2])), point.substitution, point)]);
          }
        },
        "atomic_list_concat/2": function(thread, point, atom) {
          var list = atom.args[0], concat2 = atom.args[1];
          thread.prepend([new State(point.goal.replace(new Term("atomic_list_concat", [list, new Term("", []), concat2])), point.substitution, point)]);
        },
        "atomic_list_concat/3": function(thread, point, atom) {
          var list = atom.args[0], separator = atom.args[1], concat2 = atom.args[2];
          if (pl.type.is_variable(separator) || pl.type.is_variable(list) && pl.type.is_variable(concat2)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(list) && !pl.type.is_list(list)) {
            thread.throw_error(pl.error.type("list", list, atom.indicator));
          } else if (!pl.type.is_atom(separator) && !pl.type.is_number(separator)) {
            thread.throw_error(pl.error.type("atomic", separator, atom.indicator));
          } else if (!pl.type.is_variable(concat2) && !pl.type.is_atom(concat2)) {
            thread.throw_error(pl.error.type("atom", concat2, atom.indicator));
          } else {
            var id = "";
            var pointer = list;
            while (pl.type.is_term(pointer) && pointer.indicator === "./2") {
              if (pl.type.is_variable(pointer.args[0])) {
                thread.throw_error(pl.error.instantiation(atom.indicator));
                return;
              } else if (!pl.type.is_atom(pointer.args[0]) && !pl.type.is_number(pointer.args[0])) {
                thread.throw_error(pl.error.type("atomic", pointer.args[0], atom.indicator));
                return;
              }
              if (id !== "")
                id += separator.id;
              if (pl.type.is_atom(pointer.args[0]))
                id += pointer.args[0].id;
              else
                id += "" + pointer.args[0].value;
              pointer = pointer.args[1];
            }
            id = new Term(id, []);
            if (pl.type.is_variable(pointer)) {
              thread.throw_error(pl.error.instantiation(atom.indicator));
            } else if (!pl.type.is_term(pointer) || pointer.indicator !== "[]/0") {
              thread.throw_error(pl.error.type("list", list, atom.indicator));
            } else {
              thread.prepend([new State(point.goal.replace(new Term("=", [id, concat2])), point.substitution, point)]);
            }
          }
        },
        "@=</2": function(thread, point, atom) {
          if (pl.compare(atom.args[0], atom.args[1]) <= 0) {
            thread.success(point);
          }
        },
        "==/2": function(thread, point, atom) {
          if (pl.compare(atom.args[0], atom.args[1]) === 0) {
            thread.success(point);
          }
        },
        "\\==/2": function(thread, point, atom) {
          if (pl.compare(atom.args[0], atom.args[1]) !== 0) {
            thread.success(point);
          }
        },
        "@</2": function(thread, point, atom) {
          if (pl.compare(atom.args[0], atom.args[1]) < 0) {
            thread.success(point);
          }
        },
        "@>/2": function(thread, point, atom) {
          if (pl.compare(atom.args[0], atom.args[1]) > 0) {
            thread.success(point);
          }
        },
        "@>=/2": function(thread, point, atom) {
          if (pl.compare(atom.args[0], atom.args[1]) >= 0) {
            thread.success(point);
          }
        },
        "compare/3": function(thread, point, atom) {
          var order = atom.args[0], left = atom.args[1], right = atom.args[2];
          if (!pl.type.is_variable(order) && !pl.type.is_atom(order)) {
            thread.throw_error(pl.error.type("atom", order, atom.indicator));
          } else if (pl.type.is_atom(order) && ["<", ">", "="].indexOf(order.id) === -1) {
            thread.throw_error(pl.error.domain("order", order, atom.indicator));
          } else {
            var compare = pl.compare(left, right);
            compare = compare === 0 ? "=" : compare === -1 ? "<" : ">";
            thread.prepend([new State(point.goal.replace(new Term("=", [order, new Term(compare, [])])), point.substitution, point)]);
          }
        },
        "is/2": function(thread, point, atom) {
          var op = atom.args[1].interpret(thread);
          if (!pl.type.is_number(op)) {
            thread.throw_error(op);
          } else {
            thread.prepend([new State(point.goal.replace(new Term("=", [atom.args[0], op], atom.indicator)), point.substitution, point)]);
          }
        },
        "between/3": function(thread, point, atom) {
          var lower = atom.args[0], upper = atom.args[1], bet = atom.args[2];
          if (pl.type.is_variable(lower) || pl.type.is_variable(upper)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_integer(lower)) {
            thread.throw_error(pl.error.type("integer", lower, atom.indicator));
          } else if (!pl.type.is_integer(upper)) {
            thread.throw_error(pl.error.type("integer", upper, atom.indicator));
          } else if (!pl.type.is_variable(bet) && !pl.type.is_integer(bet)) {
            thread.throw_error(pl.error.type("integer", bet, atom.indicator));
          } else {
            if (pl.type.is_variable(bet)) {
              if (lower.value <= upper.value) {
                var states = [new State(point.goal.replace(new Term("=", [bet, lower])), point.substitution, point)];
                states.push(new State(point.goal.replace(new Term("between", [new Num(lower.value + 1, false), upper, bet])), point.substitution, point));
                thread.prepend(states);
              }
            } else if (lower.value <= bet.value && upper.value >= bet.value) {
              thread.success(point);
            }
          }
        },
        "succ/2": function(thread, point, atom) {
          var n = atom.args[0], m = atom.args[1];
          if (pl.type.is_variable(n) && pl.type.is_variable(m)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(n) && !pl.type.is_integer(n)) {
            thread.throw_error(pl.error.type("integer", n, atom.indicator));
          } else if (!pl.type.is_variable(m) && !pl.type.is_integer(m)) {
            thread.throw_error(pl.error.type("integer", m, atom.indicator));
          } else if (!pl.type.is_variable(n) && n.value < 0) {
            thread.throw_error(pl.error.domain("not_less_than_zero", n, atom.indicator));
          } else if (!pl.type.is_variable(m) && m.value < 0) {
            thread.throw_error(pl.error.domain("not_less_than_zero", m, atom.indicator));
          } else {
            if (pl.type.is_variable(m) || m.value > 0) {
              if (pl.type.is_variable(n)) {
                thread.prepend([new State(point.goal.replace(new Term("=", [n, new Num(m.value - 1, false)])), point.substitution, point)]);
              } else {
                thread.prepend([new State(point.goal.replace(new Term("=", [m, new Num(n.value + 1, false)])), point.substitution, point)]);
              }
            }
          }
        },
        "=:=/2": function(thread, point, atom) {
          var cmp = pl.arithmetic_compare(thread, atom.args[0], atom.args[1]);
          if (pl.type.is_term(cmp)) {
            thread.throw_error(cmp);
          } else if (cmp === 0) {
            thread.success(point);
          }
        },
        "=\\=/2": function(thread, point, atom) {
          var cmp = pl.arithmetic_compare(thread, atom.args[0], atom.args[1]);
          if (pl.type.is_term(cmp)) {
            thread.throw_error(cmp);
          } else if (cmp !== 0) {
            thread.success(point);
          }
        },
        "</2": function(thread, point, atom) {
          var cmp = pl.arithmetic_compare(thread, atom.args[0], atom.args[1]);
          if (pl.type.is_term(cmp)) {
            thread.throw_error(cmp);
          } else if (cmp < 0) {
            thread.success(point);
          }
        },
        "=</2": function(thread, point, atom) {
          var cmp = pl.arithmetic_compare(thread, atom.args[0], atom.args[1]);
          if (pl.type.is_term(cmp)) {
            thread.throw_error(cmp);
          } else if (cmp <= 0) {
            thread.success(point);
          }
        },
        ">/2": function(thread, point, atom) {
          var cmp = pl.arithmetic_compare(thread, atom.args[0], atom.args[1]);
          if (pl.type.is_term(cmp)) {
            thread.throw_error(cmp);
          } else if (cmp > 0) {
            thread.success(point);
          }
        },
        ">=/2": function(thread, point, atom) {
          var cmp = pl.arithmetic_compare(thread, atom.args[0], atom.args[1]);
          if (pl.type.is_term(cmp)) {
            thread.throw_error(cmp);
          } else if (cmp >= 0) {
            thread.success(point);
          }
        },
        "var/1": function(thread, point, atom) {
          if (pl.type.is_variable(atom.args[0])) {
            thread.success(point);
          }
        },
        "atom/1": function(thread, point, atom) {
          if (pl.type.is_atom(atom.args[0])) {
            thread.success(point);
          }
        },
        "atomic/1": function(thread, point, atom) {
          if (pl.type.is_atomic(atom.args[0])) {
            thread.success(point);
          }
        },
        "compound/1": function(thread, point, atom) {
          if (pl.type.is_compound(atom.args[0])) {
            thread.success(point);
          }
        },
        "integer/1": function(thread, point, atom) {
          if (pl.type.is_integer(atom.args[0])) {
            thread.success(point);
          }
        },
        "float/1": function(thread, point, atom) {
          if (pl.type.is_float(atom.args[0])) {
            thread.success(point);
          }
        },
        "number/1": function(thread, point, atom) {
          if (pl.type.is_number(atom.args[0])) {
            thread.success(point);
          }
        },
        "nonvar/1": function(thread, point, atom) {
          if (!pl.type.is_variable(atom.args[0])) {
            thread.success(point);
          }
        },
        "ground/1": function(thread, point, atom) {
          if (atom.variables().length === 0) {
            thread.success(point);
          }
        },
        "acyclic_term/1": function(thread, point, atom) {
          var test = point.substitution.apply(point.substitution);
          var variables = atom.args[0].variables();
          for (var i2 = 0; i2 < variables.length; i2++)
            if (point.substitution.links[variables[i2]] !== void 0 && !point.substitution.links[variables[i2]].equals(test.links[variables[i2]]))
              return;
          thread.success(point);
        },
        "callable/1": function(thread, point, atom) {
          var callable = atom.args[0];
          if (pl.type.is_term(callable)) {
            thread.success(point);
          }
        },
        "is_list/1": function(thread, point, atom) {
          var list = atom.args[0];
          while (pl.type.is_term(list) && list.indicator === "./2")
            list = list.args[1];
          if (pl.type.is_term(list) && list.indicator === "[]/0")
            thread.success(point);
        },
        "current_input/1": function(thread, point, atom) {
          var stream = atom.args[0];
          if (!pl.type.is_variable(stream) && (!pl.type.is_stream(stream) || !thread.get_stream_by_alias(stream.alias) && !thread.get_stream_by_alias(stream.id)) && (!pl.type.is_atom(stream) || !thread.get_stream_by_alias(stream.id))) {
            thread.throw_error(pl.error.domain("stream", stream, atom.indicator));
          } else {
            if (pl.type.is_atom(stream))
              stream = thread.get_stream_by_alias(stream.id);
            thread.prepend([
              new State(
                point.goal.replace(new Term("=", [stream, thread.get_current_input()])),
                point.substitution,
                point
              )
            ]);
          }
        },
        "current_output/1": function(thread, point, atom) {
          var stream = atom.args[0];
          if (!pl.type.is_variable(stream) && (!pl.type.is_stream(stream) || !thread.get_stream_by_alias(stream.alias) && !thread.get_stream_by_alias(stream.id)) && (!pl.type.is_atom(stream) || !thread.get_stream_by_alias(stream.id))) {
            thread.throw_error(pl.error.domain("stream", stream, atom.indicator));
          } else {
            if (pl.type.is_atom(stream))
              stream = thread.get_stream_by_alias(stream.id);
            thread.prepend([
              new State(
                point.goal.replace(new Term("=", [stream, thread.get_current_output()])),
                point.substitution,
                point
              )
            ]);
          }
        },
        "set_input/1": function(thread, point, atom) {
          var input = atom.args[0];
          var stream = pl.type.is_stream(input) ? input : thread.get_stream_by_alias(input.id);
          if (pl.type.is_variable(input)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_stream(input) && !pl.type.is_atom(input)) {
            thread.throw_error(pl.error.domain("stream_or_alias", input, atom.indicator));
          } else if (!pl.type.is_stream(stream) || !thread.get_stream_by_alias(input.alias) && !thread.get_stream_by_alias(input.id)) {
            thread.throw_error(pl.error.existence("stream", input, atom.indicator));
          } else if (stream.output === true) {
            thread.throw_error(pl.error.permission("input", "stream", input, atom.indicator));
          } else {
            thread.set_current_input(stream);
            thread.success(point);
          }
        },
        "set_output/1": function(thread, point, atom) {
          var output = atom.args[0];
          var stream = pl.type.is_stream(output) ? output : thread.get_stream_by_alias(output.id);
          if (pl.type.is_variable(output)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_stream(output) && !pl.type.is_atom(output)) {
            thread.throw_error(pl.error.domain("stream_or_alias", output, atom.indicator));
          } else if (!pl.type.is_stream(stream) || !thread.get_stream_by_alias(output.alias) && !thread.get_stream_by_alias(output.id)) {
            thread.throw_error(pl.error.existence("stream", output, atom.indicator));
          } else if (stream.input === true) {
            thread.throw_error(pl.error.permission("output", "stream", output, atom.indicator));
          } else {
            thread.set_current_output(stream);
            thread.success(point);
          }
        },
        "open/3": function(thread, point, atom) {
          var dest = atom.args[0], mode = atom.args[1], stream = atom.args[2];
          thread.prepend([new State(
            point.goal.replace(new Term("open", [dest, mode, stream, new Term("[]", [])])),
            point.substitution,
            point
          )]);
        },
        "open/4": function(thread, point, atom) {
          var dest = atom.args[0], mode = atom.args[1], stream = atom.args[2], options = atom.args[3];
          if (pl.type.is_variable(dest) || pl.type.is_variable(mode) || pl.type.is_variable(options)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(mode) && !pl.type.is_atom(mode)) {
            thread.throw_error(pl.error.type("atom", mode, atom.indicator));
          } else if (!pl.type.is_list(options)) {
            thread.throw_error(pl.error.type("list", options, atom.indicator));
          } else if (!pl.type.is_variable(stream)) {
            thread.throw_error(pl.error.uninstantiation(stream, atom.indicator));
          } else if (!pl.type.is_atom(dest) && !pl.type.is_streamable(dest)) {
            thread.throw_error(pl.error.domain("source_sink", dest, atom.indicator));
          } else if (!pl.type.is_io_mode(mode)) {
            thread.throw_error(pl.error.domain("io_mode", mode, atom.indicator));
          } else {
            var obj_options = {};
            var pointer = options;
            var property;
            while (pl.type.is_term(pointer) && pointer.indicator === "./2") {
              property = pointer.args[0];
              if (pl.type.is_variable(property)) {
                thread.throw_error(pl.error.instantiation(atom.indicator));
                return;
              } else if (!pl.type.is_stream_option(property)) {
                thread.throw_error(pl.error.domain("stream_option", property, atom.indicator));
                return;
              }
              obj_options[property.id] = property.args[0].id;
              pointer = pointer.args[1];
            }
            if (pointer.indicator !== "[]/0") {
              if (pl.type.is_variable(pointer))
                thread.throw_error(pl.error.instantiation(atom.indicator));
              else
                thread.throw_error(pl.error.type("list", options, atom.indicator));
              return;
            } else {
              var alias = obj_options["alias"];
              if (alias && thread.get_stream_by_alias(alias)) {
                thread.throw_error(pl.error.permission("open", "source_sink", new Term("alias", [new Term(alias, [])]), atom.indicator));
                return;
              }
              if (!obj_options["type"])
                obj_options["type"] = "text";
              var file;
              if (pl.type.is_atom(dest))
                file = thread.file_system_open(dest.id, obj_options["type"], mode.id);
              else
                file = dest.stream(obj_options["type"], mode.id);
              if (file === false) {
                thread.throw_error(pl.error.permission("open", "source_sink", dest, atom.indicator));
                return;
              } else if (file === null) {
                thread.throw_error(pl.error.existence("source_sink", dest, atom.indicator));
                return;
              }
              var newstream = new Stream(
                file,
                mode.id,
                obj_options["alias"],
                obj_options["type"],
                obj_options["reposition"] === "true",
                obj_options["eof_action"]
              );
              if (alias)
                thread.session.streams[alias] = newstream;
              else
                thread.session.streams[newstream.id] = newstream;
              thread.prepend([new State(
                point.goal.replace(new Term("=", [stream, newstream])),
                point.substitution,
                point
              )]);
            }
          }
        },
        "close/1": function(thread, point, atom) {
          var stream = atom.args[0];
          thread.prepend([new State(
            point.goal.replace(new Term("close", [stream, new Term("[]", [])])),
            point.substitution,
            point
          )]);
        },
        "close/2": function(thread, point, atom) {
          var stream = atom.args[0], options = atom.args[1];
          var stream2 = pl.type.is_stream(stream) ? stream : thread.get_stream_by_alias(stream.id);
          if (pl.type.is_variable(stream) || pl.type.is_variable(options)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_list(options)) {
            thread.throw_error(pl.error.type("list", options, atom.indicator));
          } else if (!pl.type.is_stream(stream) && !pl.type.is_atom(stream)) {
            thread.throw_error(pl.error.domain("stream_or_alias", stream, atom.indicator));
          } else if (!pl.type.is_stream(stream2) || stream2.stream === null) {
            thread.throw_error(pl.error.existence("stream", stream, atom.indicator));
          } else {
            var obj_options = {};
            var pointer = options;
            var property;
            while (pl.type.is_term(pointer) && pointer.indicator === "./2") {
              property = pointer.args[0];
              if (pl.type.is_variable(property)) {
                thread.throw_error(pl.error.instantiation(atom.indicator));
                return;
              } else if (!pl.type.is_close_option(property)) {
                thread.throw_error(pl.error.domain("close_option", property, atom.indicator));
                return;
              }
              obj_options[property.id] = property.args[0].id === "true";
              pointer = pointer.args[1];
            }
            if (pointer.indicator !== "[]/0") {
              if (pl.type.is_variable(pointer))
                thread.throw_error(pl.error.instantiation(atom.indicator));
              else
                thread.throw_error(pl.error.type("list", options, atom.indicator));
              return;
            } else {
              if (stream2 === thread.session.standard_input || stream2 === thread.session.standard_output || stream2 === thread.session.standard_error) {
                thread.success(point);
                return;
              } else if (stream2 === thread.session.current_input) {
                thread.session.current_input = thread.session.standard_input;
              } else if (stream2 === thread.session.current_output) {
                thread.session.current_output = thread.session.standard_output;
              }
              if (stream2.alias !== null && stream2.alias !== void 0)
                delete thread.session.streams[stream2.alias];
              else
                delete thread.session.streams[stream2.id];
              if (stream2.output)
                stream2.stream.flush();
              var closed = stream2.stream.close();
              stream2.stream = null;
              if (obj_options.force === true || closed === true) {
                thread.success(point);
              }
            }
          }
        },
        "flush_output/0": [
          new Rule(new Term("flush_output", []), new Term(",", [new Term("current_output", [new Var("S")]), new Term("flush_output", [new Var("S")])]))
        ],
        "flush_output/1": function(thread, point, atom) {
          var stream = atom.args[0];
          var stream2 = pl.type.is_stream(stream) ? stream : thread.get_stream_by_alias(stream.id);
          if (pl.type.is_variable(stream)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_stream(stream) && !pl.type.is_atom(stream)) {
            thread.throw_error(pl.error.domain("stream_or_alias", stream, atom.indicator));
          } else if (!pl.type.is_stream(stream2) || stream2.stream === null) {
            thread.throw_error(pl.error.existence("stream", stream, atom.indicator));
          } else if (stream2.input === true) {
            thread.throw_error(pl.error.permission("output", "stream", stream, atom.indicator));
          } else {
            stream2.stream.flush();
            thread.success(point);
          }
        },
        "stream_property/2": function(thread, point, atom) {
          var stream = atom.args[0], property = atom.args[1];
          var stream2 = pl.type.is_stream(stream) ? stream : thread.get_stream_by_alias(stream.id);
          if (!pl.type.is_variable(stream) && !pl.type.is_stream(stream)) {
            thread.throw_error(pl.error.domain("stream", stream, atom.indicator));
          } else if (!pl.type.is_variable(stream) && (!pl.type.is_stream(stream2) || stream2.stream === null)) {
            thread.throw_error(pl.error.existence("stream", stream, atom.indicator));
          } else if (!pl.type.is_variable(property) && !pl.type.is_stream_property(property)) {
            thread.throw_error(pl.error.domain("stream_property", property, atom.indicator));
          } else {
            var streams = [];
            var states = [];
            var propvar = pl.type.is_variable(property);
            if (!pl.type.is_variable(stream))
              streams.push(stream2);
            else
              for (var key in thread.session.streams)
                streams.push(thread.session.streams[key]);
            for (var i2 = 0; i2 < streams.length; i2++) {
              var properties = [];
              if ((propvar || property.indicator === "file_name/1") && streams[i2].filename)
                properties.push(new Term("file_name", [new Term(streams[i2].file_name, [])]));
              if (propvar || property.indicator === "mode/1")
                properties.push(new Term("mode", [new Term(streams[i2].mode, [])]));
              if (propvar || property.indicator === "input/0" || property.indicator === "output/0")
                properties.push(new Term(streams[i2].input ? "input" : "output", []));
              if ((propvar || property.indicator === "alias/1") && streams[i2].alias)
                properties.push(new Term("alias", [new Term(streams[i2].alias, [])]));
              if (propvar || property.indicator === "position/1")
                properties.push(new Term("position", [
                  new Term("position", [
                    new Num(streams[i2].char_count, false),
                    new Num(streams[i2].line_count, false),
                    new Num(streams[i2].line_position, false)
                  ])
                ]));
              if (propvar || property.indicator === "end_of_stream/1")
                properties.push(new Term("end_of_stream", [new Term(
                  streams[i2].position === "end_of_stream" || streams[i2].stream.eof && streams[i2].stream.eof(streams[i2].position) ? "at" : streams[i2].position === "past_end_of_stream" ? "past" : "not",
                  []
                )]));
              if (propvar || property.indicator === "eof_action/1")
                properties.push(new Term("eof_action", [new Term(streams[i2].eof_action, [])]));
              if (propvar || property.indicator === "reposition/1")
                properties.push(new Term("reposition", [new Term(streams[i2].reposition ? "true" : "false", [])]));
              if (propvar || property.indicator === "type/1")
                properties.push(new Term("type", [new Term(streams[i2].type, [])]));
              for (var j = 0; j < properties.length; j++) {
                states.push(new State(
                  point.goal.replace(new Term(",", [
                    new Term("=", [pl.type.is_variable(stream) ? stream : stream2, streams[i2]]),
                    new Term("=", [property, properties[j]])
                  ])),
                  point.substitution,
                  point
                ));
              }
            }
            thread.prepend(states);
          }
        },
        "stream_position_data/3": function(thread, point, atom) {
          var field = atom.args[0], position = atom.args[1], value = atom.args[2];
          if (pl.type.is_variable(position)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_term(position) || position.indicator !== "position/3") {
            thread.throw_error(pl.error.domain("stream_position", position, atom.indicator));
          } else if (!pl.type.is_variable(field) && !pl.type.is_atom(field)) {
            thread.throw_error(pl.error.type("atom", field, atom.indicator));
          } else if (!pl.type.is_variable(value) && !pl.type.is_integer(value)) {
            thread.throw_error(pl.error.type("integer", value, atom.indicator));
          } else {
            var fields = ["char_count", "line_count", "line_position"];
            var states = [];
            var data_pos = { char_count: 0, line_count: 1, line_position: 2 };
            if (pl.type.is_variable(field)) {
              for (var i2 = 0; i2 < fields.length; i2++) {
                states.push(new State(point.goal.replace(
                  new Term(",", [
                    new Term("=", [new Term(fields[i2]), field]),
                    new Term("=", [value, position.args[data_pos[fields[i2]]]])
                  ])
                ), point.substitution, point));
              }
            } else if (data_pos.hasOwnProperty(field.id)) {
              states.push(new State(point.goal.replace(
                new Term("=", [value, position.args[data_pos[field.id]]])
              ), point.substitution, point));
            }
            thread.prepend(states);
          }
        },
        "at_end_of_stream/0": [
          new Rule(new Term("at_end_of_stream", []), new pl.type.Term(",", [new Term("current_input", [new Var("S")]), new Term(",", [new Term("stream_property", [new Var("S"), new Term("end_of_stream", [new Var("E")])]), new Term(",", [new Term("!", []), new Term(";", [new Term("=", [new Var("E"), new Term("at", [])]), new Term("=", [new Var("E"), new Term("past", [])])])])])]))
        ],
        "at_end_of_stream/1": function(thread, point, atom) {
          var stream = atom.args[0];
          var stream2 = pl.type.is_stream(stream) ? stream : thread.get_stream_by_alias(stream.id);
          if (pl.type.is_variable(stream)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_stream(stream2) || stream2.stream === null) {
            thread.throw_error(pl.error.existence("stream", stream, atom.indicator));
          } else {
            var e = thread.next_free_variable();
            thread.prepend([new State(
              point.goal.replace(
                new Term(",", [
                  new Term("stream_property", [stream2, new Term("end_of_stream", [e])]),
                  new Term(",", [new Term("!", []), new Term(";", [
                    new Term("=", [e, new Term("at", [])]),
                    new Term("=", [e, new Term("past", [])])
                  ])])
                ])
              ),
              point.substitution,
              point
            )]);
          }
        },
        "set_stream_position/2": function(thread, point, atom) {
          var stream = atom.args[0], position = atom.args[1];
          var stream2 = pl.type.is_stream(stream) ? stream : thread.get_stream_by_alias(stream.id);
          if (pl.type.is_variable(stream) || pl.type.is_variable(position)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_stream(stream) && !pl.type.is_atom(stream)) {
            thread.throw_error(pl.error.domain("stream_or_alias", stream, atom.indicator));
          } else if (!pl.type.is_stream(stream2) || stream2.stream === null) {
            thread.throw_error(pl.error.existence("stream", stream, atom.indicator));
          } else if (!pl.type.is_stream_position(position)) {
            thread.throw_error(pl.error.domain("stream_position", position, atom.indicator));
          } else if (stream2.reposition === false) {
            thread.throw_error(pl.error.permission("reposition", "stream", stream, atom.indicator));
          } else {
            if (position.indicator === "position/3") {
              stream2.position = position.args[0].value;
              stream2.char_count = position.args[0].value;
              stream2.line_count = position.args[1].value;
              stream2.line_position = position.args[2].value;
            } else {
              stream2.position = position.id;
            }
            thread.success(point);
          }
        },
        "get_char/1": [
          new Rule(new Term("get_char", [new Var("C")]), new Term(",", [new Term("current_input", [new Var("S")]), new Term("get_char", [new Var("S"), new Var("C")])]))
        ],
        "get_char/2": function(thread, point, atom) {
          var stream = atom.args[0], char = atom.args[1];
          var stream2 = pl.type.is_stream(stream) ? stream : thread.get_stream_by_alias(stream.id);
          if (pl.type.is_variable(stream)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(char) && !pl.type.is_in_character(char)) {
            thread.throw_error(pl.error.type("in_character", char, atom.indicator));
          } else if (!pl.type.is_stream(stream) && !pl.type.is_atom(stream)) {
            thread.throw_error(pl.error.domain("stream_or_alias", stream, atom.indicator));
          } else if (!pl.type.is_stream(stream2) || stream2.stream === null) {
            thread.throw_error(pl.error.existence("stream", stream, atom.indicator));
          } else if (stream2.output) {
            thread.throw_error(pl.error.permission("input", "stream", stream, atom.indicator));
          } else if (stream2.type === "binary") {
            thread.throw_error(pl.error.permission("input", "binary_stream", stream, atom.indicator));
          } else if (stream2.position === "past_end_of_stream" && stream2.eof_action === "error") {
            thread.throw_error(pl.error.permission("input", "past_end_of_stream", stream, atom.indicator));
          } else {
            var stream_char;
            if (stream2.position === "end_of_stream") {
              stream_char = "end_of_file";
              stream2.position = "past_end_of_stream";
            } else if (stream2.position === "past_end_of_stream") {
              stream_char = "end_of_file";
              stream2.position = "past_end_of_stream";
            } else {
              stream_char = stream2.stream.get(1, stream2.position);
              if (stream_char === null) {
                thread.throw_error(pl.error.representation("character", atom.indicator));
                return;
              } else if (stream_char === "end_of_stream") {
                stream_char = "end_of_file";
                stream2.position = "past_end_of_stream";
              } else {
                stream2.position++;
                stream2.char_count++;
                stream2.line_position++;
                if (stream_char === "\n") {
                  stream2.line_count++;
                  stream2.line_position = 0;
                }
              }
            }
            thread.prepend([new State(
              point.goal.replace(new Term("=", [new Term(stream_char, []), char])),
              point.substitution,
              point
            )]);
          }
        },
        "get_code/1": [
          new Rule(new Term("get_code", [new Var("C")]), new Term(",", [new Term("current_input", [new Var("S")]), new Term("get_code", [new Var("S"), new Var("C")])]))
        ],
        "get_code/2": function(thread, point, atom) {
          var stream = atom.args[0], code = atom.args[1];
          var stream2 = pl.type.is_stream(stream) ? stream : thread.get_stream_by_alias(stream.id);
          if (pl.type.is_variable(stream)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(code) && !pl.type.is_integer(code)) {
            thread.throw_error(pl.error.type("integer", code, atom.indicator));
          } else if (pl.type.is_integer(code) && !pl.type.is_in_character_code(code)) {
            thread.throw_error(pl.error.representation("in_character_code", atom.indicator));
          } else if (!pl.type.is_variable(stream) && !pl.type.is_stream(stream) && !pl.type.is_atom(stream)) {
            thread.throw_error(pl.error.domain("stream_or_alias", stream, atom.indicator));
          } else if (!pl.type.is_stream(stream2) || stream2.stream === null) {
            thread.throw_error(pl.error.existence("stream", stream, atom.indicator));
          } else if (stream2.output) {
            thread.throw_error(pl.error.permission("input", "stream", stream, atom.indicator));
          } else if (stream2.type === "binary") {
            thread.throw_error(pl.error.permission("input", "binary_stream", stream, atom.indicator));
          } else if (stream2.position === "past_end_of_stream" && stream2.eof_action === "error") {
            thread.throw_error(pl.error.permission("input", "past_end_of_stream", stream, atom.indicator));
          } else {
            var stream_code;
            if (stream2.position === "end_of_stream") {
              stream_code = -1;
              stream2.position = "past_end_of_stream";
            } else if (stream2.position === "past_end_of_stream") {
              stream_code = -1;
              stream2.position = "past_end_of_stream";
            } else {
              stream_code = stream2.stream.get(1, stream2.position);
              if (stream_code === null) {
                thread.throw_error(pl.error.representation("character", atom.indicator));
                return;
              } else if (stream_code === "end_of_stream") {
                stream_code = -1;
                stream2.position = "past_end_of_stream";
              } else {
                stream_code = codePointAt(stream_code, 0);
                stream2.position++;
                stream2.char_count++;
                stream2.line_position++;
                if (stream_code === 10) {
                  stream2.line_count++;
                  stream2.line_position = 0;
                }
              }
            }
            thread.prepend([new State(
              point.goal.replace(new Term("=", [new Num(stream_code, false), code])),
              point.substitution,
              point
            )]);
          }
        },
        "peek_char/1": [
          new Rule(new Term("peek_char", [new Var("C")]), new Term(",", [new Term("current_input", [new Var("S")]), new Term("peek_char", [new Var("S"), new Var("C")])]))
        ],
        "peek_char/2": function(thread, point, atom) {
          var stream = atom.args[0], char = atom.args[1];
          var stream2 = pl.type.is_stream(stream) ? stream : thread.get_stream_by_alias(stream.id);
          if (pl.type.is_variable(stream)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(char) && !pl.type.is_in_character(char)) {
            thread.throw_error(pl.error.type("in_character", char, atom.indicator));
          } else if (!pl.type.is_stream(stream) && !pl.type.is_atom(stream)) {
            thread.throw_error(pl.error.domain("stream_or_alias", stream, atom.indicator));
          } else if (!pl.type.is_stream(stream2) || stream2.stream === null) {
            thread.throw_error(pl.error.existence("stream", stream, atom.indicator));
          } else if (stream2.output) {
            thread.throw_error(pl.error.permission("input", "stream", stream, atom.indicator));
          } else if (stream2.type === "binary") {
            thread.throw_error(pl.error.permission("input", "binary_stream", stream, atom.indicator));
          } else if (stream2.position === "past_end_of_stream" && stream2.eof_action === "error") {
            thread.throw_error(pl.error.permission("input", "past_end_of_stream", stream, atom.indicator));
          } else {
            var stream_char;
            if (stream2.position === "end_of_stream") {
              stream_char = "end_of_file";
              stream2.position = "past_end_of_stream";
            } else if (stream2.position === "past_end_of_stream") {
              stream_char = "end_of_file";
              stream2.position = "past_end_of_stream";
            } else {
              stream_char = stream2.stream.get(1, stream2.position);
              if (stream_char === null) {
                thread.throw_error(pl.error.representation("character", atom.indicator));
                return;
              } else if (stream_char === "end_of_stream") {
                stream_char = "end_of_file";
              }
            }
            thread.prepend([new State(
              point.goal.replace(new Term("=", [new Term(stream_char, []), char])),
              point.substitution,
              point
            )]);
          }
        },
        "peek_code/1": [
          new Rule(new Term("peek_code", [new Var("C")]), new Term(",", [new Term("current_input", [new Var("S")]), new Term("peek_code", [new Var("S"), new Var("C")])]))
        ],
        "peek_code/2": function(thread, point, atom) {
          var stream = atom.args[0], code = atom.args[1];
          var stream2 = pl.type.is_stream(stream) ? stream : thread.get_stream_by_alias(stream.id);
          if (pl.type.is_variable(stream)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(code) && !pl.type.is_integer(code)) {
            thread.throw_error(pl.error.type("integer", code, atom.indicator));
          } else if (pl.type.is_integer(code) && !pl.type.is_in_character_code(code)) {
            thread.throw_error(pl.error.representation("in_character_code", atom.indicator));
          } else if (!pl.type.is_variable(stream) && !pl.type.is_stream(stream) && !pl.type.is_atom(stream)) {
            thread.throw_error(pl.error.domain("stream_or_alias", stream, atom.indicator));
          } else if (!pl.type.is_stream(stream2) || stream2.stream === null) {
            thread.throw_error(pl.error.existence("stream", stream, atom.indicator));
          } else if (stream2.output) {
            thread.throw_error(pl.error.permission("input", "stream", stream, atom.indicator));
          } else if (stream2.type === "binary") {
            thread.throw_error(pl.error.permission("input", "binary_stream", stream, atom.indicator));
          } else if (stream2.position === "past_end_of_stream" && stream2.eof_action === "error") {
            thread.throw_error(pl.error.permission("input", "past_end_of_stream", stream, atom.indicator));
          } else {
            var stream_code;
            if (stream2.position === "end_of_stream") {
              stream_code = -1;
              stream2.position = "past_end_of_stream";
            } else {
              stream_code = stream2.stream.get(1, stream2.position);
              if (stream_code === null) {
                thread.throw_error(pl.error.representation("character", atom.indicator));
                return;
              } else if (stream_code === "end_of_stream") {
                stream_code = -1;
              } else {
                stream_code = codePointAt(stream_code, 0);
              }
            }
            thread.prepend([new State(
              point.goal.replace(new Term("=", [new Num(stream_code, false), code])),
              point.substitution,
              point
            )]);
          }
        },
        "put_char/1": [
          new Rule(new Term("put_char", [new Var("C")]), new Term(",", [new Term("current_output", [new Var("S")]), new Term("put_char", [new Var("S"), new Var("C")])]))
        ],
        "put_char/2": function(thread, point, atom) {
          var stream = atom.args[0], char = atom.args[1];
          var stream2 = pl.type.is_stream(stream) ? stream : thread.get_stream_by_alias(stream.id);
          if (pl.type.is_variable(stream) || pl.type.is_variable(char)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_character(char)) {
            thread.throw_error(pl.error.type("character", char, atom.indicator));
          } else if (!pl.type.is_variable(stream) && !pl.type.is_stream(stream) && !pl.type.is_atom(stream)) {
            thread.throw_error(pl.error.domain("stream_or_alias", stream, atom.indicator));
          } else if (!pl.type.is_stream(stream2) || stream2.stream === null) {
            thread.throw_error(pl.error.existence("stream", stream, atom.indicator));
          } else if (stream2.input) {
            thread.throw_error(pl.error.permission("output", "stream", stream, atom.indicator));
          } else if (stream2.type === "binary") {
            thread.throw_error(pl.error.permission("output", "binary_stream", stream, atom.indicator));
          } else {
            if (stream2.stream.put(char.id, stream2.position)) {
              if (typeof stream2.position === "number")
                stream2.position++;
              stream2.char_count++;
              stream2.line_position++;
              if (char.id === "\n") {
                stream2.line_count++;
                stream2.line_position = 0;
              }
              thread.success(point);
            }
          }
        },
        "put_code/1": [
          new Rule(new Term("put_code", [new Var("C")]), new Term(",", [new Term("current_output", [new Var("S")]), new Term("put_code", [new Var("S"), new Var("C")])]))
        ],
        "put_code/2": function(thread, point, atom) {
          var stream = atom.args[0], code = atom.args[1];
          var stream2 = pl.type.is_stream(stream) ? stream : thread.get_stream_by_alias(stream.id);
          if (pl.type.is_variable(stream) || pl.type.is_variable(code)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_integer(code)) {
            thread.throw_error(pl.error.type("integer", code, atom.indicator));
          } else if (!pl.type.is_character_code(code)) {
            thread.throw_error(pl.error.representation("character_code", atom.indicator));
          } else if (!pl.type.is_variable(stream) && !pl.type.is_stream(stream) && !pl.type.is_atom(stream)) {
            thread.throw_error(pl.error.domain("stream_or_alias", stream, atom.indicator));
          } else if (!pl.type.is_stream(stream2) || stream2.stream === null) {
            thread.throw_error(pl.error.existence("stream", stream, atom.indicator));
          } else if (stream2.input) {
            thread.throw_error(pl.error.permission("output", "stream", stream, atom.indicator));
          } else if (stream2.type === "binary") {
            thread.throw_error(pl.error.permission("output", "binary_stream", stream, atom.indicator));
          } else {
            if (stream2.stream.put(fromCodePoint(code.value), stream2.position)) {
              if (typeof stream2.position === "number")
                stream2.position++;
              stream2.char_count++;
              stream2.line_position++;
              if (code.value === 10) {
                stream2.line_count++;
                stream2.line_position = 0;
              }
              thread.success(point);
            }
          }
        },
        "nl/0": [
          new Rule(new Term("nl"), new Term(",", [new Term("current_output", [new Var("S")]), new Term("put_char", [new Var("S"), new Term("\n")])]))
        ],
        "nl/1": function(thread, point, atom) {
          var stream = atom.args[0];
          thread.prepend([new State(
            point.goal.replace(new Term("put_char", [stream, new Term("\n", [])])),
            point.substitution,
            point
          )]);
        },
        "get_byte/1": [
          new Rule(new Term("get_byte", [new Var("B")]), new Term(",", [new Term("current_input", [new Var("S")]), new Term("get_byte", [new Var("S"), new Var("B")])]))
        ],
        "get_byte/2": function(thread, point, atom) {
          var stream = atom.args[0], byte = atom.args[1];
          var stream2 = pl.type.is_stream(stream) ? stream : thread.get_stream_by_alias(stream.id);
          if (pl.type.is_variable(stream)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(byte) && !pl.type.is_in_byte(byte)) {
            thread.throw_error(pl.error.type("in_byte", byte, atom.indicator));
          } else if (!pl.type.is_stream(stream) && !pl.type.is_atom(stream)) {
            thread.throw_error(pl.error.domain("stream_or_alias", stream, atom.indicator));
          } else if (!pl.type.is_stream(stream2) || stream2.stream === null) {
            thread.throw_error(pl.error.existence("stream", stream, atom.indicator));
          } else if (stream2.output) {
            thread.throw_error(pl.error.permission("input", "stream", stream, atom.indicator));
          } else if (stream2.type === "text") {
            thread.throw_error(pl.error.permission("input", "text_stream", stream, atom.indicator));
          } else if (stream2.position === "past_end_of_stream" && stream2.eof_action === "error") {
            thread.throw_error(pl.error.permission("input", "past_end_of_stream", stream, atom.indicator));
          } else {
            var stream_byte;
            if (stream2.position === "end_of_stream") {
              stream_byte = -1;
              stream2.position = "past_end_of_stream";
            } else {
              stream_byte = stream2.stream.get_byte(stream2.position);
              if (stream_byte === null) {
                thread.throw_error(pl.error.representation("byte", atom.indicator));
                return;
              } else if (stream_byte === "end_of_stream") {
                stream_byte = -1;
                stream2.position = "past_end_of_stream";
              } else {
                stream2.position++;
                stream2.char_count++;
                stream2.line_position++;
              }
            }
            thread.prepend([new State(
              point.goal.replace(new Term("=", [new Num(stream_byte, false), byte])),
              point.substitution,
              point
            )]);
          }
        },
        "peek_byte/1": [
          new Rule(new Term("peek_byte", [new Var("B")]), new Term(",", [new Term("current_input", [new Var("S")]), new Term("peek_byte", [new Var("S"), new Var("B")])]))
        ],
        "peek_byte/2": function(thread, point, atom) {
          var stream = atom.args[0], byte = atom.args[1];
          var stream2 = pl.type.is_stream(stream) ? stream : thread.get_stream_by_alias(stream.id);
          if (pl.type.is_variable(stream)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(byte) && !pl.type.is_in_byte(byte)) {
            thread.throw_error(pl.error.type("in_byte", byte, atom.indicator));
          } else if (!pl.type.is_stream(stream) && !pl.type.is_atom(stream)) {
            thread.throw_error(pl.error.domain("stream_or_alias", stream, atom.indicator));
          } else if (!pl.type.is_stream(stream2) || stream2.stream === null) {
            thread.throw_error(pl.error.existence("stream", stream, atom.indicator));
          } else if (stream2.output) {
            thread.throw_error(pl.error.permission("input", "stream", stream, atom.indicator));
          } else if (stream2.type === "text") {
            thread.throw_error(pl.error.permission("input", "text_stream", stream, atom.indicator));
          } else if (stream2.position === "past_end_of_stream" && stream2.eof_action === "error") {
            thread.throw_error(pl.error.permission("input", "past_end_of_stream", stream, atom.indicator));
          } else {
            var stream_byte;
            if (stream2.position === "end_of_stream") {
              stream_byte = -1;
              stream2.position = "past_end_of_stream";
            } else {
              stream_byte = stream2.stream.get_byte(stream2.position);
              if (stream_byte === null) {
                thread.throw_error(pl.error.representation("byte", atom.indicator));
                return;
              } else if (stream_byte === "end_of_stream") {
                stream_byte = -1;
              }
            }
            thread.prepend([new State(
              point.goal.replace(new Term("=", [new Num(stream_byte, false), byte])),
              point.substitution,
              point
            )]);
          }
        },
        "put_byte/1": [
          new Rule(new Term("put_byte", [new Var("B")]), new Term(",", [new Term("current_output", [new Var("S")]), new Term("put_byte", [new Var("S"), new Var("B")])]))
        ],
        "put_byte/2": function(thread, point, atom) {
          var stream = atom.args[0], byte = atom.args[1];
          var stream2 = pl.type.is_stream(stream) ? stream : thread.get_stream_by_alias(stream.id);
          if (pl.type.is_variable(stream) || pl.type.is_variable(byte)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_byte(byte)) {
            thread.throw_error(pl.error.type("byte", byte, atom.indicator));
          } else if (!pl.type.is_variable(stream) && !pl.type.is_stream(stream) && !pl.type.is_atom(stream)) {
            thread.throw_error(pl.error.domain("stream_or_alias", stream, atom.indicator));
          } else if (!pl.type.is_stream(stream2) || stream2.stream === null) {
            thread.throw_error(pl.error.existence("stream", stream, atom.indicator));
          } else if (stream2.input) {
            thread.throw_error(pl.error.permission("output", "stream", stream, atom.indicator));
          } else if (stream2.type === "text") {
            thread.throw_error(pl.error.permission("output", "text_stream", stream, atom.indicator));
          } else {
            if (stream2.stream.put_byte(byte.value, stream2.position)) {
              if (typeof stream2.position === "number")
                stream2.position++;
              stream2.char_count++;
              stream2.line_position++;
              thread.success(point);
            }
          }
        },
        "read/1": [
          new Rule(new Term("read", [new Var("T")]), new Term(",", [new Term("current_input", [new Var("S")]), new Term("read_term", [new Var("S"), new Var("T"), new Term("[]")])]))
        ],
        "read/2": [
          new Rule(new Term("read", [new Var("S"), new Var("T")]), new Term("read_term", [new Var("S"), new Var("T"), new Term("[]")]))
        ],
        "read_term/2": [
          new Rule(new Term("read_term", [new Var("T"), new Var("O")]), new Term(",", [new Term("current_input", [new Var("S")]), new Term("read_term", [new Var("S"), new Var("T"), new Var("O")])]))
        ],
        "read_term/3": function(thread, point, atom) {
          var stream = atom.args[0], term = atom.args[1], options = atom.args[2];
          var stream2 = pl.type.is_stream(stream) ? stream : thread.get_stream_by_alias(stream.id);
          if (pl.type.is_variable(stream) || pl.type.is_variable(options)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_list(options)) {
            thread.throw_error(pl.error.type("list", options, atom.indicator));
          } else if (!pl.type.is_stream(stream) && !pl.type.is_atom(stream)) {
            thread.throw_error(pl.error.domain("stream_or_alias", stream, atom.indicator));
          } else if (!pl.type.is_stream(stream2) || stream2.stream === null) {
            thread.throw_error(pl.error.existence("stream", stream, atom.indicator));
          } else if (stream2.output) {
            thread.throw_error(pl.error.permission("input", "stream", stream, atom.indicator));
          } else if (stream2.type === "binary") {
            thread.throw_error(pl.error.permission("input", "binary_stream", stream, atom.indicator));
          } else if (stream2.position === "past_end_of_stream" && stream2.eof_action === "error") {
            thread.throw_error(pl.error.permission("input", "past_end_of_stream", stream, atom.indicator));
          } else if (stream2.position === "past_end_of_stream" && stream2.eof_action === "eof_code") {
            expr = {
              value: new Term("end_of_file", []),
              type: SUCCESS,
              len: -1
            };
          } else {
            var obj_options = {};
            var pointer = options;
            var property;
            while (pl.type.is_term(pointer) && pointer.indicator === "./2") {
              property = pointer.args[0];
              if (pl.type.is_variable(property)) {
                thread.throw_error(pl.error.instantiation(atom.indicator));
                return;
              } else if (!pl.type.is_read_option(property)) {
                thread.throw_error(pl.error.domain("read_option", property, atom.indicator));
                return;
              }
              obj_options[property.id] = property.args[0];
              pointer = pointer.args[1];
            }
            if (pointer.indicator !== "[]/0") {
              if (pl.type.is_variable(pointer))
                thread.throw_error(pl.error.instantiation(atom.indicator));
              else
                thread.throw_error(pl.error.type("list", options, atom.indicator));
              return;
            } else {
              var char, tokenizer, expr;
              var text = "";
              var tokens = [];
              var last_token = null;
              var lexical_error = false;
              while (last_token === null || lexical_error || last_token.name !== "atom" || last_token.value !== "." || tokens.length > 0 && expr.type === ERROR) {
                char = stream2.stream.get(1, stream2.position);
                while (char !== null && char !== "." && char !== "end_of_stream" && char !== "past_end_of_stream") {
                  stream2.position++;
                  text += char;
                  char = stream2.stream.get(1, stream2.position);
                }
                if (char === null) {
                  thread.throw_error(pl.error.representation("character", atom.indicator));
                  return;
                } else if (char === "end_of_stream" || char === "past_end_of_stream") {
                  if (tokens === null || tokens.length === 0) {
                    stream2.position = "past_end_of_stream";
                    expr = {
                      value: new Term("end_of_file", []),
                      type: SUCCESS,
                      len: -1
                    };
                    break;
                  } else if (expr) {
                    thread.throw_error(pl.error.syntax(last_token, "unexpected end of file", false));
                    return;
                  } else {
                    thread.throw_error(pl.error.syntax(last_token, "token not found", true));
                    return;
                  }
                } else if (char === ".") {
                  stream2.position++;
                  text += char;
                }
                tokenizer = new Tokenizer(thread);
                tokenizer.new_text(text);
                tokens = tokenizer.get_tokens();
                num_token = tokens !== null && tokens.length > 1 ? tokens[tokens.length - 2] : null;
                last_token = tokens !== null && tokens.length > 0 ? tokens[tokens.length - 1] : null;
                if (tokens === null)
                  continue;
                lexical_error = false;
                for (var i2 = 0; i2 < tokens.length && !lexical_error; i2++)
                  lexical_error = tokens[i2].name === "lexical";
                if (lexical_error)
                  continue;
                expr = parseExpr(thread, tokens, 0, thread.__get_max_priority(), false);
                if (num_token && num_token.name === "number" && !num_token.float && !num_token.blank && last_token.value === ".") {
                  var next_char = stream2.stream.get(1, stream2.position);
                  if (next_char >= "0" && next_char <= "9") {
                    stream2.position++;
                    text += next_char;
                    last_token = null;
                    continue;
                  }
                }
              }
              if (last_token) {
                if (last_token.line_position === last_token.len)
                  stream2.line_position += last_token.line_position;
                else
                  stream2.line_position = last_token.line_position;
                stream2.line_count += last_token.line_count;
                stream2.char_count += last_token.len;
              }
              if (expr.type === SUCCESS && (expr.len === -1 || expr.len === tokens.length - 1 && last_token.value === ".")) {
                thread.session.renamed_variables = {};
                expr = expr.value.rename(thread);
                var eq = new Term("=", [term, expr]);
                if (obj_options.variables) {
                  var vars = arrayToList(map(nub(expr.variables()), function(v2) {
                    return new Var(v2);
                  }));
                  eq = new Term(",", [eq, new Term("=", [obj_options.variables, vars])]);
                }
                if (obj_options.variable_names) {
                  var vars = nub(expr.variables());
                  var plvars = [];
                  for (var i2 = 0; i2 < vars.length; i2++) {
                    var v = vars[i2];
                    for (var prop in thread.session.renamed_variables) {
                      if (thread.session.renamed_variables.hasOwnProperty(prop)) {
                        if (thread.session.renamed_variables[prop] === v) {
                          plvars.push(new Term("=", [new Term(prop, []), new Var(v)]));
                          break;
                        }
                      }
                    }
                  }
                  plvars = arrayToList(plvars);
                  eq = new Term(",", [eq, new Term("=", [obj_options.variable_names, plvars])]);
                }
                if (obj_options.singletons) {
                  var vars = nub(new Rule(expr, null).singleton_variables(true));
                  var plvars = [];
                  for (var i2 = 0; i2 < vars.length; i2++) {
                    var v = vars[i2];
                    for (var prop in thread.session.renamed_variables) {
                      if (thread.session.renamed_variables.hasOwnProperty(prop)) {
                        if (thread.session.renamed_variables[prop] === v) {
                          plvars.push(new Term("=", [new Term(prop, []), new Var(v)]));
                          break;
                        }
                      }
                    }
                  }
                  plvars = arrayToList(plvars);
                  eq = new Term(",", [eq, new Term("=", [obj_options.singletons, plvars])]);
                }
                thread.prepend([new State(point.goal.replace(eq), point.substitution, point)]);
              } else {
                if (expr.type === SUCCESS)
                  thread.throw_error(pl.error.syntax(tokens[expr.len], "unexpected token", false));
                else
                  thread.throw_error(expr.value);
              }
            }
          }
        },
        "write/1": [
          new Rule(new Term("write", [new Var("T")]), new Term(",", [new Term("current_output", [new Var("S")]), new Term("write", [new Var("S"), new Var("T")])]))
        ],
        "write/2": function(thread, point, atom) {
          var stream = atom.args[0], term = atom.args[1];
          thread.prepend([new State(
            point.goal.replace(new Term("write_term", [
              stream,
              term,
              new Term(".", [
                new Term("quoted", [new Term("false", [])]),
                new Term(".", [
                  new Term("ignore_ops", [new Term("false")]),
                  new Term(".", [new Term("numbervars", [new Term("true")]), new Term("[]", [])])
                ])
              ])
            ])),
            point.substitution,
            point
          )]);
        },
        "writeq/1": [
          new Rule(new Term("writeq", [new Var("T")]), new Term(",", [new Term("current_output", [new Var("S")]), new Term("writeq", [new Var("S"), new Var("T")])]))
        ],
        "writeq/2": function(thread, point, atom) {
          var stream = atom.args[0], term = atom.args[1];
          thread.prepend([new State(
            point.goal.replace(new Term("write_term", [
              stream,
              term,
              new Term(".", [
                new Term("quoted", [new Term("true", [])]),
                new Term(".", [
                  new Term("ignore_ops", [new Term("false")]),
                  new Term(".", [new Term("numbervars", [new Term("true")]), new Term("[]", [])])
                ])
              ])
            ])),
            point.substitution,
            point
          )]);
        },
        "write_canonical/1": [
          new Rule(new Term("write_canonical", [new Var("T")]), new Term(",", [new Term("current_output", [new Var("S")]), new Term("write_canonical", [new Var("S"), new Var("T")])]))
        ],
        "write_canonical/2": function(thread, point, atom) {
          var stream = atom.args[0], term = atom.args[1];
          thread.prepend([new State(
            point.goal.replace(new Term("write_term", [
              stream,
              term,
              new Term(".", [
                new Term("quoted", [new Term("true", [])]),
                new Term(".", [
                  new Term("ignore_ops", [new Term("true")]),
                  new Term(".", [new Term("numbervars", [new Term("false")]), new Term("[]", [])])
                ])
              ])
            ])),
            point.substitution,
            point
          )]);
        },
        "write_term/2": [
          new Rule(new Term("write_term", [new Var("T"), new Var("O")]), new Term(",", [new Term("current_output", [new Var("S")]), new Term("write_term", [new Var("S"), new Var("T"), new Var("O")])]))
        ],
        "write_term/3": function(thread, point, atom) {
          var stream = atom.args[0], term = atom.args[1], options = atom.args[2];
          var stream2 = pl.type.is_stream(stream) ? stream : thread.get_stream_by_alias(stream.id);
          if (pl.type.is_variable(stream) || pl.type.is_variable(options)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_list(options)) {
            thread.throw_error(pl.error.type("list", options, atom.indicator));
          } else if (!pl.type.is_stream(stream) && !pl.type.is_atom(stream)) {
            thread.throw_error(pl.error.domain("stream_or_alias", stream, atom.indicator));
          } else if (!pl.type.is_stream(stream2) || stream2.stream === null) {
            thread.throw_error(pl.error.existence("stream", stream, atom.indicator));
          } else if (stream2.input) {
            thread.throw_error(pl.error.permission("output", "stream", stream, atom.indicator));
          } else if (stream2.type === "binary") {
            thread.throw_error(pl.error.permission("output", "binary_stream", stream, atom.indicator));
          } else if (stream2.position === "past_end_of_stream" && stream2.eof_action === "error") {
            thread.throw_error(pl.error.permission("output", "past_end_of_stream", stream, atom.indicator));
          } else {
            var obj_options = {};
            var pointer = options;
            var property;
            while (pl.type.is_term(pointer) && pointer.indicator === "./2") {
              property = pointer.args[0];
              if (pl.type.is_variable(property)) {
                thread.throw_error(pl.error.instantiation(atom.indicator));
                return;
              } else if (!pl.type.is_write_option(property)) {
                thread.throw_error(pl.error.domain("write_option", property, atom.indicator));
                return;
              }
              if (property.indicator === "variable_names/1")
                obj_options[property.id] = property.args[0];
              else
                obj_options[property.id] = property.args[0].id === "true";
              pointer = pointer.args[1];
            }
            if (pointer.indicator !== "[]/0") {
              if (pl.type.is_variable(pointer))
                thread.throw_error(pl.error.instantiation(atom.indicator));
              else
                thread.throw_error(pl.error.type("list", options, atom.indicator));
              return;
            } else {
              obj_options.session = thread.session;
              var text = term.toString(obj_options);
              stream2.stream.put(text, stream2.position);
              if (typeof stream2.position === "number")
                stream2.position += text.length;
              var nl = (text.match(/\n/g) || []).length;
              stream2.line_count += nl;
              if (nl > 0)
                stream2.line_position = text.length - text.lastIndexOf("\n") - 1;
              else
                stream2.line_position += text.length;
              stream2.char_count += text.length;
              thread.success(point);
            }
          }
        },
        "halt/0": function(thread, point, _) {
          if (thread.get_flag("nodejs").indicator === "true/0")
            process.exit();
          thread.points = [];
        },
        "halt/1": function(thread, point, atom) {
          var int = atom.args[0];
          if (pl.type.is_variable(int)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_integer(int)) {
            thread.throw_error(pl.error.type("integer", int, atom.indicator));
          } else {
            if (thread.get_flag("nodejs").indicator === "true/0")
              process.exit(int.value);
            thread.points = [];
          }
        },
        "current_prolog_flag/2": function(thread, point, atom) {
          var flag = atom.args[0], value = atom.args[1];
          if (!pl.type.is_variable(flag) && !pl.type.is_atom(flag)) {
            thread.throw_error(pl.error.type("atom", flag, atom.indicator));
          } else if (!pl.type.is_variable(flag) && !pl.type.is_flag(flag)) {
            thread.throw_error(pl.error.domain("prolog_flag", flag, atom.indicator));
          } else {
            var states = [];
            for (var name in pl.flag) {
              if (!pl.flag.hasOwnProperty(name))
                continue;
              var goal = new Term(",", [new Term("=", [new Term(name), flag]), new Term("=", [thread.get_flag(name), value])]);
              states.push(new State(point.goal.replace(goal), point.substitution, point));
            }
            thread.prepend(states);
          }
        },
        "set_prolog_flag/2": function(thread, point, atom) {
          var flag = atom.args[0], value = atom.args[1];
          if (pl.type.is_variable(flag) || pl.type.is_variable(value)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_atom(flag)) {
            thread.throw_error(pl.error.type("atom", flag, atom.indicator));
          } else if (!pl.type.is_flag(flag)) {
            thread.throw_error(pl.error.domain("prolog_flag", flag, atom.indicator));
          } else if (!pl.type.is_modifiable_flag(flag)) {
            thread.throw_error(pl.error.permission("modify", "flag", flag, atom.indicator));
          } else if (!pl.type.is_value_flag(flag, value)) {
            thread.throw_error(pl.error.domain("flag_value", new Term("+", [flag, value]), atom.indicator));
          } else {
            thread.session.flag[flag.id] = value;
            thread.success(point);
          }
        },
        "consult/1": function(thread, point, atom) {
          var src = atom.args[0];
          var context_module = "user";
          if (src.indicator === ":/2") {
            context_module = src.args[0].id;
            src = src.args[1];
          }
          if (pl.type.is_variable(src)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_atom(src)) {
            thread.throw_error(pl.error.type("atom", src, atom.indicator));
          } else {
            if (thread.consult(src.id, {
              context_module,
              text: false,
              html: false,
              success: function() {
                thread.success(point);
                thread.again();
              },
              error: function(err) {
                thread.throw_error(err);
                thread.again();
              }
            }))
              ;
            return true;
          }
        },
        "get_time/1": function(thread, point, atom) {
          var time = atom.args[0];
          if (!pl.type.is_variable(time) && !pl.type.is_number(time)) {
            thread.throw_error(pl.error.type("number", time, atom.indicator));
          } else {
            var current = new Num(Date.now(), true);
            thread.prepend([new State(
              point.goal.replace(new Term("=", [time, current])),
              point.substitution,
              point
            )]);
          }
        },
        "time_property/2": function(thread, point, atom) {
          var time = atom.args[0], property = atom.args[1];
          if (pl.type.is_variable(time)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_variable(time) && !pl.type.is_number(time)) {
            thread.throw_error(pl.error.type("number", time, atom.indicator));
          } else if (!pl.type.is_variable(property) && !pl.type.is_time_property(property)) {
            thread.throw_error(pl.error.domain("time_property", property, atom.indicator));
          } else {
            var props;
            if (pl.type.is_variable(property)) {
              props = ["year", "month", "day", "hours", "minutes", "seconds", "milliseconds", "weekday"];
            } else {
              props = [property.id];
            }
            var date = new Date(time.value);
            var value;
            var states = [];
            for (var i2 = 0; i2 < props.length; i2++) {
              switch (props[i2]) {
                case "year":
                  value = new Term("year", [new Num(date.getFullYear(), false)]);
                  break;
                case "month":
                  value = new Term("month", [new Num(date.getMonth(), false)]);
                  break;
                case "day":
                  value = new Term("day", [new Num(date.getDate(), false)]);
                  break;
                case "hours":
                  value = new Term("hours", [new Num(date.getHours(), false)]);
                  break;
                case "minutes":
                  value = new Term("minutes", [new Num(date.getMinutes(), false)]);
                  break;
                case "seconds":
                  value = new Term("seconds", [new Num(date.getSeconds(), false)]);
                  break;
                case "milliseconds":
                  value = new Term("milliseconds", [new Num(date.getMilliseconds(), false)]);
                  break;
                case "weekday":
                  value = new Term("weekday", [new Num(date.getDay(), false)]);
                  break;
              }
              states.push(new State(
                point.goal.replace(new Term("=", [property, value])),
                point.substitution,
                point
              ));
            }
            thread.prepend(states);
          }
        },
        "time_year/2": function(thread, point, atom) {
          var time = atom.args[0], year = atom.args[1];
          if (pl.type.is_variable(time)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_number(time)) {
            thread.throw_error(pl.error.type("number", time, atom.indicator));
          } else if (!pl.type.is_variable(year) && !pl.type.is_integer(year)) {
            thread.throw_error(pl.error.type("integer", year, atom.indicator));
          } else {
            var value = new Num(new Date(time.value).getFullYear(), false);
            thread.prepend([new State(
              point.goal.replace(new Term("=", [year, value])),
              point.substitution,
              point
            )]);
          }
        },
        "time_month/2": function(thread, point, atom) {
          var time = atom.args[0], month = atom.args[1];
          if (pl.type.is_variable(time)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_number(time)) {
            thread.throw_error(pl.error.type("number", time, atom.indicator));
          } else if (!pl.type.is_variable(month) && !pl.type.is_integer(month)) {
            thread.throw_error(pl.error.type("integer", month, atom.indicator));
          } else {
            var value = new Num(new Date(time.value).getMonth(), false);
            thread.prepend([new State(
              point.goal.replace(new Term("=", [month, value])),
              point.substitution,
              point
            )]);
          }
        },
        "phrase/3": function(thread, point, atom) {
          var grbody = atom.args[0], s0 = atom.args[1], s = atom.args[2];
          var context_module = "user";
          if (grbody.indicator === ":/2") {
            context_module = grbody.args[0].id;
            grbody = grbody.args[1];
          }
          if (pl.type.is_variable(grbody)) {
            thread.throw_error(pl.error.instantiation(atom.indicator));
          } else if (!pl.type.is_callable(grbody)) {
            thread.throw_error(pl.error.type("callable", grbody, atom.indicator));
          } else {
            var goal = body_to_dcg(grbody.clone(), s0, thread);
            goal.value = new Term(":", [new Term(context_module), new Term("call", [goal.value])]);
            if (goal !== null) {
              thread.prepend([new State(
                point.goal.replace(new Term(",", [goal.value, new Term("=", [goal.variable, s])])),
                point.substitution,
                point
              )]);
            }
          }
        },
        "phrase/2": function(thread, point, atom) {
          var grbody = atom.args[0], s0 = atom.args[1];
          thread.prepend([new State(
            point.goal.replace(new Term("phrase", [grbody, s0, new Term("[]", [])])),
            point.substitution,
            point
          )]);
        },
        "version/0": function(thread, point, atom) {
          var msg = "Welcome to Tau Prolog version " + version.major + "." + version.minor + "." + version.patch + "\n";
          msg += "Tau Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.\n";
          msg += "Please run ?- license. for legal details.\n";
          msg += "For online help and background, visit http:/tau-prolog.org";
          thread.prepend([new State(
            point.goal.replace(new Term("write", [new Term(msg, [])])),
            point.substitution,
            point
          )]);
        },
        "license/0": function(thread, point, atom) {
          var msg = "Tau Prolog. A Prolog interpreter in JavaScript.\n";
          msg += "Copyright (C) 2017 - 2022 Jos\xE9 Antonio Riaza Valverde\n\n";
          msg += "Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n";
          msg += "1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n";
          msg += "2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n";
          msg += "3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\n";
          msg += 'THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n';
          msg += "You should have received a copy of the BSD 3-Clause License along with this program. If not, see https://opensource.org/licenses/BSD-3-Clause";
          thread.prepend([new State(
            point.goal.replace(new Term("write", [new Term(msg, [])])),
            point.substitution,
            point
          )]);
        }
      }, "all", {
        meta_predicates: {
          "$findall/4": new Term("$findall", [new Term("?"), new Num(0, false), new Term("-"), new Term("?")]),
          "$bagof/3": new Term("$bagof", [new Term("?"), new Term("^"), new Term("-")]),
          "$setof/3": new Term("$setof", [new Term("?"), new Term("^"), new Term("-")]),
          "$if/3": new Term("$if", [new Num(0, false), new Num(0, false), new Num(0, false)]),
          ";/2": new Term(";", [new Num(0, false), new Num(0, false)]),
          "->/2": new Term("->", [new Num(0, false), new Num(0, false)]),
          "*->/2": new Term("*->", [new Num(0, false), new Num(0, false)]),
          "\\+/1": new Term("\\+", [new Num(0, false)]),
          "abolish/1": new Term("abolish", [new Term(":")]),
          "asserta/1": new Term("asserta", [new Term(":")]),
          "assertz/1": new Term("assertz", [new Term(":")]),
          "bagof/3": new Term("bagof", [new Term("?"), new Term("^"), new Term("-")]),
          "call/1": new Term("call", [new Num(0, false)]),
          "call/2": new Term("call", [new Num(1, false), new Term("?")]),
          "call/3": new Term("call", [new Num(2, false), new Term("?"), new Term("?")]),
          "call/4": new Term("call", [new Num(3, false), new Term("?"), new Term("?"), new Term("?")]),
          "call/5": new Term("call", [new Num(4, false), new Term("?"), new Term("?"), new Term("?"), new Term("?")]),
          "call/6": new Term("call", [new Num(5, false), new Term("?"), new Term("?"), new Term("?"), new Term("?"), new Term("?")]),
          "call/7": new Term("call", [new Num(6, false), new Term("?"), new Term("?"), new Term("?"), new Term("?"), new Term("?"), new Term("?")]),
          "call/8": new Term("call", [new Num(6, false), new Term("?"), new Term("?"), new Term("?"), new Term("?"), new Term("?"), new Term("?"), new Term("?")]),
          "call_cleanup/2": new Term("call_cleanup", [new Num(0, false), new Num(0, false)]),
          "catch/3": new Term("catch", [new Num(0, false), new Term("?"), new Num(0, false)]),
          "consult/1": new Term("consult", [new Term(":")]),
          "clause/2": new Term("clause", [new Term(":"), new Term("?")]),
          "current_predicate/2": new Term("current_predicate", [new Term("?"), new Term(":")]),
          "findall/3": new Term("findall", [new Term("?"), new Num(0, false), new Term("-")]),
          "findall/4": new Term("findall", [new Term("?"), new Num(0, false), new Term("-"), new Term("?")]),
          "forall/2": new Term("forall", [new Num(0, false), new Num(0, false)]),
          "listing/1": new Term("listing", [new Term(":")]),
          "once/1": new Term("once", [new Num(0, false)]),
          "phrase/2": new Term("phrase", [new Term(":"), new Term("?")]),
          "phrase/3": new Term("phrase", [new Term(":"), new Term("?"), new Term("?")]),
          "retract/1": new Term("retract", [new Term(":")]),
          "retractall/1": new Term("retractall", [new Term(":")]),
          "setup_call_cleanup/3": new Term("setup_call_cleanup", [new Num(0, false), new Num(0, false), new Num(0, false)]),
          "setof/3": new Term("setof", [new Term("?"), new Term("^"), new Term("-")])
        }
      });
      if (typeof module2 !== "undefined") {
        module2.exports = pl;
      } else {
        window.pl = pl;
      }
    })();
  }
});

// node_modules/json5/dist/index.js
var require_dist = __commonJS({
  "node_modules/json5/dist/index.js"(exports, module2) {
    (function(global2, factory) {
      typeof exports === "object" && typeof module2 !== "undefined" ? module2.exports = factory() : typeof define === "function" && define.amd ? define(factory) : global2.JSON5 = factory();
    })(exports, function() {
      "use strict";
      function createCommonjsModule(fn, module3) {
        return module3 = { exports: {} }, fn(module3, module3.exports), module3.exports;
      }
      var _global = createCommonjsModule(function(module3) {
        var global2 = module3.exports = typeof window != "undefined" && window.Math == Math ? window : typeof self != "undefined" && self.Math == Math ? self : Function("return this")();
        if (typeof __g == "number") {
          __g = global2;
        }
      });
      var _core = createCommonjsModule(function(module3) {
        var core = module3.exports = { version: "2.6.5" };
        if (typeof __e == "number") {
          __e = core;
        }
      });
      var _core_1 = _core.version;
      var _isObject = function(it) {
        return typeof it === "object" ? it !== null : typeof it === "function";
      };
      var _anObject = function(it) {
        if (!_isObject(it)) {
          throw TypeError(it + " is not an object!");
        }
        return it;
      };
      var _fails = function(exec) {
        try {
          return !!exec();
        } catch (e) {
          return true;
        }
      };
      var _descriptors = !_fails(function() {
        return Object.defineProperty({}, "a", { get: function() {
          return 7;
        } }).a != 7;
      });
      var document2 = _global.document;
      var is = _isObject(document2) && _isObject(document2.createElement);
      var _domCreate = function(it) {
        return is ? document2.createElement(it) : {};
      };
      var _ie8DomDefine = !_descriptors && !_fails(function() {
        return Object.defineProperty(_domCreate("div"), "a", { get: function() {
          return 7;
        } }).a != 7;
      });
      var _toPrimitive = function(it, S) {
        if (!_isObject(it)) {
          return it;
        }
        var fn, val;
        if (S && typeof (fn = it.toString) == "function" && !_isObject(val = fn.call(it))) {
          return val;
        }
        if (typeof (fn = it.valueOf) == "function" && !_isObject(val = fn.call(it))) {
          return val;
        }
        if (!S && typeof (fn = it.toString) == "function" && !_isObject(val = fn.call(it))) {
          return val;
        }
        throw TypeError("Can't convert object to primitive value");
      };
      var dP = Object.defineProperty;
      var f = _descriptors ? Object.defineProperty : function defineProperty(O, P, Attributes) {
        _anObject(O);
        P = _toPrimitive(P, true);
        _anObject(Attributes);
        if (_ie8DomDefine) {
          try {
            return dP(O, P, Attributes);
          } catch (e) {
          }
        }
        if ("get" in Attributes || "set" in Attributes) {
          throw TypeError("Accessors not supported!");
        }
        if ("value" in Attributes) {
          O[P] = Attributes.value;
        }
        return O;
      };
      var _objectDp = {
        f
      };
      var _propertyDesc = function(bitmap, value) {
        return {
          enumerable: !(bitmap & 1),
          configurable: !(bitmap & 2),
          writable: !(bitmap & 4),
          value
        };
      };
      var _hide = _descriptors ? function(object, key2, value) {
        return _objectDp.f(object, key2, _propertyDesc(1, value));
      } : function(object, key2, value) {
        object[key2] = value;
        return object;
      };
      var hasOwnProperty = {}.hasOwnProperty;
      var _has = function(it, key2) {
        return hasOwnProperty.call(it, key2);
      };
      var id = 0;
      var px = Math.random();
      var _uid = function(key2) {
        return "Symbol(".concat(key2 === void 0 ? "" : key2, ")_", (++id + px).toString(36));
      };
      var _library = false;
      var _shared = createCommonjsModule(function(module3) {
        var SHARED = "__core-js_shared__";
        var store = _global[SHARED] || (_global[SHARED] = {});
        (module3.exports = function(key2, value) {
          return store[key2] || (store[key2] = value !== void 0 ? value : {});
        })("versions", []).push({
          version: _core.version,
          mode: _library ? "pure" : "global",
          copyright: "\xA9 2019 Denis Pushkarev (zloirock.ru)"
        });
      });
      var _functionToString = _shared("native-function-to-string", Function.toString);
      var _redefine = createCommonjsModule(function(module3) {
        var SRC = _uid("src");
        var TO_STRING = "toString";
        var TPL = ("" + _functionToString).split(TO_STRING);
        _core.inspectSource = function(it) {
          return _functionToString.call(it);
        };
        (module3.exports = function(O, key2, val, safe) {
          var isFunction = typeof val == "function";
          if (isFunction) {
            _has(val, "name") || _hide(val, "name", key2);
          }
          if (O[key2] === val) {
            return;
          }
          if (isFunction) {
            _has(val, SRC) || _hide(val, SRC, O[key2] ? "" + O[key2] : TPL.join(String(key2)));
          }
          if (O === _global) {
            O[key2] = val;
          } else if (!safe) {
            delete O[key2];
            _hide(O, key2, val);
          } else if (O[key2]) {
            O[key2] = val;
          } else {
            _hide(O, key2, val);
          }
        })(Function.prototype, TO_STRING, function toString() {
          return typeof this == "function" && this[SRC] || _functionToString.call(this);
        });
      });
      var _aFunction = function(it) {
        if (typeof it != "function") {
          throw TypeError(it + " is not a function!");
        }
        return it;
      };
      var _ctx = function(fn, that, length) {
        _aFunction(fn);
        if (that === void 0) {
          return fn;
        }
        switch (length) {
          case 1:
            return function(a) {
              return fn.call(that, a);
            };
          case 2:
            return function(a, b) {
              return fn.call(that, a, b);
            };
          case 3:
            return function(a, b, c2) {
              return fn.call(that, a, b, c2);
            };
        }
        return function() {
          return fn.apply(that, arguments);
        };
      };
      var PROTOTYPE = "prototype";
      var $export = function(type, name, source2) {
        var IS_FORCED = type & $export.F;
        var IS_GLOBAL = type & $export.G;
        var IS_STATIC = type & $export.S;
        var IS_PROTO = type & $export.P;
        var IS_BIND = type & $export.B;
        var target = IS_GLOBAL ? _global : IS_STATIC ? _global[name] || (_global[name] = {}) : (_global[name] || {})[PROTOTYPE];
        var exports2 = IS_GLOBAL ? _core : _core[name] || (_core[name] = {});
        var expProto = exports2[PROTOTYPE] || (exports2[PROTOTYPE] = {});
        var key2, own, out, exp;
        if (IS_GLOBAL) {
          source2 = name;
        }
        for (key2 in source2) {
          own = !IS_FORCED && target && target[key2] !== void 0;
          out = (own ? target : source2)[key2];
          exp = IS_BIND && own ? _ctx(out, _global) : IS_PROTO && typeof out == "function" ? _ctx(Function.call, out) : out;
          if (target) {
            _redefine(target, key2, out, type & $export.U);
          }
          if (exports2[key2] != out) {
            _hide(exports2, key2, exp);
          }
          if (IS_PROTO && expProto[key2] != out) {
            expProto[key2] = out;
          }
        }
      };
      _global.core = _core;
      $export.F = 1;
      $export.G = 2;
      $export.S = 4;
      $export.P = 8;
      $export.B = 16;
      $export.W = 32;
      $export.U = 64;
      $export.R = 128;
      var _export = $export;
      var ceil = Math.ceil;
      var floor = Math.floor;
      var _toInteger = function(it) {
        return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);
      };
      var _defined = function(it) {
        if (it == void 0) {
          throw TypeError("Can't call method on  " + it);
        }
        return it;
      };
      var _stringAt = function(TO_STRING) {
        return function(that, pos2) {
          var s = String(_defined(that));
          var i2 = _toInteger(pos2);
          var l = s.length;
          var a, b;
          if (i2 < 0 || i2 >= l) {
            return TO_STRING ? "" : void 0;
          }
          a = s.charCodeAt(i2);
          return a < 55296 || a > 56319 || i2 + 1 === l || (b = s.charCodeAt(i2 + 1)) < 56320 || b > 57343 ? TO_STRING ? s.charAt(i2) : a : TO_STRING ? s.slice(i2, i2 + 2) : (a - 55296 << 10) + (b - 56320) + 65536;
        };
      };
      var $at = _stringAt(false);
      _export(_export.P, "String", {
        codePointAt: function codePointAt2(pos2) {
          return $at(this, pos2);
        }
      });
      var codePointAt = _core.String.codePointAt;
      var max = Math.max;
      var min = Math.min;
      var _toAbsoluteIndex = function(index, length) {
        index = _toInteger(index);
        return index < 0 ? max(index + length, 0) : min(index, length);
      };
      var fromCharCode = String.fromCharCode;
      var $fromCodePoint = String.fromCodePoint;
      _export(_export.S + _export.F * (!!$fromCodePoint && $fromCodePoint.length != 1), "String", {
        fromCodePoint: function fromCodePoint2(x) {
          var arguments$1 = arguments;
          var res = [];
          var aLen = arguments.length;
          var i2 = 0;
          var code;
          while (aLen > i2) {
            code = +arguments$1[i2++];
            if (_toAbsoluteIndex(code, 1114111) !== code) {
              throw RangeError(code + " is not a valid code point");
            }
            res.push(
              code < 65536 ? fromCharCode(code) : fromCharCode(((code -= 65536) >> 10) + 55296, code % 1024 + 56320)
            );
          }
          return res.join("");
        }
      });
      var fromCodePoint = _core.String.fromCodePoint;
      var Space_Separator = /[\u1680\u2000-\u200A\u202F\u205F\u3000]/;
      var ID_Start = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1C80-\u1C88\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE83\uDE86-\uDE89\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4\uDD00-\uDD43]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]/;
      var ID_Continue = /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u0860-\u086A\u08A0-\u08B4\u08B6-\u08BD\u08D4-\u08E1\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u09FC\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9-\u0AFF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C80-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D00-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D54-\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1CD0-\u1CD2\u1CD4-\u1CF9\u1D00-\u1DF9\u1DFB-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312E\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FEA\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AE\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C5\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF2D-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE3E\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC00-\uDC4A\uDC50-\uDC59\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDE00-\uDE3E\uDE47\uDE50-\uDE83\uDE86-\uDE99\uDEC0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC36\uDC38-\uDC40\uDC50-\uDC59\uDC72-\uDC8F\uDC92-\uDCA7\uDCA9-\uDCB6\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD36\uDD3A\uDD3C\uDD3D\uDD3F-\uDD47\uDD50-\uDD59]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD81C-\uD820\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F\uDFE0\uDFE1]|\uD821[\uDC00-\uDFEC]|\uD822[\uDC00-\uDEF2]|\uD82C[\uDC00-\uDD1E\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD838[\uDC00-\uDC06\uDC08-\uDC18\uDC1B-\uDC21\uDC23\uDC24\uDC26-\uDC2A]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6\uDD00-\uDD4A\uDD50-\uDD59]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/;
      var unicode = {
        Space_Separator,
        ID_Start,
        ID_Continue
      };
      var util = {
        isSpaceSeparator: function isSpaceSeparator(c2) {
          return typeof c2 === "string" && unicode.Space_Separator.test(c2);
        },
        isIdStartChar: function isIdStartChar(c2) {
          return typeof c2 === "string" && (c2 >= "a" && c2 <= "z" || c2 >= "A" && c2 <= "Z" || c2 === "$" || c2 === "_" || unicode.ID_Start.test(c2));
        },
        isIdContinueChar: function isIdContinueChar(c2) {
          return typeof c2 === "string" && (c2 >= "a" && c2 <= "z" || c2 >= "A" && c2 <= "Z" || c2 >= "0" && c2 <= "9" || c2 === "$" || c2 === "_" || c2 === "\u200C" || c2 === "\u200D" || unicode.ID_Continue.test(c2));
        },
        isDigit: function isDigit(c2) {
          return typeof c2 === "string" && /[0-9]/.test(c2);
        },
        isHexDigit: function isHexDigit(c2) {
          return typeof c2 === "string" && /[0-9A-Fa-f]/.test(c2);
        }
      };
      var source;
      var parseState;
      var stack;
      var pos;
      var line;
      var column;
      var token;
      var key;
      var root;
      var parse3 = function parse4(text, reviver) {
        source = String(text);
        parseState = "start";
        stack = [];
        pos = 0;
        line = 1;
        column = 0;
        token = void 0;
        key = void 0;
        root = void 0;
        do {
          token = lex();
          parseStates[parseState]();
        } while (token.type !== "eof");
        if (typeof reviver === "function") {
          return internalize({ "": root }, "", reviver);
        }
        return root;
      };
      function internalize(holder, name, reviver) {
        var value = holder[name];
        if (value != null && typeof value === "object") {
          if (Array.isArray(value)) {
            for (var i2 = 0; i2 < value.length; i2++) {
              var key2 = String(i2);
              var replacement = internalize(value, key2, reviver);
              if (replacement === void 0) {
                delete value[key2];
              } else {
                Object.defineProperty(value, key2, {
                  value: replacement,
                  writable: true,
                  enumerable: true,
                  configurable: true
                });
              }
            }
          } else {
            for (var key$1 in value) {
              var replacement$1 = internalize(value, key$1, reviver);
              if (replacement$1 === void 0) {
                delete value[key$1];
              } else {
                Object.defineProperty(value, key$1, {
                  value: replacement$1,
                  writable: true,
                  enumerable: true,
                  configurable: true
                });
              }
            }
          }
        }
        return reviver.call(holder, name, value);
      }
      var lexState;
      var buffer;
      var doubleQuote;
      var sign;
      var c;
      function lex() {
        lexState = "default";
        buffer = "";
        doubleQuote = false;
        sign = 1;
        for (; ; ) {
          c = peek();
          var token2 = lexStates[lexState]();
          if (token2) {
            return token2;
          }
        }
      }
      function peek() {
        if (source[pos]) {
          return String.fromCodePoint(source.codePointAt(pos));
        }
      }
      function read() {
        var c2 = peek();
        if (c2 === "\n") {
          line++;
          column = 0;
        } else if (c2) {
          column += c2.length;
        } else {
          column++;
        }
        if (c2) {
          pos += c2.length;
        }
        return c2;
      }
      var lexStates = {
        default: function default$1() {
          switch (c) {
            case "	":
            case "\v":
            case "\f":
            case " ":
            case "\xA0":
            case "\uFEFF":
            case "\n":
            case "\r":
            case "\u2028":
            case "\u2029":
              read();
              return;
            case "/":
              read();
              lexState = "comment";
              return;
            case void 0:
              read();
              return newToken("eof");
          }
          if (util.isSpaceSeparator(c)) {
            read();
            return;
          }
          return lexStates[parseState]();
        },
        comment: function comment() {
          switch (c) {
            case "*":
              read();
              lexState = "multiLineComment";
              return;
            case "/":
              read();
              lexState = "singleLineComment";
              return;
          }
          throw invalidChar(read());
        },
        multiLineComment: function multiLineComment() {
          switch (c) {
            case "*":
              read();
              lexState = "multiLineCommentAsterisk";
              return;
            case void 0:
              throw invalidChar(read());
          }
          read();
        },
        multiLineCommentAsterisk: function multiLineCommentAsterisk() {
          switch (c) {
            case "*":
              read();
              return;
            case "/":
              read();
              lexState = "default";
              return;
            case void 0:
              throw invalidChar(read());
          }
          read();
          lexState = "multiLineComment";
        },
        singleLineComment: function singleLineComment() {
          switch (c) {
            case "\n":
            case "\r":
            case "\u2028":
            case "\u2029":
              read();
              lexState = "default";
              return;
            case void 0:
              read();
              return newToken("eof");
          }
          read();
        },
        value: function value() {
          switch (c) {
            case "{":
            case "[":
              return newToken("punctuator", read());
            case "n":
              read();
              literal("ull");
              return newToken("null", null);
            case "t":
              read();
              literal("rue");
              return newToken("boolean", true);
            case "f":
              read();
              literal("alse");
              return newToken("boolean", false);
            case "-":
            case "+":
              if (read() === "-") {
                sign = -1;
              }
              lexState = "sign";
              return;
            case ".":
              buffer = read();
              lexState = "decimalPointLeading";
              return;
            case "0":
              buffer = read();
              lexState = "zero";
              return;
            case "1":
            case "2":
            case "3":
            case "4":
            case "5":
            case "6":
            case "7":
            case "8":
            case "9":
              buffer = read();
              lexState = "decimalInteger";
              return;
            case "I":
              read();
              literal("nfinity");
              return newToken("numeric", Infinity);
            case "N":
              read();
              literal("aN");
              return newToken("numeric", NaN);
            case '"':
            case "'":
              doubleQuote = read() === '"';
              buffer = "";
              lexState = "string";
              return;
          }
          throw invalidChar(read());
        },
        identifierNameStartEscape: function identifierNameStartEscape() {
          if (c !== "u") {
            throw invalidChar(read());
          }
          read();
          var u = unicodeEscape();
          switch (u) {
            case "$":
            case "_":
              break;
            default:
              if (!util.isIdStartChar(u)) {
                throw invalidIdentifier();
              }
              break;
          }
          buffer += u;
          lexState = "identifierName";
        },
        identifierName: function identifierName() {
          switch (c) {
            case "$":
            case "_":
            case "\u200C":
            case "\u200D":
              buffer += read();
              return;
            case "\\":
              read();
              lexState = "identifierNameEscape";
              return;
          }
          if (util.isIdContinueChar(c)) {
            buffer += read();
            return;
          }
          return newToken("identifier", buffer);
        },
        identifierNameEscape: function identifierNameEscape() {
          if (c !== "u") {
            throw invalidChar(read());
          }
          read();
          var u = unicodeEscape();
          switch (u) {
            case "$":
            case "_":
            case "\u200C":
            case "\u200D":
              break;
            default:
              if (!util.isIdContinueChar(u)) {
                throw invalidIdentifier();
              }
              break;
          }
          buffer += u;
          lexState = "identifierName";
        },
        sign: function sign$1() {
          switch (c) {
            case ".":
              buffer = read();
              lexState = "decimalPointLeading";
              return;
            case "0":
              buffer = read();
              lexState = "zero";
              return;
            case "1":
            case "2":
            case "3":
            case "4":
            case "5":
            case "6":
            case "7":
            case "8":
            case "9":
              buffer = read();
              lexState = "decimalInteger";
              return;
            case "I":
              read();
              literal("nfinity");
              return newToken("numeric", sign * Infinity);
            case "N":
              read();
              literal("aN");
              return newToken("numeric", NaN);
          }
          throw invalidChar(read());
        },
        zero: function zero() {
          switch (c) {
            case ".":
              buffer += read();
              lexState = "decimalPoint";
              return;
            case "e":
            case "E":
              buffer += read();
              lexState = "decimalExponent";
              return;
            case "x":
            case "X":
              buffer += read();
              lexState = "hexadecimal";
              return;
          }
          return newToken("numeric", sign * 0);
        },
        decimalInteger: function decimalInteger() {
          switch (c) {
            case ".":
              buffer += read();
              lexState = "decimalPoint";
              return;
            case "e":
            case "E":
              buffer += read();
              lexState = "decimalExponent";
              return;
          }
          if (util.isDigit(c)) {
            buffer += read();
            return;
          }
          return newToken("numeric", sign * Number(buffer));
        },
        decimalPointLeading: function decimalPointLeading() {
          if (util.isDigit(c)) {
            buffer += read();
            lexState = "decimalFraction";
            return;
          }
          throw invalidChar(read());
        },
        decimalPoint: function decimalPoint() {
          switch (c) {
            case "e":
            case "E":
              buffer += read();
              lexState = "decimalExponent";
              return;
          }
          if (util.isDigit(c)) {
            buffer += read();
            lexState = "decimalFraction";
            return;
          }
          return newToken("numeric", sign * Number(buffer));
        },
        decimalFraction: function decimalFraction() {
          switch (c) {
            case "e":
            case "E":
              buffer += read();
              lexState = "decimalExponent";
              return;
          }
          if (util.isDigit(c)) {
            buffer += read();
            return;
          }
          return newToken("numeric", sign * Number(buffer));
        },
        decimalExponent: function decimalExponent() {
          switch (c) {
            case "+":
            case "-":
              buffer += read();
              lexState = "decimalExponentSign";
              return;
          }
          if (util.isDigit(c)) {
            buffer += read();
            lexState = "decimalExponentInteger";
            return;
          }
          throw invalidChar(read());
        },
        decimalExponentSign: function decimalExponentSign() {
          if (util.isDigit(c)) {
            buffer += read();
            lexState = "decimalExponentInteger";
            return;
          }
          throw invalidChar(read());
        },
        decimalExponentInteger: function decimalExponentInteger() {
          if (util.isDigit(c)) {
            buffer += read();
            return;
          }
          return newToken("numeric", sign * Number(buffer));
        },
        hexadecimal: function hexadecimal() {
          if (util.isHexDigit(c)) {
            buffer += read();
            lexState = "hexadecimalInteger";
            return;
          }
          throw invalidChar(read());
        },
        hexadecimalInteger: function hexadecimalInteger() {
          if (util.isHexDigit(c)) {
            buffer += read();
            return;
          }
          return newToken("numeric", sign * Number(buffer));
        },
        string: function string() {
          switch (c) {
            case "\\":
              read();
              buffer += escape2();
              return;
            case '"':
              if (doubleQuote) {
                read();
                return newToken("string", buffer);
              }
              buffer += read();
              return;
            case "'":
              if (!doubleQuote) {
                read();
                return newToken("string", buffer);
              }
              buffer += read();
              return;
            case "\n":
            case "\r":
              throw invalidChar(read());
            case "\u2028":
            case "\u2029":
              separatorChar(c);
              break;
            case void 0:
              throw invalidChar(read());
          }
          buffer += read();
        },
        start: function start() {
          switch (c) {
            case "{":
            case "[":
              return newToken("punctuator", read());
          }
          lexState = "value";
        },
        beforePropertyName: function beforePropertyName() {
          switch (c) {
            case "$":
            case "_":
              buffer = read();
              lexState = "identifierName";
              return;
            case "\\":
              read();
              lexState = "identifierNameStartEscape";
              return;
            case "}":
              return newToken("punctuator", read());
            case '"':
            case "'":
              doubleQuote = read() === '"';
              lexState = "string";
              return;
          }
          if (util.isIdStartChar(c)) {
            buffer += read();
            lexState = "identifierName";
            return;
          }
          throw invalidChar(read());
        },
        afterPropertyName: function afterPropertyName() {
          if (c === ":") {
            return newToken("punctuator", read());
          }
          throw invalidChar(read());
        },
        beforePropertyValue: function beforePropertyValue() {
          lexState = "value";
        },
        afterPropertyValue: function afterPropertyValue() {
          switch (c) {
            case ",":
            case "}":
              return newToken("punctuator", read());
          }
          throw invalidChar(read());
        },
        beforeArrayValue: function beforeArrayValue() {
          if (c === "]") {
            return newToken("punctuator", read());
          }
          lexState = "value";
        },
        afterArrayValue: function afterArrayValue() {
          switch (c) {
            case ",":
            case "]":
              return newToken("punctuator", read());
          }
          throw invalidChar(read());
        },
        end: function end() {
          throw invalidChar(read());
        }
      };
      function newToken(type, value) {
        return {
          type,
          value,
          line,
          column
        };
      }
      function literal(s) {
        for (var i2 = 0, list = s; i2 < list.length; i2 += 1) {
          var c2 = list[i2];
          var p = peek();
          if (p !== c2) {
            throw invalidChar(read());
          }
          read();
        }
      }
      function escape2() {
        var c2 = peek();
        switch (c2) {
          case "b":
            read();
            return "\b";
          case "f":
            read();
            return "\f";
          case "n":
            read();
            return "\n";
          case "r":
            read();
            return "\r";
          case "t":
            read();
            return "	";
          case "v":
            read();
            return "\v";
          case "0":
            read();
            if (util.isDigit(peek())) {
              throw invalidChar(read());
            }
            return "\0";
          case "x":
            read();
            return hexEscape();
          case "u":
            read();
            return unicodeEscape();
          case "\n":
          case "\u2028":
          case "\u2029":
            read();
            return "";
          case "\r":
            read();
            if (peek() === "\n") {
              read();
            }
            return "";
          case "1":
          case "2":
          case "3":
          case "4":
          case "5":
          case "6":
          case "7":
          case "8":
          case "9":
            throw invalidChar(read());
          case void 0:
            throw invalidChar(read());
        }
        return read();
      }
      function hexEscape() {
        var buffer2 = "";
        var c2 = peek();
        if (!util.isHexDigit(c2)) {
          throw invalidChar(read());
        }
        buffer2 += read();
        c2 = peek();
        if (!util.isHexDigit(c2)) {
          throw invalidChar(read());
        }
        buffer2 += read();
        return String.fromCodePoint(parseInt(buffer2, 16));
      }
      function unicodeEscape() {
        var buffer2 = "";
        var count = 4;
        while (count-- > 0) {
          var c2 = peek();
          if (!util.isHexDigit(c2)) {
            throw invalidChar(read());
          }
          buffer2 += read();
        }
        return String.fromCodePoint(parseInt(buffer2, 16));
      }
      var parseStates = {
        start: function start() {
          if (token.type === "eof") {
            throw invalidEOF();
          }
          push();
        },
        beforePropertyName: function beforePropertyName() {
          switch (token.type) {
            case "identifier":
            case "string":
              key = token.value;
              parseState = "afterPropertyName";
              return;
            case "punctuator":
              pop();
              return;
            case "eof":
              throw invalidEOF();
          }
        },
        afterPropertyName: function afterPropertyName() {
          if (token.type === "eof") {
            throw invalidEOF();
          }
          parseState = "beforePropertyValue";
        },
        beforePropertyValue: function beforePropertyValue() {
          if (token.type === "eof") {
            throw invalidEOF();
          }
          push();
        },
        beforeArrayValue: function beforeArrayValue() {
          if (token.type === "eof") {
            throw invalidEOF();
          }
          if (token.type === "punctuator" && token.value === "]") {
            pop();
            return;
          }
          push();
        },
        afterPropertyValue: function afterPropertyValue() {
          if (token.type === "eof") {
            throw invalidEOF();
          }
          switch (token.value) {
            case ",":
              parseState = "beforePropertyName";
              return;
            case "}":
              pop();
          }
        },
        afterArrayValue: function afterArrayValue() {
          if (token.type === "eof") {
            throw invalidEOF();
          }
          switch (token.value) {
            case ",":
              parseState = "beforeArrayValue";
              return;
            case "]":
              pop();
          }
        },
        end: function end() {
        }
      };
      function push() {
        var value;
        switch (token.type) {
          case "punctuator":
            switch (token.value) {
              case "{":
                value = {};
                break;
              case "[":
                value = [];
                break;
            }
            break;
          case "null":
          case "boolean":
          case "numeric":
          case "string":
            value = token.value;
            break;
        }
        if (root === void 0) {
          root = value;
        } else {
          var parent = stack[stack.length - 1];
          if (Array.isArray(parent)) {
            parent.push(value);
          } else {
            Object.defineProperty(parent, key, {
              value,
              writable: true,
              enumerable: true,
              configurable: true
            });
          }
        }
        if (value !== null && typeof value === "object") {
          stack.push(value);
          if (Array.isArray(value)) {
            parseState = "beforeArrayValue";
          } else {
            parseState = "beforePropertyName";
          }
        } else {
          var current = stack[stack.length - 1];
          if (current == null) {
            parseState = "end";
          } else if (Array.isArray(current)) {
            parseState = "afterArrayValue";
          } else {
            parseState = "afterPropertyValue";
          }
        }
      }
      function pop() {
        stack.pop();
        var current = stack[stack.length - 1];
        if (current == null) {
          parseState = "end";
        } else if (Array.isArray(current)) {
          parseState = "afterArrayValue";
        } else {
          parseState = "afterPropertyValue";
        }
      }
      function invalidChar(c2) {
        if (c2 === void 0) {
          return syntaxError("JSON5: invalid end of input at " + line + ":" + column);
        }
        return syntaxError("JSON5: invalid character '" + formatChar(c2) + "' at " + line + ":" + column);
      }
      function invalidEOF() {
        return syntaxError("JSON5: invalid end of input at " + line + ":" + column);
      }
      function invalidIdentifier() {
        column -= 5;
        return syntaxError("JSON5: invalid identifier character at " + line + ":" + column);
      }
      function separatorChar(c2) {
        console.warn("JSON5: '" + formatChar(c2) + "' in strings is not valid ECMAScript; consider escaping");
      }
      function formatChar(c2) {
        var replacements = {
          "'": "\\'",
          '"': '\\"',
          "\\": "\\\\",
          "\b": "\\b",
          "\f": "\\f",
          "\n": "\\n",
          "\r": "\\r",
          "	": "\\t",
          "\v": "\\v",
          "\0": "\\0",
          "\u2028": "\\u2028",
          "\u2029": "\\u2029"
        };
        if (replacements[c2]) {
          return replacements[c2];
        }
        if (c2 < " ") {
          var hexString = c2.charCodeAt(0).toString(16);
          return "\\x" + ("00" + hexString).substring(hexString.length);
        }
        return c2;
      }
      function syntaxError(message) {
        var err = new SyntaxError(message);
        err.lineNumber = line;
        err.columnNumber = column;
        return err;
      }
      var stringify = function stringify2(value, replacer, space) {
        var stack2 = [];
        var indent = "";
        var propertyList;
        var replacerFunc;
        var gap = "";
        var quote;
        if (replacer != null && typeof replacer === "object" && !Array.isArray(replacer)) {
          space = replacer.space;
          quote = replacer.quote;
          replacer = replacer.replacer;
        }
        if (typeof replacer === "function") {
          replacerFunc = replacer;
        } else if (Array.isArray(replacer)) {
          propertyList = [];
          for (var i2 = 0, list = replacer; i2 < list.length; i2 += 1) {
            var v = list[i2];
            var item = void 0;
            if (typeof v === "string") {
              item = v;
            } else if (typeof v === "number" || v instanceof String || v instanceof Number) {
              item = String(v);
            }
            if (item !== void 0 && propertyList.indexOf(item) < 0) {
              propertyList.push(item);
            }
          }
        }
        if (space instanceof Number) {
          space = Number(space);
        } else if (space instanceof String) {
          space = String(space);
        }
        if (typeof space === "number") {
          if (space > 0) {
            space = Math.min(10, Math.floor(space));
            gap = "          ".substr(0, space);
          }
        } else if (typeof space === "string") {
          gap = space.substr(0, 10);
        }
        return serializeProperty("", { "": value });
        function serializeProperty(key2, holder) {
          var value2 = holder[key2];
          if (value2 != null) {
            if (typeof value2.toJSON5 === "function") {
              value2 = value2.toJSON5(key2);
            } else if (typeof value2.toJSON === "function") {
              value2 = value2.toJSON(key2);
            }
          }
          if (replacerFunc) {
            value2 = replacerFunc.call(holder, key2, value2);
          }
          if (value2 instanceof Number) {
            value2 = Number(value2);
          } else if (value2 instanceof String) {
            value2 = String(value2);
          } else if (value2 instanceof Boolean) {
            value2 = value2.valueOf();
          }
          switch (value2) {
            case null:
              return "null";
            case true:
              return "true";
            case false:
              return "false";
          }
          if (typeof value2 === "string") {
            return quoteString(value2, false);
          }
          if (typeof value2 === "number") {
            return String(value2);
          }
          if (typeof value2 === "object") {
            return Array.isArray(value2) ? serializeArray(value2) : serializeObject(value2);
          }
          return void 0;
        }
        function quoteString(value2) {
          var quotes = {
            "'": 0.1,
            '"': 0.2
          };
          var replacements = {
            "'": "\\'",
            '"': '\\"',
            "\\": "\\\\",
            "\b": "\\b",
            "\f": "\\f",
            "\n": "\\n",
            "\r": "\\r",
            "	": "\\t",
            "\v": "\\v",
            "\0": "\\0",
            "\u2028": "\\u2028",
            "\u2029": "\\u2029"
          };
          var product = "";
          for (var i3 = 0; i3 < value2.length; i3++) {
            var c2 = value2[i3];
            switch (c2) {
              case "'":
              case '"':
                quotes[c2]++;
                product += c2;
                continue;
              case "\0":
                if (util.isDigit(value2[i3 + 1])) {
                  product += "\\x00";
                  continue;
                }
            }
            if (replacements[c2]) {
              product += replacements[c2];
              continue;
            }
            if (c2 < " ") {
              var hexString = c2.charCodeAt(0).toString(16);
              product += "\\x" + ("00" + hexString).substring(hexString.length);
              continue;
            }
            product += c2;
          }
          var quoteChar = quote || Object.keys(quotes).reduce(function(a, b) {
            return quotes[a] < quotes[b] ? a : b;
          });
          product = product.replace(new RegExp(quoteChar, "g"), replacements[quoteChar]);
          return quoteChar + product + quoteChar;
        }
        function serializeObject(value2) {
          if (stack2.indexOf(value2) >= 0) {
            throw TypeError("Converting circular structure to JSON5");
          }
          stack2.push(value2);
          var stepback = indent;
          indent = indent + gap;
          var keys = propertyList || Object.keys(value2);
          var partial = [];
          for (var i3 = 0, list2 = keys; i3 < list2.length; i3 += 1) {
            var key2 = list2[i3];
            var propertyString = serializeProperty(key2, value2);
            if (propertyString !== void 0) {
              var member = serializeKey(key2) + ":";
              if (gap !== "") {
                member += " ";
              }
              member += propertyString;
              partial.push(member);
            }
          }
          var final;
          if (partial.length === 0) {
            final = "{}";
          } else {
            var properties;
            if (gap === "") {
              properties = partial.join(",");
              final = "{" + properties + "}";
            } else {
              var separator = ",\n" + indent;
              properties = partial.join(separator);
              final = "{\n" + indent + properties + ",\n" + stepback + "}";
            }
          }
          stack2.pop();
          indent = stepback;
          return final;
        }
        function serializeKey(key2) {
          if (key2.length === 0) {
            return quoteString(key2, true);
          }
          var firstChar = String.fromCodePoint(key2.codePointAt(0));
          if (!util.isIdStartChar(firstChar)) {
            return quoteString(key2, true);
          }
          for (var i3 = firstChar.length; i3 < key2.length; i3++) {
            if (!util.isIdContinueChar(String.fromCodePoint(key2.codePointAt(i3)))) {
              return quoteString(key2, true);
            }
          }
          return key2;
        }
        function serializeArray(value2) {
          if (stack2.indexOf(value2) >= 0) {
            throw TypeError("Converting circular structure to JSON5");
          }
          stack2.push(value2);
          var stepback = indent;
          indent = indent + gap;
          var partial = [];
          for (var i3 = 0; i3 < value2.length; i3++) {
            var propertyString = serializeProperty(String(i3), value2);
            partial.push(propertyString !== void 0 ? propertyString : "null");
          }
          var final;
          if (partial.length === 0) {
            final = "[]";
          } else {
            if (gap === "") {
              var properties = partial.join(",");
              final = "[" + properties + "]";
            } else {
              var separator = ",\n" + indent;
              var properties$1 = partial.join(separator);
              final = "[\n" + indent + properties$1 + ",\n" + stepback + "]";
            }
          }
          stack2.pop();
          indent = stepback;
          return final;
        }
      };
      var JSON52 = {
        parse: parse3,
        stringify
      };
      var lib = JSON52;
      var es5 = lib;
      return es5;
    });
  }
});

// src/main.ts
var main_exports = {};
__export(main_exports, {
  canonicalLanguages: () => canonicalLanguages,
  default: () => ExecuteCodePlugin2,
  languageAliases: () => languageAliases,
  supportedLanguages: () => supportedLanguages
});
module.exports = __toCommonJS(main_exports);
var import_obsidian50 = require("obsidian");

// src/settings/Settings.ts
var DEFAULT_SETTINGS = {
  lastOpenLanguageTab: void 0,
  releaseNote2_1_0wasShowed: false,
  persistentOuput: false,
  timeout: 1e4,
  allowInput: true,
  wslMode: false,
  shellWSLMode: false,
  onlyCurrentBlock: false,
  nodePath: "node",
  nodeArgs: "",
  jsFileExtension: "js",
  jsInject: "",
  tsPath: "ts-node",
  tsArgs: "",
  tsInject: "",
  latexCompilerPath: "lualatex",
  latexCompilerArgs: "-interaction=nonstopmode",
  latexDoFilter: true,
  latexTexfotPath: "texfot",
  latexTexfotArgs: "--quiet",
  latexDocumentclass: "article",
  latexAdaptFont: "obsidian",
  latexKeepLog: false,
  latexSubprocessesUseShell: false,
  latexMaxFigures: 10,
  latexFigureTitlePattern: /[^\n][^%`]*\\title\s*\{(?<name>[^\}]*)\}/.source,
  latexDoCrop: false,
  latexCropPath: "pdfcrop",
  latexCropArgs: "--quiet",
  latexCropNoStandalone: true,
  latexCropNoPagenum: true,
  latexSaveSvg: "poppler",
  latexSvgPath: "pdftocairo",
  latexSvgArgs: "-svg",
  latexInkscapePath: "inkscape",
  latexInkscapeArgs: "--pages=all --export-plain-svg",
  latexSavePdf: true,
  latexSavePng: false,
  latexPngPath: "pdftocairo",
  latexPngArgs: "-singlefile -png",
  latexOutputEmbeddings: true,
  latexInvertFigures: true,
  latexCenterFigures: true,
  latexInject: "",
  leanPath: "lean",
  leanArgs: "",
  leanInject: "",
  luaPath: "lua",
  luaArgs: "",
  luaFileExtension: "lua",
  luaInject: "",
  dartPath: "dart",
  dartArgs: "",
  dartFileExtension: "dart",
  dartInject: "",
  csPath: "dotnet-script",
  csArgs: "",
  csFileExtension: "csx",
  csInject: "",
  pythonPath: "python",
  pythonArgs: "",
  pythonEmbedPlots: true,
  pythonFileExtension: "py",
  pythonInject: "",
  shellPath: "bash",
  shellArgs: "",
  shellFileExtension: "sh",
  shellInject: "",
  batchPath: "call",
  batchArgs: "",
  batchFileExtension: "bat",
  batchInject: "",
  groovyPath: "groovy",
  groovyArgs: "",
  groovyFileExtension: "groovy",
  groovyInject: "",
  golangPath: "go",
  golangArgs: "run",
  golangFileExtension: "go",
  goInject: "",
  javaPath: "java",
  javaArgs: "-ea",
  javaFileExtension: "java",
  javaInject: "",
  maxPrologAnswers: 15,
  prologInject: "",
  powershellPath: "powershell",
  powershellArgs: "-file",
  powershellFileExtension: "ps1",
  powershellInject: "$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding",
  powershellEncoding: "latin1",
  cargoPath: "cargo",
  cargoEvalArgs: "",
  rustInject: "",
  cppRunner: "cling",
  cppFileExtension: "cpp",
  cppInject: "",
  cppArgs: "",
  cppUseMain: false,
  clingPath: "cling",
  clingArgs: "",
  clingStd: "c++17",
  rustFileExtension: "rs",
  RPath: "Rscript",
  RArgs: "",
  REmbedPlots: true,
  RFileExtension: "R",
  rInject: "",
  kotlinPath: "kotlinc",
  kotlinArgs: "-script",
  kotlinFileExtension: "kts",
  kotlinInject: "",
  swiftPath: "swift",
  swiftArgs: "",
  swiftFileExtension: "swift",
  swiftInject: "",
  runghcPath: "runghc",
  ghcPath: "ghc",
  ghciPath: "ghci",
  useGhci: false,
  haskellInject: "",
  mathematicaPath: "wolframscript",
  mathematicaArgs: "-file",
  mathematicaFileExtension: "wls",
  mathematicaInject: "",
  scalaPath: "scala",
  scalaArgs: "",
  scalaFileExtension: "scala",
  scalaInject: "",
  racketPath: "racket",
  racketArgs: "",
  racketFileExtension: "rkt",
  racketInject: "#lang racket",
  fsharpPath: "dotnet",
  fsharpArgs: "fsi",
  fsharpInject: "",
  fsharpFileExtension: "fsx",
  cArgs: "",
  cUseMain: true,
  cInject: "",
  rubyPath: "ruby",
  rubyArgs: "",
  rubyFileExtension: "rb",
  rubyInject: "",
  sqlPath: "psql",
  sqlArgs: "-d <database> -U <user> -f",
  sqlInject: "",
  octavePath: "octave",
  octaveArgs: "-q",
  octaveFileExtension: "m",
  octaveInject: "figure('visible','off')  # Necessary to embed plots",
  maximaPath: "maxima",
  maximaArgs: "-qb",
  maximaFileExtension: "mx",
  maximaInject: "",
  applescriptPath: "osascript",
  applescriptArgs: "",
  applescriptFileExtension: "scpt",
  applescriptInject: "",
  zigPath: "zig",
  zigArgs: "run",
  zigInject: "",
  ocamlPath: "ocaml",
  ocamlArgs: "",
  ocamlInject: "",
  phpPath: "php",
  phpArgs: "",
  phpFileExtension: "php",
  phpInject: "",
  jsInteractive: true,
  tsInteractive: false,
  csInteractive: false,
  latexInteractive: false,
  leanInteractive: false,
  luaInteractive: false,
  dartInteractive: false,
  pythonInteractive: true,
  cppInteractive: false,
  prologInteractive: false,
  shellInteractive: false,
  batchInteractive: false,
  bashInteractive: false,
  groovyInteractive: false,
  rInteractive: false,
  goInteractive: false,
  rustInteractive: false,
  javaInteractive: false,
  powershellInteractive: false,
  kotlinInteractive: false,
  swiftInteractive: false,
  mathematicaInteractive: false,
  haskellInteractive: false,
  scalaInteractive: false,
  fsharpInteractive: false,
  cInteractive: false,
  racketInteractive: false,
  rubyInteractive: false,
  sqlInteractive: false,
  octaveInteractive: false,
  maximaInteractive: false,
  applescriptInteractive: false,
  zigInteractive: false,
  ocamlInteractive: false,
  phpInteractive: false
};

// src/settings/SettingsTab.ts
var import_obsidian36 = require("obsidian");

// src/settings/languageDisplayName.ts
var DISPLAY_NAMES = {
  cpp: "C++",
  cs: "C#",
  go: "Golang",
  groovy: "Groovy",
  haskell: "Haskell",
  java: "Java",
  js: "Javascript",
  kotlin: "Kotlin",
  latex: "LaTeX",
  lua: "Lua",
  mathematica: "Mathematica",
  php: "PHP",
  powershell: "Powershell",
  prolog: "Prolog",
  python: "Python",
  r: "R",
  rust: "Rust",
  shell: "Shell",
  batch: "Batch",
  ts: "Typescript",
  scala: "Scala",
  swift: "Swift",
  racket: "Racket",
  c: "C",
  fsharp: "F#",
  ruby: "Ruby",
  dart: "Dart",
  lean: "Lean",
  sql: "SQL",
  octave: "Octave",
  maxima: "Maxima",
  applescript: "Applescript",
  zig: "Zig",
  ocaml: "OCaml"
};

// src/settings/per-lang/makeCppSettings.ts
var import_obsidian = require("obsidian");
var makeCppSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "C++ Settings" });
  new import_obsidian.Setting(containerEl).setName("Cling path").setDesc("The path to your Cling installation.").addText((text) => text.setValue(tab.plugin.settings.clingPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.clingPath = sanitized;
    console.log("Cling path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian.Setting(containerEl).setName("Cling arguments for C++").addText((text) => text.setValue(tab.plugin.settings.cppArgs).onChange(async (value) => {
    tab.plugin.settings.cppArgs = value;
    console.log("CPP args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian.Setting(containerEl).setName("Cling std").addDropdown((dropdown) => dropdown.addOption("c++98", "C++ 98").addOption("c++11", "C++ 11").addOption("c++14", "C++ 14").addOption("c++17", "C++ 17").addOption("c++2a", "C++ 20").setValue(tab.plugin.settings.clingStd).onChange(async (value) => {
    tab.plugin.settings.clingStd = value;
    console.log("Cling std set to: " + value);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian.Setting(containerEl).setName("Use main function").setDesc("If enabled, will use a main() function as the code block entrypoint.").addToggle((toggle) => toggle.setValue(tab.plugin.settings.cppUseMain).onChange(async (value) => {
    tab.plugin.settings.cppUseMain = value;
    console.log("Cpp use main set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "cpp");
};

// src/settings/per-lang/makeCSettings.ts
var import_obsidian2 = require("obsidian");
var makeCSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "C Settings" });
  new import_obsidian2.Setting(containerEl).setName("gcc / Cling path").setDesc("The path to your gcc / Cling installation.").addText((text) => text.setValue(tab.plugin.settings.clingPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.clingPath = sanitized;
    console.log("gcc / Cling path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian2.Setting(containerEl).setName("gcc / Cling arguments for C").addText((text) => text.setValue(tab.plugin.settings.cArgs).onChange(async (value) => {
    tab.plugin.settings.cArgs = value;
    console.log("gcc / Cling args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian2.Setting(containerEl).setName("Cling std (ignored for gcc)").addDropdown((dropdown) => dropdown.addOption("c++98", "C++ 98").addOption("c++11", "C++ 11").addOption("c++14", "C++ 14").addOption("c++17", "C++ 17").addOption("c++2a", "C++ 20").setValue(tab.plugin.settings.clingStd).onChange(async (value) => {
    tab.plugin.settings.clingStd = value;
    console.log("Cling std set to: " + value);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian2.Setting(containerEl).setName("Use main function (mandatory for gcc)").setDesc("If enabled, will use a main() function as the code block entrypoint.").addToggle((toggle) => toggle.setValue(tab.plugin.settings.cUseMain).onChange(async (value) => {
    tab.plugin.settings.cUseMain = value;
    console.log("C use main set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "c");
};

// src/settings/per-lang/makeCsSettings.ts
var import_obsidian3 = require("obsidian");
var makeCsSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "CSharp Settings" });
  new import_obsidian3.Setting(containerEl).setName("dotnet path").addText((text) => text.setValue(tab.plugin.settings.csPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.csPath = sanitized;
    console.log("dotnet path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian3.Setting(containerEl).setName("CSharp arguments").addText((text) => text.setValue(tab.plugin.settings.csArgs).onChange(async (value) => {
    tab.plugin.settings.csArgs = value;
    console.log("CSharp args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "cs");
};

// src/settings/per-lang/makeFSharpSettings.ts
var import_obsidian4 = require("obsidian");
var makeFSharpSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "F# Settings" });
  new import_obsidian4.Setting(containerEl).setName("F# path").setDesc("The path to dotnet.").addText((text) => text.setValue(tab.plugin.settings.fsharpPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.fsharpPath = sanitized;
    console.log("F# path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian4.Setting(containerEl).setName("F# arguments").addText((text) => text.setValue(tab.plugin.settings.fsharpArgs).onChange(async (value) => {
    tab.plugin.settings.fsharpArgs = value;
    console.log("F# args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian4.Setting(containerEl).setName("F# file extension").setDesc("Changes the file extension for generated F# scripts.").addText((text) => text.setValue(tab.plugin.settings.fsharpFileExtension).onChange(async (value) => {
    tab.plugin.settings.fsharpFileExtension = value;
    console.log("F# file extension set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "fsharp");
};

// src/settings/per-lang/makeGoSettings.ts
var import_obsidian5 = require("obsidian");
var makeGoSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Golang Settings" });
  new import_obsidian5.Setting(containerEl).setName("Golang Path").setDesc("The path to your Golang installation.").addText((text) => text.setValue(tab.plugin.settings.golangPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.golangPath = sanitized;
    console.log("Golang path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "go");
};

// src/settings/per-lang/makeGroovySettings.ts
var import_obsidian6 = require("obsidian");
var makeGroovySettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Groovy Settings" });
  new import_obsidian6.Setting(containerEl).setName("Groovy path").setDesc("The path to your Groovy installation.").addText((text) => text.setValue(tab.plugin.settings.groovyPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.groovyPath = sanitized;
    console.log("Groovy path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian6.Setting(containerEl).setName("Groovy arguments").addText((text) => text.setValue(tab.plugin.settings.groovyArgs).onChange(async (value) => {
    tab.plugin.settings.groovyArgs = value;
    console.log("Groovy args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "groovy");
};

// src/settings/per-lang/makeHaskellSettings.ts
var import_obsidian7 = require("obsidian");
var makeHaskellSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Haskell Settings" });
  new import_obsidian7.Setting(containerEl).setName("Use Ghci").setDesc("Run haskell code with ghci instead of runghc").addToggle((toggle) => toggle.setValue(tab.plugin.settings.useGhci).onChange(async (value) => {
    tab.plugin.settings.useGhci = value;
    console.log(value ? "Now using ghci for haskell" : "Now using runghc for haskell.");
    await tab.plugin.saveSettings();
  }));
  new import_obsidian7.Setting(containerEl).setName("Ghci path").setDesc("The path to your ghci installation.").addText((text) => text.setValue(tab.plugin.settings.ghciPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.ghciPath = sanitized;
    console.log("ghci path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian7.Setting(containerEl).setName("Runghc path").setDesc("The path to your runghc installation.").addText((text) => text.setValue(tab.plugin.settings.runghcPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.runghcPath = sanitized;
    console.log("runghc path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian7.Setting(containerEl).setName("Ghc path").setDesc("The Ghc path your runghc installation will call.").addText((text) => text.setValue(tab.plugin.settings.ghcPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.ghcPath = sanitized;
    console.log("ghc path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "haskell");
};

// src/settings/per-lang/makeJavaSettings.ts
var import_obsidian8 = require("obsidian");
var makeJavaSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Java Settings" });
  new import_obsidian8.Setting(containerEl).setName("Java path (Java 11 or higher)").setDesc("The path to your Java installation.").addText((text) => text.setValue(tab.plugin.settings.javaPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.javaPath = sanitized;
    console.log("Java path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian8.Setting(containerEl).setName("Java arguments").addText((text) => text.setValue(tab.plugin.settings.javaArgs).onChange(async (value) => {
    tab.plugin.settings.javaArgs = value;
    console.log("Java args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "java");
};

// src/settings/per-lang/makeJsSettings.ts
var import_obsidian9 = require("obsidian");
var makeJsSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "JavaScript / Node Settings" });
  new import_obsidian9.Setting(containerEl).setName("Node path").addText((text) => text.setValue(tab.plugin.settings.nodePath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.nodePath = sanitized;
    console.log("Node path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian9.Setting(containerEl).setName("Node arguments").addText((text) => text.setValue(tab.plugin.settings.nodeArgs).onChange(async (value) => {
    tab.plugin.settings.nodeArgs = value;
    console.log("Node args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian9.Setting(containerEl).setName("Run Javascript blocks in Notebook Mode").addToggle(
    (toggle) => toggle.setValue(tab.plugin.settings.jsInteractive).onChange(async (value) => {
      tab.plugin.settings.jsInteractive = value;
      await tab.plugin.saveSettings();
    })
  );
  tab.makeInjectSetting(containerEl, "js");
};

// src/settings/per-lang/makeKotlinSettings.ts
var import_obsidian10 = require("obsidian");
var makeKotlinSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Kotlin Settings" });
  new import_obsidian10.Setting(containerEl).setName("Kotlin path").setDesc("The path to your Kotlin installation.").addText((text) => text.setValue(tab.plugin.settings.kotlinPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.kotlinPath = sanitized;
    console.log("Kotlin path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian10.Setting(containerEl).setName("Kotlin arguments").addText((text) => text.setValue(tab.plugin.settings.kotlinArgs).onChange(async (value) => {
    tab.plugin.settings.kotlinArgs = value;
    console.log("Kotlin args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "kotlin");
};

// src/settings/per-lang/makeLatexSettings.ts
var import_obsidian12 = require("obsidian");

// src/transforms/LatexFontHandler.ts
var import_obsidian11 = require("obsidian");
var path = __toESM(require("path"));
var validFonts = /* @__PURE__ */ new Set();
var invalidFonts = /* @__PURE__ */ new Set();
function addFontSpec(settings) {
  const isPdflatex = path.basename(settings.latexCompilerPath).toLowerCase().includes("pdflatex");
  if (isPdflatex || settings.latexAdaptFont === "")
    return "";
  const platformFonts = getPlatformFonts();
  const fontSpec = buildFontCommand(settings, platformFonts);
  if (!fontSpec)
    return "";
  const packageSrc = `\\usepackage{fontspec}
`;
  return packageSrc + fontSpec;
}
function getObsidianFonts(cssVariable) {
  const cssDeclarations = getComputedStyle(document.body);
  const fonts = cssDeclarations.getPropertyValue(cssVariable).split(`'??'`)[0];
  return sanitizeCommaList(fonts);
}
function buildFontCommand(settings, fonts) {
  if (settings.latexAdaptFont === "obsidian") {
    fonts.main = [getObsidianFonts("--font-text"), fonts.main].join(",");
    fonts.sans = [getObsidianFonts("--font-interface"), fonts.sans].join(",");
    fonts.mono = [getObsidianFonts("--font-monospace"), fonts.mono].join(",");
  }
  const mainSrc = buildSetfont("main", fonts.main);
  const sansSrc = buildSetfont("sans", fonts.sans);
  const monoSrc = buildSetfont("mono", fonts.mono);
  return mainSrc + sansSrc + monoSrc;
}
function getPlatformFonts() {
  if (import_obsidian11.Platform.isWin)
    return { main: "Segoe UI", sans: "Segoe UI", mono: "Consolas" };
  if (import_obsidian11.Platform.isMacOS)
    return { main: "SF Pro", sans: "SF Pro", mono: "SF Mono" };
  if (import_obsidian11.Platform.isLinux)
    return { main: "DejaVu Sans", sans: "DejaVu Sans", mono: "DejaVu Sans Mono" };
  return { main: "", sans: "", mono: "" };
}
function buildSetfont(type, fallbackList) {
  const font = firstValidFont(fallbackList);
  return font ? `\\set${type}font{${font}}
` : "";
}
function firstValidFont(fallbackList) {
  return sanitizeCommaList(fallbackList).split(", ").reduce((result, font) => result || (cachedTestFont(font) ? font : void 0), void 0);
}
function cachedTestFont(fontName) {
  if (validFonts.has(fontName))
    return true;
  if (invalidFonts.has(fontName))
    return false;
  if (!testFont(fontName)) {
    invalidFonts.add(fontName);
    return false;
  }
  validFonts.add(fontName);
  return true;
}
function testFont(fontName) {
  const canvas = document.createElement("canvas");
  const context = canvas.getContext("2d");
  if (!context)
    return false;
  const text = "abcdefghijklmnopqrstuvwxyz";
  context.font = `16px monospace`;
  const baselineWidth = context.measureText(text).width;
  context.font = `16px "${fontName}", monospace`;
  const testWidth = context.measureText(text).width;
  const isFontAvailable = baselineWidth !== testWidth;
  console.debug(isFontAvailable ? `Font ${fontName} accepted.` : `Font ${fontName} ignored.`);
  return isFontAvailable;
}
function sanitizeCommaList(commaList) {
  return commaList.split(",").map((font) => font.trim().replace(/^["']|["']$/g, "")).filter(Boolean).join(", ");
}

// src/transforms/LatexTransformer.ts
var appInstance;
var settingsInstance;
var DOCUMENT_CLASS = /^[^%]*(?<src>\\documentclass\s*(\[(?<options>[^\]]*?)\])?\s*{\s*(?<class>[^}]*?)\s*})/;
function modifyLatexCode(latexSrc, settings) {
  const documentClass = captureDocumentClass(latexSrc);
  const injectSrc = "" + provideDocumentClass(documentClass == null ? void 0 : documentClass.class, settings.latexDocumentclass) + addFontSpec(settings) + disablePageNumberForCropping(settings);
  latexSrc = injectSrc + latexSrc;
  console.debug(`Injected LaTeX code:`, documentClass, injectSrc);
  latexSrc = moveDocumentClassToBeginning(latexSrc, documentClass);
  return latexSrc;
}
function disablePageNumberForCropping(settings) {
  return settings.latexDoCrop && settings.latexCropNoPagenum ? `\\pagestyle{empty}
` : "";
}
function provideDocumentClass(currentClass, defaultClass) {
  return currentClass || defaultClass === "" ? "" : `\\documentclass{${defaultClass}}
`;
}
function moveDocumentClassToBeginning(latexSrc, documentClass) {
  return !(documentClass == null ? void 0 : documentClass.src) ? latexSrc : documentClass.src + "\n" + latexSrc.replace(documentClass.src, "");
}
function captureDocumentClass(latexSrc) {
  var _a, _b, _c;
  const match = latexSrc.match(DOCUMENT_CLASS);
  if (!match)
    return void 0;
  return { src: (_a = match.groups) == null ? void 0 : _a.src, class: (_b = match.groups) == null ? void 0 : _b.class, options: (_c = match.groups) == null ? void 0 : _c.options };
}
function isStandaloneClass(latexSrc) {
  var _a;
  const className = (_a = captureDocumentClass(latexSrc)) == null ? void 0 : _a.class;
  return className === "standalone";
}
function updateBodyClass(className, isActive) {
  if (isActive) {
    document.body.classList.add(className);
  } else {
    document.body.classList.remove(className);
  }
}
function applyLatexBodyClasses(app, settings) {
  updateBodyClass("center-latex-figures", settings.latexCenterFigures);
  updateBodyClass("invert-latex-figures", settings.latexInvertFigures);
  appInstance = app;
  settingsInstance = settings;
}

// src/output/RegExpUtilities.ts
function escape(str) {
  return new RegExp(str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
}
function parse(pattern) {
  try {
    const trimmedSlashes = pattern.replace(/^\/|\/$/g, "");
    return RegExp(trimmedSlashes);
  } catch (e) {
    return void 0;
  }
}
function optional(pattern) {
  return new RegExp(group2(pattern).source + "?");
}
function capture(pattern, groupName) {
  return group2(pattern, { name: groupName });
}
function group2(inner, options) {
  let identifier = "";
  if (options == null ? void 0 : options.name)
    identifier = `?<${options.name}>`;
  return new RegExp("(" + identifier + inner.source + ")");
}
function concat(...chain) {
  const combined = chain.filter(Boolean).map((pattern) => pattern.source).join("");
  return new RegExp(combined);
}
function alternate(...options) {
  const alternated = options.filter(Boolean).map((pattern) => pattern.source).join("|");
  return group2(new RegExp(alternated));
}

// src/settings/per-lang/makeLatexSettings.ts
var makeLatexSettings_default = (tab, containerEl) => {
  const s = tab.plugin.settings;
  const linkTexDistributions = "Distributed through <a href='https://miktex.org/'>MiKTeX</a> or <a href='https://www.tug.org/texlive/'>TeX Live</a>.";
  const linkInkscape = "Download <a href='https://inkscape.org/'>Inkscape</a>.";
  containerEl.createEl("h3", { text: "LaTeX Settings" });
  containerEl.createEl("h4", { text: "Code injection" });
  new import_obsidian12.Setting(containerEl).setName("Default document class").addText((text) => text.setPlaceholder("disabled").setValue(s.latexDocumentclass).onChange(async (value) => {
    const sanitized = value.trim();
    s.latexDocumentclass = sanitized;
    console.log(`Default documentclass set to: ${sanitized}`);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `Inject ${selectableText("\\documentclass{}")} if no class is specified. The document class macro is always moved to the very top of code blocks.
            Set empty to disable, default is ${selectableText(DEFAULT_SETTINGS.latexDocumentclass, true)}.`;
  new import_obsidian12.Setting(containerEl).setName("Adopt fonts").addDropdown((dropdown) => dropdown.addOptions({ "": "Disabled", system: "Use system default", obsidian: "Same as Obsidian" }).setValue(s.latexAdaptFont).onChange(async (value) => {
    s.latexAdaptFont = value;
    console.log(value ? `Now using ${value} fonts.` : "Now keeping default fonts.");
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `Inject fontspec ${selectableText("\\setmainfont{}")}, ${selectableText("\\setsansfont{}")}, ${selectableText("\\setmonofont{}")} to the top of code blocks. 
            Ignores fonts that can not be loaded by CSS. Skipped if PdfLaTeX is used. Default is ${DEFAULT_SETTINGS.latexAdaptFont === "" ? "disabled" : DEFAULT_SETTINGS.latexAdaptFont}.`;
  tab.makeInjectSetting(containerEl, "latex");
  containerEl.createEl("h4", { text: "LaTeX Compiler" });
  new import_obsidian12.Setting(containerEl).setName("Compiler path").addText((text) => text.setPlaceholder(`Example: ${DEFAULT_SETTINGS.latexCompilerPath}`).setValue(s.latexCompilerPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    s.latexCompilerPath = sanitized;
    console.log(`latex compiler path set to: ${sanitized}`);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `The path to your LuaLaTeX installation. Or use PdfLaTeX, XeLaTeX. ${linkTexDistributions}`;
  new import_obsidian12.Setting(containerEl.createDiv()).setName("Compiler arguments").addText((text) => text.setValue(s.latexCompilerArgs).onChange(async (value) => {
    const sanitized = value.trim();
    s.latexCompilerArgs = sanitized;
    console.log(`LaTeX args set to: ${sanitized}`);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `${selectableText("-shell-escape")} Allow LaTeX packages to execute external programs. 
            Default is ${selectableText(DEFAULT_SETTINGS.latexCompilerArgs)}.`;
  containerEl.createEl("h4", { text: "Post-processing" });
  new import_obsidian12.Setting(containerEl).setName("Crop to content").addToggle((toggle) => toggle.setValue(s.latexDoCrop).onChange(async (value) => {
    s.latexDoCrop = value;
    showSubSettings(requiresCrop, value);
    console.log(value ? "Now cropping pdf to content." : "Now keeping entire page.");
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `Crop PDF to visible content area with pdfcrop. Default is ${DEFAULT_SETTINGS.latexDoCrop ? "on" : "off"}.`;
  const requiresCrop = containerEl.createDiv();
  showSubSettings(requiresCrop, s.latexDoCrop);
  new import_obsidian12.Setting(requiresCrop.createDiv()).setName("Pdfcrop path").addText((text) => text.setPlaceholder(`Example: ${DEFAULT_SETTINGS.latexCropPath}`).setValue(s.latexCropPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    s.latexCropPath = sanitized;
    console.log(`latex compiler path set to: ${sanitized}`);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `The path to your pdfcrop installation. ${linkTexDistributions}`;
  new import_obsidian12.Setting(requiresCrop.createDiv()).setName("Pdfcrop arguments").addText((text) => text.setPlaceholder("Example: --margins 10").setValue(s.latexCropArgs).onChange(async (value) => {
    const sanitized = value.trim();
    s.latexCropArgs = sanitized;
    console.log(`LaTeX args set to: ${sanitized}`);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `${selectableText("--margins 10")} Whitespace in all directions. ${selectableText('--margins "left top right bottom"')} Specify margins. 
            Default is ${selectableText(DEFAULT_SETTINGS.latexCropArgs)}.`;
  new import_obsidian12.Setting(requiresCrop.createDiv()).setName("Disable page number").addToggle((toggle) => toggle.setValue(s.latexCropNoPagenum).onChange(async (value) => {
    s.latexCropNoPagenum = value;
    console.log(value ? "Now disabling page number for cropping." : "Now keeping page number for cropping.");
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `Inject ${selectableText("\\pagestyle{empty}")} to reduce the height of the content. 
            Default is ${DEFAULT_SETTINGS.latexCropNoPagenum ? "on" : "off"}.`;
  new import_obsidian12.Setting(requiresCrop.createDiv()).setName("Exclude standalone").addToggle((toggle) => toggle.setValue(s.latexCropNoStandalone).onChange(async (value) => {
    s.latexCropNoStandalone = value;
    console.log(value ? "Now excluding standalone for cropping." : "Now including standalone for cropping.");
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `Skip if document class ${selectableText("standalone")} is used, because it is already cropped. 
            Default is ${DEFAULT_SETTINGS.latexCropNoStandalone ? "on" : "off"}.`;
  new import_obsidian12.Setting(containerEl).setName("Save PDF").addToggle((toggle) => toggle.setValue(s.latexSavePdf).onChange(async (value) => {
    s.latexSavePdf = value;
    console.log(value ? "Now saving PDFs." : "Now discarding PDFs.");
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `Save the generated PDF as attachment. Default is ${DEFAULT_SETTINGS.latexSavePdf ? "on" : "off"}.`;
  new import_obsidian12.Setting(containerEl).setName("Convert to SVG").addDropdown((dropdown) => dropdown.addOptions({ "": "Disabled", poppler: "Poppler: draw fonts perfectly", inkscape: "Inkscape: keep text editable" }).setValue(s.latexSaveSvg).onChange(async (value) => {
    s.latexSaveSvg = value;
    showSubSettings(requiresSvg, value === "poppler");
    showSubSettings(requiresInkscape, value === "inkscape");
    console.log(value === "" ? "Now discarding SVGs." : `Svg converter set to: ${value}`);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `Convert the PDF to SVG and save it as attachment. Background is transparant. 
            Default is ${DEFAULT_SETTINGS.latexSaveSvg === "" ? "disabled" : DEFAULT_SETTINGS.latexSaveSvg}.`;
  const requiresSvg = containerEl.createDiv();
  showSubSettings(requiresSvg, s.latexSaveSvg === "poppler");
  new import_obsidian12.Setting(requiresSvg.createDiv()).setName("SVG converter path").addText((text) => text.setPlaceholder(`Example: ${DEFAULT_SETTINGS.latexSvgPath}`).setValue(s.latexSvgPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    s.latexSvgPath = sanitized;
    console.log(`Pdftocairo path for svg set to: ${sanitized}`);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `The path to your pdftocairo installation. ${linkTexDistributions}`;
  new import_obsidian12.Setting(requiresSvg.createDiv()).setName("SVG converter arguments").addText((text) => text.setValue(s.latexSvgArgs).onChange(async (value) => {
    const sanitized = value.trim();
    s.latexSvgArgs = sanitized;
    console.log(`Pdftocairo args for svg set to: ${sanitized}`);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `Default is ${selectableText(DEFAULT_SETTINGS.latexSvgArgs)}.`;
  const requiresInkscape = containerEl.createDiv();
  showSubSettings(requiresInkscape, s.latexSaveSvg === "inkscape");
  new import_obsidian12.Setting(requiresInkscape.createDiv()).setName("Inkscape path").addText((text) => text.setPlaceholder(`Example: ${DEFAULT_SETTINGS.latexInkscapePath}`).setValue(s.latexInkscapePath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    s.latexInkscapePath = sanitized;
    console.log(`latex compiler path set to: ${sanitized}`);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `The path to your Inkscape installation. ${linkInkscape}`;
  new import_obsidian12.Setting(requiresInkscape.createDiv()).setName("Inkscape arguments").addText((text) => text.setValue(s.latexInkscapeArgs).onChange(async (value) => {
    const sanitized = value.trim();
    s.latexInkscapeArgs = sanitized;
    console.log(`LaTeX args set to: ${sanitized}`);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `${selectableText("--pdf-font-strategy=draw-missing|substitute|keep|\u2026")} How fonts are parsed in the internal PDF importer. 
            Default is ${selectableText(DEFAULT_SETTINGS.latexInkscapeArgs)}.`;
  new import_obsidian12.Setting(containerEl).setName("Convert to PNG").addToggle((toggle) => toggle.setValue(s.latexSavePng).onChange(async (value) => {
    s.latexSavePng = value;
    showSubSettings(requiresPng, value);
    console.log(value ? "Now generation PNGs." : "Now discarding PNGs.");
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `Convert the PDF to PNG and save it as attachment. Default is ${DEFAULT_SETTINGS.latexSavePng ? "on" : "off"}.`;
  const requiresPng = containerEl.createDiv();
  showSubSettings(requiresPng, s.latexSavePng);
  new import_obsidian12.Setting(requiresPng.createDiv()).setName("PNG converter path").addText((text) => text.setPlaceholder(`Example: ${DEFAULT_SETTINGS.latexPngPath}`).setValue(s.latexPngPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    s.latexPngPath = sanitized;
    console.log(`Pdftocairo args for png set to: ${sanitized}`);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `The path to your pdftocairo installation. ${linkTexDistributions}`;
  new import_obsidian12.Setting(requiresPng.createDiv()).setName("PNG converter arguments").addText((text) => text.setValue(s.latexPngArgs).onChange(async (value) => {
    const sanitized = value.trim();
    s.latexPngArgs = sanitized;
    console.log(`Pdftocairo args for png set to: ${sanitized}`);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `${selectableText("-transp")} Transparent background. ${selectableText("-gray")} Grayscale. ${selectableText("-mono")} Monochrome. 
            ${selectableText("-f int")} Page to save. Default is ${selectableText(DEFAULT_SETTINGS.latexPngArgs)}.`;
  containerEl.createEl("h4", { text: "Appearance" });
  new import_obsidian12.Setting(containerEl).setName("Output embeddings").addToggle((toggle) => toggle.setValue(s.latexOutputEmbeddings).onChange(async (value) => {
    s.latexOutputEmbeddings = value;
    console.log(value ? "Now embedding figures." : `Now linking figures.`);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `When running a LaTeX code block, show embeddings of saved figures. Default is ${DEFAULT_SETTINGS.latexOutputEmbeddings ? "on" : "off"}.`;
  new import_obsidian12.Setting(containerEl).setName("Center SVGs").addToggle((toggle) => toggle.setValue(s.latexCenterFigures).onChange(async (value) => {
    s.latexCenterFigures = value;
    console.log(value ? "Now centering SVGs." : `Now left aligning SVGs.`);
    updateBodyClass("center-latex-figures", value);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `Horizontally align SVGs whose filename starts with ${selectableText("figure")}. 
            Default is ${DEFAULT_SETTINGS.latexCenterFigures ? "on" : "off"}.`;
  new import_obsidian12.Setting(containerEl).setName("Invert SVGs in dark mode").addToggle((toggle) => toggle.setValue(s.latexInvertFigures).onChange(async (value) => {
    s.latexInvertFigures = value;
    console.log(value ? "Now inverting SVGs." : `Now not inverting SVGs.`);
    updateBodyClass("invert-latex-figures", value);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `If dark mode is enabled, invert the color of SVGs whose filename starts with ${selectableText("figure")}. 
            Default is ${DEFAULT_SETTINGS.latexInvertFigures ? "on" : "off"}.`;
  containerEl.createEl("h4", { text: "Troubleshooting" });
  const maxFigures = containerEl.createDiv();
  new import_obsidian12.Setting(maxFigures).setName("Keep last n unnamed figures").addText((text) => text.setPlaceholder("unlimited").setValue(s.latexMaxFigures === Infinity ? "" : `${s.latexMaxFigures}`).onChange(async (value) => {
    const numValue = value === "" ? Infinity : Number(value);
    const isValid = isIntegerOrInfinity(numValue) && numValue > 0;
    updateTextColor(maxFigures, isValid);
    if (isValid) {
      s.latexMaxFigures = numValue;
      console.log(`max number of figures set to: ${numValue}`);
      await tab.plugin.saveSettings();
    }
  })).descEl.innerHTML = `Generated attachments receive an increasing index. To prevent too many files from piling up, jump back to zero after <i>n</i> executions. 
            Set empty for unlimited. Default is ${selectableText(DEFAULT_SETTINGS.latexMaxFigures.toString(), true)}.`;
  maxFigures.querySelector("input").type = "number";
  const captureFigureName = containerEl.createDiv();
  new import_obsidian12.Setting(captureFigureName).setName("Capture figure name").addText((text) => text.setPlaceholder("/regex/").setValue(`${s.latexFigureTitlePattern}`).onChange(async (value) => {
    const pattern = parse(value);
    const isValid = pattern != void 0;
    updateTextColor(captureFigureName, isValid);
    if (isValid) {
      s.latexFigureTitlePattern = pattern.toString();
      console.log("capture figure name pattern set to: " + pattern);
      await tab.plugin.saveSettings();
    }
  })).descEl.innerHTML = `Search LaTeX code block for ${selectableText("\\title{\u2026}")} to retrieve the figure name: 
            ${selectableText(/[^\n][^%`]*/.source)} Ignore comments after % symbol. ${selectableText(/(?<name>.*?)/.source)} Capture group for figure name.
            Default is ${selectableText(DEFAULT_SETTINGS.latexFigureTitlePattern)}.`;
  new import_obsidian12.Setting(containerEl).setName("Filter output").addToggle((toggle) => toggle.setValue(s.latexDoFilter).onChange(async (value) => {
    s.latexDoFilter = value;
    showSubSettings(requiresTexfot, value);
    console.log(value ? "Now filtering latex stdout with texfot." : "Now showing full latex stdout.");
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `Filtering stdout to relevant messages with texfot. Default is ${DEFAULT_SETTINGS.latexKeepLog ? "on" : "off"}.`;
  const requiresTexfot = containerEl.createDiv();
  showSubSettings(requiresTexfot, s.latexDoFilter);
  new import_obsidian12.Setting(requiresTexfot.createDiv()).setName("Texfot path").addText((text) => text.setPlaceholder(`Example: ${DEFAULT_SETTINGS.latexTexfotPath}`).setValue(s.latexTexfotPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    s.latexTexfotPath = sanitized;
    console.log(`texfot path set to: ${sanitized}`);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `The path to your texfot installation. ${linkTexDistributions}`;
  new import_obsidian12.Setting(requiresTexfot.createDiv()).setName("Texfot arguments").addText((text) => text.setPlaceholder(`Example: ${DEFAULT_SETTINGS.latexTexfotArgs}`).setValue(s.latexTexfotArgs).onChange(async (value) => {
    const sanitized = value.trim();
    s.latexTexfotArgs = sanitized;
    console.log(`texfot arguments set to: ${sanitized}`);
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `${selectableText("--accept regex")}, ${selectableText("--ignore regex")} Filter lines in the TeX output matching RegExp. 
            Default is ${selectableText(DEFAULT_SETTINGS.latexTexfotArgs)}.`;
  new import_obsidian12.Setting(containerEl).setName("Keep log").addToggle((toggle) => toggle.setValue(s.latexKeepLog).onChange(async (value) => {
    s.latexKeepLog = value;
    console.log(value ? "Now preserving latex build folder." : "Now clearing latex build folder.");
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `Prevent deletion of temporary build folder. Default is ${DEFAULT_SETTINGS.latexKeepLog ? "on" : "off"}.`;
  new import_obsidian12.Setting(containerEl).setName("Run subprocesses in shell").addToggle((toggle) => toggle.setValue(s.latexSubprocessesUseShell).onChange(async (value) => {
    s.latexSubprocessesUseShell = value;
    console.log(value ? "Now running subprocesses in shell." : "Now running subprocesses directly.");
    await tab.plugin.saveSettings();
  })).descEl.innerHTML = `Run compilation and conversion tools in shell environment. Default is ${DEFAULT_SETTINGS.latexSubprocessesUseShell ? "on" : "off"}.`;
};
function showSubSettings(settingsDiv, doShow) {
  settingsDiv.setAttr("style", doShow ? "display: block" : "display: none");
}
function updateTextColor(containerEl, isValid) {
  const inputEl = containerEl.querySelector("input");
  inputEl.style.color = isValid ? "" : "red";
}
function isIntegerOrInfinity(value) {
  return Number.isInteger(value) || value === Infinity;
}
function selectableText(text, noMonospace) {
  if (noMonospace)
    return `<span class='selectable-description-text'>${text}</span>`;
  const escapedAngleBrackets = text.replace(/</g, "&lt;").replace(/>/g, "&gt;");
  return `<span><code class='selectable-description-text'>${escapedAngleBrackets}</code></span>`;
}

// src/settings/per-lang/makeLeanSettings.ts
var import_obsidian13 = require("obsidian");
var makeLeanSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Lean Settings" });
  new import_obsidian13.Setting(containerEl).setName("lean path").addText((text) => text.setValue(tab.plugin.settings.leanPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.leanPath = sanitized;
    console.log("lean path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian13.Setting(containerEl).setName("Lean arguments").addText((text) => text.setValue(tab.plugin.settings.leanArgs).onChange(async (value) => {
    tab.plugin.settings.leanArgs = value;
    console.log("Lean args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "lean");
};

// src/settings/per-lang/makeLuaSettings.ts
var import_obsidian14 = require("obsidian");
var makeLuaSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Lua Settings" });
  new import_obsidian14.Setting(containerEl).setName("lua path").addText((text) => text.setValue(tab.plugin.settings.luaPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.luaPath = sanitized;
    console.log("lua path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian14.Setting(containerEl).setName("Lua arguments").addText((text) => text.setValue(tab.plugin.settings.luaArgs).onChange(async (value) => {
    tab.plugin.settings.luaArgs = value;
    console.log("Lua args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "lua");
};

// src/settings/per-lang/makeDartSettings.ts
var import_obsidian15 = require("obsidian");
var makeDartSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Dart Settings" });
  new import_obsidian15.Setting(containerEl).setName("dart path").addText((text) => text.setValue(tab.plugin.settings.dartPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.dartPath = sanitized;
    console.log("dart path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian15.Setting(containerEl).setName("Dart arguments").addText((text) => text.setValue(tab.plugin.settings.dartArgs).onChange(async (value) => {
    tab.plugin.settings.dartArgs = value;
    console.log("Dart args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "dart");
};

// src/settings/per-lang/makeMathematicaSettings.ts
var import_obsidian16 = require("obsidian");
var makeMathematicaSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Wolfram Mathematica Settings" });
  new import_obsidian16.Setting(containerEl).setName("Mathematica path").setDesc("The path to your Mathematica installation.").addText((text) => text.setValue(tab.plugin.settings.mathematicaPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.mathematicaPath = sanitized;
    console.log("Mathematica path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian16.Setting(containerEl).setName("Mathematica arguments").addText((text) => text.setValue(tab.plugin.settings.mathematicaArgs).onChange(async (value) => {
    tab.plugin.settings.mathematicaArgs = value;
    console.log("Mathematica args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "mathematica");
};

// src/settings/per-lang/makePhpSettings.ts
var import_obsidian17 = require("obsidian");
var makePhpSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "PHP Settings" });
  new import_obsidian17.Setting(containerEl).setName("php path").setDesc("Path to your php installation").addText((text) => text.setValue(tab.plugin.settings.phpPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.phpPath = sanitized;
    console.log("php path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian17.Setting(containerEl).setName("php arguments").addText((text) => text.setValue(tab.plugin.settings.phpArgs).onChange(async (value) => {
    tab.plugin.settings.phpArgs = value;
    console.log("php args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "php");
};

// src/settings/per-lang/makePowershellSettings.ts
var import_obsidian18 = require("obsidian");
var makePowershellSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Powershell Settings" });
  new import_obsidian18.Setting(containerEl).setName("Powershell path").setDesc("The path to Powershell.").addText((text) => text.setValue(tab.plugin.settings.powershellPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.powershellPath = sanitized;
    console.log("Powershell path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian18.Setting(containerEl).setName("Powershell arguments").addText((text) => text.setValue(tab.plugin.settings.powershellArgs).onChange(async (value) => {
    tab.plugin.settings.powershellArgs = value;
    console.log("Powershell args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian18.Setting(containerEl).setName("Powershell file extension").setDesc("Changes the file extension for generated shell scripts. This is useful if you don't want to use PowerShell.").addText((text) => text.setValue(tab.plugin.settings.powershellFileExtension).onChange(async (value) => {
    tab.plugin.settings.powershellFileExtension = value;
    console.log("Powershell file extension set to: " + value);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian18.Setting(containerEl).setName("PowerShell script encoding").setDesc('Windows still uses windows-1252 as default encoding on most systems for legacy reasons. If you change your encodings systemwide to UTF-8, you can change this setting to UTF-8 as well. Only use one of the following encodings: "ascii", "utf8", "utf-8", "utf16le", "ucs2", "ucs-2", "base64", "latin1", "binary", "hex" (default: "latin1")').addText((text) => text.setValue(tab.plugin.settings.powershellEncoding).onChange(async (value) => {
    value = value.replace(/["'`´]/, "").trim().toLowerCase();
    if (["ascii", "utf8", "utf-8", "utf16le", "ucs2", "ucs-2", "base64", "latin1", "binary", "hex"].includes(value)) {
      tab.plugin.settings.powershellEncoding = value;
      console.log("Powershell file extension set to: " + value);
      await tab.plugin.saveSettings();
    } else {
      console.error("Invalid encoding. " + value + 'Please use one of the following encodings: "ascii", "utf8", "utf-8", "utf16le", "ucs2", "ucs-2", "base64", "latin1", "binary", "hex"');
    }
  }));
  tab.makeInjectSetting(containerEl, "powershell");
};

// src/settings/per-lang/makePrologSettings.ts
var import_obsidian19 = require("obsidian");
var makePrologSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Prolog Settings" });
  new import_obsidian19.Setting(containerEl).setName("Prolog Answer Limit").setDesc("Maximal number of answers to be returned by the Prolog engine. tab is to prevent creating too huge texts in the notebook.").addText((text) => text.setValue("" + tab.plugin.settings.maxPrologAnswers).onChange(async (value) => {
    if (Number(value) * 1e3) {
      console.log("Prolog answer limit set to: " + value);
      tab.plugin.settings.maxPrologAnswers = Number(value);
    }
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "prolog");
};

// src/settings/per-lang/makePythonSettings.ts
var import_obsidian20 = require("obsidian");
var makePythonSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Python Settings" });
  new import_obsidian20.Setting(containerEl).setName("Embed Python Plots").addToggle((toggle) => toggle.setValue(tab.plugin.settings.pythonEmbedPlots).onChange(async (value) => {
    tab.plugin.settings.pythonEmbedPlots = value;
    console.log(value ? "Embedding Plots into Notes." : "Not embedding Plots into Notes.");
    await tab.plugin.saveSettings();
  }));
  new import_obsidian20.Setting(containerEl).setName("Python path").setDesc("The path to your Python installation.").addText((text) => text.setValue(tab.plugin.settings.pythonPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.pythonPath = sanitized;
    console.log("Python path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian20.Setting(containerEl).setName("Python arguments").addText((text) => text.setValue(tab.plugin.settings.pythonArgs).onChange(async (value) => {
    tab.plugin.settings.pythonArgs = value;
    console.log("Python args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian20.Setting(containerEl).setName("Run Python blocks in Notebook Mode").addToggle((toggle) => toggle.setValue(tab.plugin.settings.pythonInteractive).onChange(async (value) => {
    tab.plugin.settings.pythonInteractive = value;
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "python");
};

// src/settings/per-lang/makeRSettings.ts
var import_obsidian21 = require("obsidian");
var makeRSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "R Settings" });
  new import_obsidian21.Setting(containerEl).setName("Embed R Plots created via `plot()` into Notes").addToggle((toggle) => toggle.setValue(tab.plugin.settings.REmbedPlots).onChange(async (value) => {
    tab.plugin.settings.REmbedPlots = value;
    console.log(value ? "Embedding R Plots into Notes." : "Not embedding R Plots into Notes.");
    await tab.plugin.saveSettings();
  }));
  new import_obsidian21.Setting(containerEl).setName("Rscript path").setDesc("The path to your Rscript installation. Ensure you provide the Rscript binary instead of the ordinary R binary.").addText((text) => text.setValue(tab.plugin.settings.RPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.RPath = sanitized;
    console.log("R path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian21.Setting(containerEl).setName("R arguments").addText((text) => text.setValue(tab.plugin.settings.RArgs).onChange(async (value) => {
    tab.plugin.settings.RArgs = value;
    console.log("R args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian21.Setting(containerEl).setName("Run R blocks in Notebook Mode").addToggle((toggle) => toggle.setValue(tab.plugin.settings.rInteractive).onChange(async (value) => {
    tab.plugin.settings.rInteractive = value;
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "r");
};

// src/settings/per-lang/makeRubySettings.ts
var import_obsidian22 = require("obsidian");
var makeRubySettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Ruby Settings" });
  new import_obsidian22.Setting(containerEl).setName("ruby path").setDesc("Path to your ruby installation").addText((text) => text.setValue(tab.plugin.settings.rubyPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.rubyPath = sanitized;
    console.log("ruby path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian22.Setting(containerEl).setName("ruby arguments").addText((text) => text.setValue(tab.plugin.settings.rubyArgs).onChange(async (value) => {
    tab.plugin.settings.rubyArgs = value;
    console.log("ruby args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "ruby");
};

// src/settings/per-lang/makeRustSettings.ts
var import_obsidian23 = require("obsidian");
var makeRustSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Rust Settings" });
  new import_obsidian23.Setting(containerEl).setName("Cargo Path").setDesc("The path to your Cargo installation.").addText((text) => text.setValue(tab.plugin.settings.cargoPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.cargoPath = sanitized;
    console.log("Cargo path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "rust");
};

// src/settings/per-lang/makeScalaSettings.ts
var import_obsidian24 = require("obsidian");
var makeScalaSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Scala Settings" });
  new import_obsidian24.Setting(containerEl).setName("scala path").setDesc("Path to your scala installation").addText((text) => text.setValue(tab.plugin.settings.scalaPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.scalaPath = sanitized;
    console.log("scala path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian24.Setting(containerEl).setName("Scala arguments").addText((text) => text.setValue(tab.plugin.settings.scalaArgs).onChange(async (value) => {
    tab.plugin.settings.scalaArgs = value;
    console.log("Scala args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "scala");
};

// src/settings/per-lang/makeRacketSettings.ts
var import_obsidian25 = require("obsidian");
var makeRacketSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Racket Settings" });
  new import_obsidian25.Setting(containerEl).setName("racket path").setDesc("Path to your racket installation").addText((text) => text.setValue(tab.plugin.settings.racketPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.racketPath = sanitized;
    console.log("racket path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian25.Setting(containerEl).setName("Racket arguments").addText((text) => text.setValue(tab.plugin.settings.racketArgs).onChange(async (value) => {
    tab.plugin.settings.racketArgs = value;
    console.log("Racket args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "racket");
};

// src/settings/per-lang/makeShellSettings.ts
var import_obsidian26 = require("obsidian");
var makeShellSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Shell Settings" });
  new import_obsidian26.Setting(containerEl).setName("Shell path").setDesc("The path to shell. Default is Bash but you can use any shell you want, e.g. bash, zsh, fish, ...").addText((text) => text.setValue(tab.plugin.settings.shellPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.shellPath = sanitized;
    console.log("Shell path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian26.Setting(containerEl).setName("Shell arguments").addText((text) => text.setValue(tab.plugin.settings.shellArgs).onChange(async (value) => {
    tab.plugin.settings.shellArgs = value;
    console.log("Shell args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian26.Setting(containerEl).setName("Shell file extension").setDesc("Changes the file extension for generated shell scripts. This is useful if you want to use a shell other than bash.").addText((text) => text.setValue(tab.plugin.settings.shellFileExtension).onChange(async (value) => {
    tab.plugin.settings.shellFileExtension = value;
    console.log("Shell file extension set to: " + value);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian26.Setting(containerEl).setName("Shell WSL mode").setDesc('Run the shell script in Windows Subsystem for Linux. This option is used if the global "WSL Mode" is disabled.').addToggle(
    (toggle) => toggle.setValue(tab.plugin.settings.shellWSLMode).onChange(async (value) => {
      tab.plugin.settings.shellWSLMode = value;
      await tab.plugin.saveSettings();
    })
  );
  tab.makeInjectSetting(containerEl, "shell");
};

// src/settings/per-lang/makeBatchSettings.ts
var import_obsidian27 = require("obsidian");
var makeBatchSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Batch Settings" });
  new import_obsidian27.Setting(containerEl).setName("Batch path").setDesc("The path to the terminal. Default is command prompt.").addText((text) => text.setValue(tab.plugin.settings.batchPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.batchPath = sanitized;
    console.log("Batch path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian27.Setting(containerEl).setName("Batch arguments").addText((text) => text.setValue(tab.plugin.settings.batchArgs).onChange(async (value) => {
    tab.plugin.settings.batchArgs = value;
    console.log("Batch args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian27.Setting(containerEl).setName("Batch file extension").setDesc("Changes the file extension for generated batch scripts. Default is .bat").addText((text) => text.setValue(tab.plugin.settings.batchFileExtension).onChange(async (value) => {
    tab.plugin.settings.batchFileExtension = value;
    console.log("Batch file extension set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "batch");
};

// src/settings/per-lang/makeTsSettings.ts
var import_obsidian28 = require("obsidian");
var makeTsSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "TypeScript Settings" });
  new import_obsidian28.Setting(containerEl).setName("ts-node path").addText((text) => text.setValue(tab.plugin.settings.tsPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.tsPath = sanitized;
    console.log("ts-node path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian28.Setting(containerEl).setName("TypeScript arguments").addText((text) => text.setValue(tab.plugin.settings.tsArgs).onChange(async (value) => {
    tab.plugin.settings.tsArgs = value;
    console.log("TypeScript args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "ts");
};

// src/settings/per-lang/makeSQLSettings.ts
var import_obsidian29 = require("obsidian");
var makeSQLSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "SQL Settings" });
  new import_obsidian29.Setting(containerEl).setName("SQL path").setDesc("Path to your SQL installation. You can select the SQL dialect you prefer but you need to set the right arguments by yourself.").addText((text) => text.setValue(tab.plugin.settings.sqlPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.sqlPath = sanitized;
    console.log("ruby path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian29.Setting(containerEl).setName("SQL arguments").setDesc("Set the right arguments for your database.").addText((text) => text.setValue(tab.plugin.settings.sqlArgs).onChange(async (value) => {
    tab.plugin.settings.sqlArgs = value;
    console.log("SQL args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "sql");
};

// src/settings/per-lang/makeOctaveSettings.ts
var import_obsidian30 = require("obsidian");
var makeOctaveSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Octave Settings" });
  new import_obsidian30.Setting(containerEl).setName("Octave path").setDesc("The path to your Octave installation.").addText((text) => text.setValue(tab.plugin.settings.octavePath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.octavePath = sanitized;
    console.log("Octave path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian30.Setting(containerEl).setName("Octave arguments").addText((text) => text.setValue(tab.plugin.settings.octaveArgs).onChange(async (value) => {
    tab.plugin.settings.octaveArgs = value;
    console.log("Octave args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "octave");
};

// src/settings/per-lang/makeMaximaSettings.ts
var import_obsidian31 = require("obsidian");
var makeMaximaSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Maxima Settings" });
  new import_obsidian31.Setting(containerEl).setName("Maxima path").setDesc("The path to your Maxima installation.").addText((text) => text.setValue(tab.plugin.settings.maximaPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.maximaPath = sanitized;
    console.log("Maxima path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian31.Setting(containerEl).setName("Maxima arguments").addText((text) => text.setValue(tab.plugin.settings.maximaArgs).onChange(async (value) => {
    tab.plugin.settings.maximaArgs = value;
    console.log("Maxima args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "maxima");
};

// src/settings/per-lang/makeApplescriptSettings.ts
var import_obsidian32 = require("obsidian");
var makeApplescriptSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Applescript Settings" });
  new import_obsidian32.Setting(containerEl).setName("Osascript path").setDesc("The path to your osascript installation (only available on MacOS).").addText((text) => text.setValue(tab.plugin.settings.applescriptPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.applescriptPath = sanitized;
    console.log("Applescript path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian32.Setting(containerEl).setName("Applescript arguments").addText((text) => text.setValue(tab.plugin.settings.applescriptArgs).onChange(async (value) => {
    tab.plugin.settings.applescriptArgs = value;
    console.log("Applescript args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "applescript");
};

// src/settings/per-lang/makeZigSettings.ts
var import_obsidian33 = require("obsidian");
var makeZigSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Zig Settings" });
  new import_obsidian33.Setting(containerEl).setName("zig path").setDesc("Path to your zig installation").addText((text) => text.setValue(tab.plugin.settings.zigPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.zigPath = sanitized;
    console.log("zig path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian33.Setting(containerEl).setName("zig arguments").addText((text) => text.setValue(tab.plugin.settings.zigArgs).onChange(async (value) => {
    tab.plugin.settings.zigArgs = value;
    console.log("zig args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "zig");
};

// src/settings/per-lang/makeOCamlSettings.ts
var import_obsidian34 = require("obsidian");
var makeOCamlSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "OCaml Settings" });
  new import_obsidian34.Setting(containerEl).setName("ocaml path").setDesc("Path to your ocaml installation").addText((text) => text.setValue(tab.plugin.settings.ocamlPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.ocamlPath = sanitized;
    console.log("ocaml path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian34.Setting(containerEl).setName("ocaml arguments").addText((text) => text.setValue(tab.plugin.settings.ocamlArgs).onChange(async (value) => {
    tab.plugin.settings.ocamlArgs = value;
    console.log("ocaml args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "ocaml");
};

// src/settings/per-lang/makeSwiftSettings.ts
var import_obsidian35 = require("obsidian");
var makeSwiftSettings_default = (tab, containerEl) => {
  containerEl.createEl("h3", { text: "Swift Settings" });
  new import_obsidian35.Setting(containerEl).setName("Swift path").setDesc("The path to your Swift installation.").addText((text) => text.setValue(tab.plugin.settings.swiftPath).onChange(async (value) => {
    const sanitized = tab.sanitizePath(value);
    tab.plugin.settings.swiftPath = sanitized;
    console.log("Swift path set to: " + sanitized);
    await tab.plugin.saveSettings();
  }));
  new import_obsidian35.Setting(containerEl).setName("Swift arguments").addText((text) => text.setValue(tab.plugin.settings.swiftArgs).onChange(async (value) => {
    tab.plugin.settings.swiftArgs = value;
    console.log("Swift args set to: " + value);
    await tab.plugin.saveSettings();
  }));
  tab.makeInjectSetting(containerEl, "swift");
};

// src/settings/SettingsTab.ts
var SettingsTab = class extends import_obsidian36.PluginSettingTab {
  constructor(app, plugin) {
    super(app, plugin);
    this.plugin = plugin;
    this.languageContainers = {};
  }
  display() {
    const { containerEl } = this;
    containerEl.empty();
    containerEl.createEl("h2", { text: "Settings for the Code Execution Plugin." });
    containerEl.createEl("h3", { text: "General Settings" });
    new import_obsidian36.Setting(containerEl).setName("Timeout (in seconds)").setDesc("The time after which a program gets shut down automatically. This is to prevent infinite loops. ").addText((text) => text.setValue("" + this.plugin.settings.timeout / 1e3).onChange(async (value) => {
      if (Number(value) * 1e3) {
        console.log("Timeout set to: " + value);
        this.plugin.settings.timeout = Number(value) * 1e3;
      }
      await this.plugin.saveSettings();
    }));
    new import_obsidian36.Setting(containerEl).setName("Allow Input").setDesc("Whether or not to include a stdin input box when running blocks. In order to apply changes to this, Obsidian must be refreshed. ").addToggle((text) => text.setValue(this.plugin.settings.allowInput).onChange(async (value) => {
      console.log("Allow Input set to: " + value);
      this.plugin.settings.allowInput = value;
      await this.plugin.saveSettings();
    }));
    if (process.platform === "win32") {
      new import_obsidian36.Setting(containerEl).setName("WSL Mode").setDesc("Whether or not to run code in the Windows Subsystem for Linux. If you don't have WSL installed, don't turn this on!").addToggle((text) => text.setValue(this.plugin.settings.wslMode).onChange(async (value) => {
        console.log("WSL Mode set to: " + value);
        this.plugin.settings.wslMode = value;
        await this.plugin.saveSettings();
      }));
    }
    new import_obsidian36.Setting(containerEl).setName("[Experimental] Persistent Output").setDesc("If enabled, the output of the code block is written into the markdown file. This feature is experimental and may not work as expected.").addToggle((text) => text.setValue(this.plugin.settings.persistentOuput).onChange(async (value) => {
      console.log("Allow Input set to: " + value);
      this.plugin.settings.persistentOuput = value;
      await this.plugin.saveSettings();
    }));
    containerEl.createEl("hr");
    new import_obsidian36.Setting(containerEl).setName("Language-Specific Settings").setDesc("Pick a language to edit its language-specific settings").addDropdown(
      (dropdown) => dropdown.addOptions(Object.fromEntries(
        canonicalLanguages.map((lang) => [lang, DISPLAY_NAMES[lang]])
      )).setValue(this.plugin.settings.lastOpenLanguageTab || canonicalLanguages[0]).onChange(async (value) => {
        this.focusContainer(value);
        this.plugin.settings.lastOpenLanguageTab = value;
        await this.plugin.saveSettings();
      })
    ).settingEl.style.borderTop = "0";
    makeJsSettings_default(this, this.makeContainerFor("js"));
    makeTsSettings_default(this, this.makeContainerFor("ts"));
    makeLeanSettings_default(this, this.makeContainerFor("lean"));
    makeLuaSettings_default(this, this.makeContainerFor("lua"));
    makeDartSettings_default(this, this.makeContainerFor("dart"));
    makeCsSettings_default(this, this.makeContainerFor("cs"));
    makeJavaSettings_default(this, this.makeContainerFor("java"));
    makePythonSettings_default(this, this.makeContainerFor("python"));
    makeGoSettings_default(this, this.makeContainerFor("go"));
    makeRustSettings_default(this, this.makeContainerFor("rust"));
    makeCppSettings_default(this, this.makeContainerFor("cpp"));
    makeCSettings_default(this, this.makeContainerFor("c"));
    makeBatchSettings_default(this, this.makeContainerFor("batch"));
    makeShellSettings_default(this, this.makeContainerFor("shell"));
    makePowershellSettings_default(this, this.makeContainerFor("powershell"));
    makePrologSettings_default(this, this.makeContainerFor("prolog"));
    makeGroovySettings_default(this, this.makeContainerFor("groovy"));
    makeRSettings_default(this, this.makeContainerFor("r"));
    makeKotlinSettings_default(this, this.makeContainerFor("kotlin"));
    makeMathematicaSettings_default(this, this.makeContainerFor("mathematica"));
    makeHaskellSettings_default(this, this.makeContainerFor("haskell"));
    makeScalaSettings_default(this, this.makeContainerFor("scala"));
    makeSwiftSettings_default(this, this.makeContainerFor("swift"));
    makeRacketSettings_default(this, this.makeContainerFor("racket"));
    makeFSharpSettings_default(this, this.makeContainerFor("fsharp"));
    makeRubySettings_default(this, this.makeContainerFor("ruby"));
    makeSQLSettings_default(this, this.makeContainerFor("sql"));
    makeOctaveSettings_default(this, this.makeContainerFor("octave"));
    makeMaximaSettings_default(this, this.makeContainerFor("maxima"));
    makeApplescriptSettings_default(this, this.makeContainerFor("applescript"));
    makeZigSettings_default(this, this.makeContainerFor("zig"));
    makeOCamlSettings_default(this, this.makeContainerFor("ocaml"));
    makePhpSettings_default(this, this.makeContainerFor("php"));
    makeLatexSettings_default(this, this.makeContainerFor("latex"));
    this.focusContainer(this.plugin.settings.lastOpenLanguageTab || canonicalLanguages[0]);
  }
  makeContainerFor(language) {
    const container = this.containerEl.createDiv();
    container.style.display = "none";
    this.languageContainers[language] = container;
    return container;
  }
  focusContainer(language) {
    if (this.activeLanguageContainer)
      this.activeLanguageContainer.style.display = "none";
    if (language in this.languageContainers) {
      this.activeLanguageContainer = this.languageContainers[language];
      this.activeLanguageContainer.style.display = "block";
    }
  }
  sanitizePath(path6) {
    path6 = path6.replace(/\\/g, "/");
    path6 = path6.replace(/['"`]/, "");
    path6 = path6.trim();
    return path6;
  }
  makeInjectSetting(containerEl, language) {
    const languageAlt = DISPLAY_NAMES[language];
    new import_obsidian36.Setting(containerEl).setName(`Inject ${languageAlt} code`).setDesc(`Code to add to the top of every ${languageAlt} code block before running.`).setClass("settings-code-input-box").addTextArea((textarea) => {
      const val = this.plugin.settings[`${language}Inject`];
      return textarea.setValue(val).onChange(async (value) => {
        this.plugin.settings[`${language}Inject`] = value;
        console.log(`${language} inject set to ${value}`);
        await this.plugin.saveSettings();
      });
    });
  }
};

// src/ExecutorContainer.ts
var import_events = require("events");

// src/executors/ReplExecutor.ts
var import_child_process2 = require("child_process");
var import_obsidian38 = require("obsidian");

// src/executors/Executor.ts
var import_obsidian37 = require("obsidian");
var os = __toESM(require("os"));
var path2 = __toESM(require("path"));
var import_stream = require("stream");
var Executor = class extends import_stream.EventEmitter {
  constructor(file, language) {
    super();
    this.tempFileId = void 0;
    this.file = file;
    this.language = language;
  }
  notifyError(cmd, cmdArgs, tempFileName, err, outputter, label = "Error while executing code") {
    const errorMSG = `Error while executing ${cmd} ${cmdArgs} ${tempFileName}: ${err}`;
    console.error(errorMSG);
    if (outputter)
      outputter.writeErr(errorMSG);
    new import_obsidian37.Notice(label);
  }
  getTempFile(ext) {
    if (this.tempFileId === void 0)
      this.tempFileId = Date.now().toString();
    return path2.join(os.tmpdir(), `temp_${this.tempFileId}.${ext}`);
  }
};

// src/executors/AsyncExecutor.ts
var AsyncExecutor = class extends Executor {
  constructor() {
    super(...arguments);
    this.runningTask = Promise.resolve();
  }
  async addJobToQueue(promiseCallback) {
    const previousJob = this.runningTask;
    this.runningTask = new Promise((resolve, reject) => {
      previousJob.finally(async () => {
        try {
          await new Promise((innerResolve, innerReject) => {
            this.once("close", () => innerResolve(void 0));
            promiseCallback(innerResolve, innerReject);
          });
          resolve();
        } catch (e) {
          reject(e);
        }
      });
    });
    return this.runningTask;
  }
};

// src/executors/killWithChildren.ts
var import_child_process = require("child_process");
var killWithChildren_default = (pid) => {
  if (process.platform === "win32") {
    (0, import_child_process.execSync)(`taskkill /pid ${pid} /T /F`);
  } else {
    try {
      (0, import_child_process.execSync)(`pkill -P ${pid}`);
    } catch (err) {
      if (err.status !== 1)
        throw err;
    }
    process.kill(pid);
  }
};

// src/executors/ReplExecutor.ts
var ReplExecutor = class extends AsyncExecutor {
  constructor(settings, path6, args, file, language) {
    var _a;
    super(file, language);
    this.settings = settings;
    if (this.settings.wslMode) {
      args.unshift("-e", path6);
      path6 = "wsl";
    }
    if (path6.includes("%USERNAME%") && ((_a = process == null ? void 0 : process.env) == null ? void 0 : _a.USERNAME))
      path6 = path6.replace("%USERNAME%", process.env.USERNAME);
    this.process = (0, import_child_process2.spawn)(path6, args, { env: process.env });
    this.process.on("close", () => {
      this.emit("close");
      new import_obsidian38.Notice("Runtime exited");
      this.process = null;
    });
    this.process.on("error", (err) => {
      this.notifyError(settings.pythonPath, args.join(" "), "", err, void 0, "Error launching process: " + err);
      this.stop();
    });
    this.setup().then(() => {
    });
  }
  run(code, outputter, cmd, cmdArgs, ext) {
    outputter.queueBlock();
    return this.addJobToQueue((resolve, _reject) => {
      if (this.process === null)
        return resolve();
      const finishSigil = `SIGIL_BLOCK_DONE_${Math.random()}_${Date.now()}_${code.length}`;
      outputter.startBlock();
      const wrappedCode = this.wrapCode(code, finishSigil);
      this.process.stdin.write(wrappedCode);
      outputter.clear();
      outputter.on("data", (data) => {
        this.process.stdin.write(data);
      });
      const writeToStdout = (data) => {
        let str = data.toString();
        if (str.endsWith(finishSigil)) {
          str = str.substring(0, str.length - finishSigil.length);
          this.process.stdout.removeListener("data", writeToStdout);
          this.process.stderr.removeListener("data", writeToStderr);
          this.process.removeListener("close", resolve);
          outputter.write(str);
          resolve();
        } else {
          outputter.write(str);
        }
      };
      const writeToStderr = (data) => {
        outputter.writeErr(
          this.removePrompts(data.toString(), "stderr")
        );
      };
      this.process.on("close", resolve);
      this.process.stdout.on("data", writeToStdout);
      this.process.stderr.on("data", writeToStderr);
    });
  }
  stop() {
    return new Promise((resolve, _reject) => {
      this.process.on("close", () => {
        resolve();
      });
      killWithChildren_default(this.process.pid);
      this.process = null;
    });
  }
};

// src/executors/NodeJSExecutor.ts
var NodeJSExecutor = class extends ReplExecutor {
  constructor(settings, file) {
    const args = settings.nodeArgs ? settings.nodeArgs.split(" ") : [];
    args.unshift(`-e`, `require("repl").start({prompt: "", preview: false, ignoreUndefined: true}).on("exit", ()=>process.exit())`);
    super(settings, settings.nodePath, args, file, "js");
  }
  async setup() {
    this.process.stdin.write("\n");
  }
  wrapCode(code, finishSigil) {
    return `try { eval(${JSON.stringify(code)}); }catch(e) { console.error(e); }finally { process.stdout.write(${JSON.stringify(finishSigil)}); }
`;
  }
  removePrompts(output, source) {
    return output;
  }
};

// src/executors/NonInteractiveCodeExecutor.ts
var import_obsidian39 = require("obsidian");
var fs = __toESM(require("fs"));
var child_process = __toESM(require("child_process"));

// src/transforms/windowsPathToWsl.ts
var import_posix = require("path/posix");
var import_path = require("path");
var windowsPathToWsl_default = (windowsPath) => {
  const driveLetter = windowsPath[0].toLowerCase();
  const posixyPath = windowsPath.replace(/^[^:]*:/, "").split(import_path.sep).join("/");
  return (0, import_posix.join)("/mnt/", driveLetter, posixyPath);
};

// src/executors/NonInteractiveCodeExecutor.ts
var NonInteractiveCodeExecutor = class extends Executor {
  constructor(settings, usesShell, file, language) {
    super(file, language);
    this.resolveRun = void 0;
    this.settings = settings;
    this.usesShell = usesShell;
  }
  stop() {
    return Promise.resolve();
  }
  run(codeBlockContent, outputter, cmd, cmdArgs, ext) {
    if (this.resolveRun !== void 0)
      this.resolveRun();
    this.resolveRun = void 0;
    return new Promise((resolve, reject) => {
      const tempFileName = this.getTempFile(ext);
      fs.promises.writeFile(tempFileName, codeBlockContent).then(() => {
        const args = cmdArgs ? cmdArgs.split(" ") : [];
        if (this.isWSLEnabled()) {
          args.unshift("-e", cmd);
          cmd = "wsl";
          args.push(windowsPathToWsl_default(tempFileName));
        } else {
          args.push(tempFileName);
        }
        let child;
        if (cmd.endsWith("gcc") || cmd.endsWith("gcc.exe")) {
          const tempFileNameWExe = tempFileName.slice(0, -2) + ".out";
          args.push("-o", tempFileNameWExe);
          const childGCC = child_process.spawn(cmd, args, { env: process.env, shell: this.usesShell });
          this.handleChildOutput(childGCC, outputter, tempFileName);
          childGCC.on("exit", (code) => {
            if (code === 0) {
              child = child_process.spawn(tempFileNameWExe, { env: process.env, shell: this.usesShell });
              this.handleChildOutput(child, outputter, tempFileNameWExe).then(() => {
                this.tempFileId = void 0;
              });
            }
          });
        } else {
          child = child_process.spawn(cmd, args, { env: process.env, shell: this.usesShell });
          this.handleChildOutput(child, outputter, tempFileName).then(() => {
            this.tempFileId = void 0;
          });
        }
        this.resolveRun = resolve;
      }).catch((err) => {
        this.notifyError(cmd, cmdArgs, tempFileName, err, outputter);
        resolve();
      });
    });
  }
  isWSLEnabled() {
    if (this.settings.wslMode) {
      return true;
    }
    if (this.language == "shell" && this.settings.shellWSLMode) {
      return true;
    }
    return false;
  }
  async handleChildOutput(child, outputter, fileName) {
    outputter.clear();
    outputter.killBlock = () => {
      child.kill("SIGINT");
    };
    this.stdoutCb = (data) => {
      outputter.write(data.toString());
    };
    this.stderrCb = (data) => {
      outputter.writeErr(data.toString());
    };
    child.stdout.on("data", this.stdoutCb);
    child.stderr.on("data", this.stderrCb);
    outputter.on("data", (data) => {
      child.stdin.write(data);
    });
    child.on("close", (code) => {
      if (code !== 0)
        new import_obsidian39.Notice("Error!");
      if (this.resolveRun !== void 0)
        this.resolveRun();
      outputter.closeInput();
      if (fileName === void 0)
        return;
      fs.promises.rm(fileName).catch((err) => {
        console.error("Error in 'Obsidian Execute Code' Plugin while removing file: " + err);
      });
    });
    child.on("error", (err) => {
      new import_obsidian39.Notice("Error!");
      outputter.writeErr(err.toString());
    });
  }
};

// src/executors/PrologExecutor.ts
var prolog = __toESM(require_core());
var import_obsidian40 = require("obsidian");
var PrologExecutor = class extends Executor {
  constructor(settings, file) {
    super(file, "prolog");
    this.runQueries = true;
    this.maxPrologAnswers = settings.maxPrologAnswers;
  }
  async run(code, outputter, cmd, cmdArgs, ext) {
    const prologCode = code.split(/\n+%+\s*query\n+/);
    if (prologCode.length < 2)
      return;
    outputter.closeInput();
    outputter.clear();
    this.runPrologCode(prologCode[0], prologCode[1], outputter);
  }
  async stop() {
    this.runQueries = false;
    this.emit("close");
  }
  runPrologCode(facts, queries, out) {
    new import_obsidian40.Notice("Running...");
    const session = prolog.create();
    session.consult(
      facts,
      {
        success: () => {
          session.query(
            queries,
            {
              success: async (goal) => {
                console.debug(`Prolog goal: ${goal}`);
                let answersLeft = true;
                let counter = 0;
                while (answersLeft && counter < this.maxPrologAnswers) {
                  await session.answer({
                    success: function(answer) {
                      new import_obsidian40.Notice("Done!");
                      console.debug(`Prolog result: ${session.format_answer(answer)}`);
                      out.write(session.format_answer(answer) + "\n");
                      out.closeInput();
                    },
                    fail: function() {
                      answersLeft = false;
                    },
                    error: function(err) {
                      new import_obsidian40.Notice("Error!");
                      console.error(err);
                      answersLeft = false;
                      out.writeErr(`Error while executing code: ${err}`);
                      out.closeInput();
                    },
                    limit: function() {
                      answersLeft = false;
                    }
                  });
                  counter++;
                }
              },
              error: (err) => {
                new import_obsidian40.Notice("Error!");
                out.writeErr("Query failed.\n");
                out.writeErr(err.toString());
              }
            }
          );
        },
        error: (err) => {
          out.writeErr("Adding facts failed.\n");
          out.writeErr(err.toString());
        }
      }
    );
  }
};

// src/executors/python/wrapPython.ts
var PLT_DEFAULT_BACKEND_PY_VAR = "OBSIDIAN_EXECUTE_CODE_MATPLOTLIB_DEFAULT_BACKEND";
var wrapPython_default = (code, globalsName, printName, finishSigil, embedPlots) => `
${embedPlots ? `
try:
    matplotlib.use('agg')
except:
    pass
` : `
try:
    matplotlib.use(${PLT_DEFAULT_BACKEND_PY_VAR})
except:
    pass
`}

try:
    try:
        ${printName}(eval(
            compile(${JSON.stringify(code.replace(/\r\n/g, "\n") + "\n")}, "<code block>", "eval"),
            ${globalsName}
        ))
    except SyntaxError:
        exec(
            compile(${JSON.stringify(code.replace(/\r\n/g, "\n") + "\n")}, "<code block>", "exec"),
            ${globalsName}
        )
except Exception as e:
    ${printName} (e, file=sys.stderr)
finally:
    ${printName} ("${finishSigil}", end="")

`;

// src/executors/python/PythonExecutor.ts
var PythonExecutor = class extends ReplExecutor {
  constructor(settings, file) {
    const args = settings.pythonArgs ? settings.pythonArgs.split(" ") : [];
    args.unshift("-i");
    super(
      settings,
      settings.pythonPath,
      args,
      file,
      "python"
    );
    this.printFunctionName = `__print_${Math.random().toString().substring(2)}_${Date.now()}`;
    this.globalsDictionaryName = `__globals_${Math.random().toString().substring(2)}_${Date.now()}`;
  }
  removePrompts(output, source) {
    if (source == "stderr") {
      return output.replace(/(^((\.\.\.|>>>) )+)|(((\.\.\.|>>>) )+$)/g, "");
    } else {
      return output;
    }
  }
  wrapCode(code, finishSigil) {
    return wrapPython_default(
      code,
      this.globalsDictionaryName,
      this.printFunctionName,
      finishSigil,
      this.settings.pythonEmbedPlots
    );
  }
  async setup() {
    this.addJobToQueue((resolve, reject) => {
      this.process.stdin.write(
        `
${this.globalsDictionaryName} = {**globals()}
${this.settings.pythonEmbedPlots ? `
try:
    import matplotlib
    ${PLT_DEFAULT_BACKEND_PY_VAR} = matplotlib.get_backend()
except:
    pass
` : ""}

from __future__ import print_function
import sys
${this.printFunctionName} = print
`.replace(/\r\n/g, "\n")
      );
      this.process.stderr.once("data", (data) => {
        resolve();
      });
    }).then(() => {
    });
  }
};

// src/executors/ClingExecutor.ts
var child_process2 = __toESM(require("child_process"));
var ClingExecutor = class extends NonInteractiveCodeExecutor {
  constructor(settings, file, language) {
    super(settings, false, file, language);
  }
  run(codeBlockContent, outputter, cmd, args, ext) {
    if (this.settings[`${this.language}UseMain`]) {
      this.getTempFile(ext);
      let code;
      if (ext != "c") {
        code = codeBlockContent.replace(/main\(\)/g, `temp_${this.tempFileId}()`);
      } else {
        code = codeBlockContent;
      }
      return super.run(code, outputter, this.settings.clingPath, args, ext);
    }
    return new Promise((resolve, reject) => {
      const childArgs = [...args.split(" "), ...codeBlockContent.split("\n")];
      const child = child_process2.spawn(this.settings.clingPath, childArgs, { env: process.env, shell: this.usesShell });
      this.resolveRun = resolve;
      this.handleChildOutput(child, outputter, this.tempFileId);
    });
  }
  async handleChildOutput(child, outputter, fileName) {
    super.handleChildOutput(child, outputter, fileName);
    child.stdout.removeListener("data", this.stdoutCb);
    child.stderr.removeListener("data", this.stderrCb);
    const fileId = this.tempFileId;
    const replaceTmpId = (data) => {
      return data.replace(new RegExp(`temp_${fileId}\\(\\)`, "g"), "main()");
    };
    child.stdout.on("data", (data) => {
      this.stdoutCb(replaceTmpId(data.toString()));
    });
    child.stderr.on("data", (data) => {
      this.stderrCb(replaceTmpId(data.toString()));
    });
  }
};

// src/executors/CppExecutor.ts
var CppExecutor = class extends ClingExecutor {
  constructor(settings, file) {
    super(settings, file, "cpp");
  }
  run(codeBlockContent, outputter, cmd, cmdArgs, ext) {
    return super.run(codeBlockContent, outputter, cmd, `-std=${this.settings.clingStd} ${cmdArgs}`, "cpp");
  }
};

// src/executors/RExecutor.ts
var RExecutor = class extends ReplExecutor {
  constructor(settings, file) {
    const args = settings.RArgs ? settings.RArgs.split(" ") : [];
    let conArgName = `notebook_connection_${Math.random().toString(16).substring(2)}`;
    args.unshift(
      `-e`,
      `${conArgName}=file("stdin", "r"); while(1) { eval(parse(text=tail(readLines(con = ${conArgName}, n=1)))) }`
    );
    super(settings, settings.RPath, args, file, "r");
  }
  async setup() {
    console.log("setup");
  }
  wrapCode(code, finishSigil) {
    return `tryCatch({
			cat(sprintf("%s", 
				eval(parse(text = ${JSON.stringify(code)} ))
			))
		},
		error = function(e){
			cat(sprintf("%s", e), file=stderr())
		}, 
		finally = {
			cat(${JSON.stringify(finishSigil)});
			flush.console()
		})`.replace(/\r?\n/g, "") + "\n";
  }
  removePrompts(output, source) {
    return output;
  }
};

// src/executors/CExecutor.ts
var CExecutor = class extends ClingExecutor {
  constructor(settings, file) {
    super(settings, file, "c");
  }
  run(codeBlockContent, outputter, cmd, cmdArgs, ext) {
    const install_path = this.settings[`clingPath`];
    if (install_path.endsWith("cling") || install_path.endsWith("cling.exe")) {
      return super.run(codeBlockContent, outputter, cmd, this.settings[`cArgs`], "cpp");
    } else {
      return super.run(codeBlockContent, outputter, cmd, this.settings[`cArgs`], "c");
    }
  }
};

// src/executors/FSharpExecutor.ts
var FSharpExecutor = class extends NonInteractiveCodeExecutor {
  constructor(settings, file) {
    super(settings, false, file, "fsharp");
  }
  run(codeBlockContent, outputter, cmd, args, ext) {
    return super.run(codeBlockContent, outputter, cmd, args, ext);
  }
};

// src/executors/LatexExecutor.ts
var fs2 = __toESM(require("fs/promises"));
var fsSync = __toESM(require("fs"));
var path5 = __toESM(require("path"));
var import_child_process3 = require("child_process");
var os2 = __toESM(require("os"));

// src/transforms/LatexFigureName.ts
var path3 = __toESM(require("path"));
var ILLEGAL_FILENAME_CHARS = /[<>:"/\\|?*]+/g;
var WHITESPACE_AND_ILLEGAL_CHARS = /[<>:"/\\|?*\s]+/;
var MAYBE_WHITESPACE_AND_ILLEGAL = /[<>:"/\\|?*\s]*/;
var FIGURE_FILENAME_EXTENSIONS = /(.pdf|.svg|.png)/;
var FILENAME_PREFIX = /figure /;
var UNNAMED_PREFIX = /temp /;
var TEMP_FIGURE_NAME = /figure temp \d+/;
var latexFilenameIndex = 0;
async function retrieveFigurePath(codeblockContent, titlePattern, srcFile, settings) {
  const vaultAbsolutePath = this.app.vault.adapter.basePath;
  const vaultAttachmentPath = await this.app.fileManager.getAvailablePathForAttachment("test", srcFile);
  const vaultAttachmentDir = path3.dirname(vaultAttachmentPath);
  const figureDir = path3.join(vaultAbsolutePath, vaultAttachmentDir);
  let figureTitle = captureFigureTitle(codeblockContent, titlePattern);
  if (!figureTitle) {
    const index = nextLatexFilenameIndex(settings.latexMaxFigures);
    figureTitle = UNNAMED_PREFIX.source + index;
  }
  return path3.join(figureDir, FILENAME_PREFIX.source + figureTitle);
}
function captureFigureTitle(codeblockContent, titlePattern) {
  const pattern = parse(titlePattern);
  if (!pattern)
    return void 0;
  const match = codeblockContent.match(pattern);
  const title = match == null ? void 0 : match[1];
  if (!title)
    return void 0;
  return sanitizeFilename(title);
}
function sanitizeFilename(input) {
  const trailingFilenames = concat(FIGURE_FILENAME_EXTENSIONS, /$/);
  return input.replace(ILLEGAL_FILENAME_CHARS, " ").replace(/\s+/g, " ").trim().replace(concat(/^/, FILENAME_PREFIX), "").replace(trailingFilenames, "");
}
function generalizeFigureTitle(figureName) {
  const normalized = sanitizeFilename(figureName);
  const escaped = escape(normalized);
  const whitespaced = new RegExp(escaped.source.replace(/\s+/g, WHITESPACE_AND_ILLEGAL_CHARS.source));
  return concat(
    MAYBE_WHITESPACE_AND_ILLEGAL,
    optional(FILENAME_PREFIX),
    MAYBE_WHITESPACE_AND_ILLEGAL,
    whitespaced,
    MAYBE_WHITESPACE_AND_ILLEGAL,
    optional(FIGURE_FILENAME_EXTENSIONS),
    MAYBE_WHITESPACE_AND_ILLEGAL
  );
}
function nextLatexFilenameIndex(maxIndex) {
  latexFilenameIndex %= maxIndex;
  return latexFilenameIndex++;
}

// src/output/LatexInserter.ts
var path4 = __toESM(require("path"));
var LINK_ALIAS = /\|[^\]]*/;
var ANY_WIKILINK_EMBEDDING = concat(/!\[\[.*?/, FIGURE_FILENAME_EXTENSIONS, optional(LINK_ALIAS), /\]\]/);
var ANY_MARKDOWN_EMBEDDING = concat(/!\[.*?\]\(.*?/, FIGURE_FILENAME_EXTENSIONS, /\)/);
var ANY_FIGURE_EMBEDDING = alternate(ANY_WIKILINK_EMBEDDING, ANY_MARKDOWN_EMBEDDING);
var SAFE_ANY = /([^`]|`[^`]|``[^`])*?/;
var EMPTY_LINES = /[\s\n]*/;
function updateImage(image) {
  const baseUrl = image.src.split("?")[0];
  image.src = `${baseUrl}?cache=${Date.now()}`;
}
async function writeFileLink(figureName, figurePath, outputter) {
  await outputter.writeMarkdown(`Saved [[${figureName}]]`);
  const isTempFigure = TEMP_FIGURE_NAME.test(figureName);
  if (isTempFigure)
    return outputter.write("\n");
  const file = outputter.app.vault.getFileByPath(outputter.srcFile);
  if (!file)
    throw new Error(`File not found: ${outputter.srcFile}`);
  const link = () => createObsidianLink(outputter.app, figurePath, outputter.srcFile);
  const figure = { app: outputter.app, figureName, link, file };
  const buttonClass2 = "insert-figure-icon";
  const insertAbove = outputter.writeIcon("image-up", "Click to embed file above codeblock.\nCtrl + Click to replace previous embedding.", buttonClass2);
  insertAbove.addEventListener("click", (event) => insertEmbedding("above", event.ctrlKey, figure));
  const insertBelow = outputter.writeIcon("image-down", "Click to embed file below codeblock.\nCtrl + Click to replace next embedding.", buttonClass2);
  insertBelow.addEventListener("click", (event) => insertEmbedding("below", event.ctrlKey, figure));
  const copyLink = outputter.writeIcon("copy", "Copy the markdown link.", buttonClass2);
  copyLink.addEventListener("click", () => navigator.clipboard.writeText(link()));
  outputter.write("\n");
}
async function insertEmbedding(pastePosition, doReplace, figure) {
  try {
    const vault = figure.app.vault;
    const content = await vault.read(figure.file);
    const identifierSrc = settingsInstance.latexFigureTitlePattern.replace(/\(\?<name>[^)]*\)/, generalizeFigureTitle(figure.figureName).source);
    const identifier = parse(identifierSrc);
    if (!identifier)
      return;
    const codeBlocks = findMatchingCodeBlocks(content, /(la)?tex/, identifier, figure.link(), doReplace);
    if (codeBlocks.length === 0)
      return false;
    codeBlocks.forEach(async (block) => {
      await insertAtCodeBlock(block, pastePosition, figure);
    });
    return true;
  } catch (error) {
    console.error("Error inserting embedding:", error);
    throw error;
  }
}
function findMatchingCodeBlocks(content, language, identifier, link, doReplace) {
  const alreadyLinked = group2(escape(link));
  const codeblock = concat(
    /```(run-)?/,
    group2(language),
    /[\s\n]/,
    SAFE_ANY,
    group2(identifier),
    SAFE_ANY,
    /```/
  );
  const previous = capture(concat(ANY_FIGURE_EMBEDDING, EMPTY_LINES), "replacePrevious");
  const above = capture(concat(alreadyLinked, EMPTY_LINES), "alreadyAbove");
  const below = capture(concat(EMPTY_LINES, alreadyLinked), "alreadyBelow");
  const next = capture(concat(EMPTY_LINES, ANY_FIGURE_EMBEDDING), "replaceNext");
  const blocksWithEmbeds = new RegExp(concat(
    doReplace ? optional(previous) : null,
    optional(above),
    capture(codeblock, "codeblock"),
    optional(below),
    doReplace ? optional(next) : null
  ), "g");
  const matches = Array.from(content.matchAll(blocksWithEmbeds));
  console.debug(`Searching markdown for`, blocksWithEmbeds, `resulted in `, matches.length, `codeblock(s)`, matches.map((match) => match.groups));
  return matches;
}
async function insertAtCodeBlock(block, pastePosition, figure) {
  var _a, _b, _c, _d;
  const vault = figure.app.vault;
  const groups = block.groups;
  if (!groups || !groups.codeblock)
    return;
  const canReplace = pastePosition === "above" ? ((_a = groups.replacePrevious) == null ? void 0 : _a.length) > 0 : ((_b = groups.replaceNext) == null ? void 0 : _b.length) > 0;
  const isAlreadyEmbedded = pastePosition === "above" ? ((_c = groups.alreadyAbove) == null ? void 0 : _c.length) > 0 : ((_d = groups.alreadyBelow) == null ? void 0 : _d.length) > 0;
  if (isAlreadyEmbedded && !canReplace)
    return;
  const newText = pastePosition === "above" ? figure.link() + "\n\n" + groups.codeblock : groups.codeblock + "\n\n" + figure.link();
  if (!canReplace) {
    await vault.process(figure.file, (data) => data.replace(groups.codeblock, newText));
    return;
  }
  const oldTexts = pastePosition === "above" ? [groups.replacePrevious, groups.alreadyAbove, groups.codeblock] : [groups.codeblock, groups.alreadyBelow, groups.replaceNext];
  const oldCombined = oldTexts.filter(Boolean).join("");
  await vault.process(figure.file, (data) => data.replace(oldCombined, newText));
}
function createObsidianLink(app, filePath, sourcePath, subpath, alias) {
  const relative = getPathRelativeToVault(filePath);
  try {
    const file = app.vault.getFileByPath(relative);
    return app.fileManager.generateMarkdownLink(file, sourcePath, subpath, alias);
  } catch (error) {
    console.error(`File not found: ${relative}`);
    return "![[" + path4.basename(filePath) + "]]";
  }
}
function getPathRelativeToVault(absolutePath) {
  const vaultPath = this.app.vault.adapter.basePath;
  absolutePath = path4.normalize(absolutePath);
  if (!absolutePath.startsWith(vaultPath))
    return absolutePath;
  return absolutePath.slice(vaultPath.length).replace(/^[\\\/]/, "").replace(/\\/g, "/").replace(/['"`]/, "").trim();
}

// src/executors/LatexExecutor.ts
var REQUEST_RERUN_WARNING = /LaTeX Warning: .* Rerun to get cross-references right./;
var MAX_COMPILER_RERUNS = 10;
var LaTeXExecutor = class extends NonInteractiveCodeExecutor {
  constructor() {
    super(...arguments);
    this.compilerRequestsRerun = /* @__PURE__ */ new Set();
  }
  async run(latexSrc, outputter, compilerPath, compilerArgs, exportPath) {
    outputter.clear();
    outputter.killBlock = (subprocesses) => this.killSubprocesses(subprocesses);
    const s = this.settings;
    const exec = {
      outputter,
      outputDir: path5.dirname(exportPath)
    };
    const figureName = path5.basename(exportPath, path5.extname(exportPath));
    const errorHandler = (error) => {
      outputter.writeErr(error + "\n");
      outputter.closeInput();
    };
    let pdfFile;
    try {
      exec.workingDir = await this.createTempDirectory(outputter);
      pdfFile = await this.compileAndCrop(latexSrc, compilerArgs, compilerPath, exec);
    } catch (error) {
      errorHandler(error);
      this.cleanupBuildDir(exec);
      return;
    }
    if (s.latexSavePdf) {
      this.savePdf(pdfFile, exportPath, `${figureName}.pdf`, exec).catch(errorHandler);
    }
    if (s.latexSaveSvg === "poppler") {
      this.runChildProcess(s.latexSvgPath, [s.latexSvgArgs, pdfFile], `${figureName}.svg`, exec).catch(errorHandler);
    }
    if (s.latexSaveSvg === "inkscape") {
      this.runChildProcess(s.latexInkscapePath, [s.latexInkscapeArgs, pdfFile, "--export-filename"], `${figureName}.svg`, exec).catch(errorHandler);
    }
    if (s.latexSavePng) {
      this.runChildProcess(s.latexPngPath, [s.latexPngArgs, pdfFile], `${figureName}.png`, exec, { outFileArg: figureName }).catch(errorHandler);
    }
    this.cleanupBuildDir(exec);
  }
  async compileAndCrop(latexSrc, compilerArgs, compilerPath, exec) {
    const s = this.settings;
    const buildDir = exec.workingDir;
    const texFile = await this.writeContentToTexFile(latexSrc, buildDir, "o.tex");
    compilerArgs = [compilerArgs, `-output-directory=${buildDir}`, texFile].join(" ");
    const allowIncludesRelativeToAttachmentDir = { outputDir: buildDir, workingDir: exec.outputDir, outputter: exec.outputter };
    const cropInBuildDir = { outputDir: buildDir, workingDir: buildDir, outputter: exec.outputter };
    let pdfFile = await this.compileAndRerun(compilerPath, compilerArgs, allowIncludesRelativeToAttachmentDir);
    if (s.latexKeepLog) {
      const logFile = path5.join(buildDir, "o.log");
      await exec.outputter.writeMarkdown(`Log: [${logFile}](file://${logFile})`, true);
    }
    const isExcludedDocumentclass = s.latexCropNoStandalone && isStandaloneClass(latexSrc);
    if (s.latexDoCrop && !isExcludedDocumentclass) {
      await fs2.rename(path5.join(buildDir, pdfFile), path5.join(buildDir, "original.pdf"));
      pdfFile = await this.runChildProcess(s.latexCropPath, [s.latexCropArgs, "original.pdf"], pdfFile, cropInBuildDir, { skipWriteFileLink: true });
    }
    return pdfFile;
  }
  async compileAndRerun(compilerPath, args, exec) {
    for (let attempt = 0; attempt <= MAX_COMPILER_RERUNS; attempt++) {
      const isLastAttempt = attempt == MAX_COMPILER_RERUNS;
      const result = await this.runChildProcess(compilerPath, args.split(" "), "o.pdf", exec, { skipWriteFileLink: true, outFileArg: "", doDetectRerun: !isLastAttempt });
      const hasRequestedRerun = result === void 0;
      if (!hasRequestedRerun)
        return result;
    }
    throw `LaTeX compilation did not result in a PDF file.`;
  }
  killSubprocesses(subprocesses) {
    for (const child of subprocesses) {
      child.kill("SIGINT");
      console.log(`Subprocess ${path5.basename(child.spawnfile)} killed.`);
      subprocesses.delete(child);
    }
  }
  async savePdf(pdfFile, exportPath, figureName, exec) {
    const pdfPath = path5.join(exec.workingDir, pdfFile);
    const destinationPath = `${exportPath}.pdf`;
    try {
      await fs2.copyFile(pdfPath, destinationPath);
    } catch (error) {
      throw `Failed to copy ${pdfPath} to ${destinationPath}: ${error}`;
    }
    await writeFileLink(figureName, destinationPath, exec.outputter);
  }
  async runChildProcess(cmd, args, outName, exec, options) {
    const outDir = exec.outputDir;
    const cwdDir = exec.workingDir;
    const outputter = exec.outputter;
    let outFileArg = (options == null ? void 0 : options.outFileArg) || outName;
    const outFile = path5.join(outDir, outFileArg);
    if (outFileArg) {
      if (outDir !== cwdDir) {
        outFileArg = outFile;
      }
      args.push(`"${outFileArg}"`);
    }
    const child = (0, import_child_process3.spawn)(cmd, args, {
      env: process.env,
      windowsVerbatimArguments: true,
      cwd: cwdDir,
      shell: Boolean(this.settings.latexSubprocessesUseShell)
    });
    outputter.runningSubprocesses.add(child);
    const description = `Subprocess ${cmd} ${args.join(" ")}`;
    child.stdout.on("data", (data) => outputter.write(data.toString()));
    child.stderr.on("data", (data) => outputter.writeErr(data.toString()));
    outputter.on("data", (data) => child.stdin.write(data));
    if (options == null ? void 0 : options.doDetectRerun) {
      child.stdout.on("data", (data) => this.detectWarningRequestingRerun(data, child));
    }
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (!outputter.runningSubprocesses.has(child))
          return;
        child.kill("SIGTERM");
        reject(new Error(`${description} timed out after ${this.settings.timeout} ms.`));
      }, this.settings.timeout);
      child.on("error", (err) => reject(`${description} throws:
${err}`));
      child.on("close", async (code) => {
        const resultedInFile = fsSync.existsSync(path5.join(outDir, outName));
        outputter.runningSubprocesses.delete(child);
        if (code != 0)
          return reject(`${description} failed with code ${code}.`);
        if (!resultedInFile)
          return reject(`${description} failed to create ${outFile}.`);
        if ((options == null ? void 0 : options.doDetectRerun) && this.compilerRequestsRerun.has(child)) {
          this.compilerRequestsRerun.delete(child);
          return resolve(void 0);
        }
        if (options == null ? void 0 : options.skipWriteFileLink)
          return resolve(outName);
        const figureEmbeddings = document.querySelectorAll(`img[alt="${outName}"]`);
        figureEmbeddings.forEach((img) => updateImage(img));
        await writeFileLink(outName, path5.join(outDir, outName), outputter);
        await sleep(200);
        if (this.settings.latexOutputEmbeddings) {
          await outputter.writeMarkdown(`![[${outName}]]`, true);
        }
        outputter.closeInput();
        return resolve(outName);
      });
    });
  }
  detectWarningRequestingRerun(data, child) {
    if (REQUEST_RERUN_WARNING.test(data.toString())) {
      this.compilerRequestsRerun.add(child);
    }
    ;
  }
  async writeContentToTexFile(codeBlockContent, buildDir, filename) {
    const texFile = path5.join(buildDir, filename);
    await fs2.writeFile(texFile, codeBlockContent);
    return filename;
  }
  async createTempDirectory(outputter) {
    const millisToday = Date.now() - new Date().setHours(0, 0, 0, 0);
    const prefix = "tex" + millisToday.toString();
    const prefixPath = path5.join(os2.tmpdir(), prefix);
    const buildDir = await fs2.mkdtemp(prefixPath);
    this.removeBuildDir = async () => {
      const success = await this.removeLockedFolder(buildDir);
      if (success)
        outputter.closeInput();
    };
    return buildDir;
  }
  async cleanupBuildDir(exec) {
    const path6 = exec.workingDir;
    if (!path6 || this.settings.latexKeepLog)
      return;
    await sleep(100);
    if (!fsSync.existsSync(path6))
      return;
    const maxRetries = 10;
    for (let attempt = 0; attempt < maxRetries; attempt++) {
      await sleep(500);
      if (!fsSync.existsSync(path6))
        return;
      if (exec.outputter.runningSubprocesses.size > 0)
        continue;
      const success = await this.removeLockedFolder(path6, `Build folder busy, retrying (${attempt + 1}/${maxRetries}).`);
      if (success) {
        exec.outputter.closeInput();
        return;
      }
    }
    throw new Error("Failed to delete folder after multiple attempts.");
  }
  async removeLockedFolder(path6, comment) {
    try {
      await fs2.rmdir(path6, { recursive: true });
      console.debug(`Removed build folder: ${path6}`);
      return true;
    } catch (error) {
      if (error.code != "EBUSY" && error.code != "ENOENT")
        throw error;
      if (comment) {
        console.log(comment);
      }
    }
    return false;
  }
};

// src/ExecutorContainer.ts
var interactiveExecutors = {
  "js": NodeJSExecutor,
  "python": PythonExecutor,
  "r": RExecutor
};
var nonInteractiveExecutors = {
  "prolog": PrologExecutor,
  "cpp": CppExecutor,
  "c": CExecutor,
  "fsharp": FSharpExecutor,
  "latex": LaTeXExecutor
};
var ExecutorContainer = class extends import_events.EventEmitter {
  constructor(plugin) {
    super();
    this.executors = {};
    this.plugin = plugin;
    window.addEventListener("beforeunload", async () => {
      for (const executor of this) {
        executor.stop();
      }
    });
  }
  *[Symbol.iterator]() {
    for (const language in this.executors) {
      for (const file in this.executors[language]) {
        yield this.executors[language][file];
      }
    }
  }
  getExecutorFor(file, language, needsShell) {
    if (!this.executors[language])
      this.executors[language] = {};
    if (!this.executors[language][file])
      this.setExecutorInExecutorsObject(file, language, needsShell);
    return this.executors[language][file];
  }
  setExecutorInExecutorsObject(file, language, needsShell) {
    const exe = this.createExecutorFor(file, language, needsShell);
    if (!(exe instanceof NonInteractiveCodeExecutor))
      this.emit("add", exe);
    exe.on("close", () => {
      delete this.executors[language][file];
    });
    this.executors[language][file] = exe;
  }
  createExecutorFor(file, language, needsShell) {
    if (this.plugin.settings[`${language}Interactive`]) {
      if (!(language in interactiveExecutors))
        throw new Error(`Attempted to use interactive executor for '${language}' but no such executor exists`);
      return new interactiveExecutors[language](this.plugin.settings, file);
    } else if (language in nonInteractiveExecutors)
      return new nonInteractiveExecutors[language](this.plugin.settings, file);
    return new NonInteractiveCodeExecutor(this.plugin.settings, needsShell, file, language);
  }
};

// src/ExecutorManagerView.ts
var import_obsidian41 = require("obsidian");
var import_path2 = require("path");
var EXECUTOR_MANAGER_VIEW_ID = "code-execute-manage-executors";
var EXECUTOR_MANAGER_OPEN_VIEW_COMMAND_ID = "code-execute-open-manage-executors";
var ExecutorManagerView = class extends import_obsidian41.ItemView {
  constructor(leaf, executors) {
    super(leaf);
    this.executors = executors;
    this.executors.on("add", (executor) => {
      this.addExecutorElement(executor);
    });
  }
  static async activate(workspace) {
    workspace.detachLeavesOfType(EXECUTOR_MANAGER_VIEW_ID);
    await workspace.getRightLeaf(false).setViewState({
      type: EXECUTOR_MANAGER_VIEW_ID,
      active: true
    });
    workspace.revealLeaf(
      workspace.getLeavesOfType(EXECUTOR_MANAGER_VIEW_ID)[0]
    );
  }
  getViewType() {
    return EXECUTOR_MANAGER_VIEW_ID;
  }
  getDisplayText() {
    return "Execution Runtimes";
  }
  getIcon() {
    return "command-glyph";
  }
  async onOpen() {
    const container = this.contentEl;
    container.empty();
    container.classList.add("manage-executors-view");
    const header = document.createElement("h3");
    header.textContent = "Runtimes";
    container.appendChild(header);
    this.list = document.createElement("ul");
    container.appendChild(document.createElement("div")).appendChild(this.list);
    for (const executor of this.executors) {
      this.addExecutorElement(executor);
    }
    this.addEmptyState();
  }
  async onClose() {
  }
  addEmptyState() {
    this.emptyStateElement = document.createElement("div");
    this.emptyStateElement.classList.add("empty-state");
    this.emptyStateElement.textContent = "There are currently no runtimes online. Run some code blocks, and their runtimes will appear here.";
    this.list.parentElement.appendChild(this.emptyStateElement);
    this.updateEmptyState();
  }
  updateEmptyState() {
    if (this.list.childElementCount == 0) {
      this.emptyStateElement.style.display = "block";
    } else {
      this.emptyStateElement.style.display = "none";
    }
  }
  addExecutorElement(executor) {
    const li = document.createElement("li");
    const simpleName = (0, import_path2.basename)(executor.file);
    const langElem = document.createElement("small");
    langElem.textContent = executor.language;
    li.appendChild(langElem);
    li.appendChild(this.createFilenameRowElem(simpleName));
    executor.on("close", () => {
      li.remove();
      this.updateEmptyState();
    });
    const button = document.createElement("button");
    button.addEventListener("click", () => executor.stop());
    (0, import_obsidian41.setIcon)(button, "trash");
    button.setAttribute("aria-label", "Stop Runtime");
    li.appendChild(button);
    this.list.appendChild(li);
    this.updateEmptyState();
  }
  createFilenameRowElem(text) {
    const fElem = document.createElement("span");
    fElem.textContent = text;
    fElem.classList.add("filename");
    return fElem;
  }
};

// src/runAllCodeBlocks.ts
var import_obsidian48 = require("obsidian");

// src/RunButton.ts
var import_obsidian47 = require("obsidian");

// src/output/Outputter.ts
var import_events2 = require("events");

// src/svgs/parseHTML.ts
var parseHTML_default = (html) => {
  let container = document.createElement("div");
  container.innerHTML = html;
  return container.firstElementChild;
};

// src/svgs/loadEllipses.ts
var svg = parseHTML_default(`<svg width="10" height="10" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
    <style>
        @keyframes load_ellipse_anim{
	    0%{transform: translateY(0);}
	    25%{transform: translateY(-1.5px);}
	    100%{transform: translateY(0);}
        }
    </style>
    <circle cx="1.5" r="1" cy="5" style="fill:currentColor; animation: load_ellipse_anim 1.3s infinite ease-in-out 0.3s;"/>
    <circle cx="5" r="1" cy="5" style="fill:currentColor; animation: load_ellipse_anim 1.3s infinite ease-in-out 0.6s;"/>
    <circle cx="8.5" r="1" cy="5" style="fill:currentColor; animation: load_ellipse_anim 1.3s infinite ease-in-out 0.9s;"/>
</svg>`);
var loadEllipses_default = () => {
  return svg.cloneNode(true);
};

// src/svgs/loadSpinner.ts
var svg2 = parseHTML_default(`<svg width="10" height="10" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
        <style>@keyframes spinner_svv2{100%{transform:rotate(360deg)}}</style>
        <path d="M1 5 A 4 4 0 1 1 9 5" style="transform-origin: center; fill: none; stroke: currentColor; stroke-width: 0.5; animation:spinner_svv2 .75s infinite linear"/>
        </svg>`);
var loadSpinner_default = () => {
  return svg2.cloneNode(true);
};

// src/output/FileAppender.ts
var FileAppender = class {
  constructor(view, blockElem) {
    this.view = view;
    this.codeBlockElement = blockElem;
    try {
      this.codeBlockRange = this.getRangeOfCodeBlock(blockElem);
    } catch (e) {
      console.error("Error finding code block range: Probably because of 'run-' prefix");
      this.codeBlockRange = null;
    }
  }
  clearOutput() {
    if (this.codeBlockRange && this.outputPosition) {
      const editor = this.view.editor;
      const afterEndOfOutputCodeBlock = {
        line: this.outputPosition.line + 1,
        ch: "```".length + 1
      };
      editor.replaceRange("", this.codeBlockRange.to, afterEndOfOutputCodeBlock);
      this.view.setViewData(editor.getValue(), false);
      this.outputPosition = null;
    }
  }
  addOutput(output) {
    try {
      this.findOutputTarget();
    } catch (e) {
      console.error("Error finding output target: Probably because of 'run-' prefix");
      this.view.setViewData(this.view.editor.getValue(), false);
      return;
    }
    const editor = this.view.editor;
    editor.replaceRange(output, this.outputPosition);
    const lines = output.split("\n");
    this.outputPosition = {
      line: this.outputPosition.line + (lines.length - 1),
      ch: (lines.length == 1 ? this.outputPosition.ch : 0) + lines[lines.length - 1].length
    };
    this.view.setViewData(this.view.editor.getValue(), false);
  }
  findOutputTarget(addIfNotExist = true) {
    const editor = this.view.editor;
    const EXPECTED_SUFFIX = "\n```output\n";
    const sigilEndIndex = editor.posToOffset(this.codeBlockRange.to) + EXPECTED_SUFFIX.length;
    const outputBlockSigilRange = {
      from: this.codeBlockRange.to,
      to: {
        ch: 0,
        line: this.codeBlockRange.to.line + 2
      }
    };
    const hasOutput = editor.getRange(outputBlockSigilRange.from, outputBlockSigilRange.to) == EXPECTED_SUFFIX;
    if (hasOutput) {
      const index = editor.getValue().indexOf("\n```\n", sigilEndIndex);
      if (index == -1) {
        this.outputPosition = outputBlockSigilRange.to;
      } else {
        this.outputPosition = editor.offsetToPos(index - 1);
      }
    } else if (addIfNotExist) {
      editor.replaceRange(EXPECTED_SUFFIX + "```\n", this.codeBlockRange.to);
      this.view.data = this.view.editor.getValue();
      this.outputPosition = {
        ch: 0,
        line: this.codeBlockRange.to.line + 2
      };
    } else {
      this.outputPosition = outputBlockSigilRange.to;
    }
  }
  findExactCodeBlockRange(startLine, endLine, searchBlockIndex) {
    const editor = this.view.editor;
    const textContent = editor.getValue();
    const startIndex = editor.posToOffset({ ch: 0, line: startLine });
    const endIndex = editor.posToOffset({ ch: 0, line: endLine + 1 });
    const PADDING = "\n\n\n\n\n";
    let escaped, inBlock, blockI = 0, last5 = PADDING, blockStart;
    for (let i2 = startIndex; i2 < endIndex + PADDING.length; i2++) {
      const char = i2 < endIndex ? textContent[i2] : PADDING[0];
      last5 = last5.substring(1) + char;
      if (escaped) {
        escaped = false;
        continue;
      }
      if (char == "\\") {
        escaped = true;
        continue;
      }
      if (last5.substring(0, 4) == "\n```") {
        inBlock = !inBlock;
        if (inBlock) {
          blockStart = i2 - 4;
        } else {
          if (blockI == searchBlockIndex) {
            return {
              from: this.view.editor.offsetToPos(blockStart),
              to: this.view.editor.offsetToPos(i2)
            };
          } else {
            blockI++;
          }
        }
      }
    }
    return null;
  }
  getRangeOfCodeBlock(codeBlock) {
    const parent = codeBlock.parentElement;
    const index = Array.from(parent.children).indexOf(codeBlock);
    const section = this.view.previewMode.renderer.sections.find((x) => x.el == parent);
    if (section) {
      return this.findExactCodeBlockRange(section.lineStart, section.lineEnd, index);
    } else {
      return null;
    }
  }
};

// src/output/Outputter.ts
var import_obsidian42 = require("obsidian");
var TOGGLE_HTML_SIGIL = `TOGGLE_HTML_${Math.random().toString(16).substring(2)}`;
var Outputter = class extends import_events2.EventEmitter {
  constructor(codeBlock, settings, view, app, srcFile) {
    super();
    this.runningSubprocesses = /* @__PURE__ */ new Set();
    this.settings = settings;
    this.app = app;
    this.srcFile = srcFile;
    this.inputState = this.settings.allowInput ? "INACTIVE" : "NOT_DOING";
    this.codeBlockElement = codeBlock;
    this.hadPreviouslyPrinted = false;
    this.escapeHTML = true;
    this.htmlBuffer = "";
    this.blockRunState = "INITIAL";
    this.saveToFile = new FileAppender(view, codeBlock.parentElement);
  }
  clear() {
    if (this.outputElement) {
      for (const child of Array.from(this.outputElement.children)) {
        if (child instanceof HTMLSpanElement)
          this.outputElement.removeChild(child);
      }
    }
    this.lastPrintElem = null;
    this.hadPreviouslyPrinted = false;
    this.lastPrinted = "";
    if (this.clearButton)
      this.clearButton.className = "clear-button-disabled";
    this.closeInput();
    this.inputState = "INACTIVE";
    this.saveToFile.clearOutput();
    this.killBlock(this.runningSubprocesses);
  }
  killBlock(subprocesses) {
  }
  delete() {
    if (this.outputElement)
      this.outputElement.style.display = "none";
    this.clear();
  }
  write(text) {
    this.processSigilsAndWriteText(text);
  }
  writeIcon(icon, hoverTooltip, styleClass) {
    const button = this.lastPrintElem.createEl("a", { title: hoverTooltip, cls: styleClass });
    (0, import_obsidian42.setIcon)(button, icon);
    return button;
  }
  async writeMarkdown(markdown, addLineBreak, relativeFile = this.srcFile) {
    if (relativeFile !== this.srcFile) {
      relativeFile = (0, import_obsidian42.normalizePath)(relativeFile);
    }
    const renderedEl = document.createElement("div");
    await import_obsidian42.MarkdownRenderer.render(this.app, markdown, renderedEl, relativeFile, new import_obsidian42.Component());
    for (const child of Array.from(renderedEl.children)) {
      this.write(TOGGLE_HTML_SIGIL + child.innerHTML + TOGGLE_HTML_SIGIL);
    }
    if (addLineBreak)
      this.write(`
`);
  }
  processSigilsAndWriteText(text) {
    while (true) {
      let index = text.indexOf(TOGGLE_HTML_SIGIL);
      if (index === -1)
        break;
      if (index > 0)
        this.writeRaw(text.substring(0, index));
      this.escapeHTML = !this.escapeHTML;
      this.writeHTMLBuffer(this.addStdout());
      text = text.substring(index + TOGGLE_HTML_SIGIL.length);
    }
    this.writeRaw(text);
  }
  writeRaw(text) {
    text = text.replace(/\x1b\\[;\d]*m/g, "");
    if (this.textPrinted(text)) {
      this.makeOutputVisible();
    }
    this.escapeAwareAppend(this.addStdout(), text);
  }
  writeErr(text) {
    text = text.replace(/\x1b\\[;\d]*m/g, "");
    if (this.textPrinted(text)) {
      this.makeOutputVisible();
    }
    this.addStderr().appendText(text);
  }
  closeInput() {
    this.inputState = "CLOSED";
    if (this.inputElement)
      this.inputElement.style.display = "none";
  }
  startBlock() {
    if (!this.loadStateIndicatorElement)
      this.addLoadStateIndicator();
    setTimeout(() => {
      if (this.blockRunState !== "FINISHED")
        this.loadStateIndicatorElement.classList.add("visible");
    }, 100);
    this.loadStateIndicatorElement.empty();
    this.loadStateIndicatorElement.appendChild(loadSpinner_default());
    this.loadStateIndicatorElement.setAttribute("aria-label", "This block is running.\nClick to stop.");
    this.blockRunState = "RUNNING";
  }
  queueBlock() {
    if (!this.loadStateIndicatorElement)
      this.addLoadStateIndicator();
    setTimeout(() => {
      if (this.blockRunState !== "FINISHED")
        this.loadStateIndicatorElement.classList.add("visible");
    }, 100);
    this.loadStateIndicatorElement.empty();
    this.loadStateIndicatorElement.appendChild(loadEllipses_default());
    this.loadStateIndicatorElement.setAttribute("aria-label", "This block is waiting for another block to finish.\nClick to cancel.");
    this.blockRunState = "QUEUED";
  }
  finishBlock() {
    if (this.loadStateIndicatorElement) {
      this.loadStateIndicatorElement.classList.remove("visible");
    }
    this.blockRunState = "FINISHED";
  }
  addLoadStateIndicator() {
    this.loadStateIndicatorElement = document.createElement("div");
    this.loadStateIndicatorElement.classList.add("load-state-indicator");
    this.loadStateIndicatorElement.addEventListener("click", () => this.killBlock(this.runningSubprocesses));
    this.getParentElement().parentElement.appendChild(this.loadStateIndicatorElement);
  }
  getParentElement() {
    return this.codeBlockElement.parentElement;
  }
  addClearButton() {
    const parentEl = this.getParentElement();
    this.clearButton = document.createElement("button");
    this.clearButton.className = "clear-button";
    this.clearButton.setText("Clear");
    this.clearButton.addEventListener("click", () => this.delete());
    parentEl.appendChild(this.clearButton);
  }
  addOutputElement() {
    const parentEl = this.getParentElement();
    const hr = document.createElement("hr");
    this.outputElement = document.createElement("code");
    this.outputElement.classList.add("language-output");
    this.outputElement.appendChild(hr);
    if (this.inputState != "NOT_DOING")
      this.addInputElement();
    parentEl.appendChild(this.outputElement);
  }
  addInputElement() {
    this.inputElement = document.createElement("input");
    this.inputElement.classList.add("interactive-stdin");
    this.inputElement.addEventListener("keypress", (e) => {
      if (e.key == "Enter") {
        this.processInput(this.inputElement.value + "\n");
        this.inputElement.value = "";
      }
    });
    this.outputElement.appendChild(this.inputElement);
  }
  processInput(input) {
    this.addStdin().appendText(input);
    this.emit("data", input);
  }
  addStdin() {
    return this.addStreamSegmentElement("stdin");
  }
  addStderr() {
    return this.addStreamSegmentElement("stderr");
  }
  addStdout() {
    return this.addStreamSegmentElement("stdout");
  }
  addStreamSegmentElement(streamId) {
    if (!this.outputElement)
      this.addOutputElement();
    if (this.lastPrintElem) {
      if (this.lastPrintElem.classList.contains(streamId))
        return this.lastPrintElem;
    }
    const stdElem = document.createElement("span");
    stdElem.addClass(streamId);
    if (this.inputElement) {
      this.outputElement.insertBefore(stdElem, this.inputElement);
    } else {
      this.outputElement.appendChild(stdElem);
    }
    this.lastPrintElem = stdElem;
    return stdElem;
  }
  escapeAwareAppend(element, text) {
    if (this.escapeHTML) {
      element.appendChild(document.createTextNode(text));
      if (this.settings.persistentOuput) {
        this.saveToFile.addOutput(text);
      }
    } else {
      this.htmlBuffer += text;
    }
  }
  writeHTMLBuffer(element) {
    if (this.htmlBuffer !== "") {
      this.makeOutputVisible();
      const content = document.createElement("div");
      content.innerHTML = this.htmlBuffer;
      for (const childElem of Array.from(content.childNodes))
        element.appendChild(childElem);
      this.htmlBuffer = "";
    }
  }
  textPrinted(text) {
    if (this.hadPreviouslyPrinted)
      return true;
    if (text.contains(TOGGLE_HTML_SIGIL))
      return false;
    if (text === "")
      return false;
    this.hadPreviouslyPrinted = true;
    return true;
  }
  makeOutputVisible() {
    this.closeInput();
    if (!this.clearButton)
      this.addClearButton();
    if (!this.outputElement)
      this.addOutputElement();
    this.inputState = "OPEN";
    this.outputElement.style.display = "block";
    this.clearButton.className = "clear-button";
    setTimeout(() => {
      if (this.inputState === "OPEN")
        this.inputElement.style.display = "inline";
    }, 1e3);
  }
};

// src/transforms/CodeInjector.ts
var import_obsidian46 = require("obsidian");

// src/transforms/Magic.ts
var os3 = __toESM(require("os"));
var import_obsidian43 = require("obsidian");
var SHOW_REGEX = /@show\(["'](?<path>[^<>?*=!\n#()\[\]{}]+)["'](,\s*(?<width>\d+[\w%]+),?\s*(?<height>\d+[\w%]+))?(,\s*(?<align>left|center|right))?\)/g;
var HTML_REGEX = /@html\((?<html>[^)]+)\)/g;
var VAULT_REGEX = /@vault/g;
var VAULT_PATH_REGEX = /@vault_path/g;
var VAULT_URL_REGEX = /@vault_url/g;
var CURRENT_NOTE_REGEX = /@note/g;
var CURRENT_NOTE_PATH_REGEX = /@note_path/g;
var CURRENT_NOTE_URL_REGEX = /@note_url/g;
var NOTE_TITLE_REGEX = /@title/g;
var NOTE_CONTENT_REGEX = /@content/g;
var COLOR_THEME_REGEX = /@theme/g;
var PYTHON_PLOT_REGEX = /^(plt|matplotlib.pyplot|pyplot)\.show\(\)/gm;
var R_PLOT_REGEX = /^plot\(.*\)/gm;
var OCTAVE_PLOT_REGEX = /^plot\s*\(.*\);/gm;
var MAXIMA_PLOT_REGEX = /^plot2d\s*\(.*\[.+\]\)\s*[$;]/gm;
function expandVaultPath(source, vaultPath) {
  let vaultPathClean = vaultPath.replace(/\\/g, "/").replace(/^\//, "");
  source = source.replace(VAULT_PATH_REGEX, `"${vaultPath.replace(/\\/g, "/")}"`);
  source = source.replace(VAULT_URL_REGEX, `"${import_obsidian43.Platform.resourcePathPrefix + vaultPathClean}"`);
  source = source.replace(VAULT_REGEX, `"${import_obsidian43.Platform.resourcePathPrefix + vaultPathClean}"`);
  return source;
}
function expandNotePath(source, notePath) {
  let notePathClean = notePath.replace(/\\/g, "/").replace(/^\//, "");
  source = source.replace(CURRENT_NOTE_PATH_REGEX, `"${notePath.replace(/\\/g, "/")}"`);
  source = source.replace(CURRENT_NOTE_URL_REGEX, `"${import_obsidian43.Platform.resourcePathPrefix + notePathClean}"`);
  source = source.replace(CURRENT_NOTE_REGEX, `"${import_obsidian43.Platform.resourcePathPrefix + notePathClean}"`);
  return source;
}
function expandNoteTitle(source, noteTitle) {
  let t = "";
  if (noteTitle.contains("."))
    t = noteTitle.split(".").slice(0, -1).join(".");
  return source.replace(NOTE_TITLE_REGEX, `"${t}"`);
}
function insertNoteContent(source, content) {
  const escaped_content = JSON.stringify(content);
  return source.replace(NOTE_CONTENT_REGEX, `${escaped_content}`);
}
function expandColorTheme(source, theme) {
  return source.replace(COLOR_THEME_REGEX, `"${theme}"`);
}
function expandPython(source, settings) {
  if (settings.pythonEmbedPlots) {
    source = expandPythonPlots(source, TOGGLE_HTML_SIGIL);
  }
  source = expandPythonShowImage(source);
  source = expandPythonHtmlMacro(source);
  return source;
}
function expandJS(source) {
  source = expandJsShowImage(source);
  source = expandJsHtmlMacro(source);
  return source;
}
function expandPythonPlots(source, toggleHtmlSigil) {
  const showPlot = `import io; import sys; __obsidian_execute_code_temp_pyplot_var__=io.BytesIO(); plt.plot(); plt.savefig(__obsidian_execute_code_temp_pyplot_var__, format='svg'); plt.close(); sys.stdout.write(${JSON.stringify(toggleHtmlSigil)}); sys.stdout.flush(); sys.stdout.buffer.write(__obsidian_execute_code_temp_pyplot_var__.getvalue()); sys.stdout.flush(); sys.stdout.write(${JSON.stringify(toggleHtmlSigil)}); sys.stdout.flush()`;
  return source.replace(PYTHON_PLOT_REGEX, showPlot);
}
function expandRPlots(source) {
  const matches = source.matchAll(R_PLOT_REGEX);
  for (const match of matches) {
    const tempFile = `${os3.tmpdir()}/temp_${Date.now()}.png`.replace(/\\/g, "/").replace(/^\//, "");
    const substitute = `png("${tempFile}"); ${match[0]}; dev.off(); cat('${TOGGLE_HTML_SIGIL}<img src="${import_obsidian43.Platform.resourcePathPrefix + tempFile}" align="center">${TOGGLE_HTML_SIGIL}')`;
    source = source.replace(match[0], substitute);
  }
  return source;
}
function expandPythonShowImage(source) {
  const matches = source.matchAll(SHOW_REGEX);
  for (const match of matches) {
    const imagePath = match.groups.path;
    const width = match.groups.width;
    const height = match.groups.height;
    const alignment = match.groups.align;
    const image = expandShowImage(imagePath.replace(/\\/g, "\\\\"), width, height, alignment);
    source = source.replace(match[0], "print('" + TOGGLE_HTML_SIGIL + image + TOGGLE_HTML_SIGIL + "')");
  }
  return source;
}
function expandPythonHtmlMacro(source) {
  const matches = source.matchAll(HTML_REGEX);
  for (const match of matches) {
    const html = match.groups.html;
    const toggle = JSON.stringify(TOGGLE_HTML_SIGIL);
    source = source.replace(match[0], `print(${toggle}); print(${html}); print(${toggle})`);
  }
  return source;
}
function expandJsShowImage(source) {
  const matches = source.matchAll(SHOW_REGEX);
  for (const match of matches) {
    const imagePath = match.groups.path;
    const width = match.groups.width;
    const height = match.groups.height;
    const alignment = match.groups.align;
    const image = expandShowImage(imagePath.replace(/\\/g, "\\\\").replace(/^\//, ""), width, height, alignment);
    source = source.replace(match[0], "console.log('" + TOGGLE_HTML_SIGIL + image + TOGGLE_HTML_SIGIL + "')");
    console.log(source);
  }
  return source;
}
function expandJsHtmlMacro(source) {
  const matches = source.matchAll(HTML_REGEX);
  for (const match of matches) {
    const html = match.groups.html;
    const toggle = JSON.stringify(TOGGLE_HTML_SIGIL);
    source = source.replace(match[0], `console.log(${toggle}); console.log(${html}); console.log(${toggle})`);
  }
  return source;
}
function expandShowImage(imagePath, width = "0", height = "0", alignment = "center") {
  if (imagePath.contains("+")) {
    let splittedPath = imagePath.replace(/['"]/g, "").split("+");
    splittedPath = splittedPath.map((element) => element.trim());
    imagePath = splittedPath.join("");
  }
  if (width == "0" || height == "0")
    return `<img src="${imagePath}" align="${alignment}" alt="Image found at path ${imagePath}." />`;
  return `<img src="${imagePath}" width="${width}" height="${height}" align="${alignment}" alt="Image found at path ${imagePath}." />`;
}
function expandOctavePlot(source) {
  const matches = source.matchAll(OCTAVE_PLOT_REGEX);
  for (const match of matches) {
    const tempFile = `${os3.tmpdir()}/temp_${Date.now()}.png`.replace(/\\/g, "/").replace(/^\//, "");
    const substitute = `${match[0]}; print -dpng ${tempFile}; disp('${TOGGLE_HTML_SIGIL}<img src="${import_obsidian43.Platform.resourcePathPrefix + tempFile}" align="center">${TOGGLE_HTML_SIGIL}');`;
    source = source.replace(match[0], substitute);
  }
  return source;
}
function expandMaximaPlot(source) {
  const matches = source.matchAll(MAXIMA_PLOT_REGEX);
  for (const match of matches) {
    const tempFile = `${os3.tmpdir()}/temp_${Date.now()}.png`.replace(/\\/g, "/").replace(/^\//, "");
    const updated_plot_call = match[0].substring(0, match[0].lastIndexOf(")")) + `, [png_file, "${tempFile}"])`;
    const substitute = `${updated_plot_call}; print ('${TOGGLE_HTML_SIGIL}<img src="${import_obsidian43.Platform.resourcePathPrefix + tempFile}" align="center">${TOGGLE_HTML_SIGIL}');`;
    source = source.replace(match[0], substitute);
  }
  return source;
}

// src/Vault.ts
var import_obsidian44 = require("obsidian");
function getFullContentHtml(view) {
  const codeMirror = view.editor.cm;
  codeMirror.viewState.printing = true;
  codeMirror.measure();
  const html = view.contentEl.innerHTML;
  codeMirror.viewState.printing = false;
  codeMirror.measure();
  return html;
}
function getVaultVariables(app) {
  const activeView = app.workspace.getActiveViewOfType(import_obsidian44.MarkdownView);
  if (activeView === null) {
    return null;
  }
  const adapter = app.vault.adapter;
  const vaultPath = adapter.getBasePath();
  const folder = activeView.file.parent.path;
  const fileName = activeView.file.name;
  const filePath = activeView.file.path;
  const fileContent = getFullContentHtml(activeView);
  const theme = document.body.classList.contains("theme-light") ? "light" : "dark";
  return {
    vaultPath,
    folder,
    fileName,
    filePath,
    theme,
    fileContent
  };
}

// src/transforms/TransformCode.ts
function getLanguageAlias(language) {
  if (language === void 0)
    return void 0;
  switch (language) {
    case "javascript":
      return "js";
    case "typescript":
      return "ts";
    case "csharp":
      return "cs";
    case "bash":
      return "shell";
    case "py":
      return "python";
    case "wolfram":
      return "mathematica";
    case "nb":
      return "mathematica";
    case "wl":
      "mathematica";
    case "hs":
      return "haskell";
  }
  if (canonicalLanguages.includes(language))
    return language;
  return void 0;
}
function transformMagicCommands(app, srcCode) {
  let ret = srcCode;
  const vars = getVaultVariables(app);
  if (vars) {
    ret = expandVaultPath(ret, vars.vaultPath);
    ret = expandNotePath(ret, vars.filePath);
    ret = expandNoteTitle(ret, vars.fileName);
    ret = expandColorTheme(ret, vars.theme);
    ret = insertNoteContent(ret, vars.fileContent);
  } else {
    console.warn(`Could not load all Vault variables! ${vars}`);
  }
  return ret;
}
function getCodeBlockLanguage(firstLineOfCode) {
  let currentLanguage = firstLineOfCode.split("```")[1].trim().split(" ")[0].split("{")[0];
  if (isStringNotEmpty(currentLanguage) && currentLanguage.startsWith("run-")) {
    currentLanguage = currentLanguage.replace("run-", "");
  }
  return getLanguageAlias(currentLanguage);
}
function isStringNotEmpty(str) {
  return !!str && str.trim().length > 0;
}

// src/CodeBlockArgs.ts
var import_obsidian45 = require("obsidian");
var JSON5 = __toESM(require_dist());
function getArgs(firstLineOfCode) {
  if (!firstLineOfCode.contains("{") && !firstLineOfCode.contains("}"))
    return {};
  try {
    let args = firstLineOfCode.substring(firstLineOfCode.indexOf("{") + 1).trim();
    args = args.replace(/=/g, ":");
    const exports = [];
    const handleUnnamedExport = (exportName) => {
      let i2 = args.indexOf(exportName);
      while (i2 !== -1) {
        const nextChar = args[i2 + exportName.length];
        if (nextChar !== `"` && nextChar !== `'`) {
          args = args.substring(0, i2) + args.substring(i2 + exportName.length + (nextChar === "}" ? 0 : 1));
          exports.push(exportName);
        }
        i2 = args.indexOf(exportName, i2 + 1);
      }
    };
    handleUnnamedExport("pre");
    handleUnnamedExport("post");
    args = `{export: ['${exports.join("', '")}'], ${args}`;
    return JSON5.parse(args);
  } catch (err) {
    new import_obsidian45.Notice(`Failed to parse code block arguments from line:
${firstLineOfCode}

Failed with error:
${err}`);
    return {};
  }
}

// src/transforms/CodeInjector.ts
var CodeInjector = class {
  constructor(app, settings, language) {
    this.prependSrcCode = "";
    this.appendSrcCode = "";
    this.namedImportSrcCode = "";
    this.mainArgs = {};
    this.namedExports = {};
    this.app = app;
    this.settings = settings;
    this.language = language;
  }
  async injectCode(srcCode) {
    const language = getLanguageAlias(this.language);
    const activeView = this.app.workspace.getActiveViewOfType(import_obsidian46.MarkdownView);
    if (activeView === null)
      return srcCode;
    await this.parseFile(activeView.data, srcCode, language);
    const realLanguage = /[^-]*$/.exec(language)[0];
    const globalInject = this.settings[`${realLanguage}Inject`];
    let injectedCode = `${this.namedImportSrcCode}
${srcCode}`;
    if (!this.mainArgs.ignore)
      injectedCode = `${globalInject}
${this.prependSrcCode}
${injectedCode}
${this.appendSrcCode}`;
    else {
      if (!Array.isArray(this.mainArgs.ignore) && this.mainArgs.ignore !== "all")
        this.mainArgs.ignore = [this.mainArgs.ignore];
      if (this.mainArgs.ignore !== "all") {
        if (!this.mainArgs.ignore.contains("pre"))
          injectedCode = `${this.prependSrcCode}
${injectedCode}`;
        if (!this.mainArgs.ignore.contains("post"))
          injectedCode = `${injectedCode}
${this.appendSrcCode}`;
        if (!this.mainArgs.ignore.contains("global"))
          injectedCode = `${globalInject}
${injectedCode}`;
      }
    }
    return transformMagicCommands(this.app, injectedCode);
  }
  async handleNamedImports(namedImports) {
    const handleNamedImport = (namedImport) => {
      if (!this.namedExports.hasOwnProperty(namedImport)) {
        new import_obsidian46.Notice(`Named export "${namedImport}" does not exist but was imported`);
        return true;
      }
      this.namedImportSrcCode += `${this.disable_print(this.namedExports[namedImport])}
`;
      return false;
    };
    if (!Array.isArray(namedImports))
      return handleNamedImport(namedImports);
    for (const namedImport of namedImports) {
      const err = handleNamedImport(namedImport);
      if (err)
        return true;
    }
    return false;
  }
  async parseFile(fileContents, srcCode, language) {
    let currentArgs = {};
    let insideCodeBlock = false;
    let isLanguageEqual = false;
    let currentLanguage = "";
    let currentCode = "";
    let currentFirstLine = "";
    for (const line of fileContents.split("\n")) {
      if (line.startsWith("```")) {
        if (insideCodeBlock) {
          const srcCodeTrimmed = srcCode.trim();
          const currentCodeTrimmed = currentCode.trim();
          if (isLanguageEqual && srcCodeTrimmed.length === currentCodeTrimmed.length && srcCodeTrimmed === currentCodeTrimmed) {
            this.mainArgs = getArgs(currentFirstLine);
            if (this.mainArgs.import) {
              const err = this.handleNamedImports(this.mainArgs.import);
              if (err)
                return "";
            }
            break;
          }
          if (currentArgs.label) {
            if (this.namedExports.hasOwnProperty(currentArgs.label)) {
              new import_obsidian46.Notice(`Error: named export ${currentArgs.label} exported more than once`);
              return "";
            }
            this.namedExports[currentArgs.label] = currentCode;
          }
          if (!Array.isArray(currentArgs.export))
            currentArgs.export = [currentArgs.export];
          if (currentArgs.export.contains("pre"))
            this.prependSrcCode += `${this.disable_print(currentCode)}
`;
          if (currentArgs.export.contains("post"))
            this.appendSrcCode += `${this.disable_print(currentCode)}
`;
          currentLanguage = "";
          currentCode = "";
          insideCodeBlock = false;
          currentArgs = {};
        } else {
          currentLanguage = getCodeBlockLanguage(line);
          isLanguageEqual = /[^-]*$/.exec(language)[0] === /[^-]*$/.exec(currentLanguage)[0];
          if (isLanguageEqual) {
            currentArgs = getArgs(line);
            currentFirstLine = line;
          }
          insideCodeBlock = true;
        }
      } else if (insideCodeBlock && isLanguageEqual) {
        currentCode += `${line}
`;
      }
    }
  }
  disable_print(code) {
    if (!this.settings.onlyCurrentBlock) {
      return code;
    }
    const pattern = /^print\s*(.*)/gm;
    return code.replace(pattern, " ");
  }
};

// src/RunButton.ts
var buttonText = "Run";
var buttonClass = "run-code-button";
var disabledClass = "run-button-disabled";
var codeBlockHasButtonClass = "has-run-code-button";
async function handleExecution(block) {
  const language = block.language;
  const button = block.button;
  const srcCode = block.srcCode;
  const app = block.outputter.app;
  const s = block.outputter.settings;
  button.className = disabledClass;
  block.srcCode = await new CodeInjector(app, s, language).injectCode(srcCode);
  switch (language) {
    case "js":
      return runCode(s.nodePath, s.nodeArgs, s.jsFileExtension, block, { transform: (code) => expandJS(code) });
    case "java":
      return runCode(s.javaPath, s.javaArgs, s.javaFileExtension, block);
    case "python":
      return runCode(s.pythonPath, s.pythonArgs, s.pythonFileExtension, block, { transform: (code) => expandPython(code, s) });
    case "shell":
      return runCode(s.shellPath, s.shellArgs, s.shellFileExtension, block, { shell: true });
    case "batch":
      return runCode(s.batchPath, s.batchArgs, s.batchFileExtension, block, { shell: true });
    case "powershell":
      return runCode(s.powershellPath, s.powershellArgs, s.powershellFileExtension, block, { shell: true });
    case "cpp":
      return runCode(s.clingPath, `-std=${s.clingStd} ${s.clingArgs}`, s.cppFileExtension, block);
    case "prolog":
      runCode("", "", "", block);
      button.className = buttonClass;
      break;
    case "groovy":
      return runCode(s.groovyPath, s.groovyArgs, s.groovyFileExtension, block, { shell: true });
    case "rust":
      return runCode(s.cargoPath, "eval" + s.cargoEvalArgs, s.rustFileExtension, block);
    case "r":
      return runCode(s.RPath, s.RArgs, s.RFileExtension, block, { transform: (code) => expandRPlots(code) });
    case "go":
      return runCode(s.golangPath, s.golangArgs, s.golangFileExtension, block);
    case "kotlin":
      return runCode(s.kotlinPath, s.kotlinArgs, s.kotlinFileExtension, block, { shell: true });
    case "ts":
      return runCode(s.tsPath, s.tsArgs, "ts", block, { shell: true });
    case "lua":
      return runCode(s.luaPath, s.luaArgs, s.luaFileExtension, block, { shell: true });
    case "dart":
      return runCode(s.dartPath, s.dartArgs, s.dartFileExtension, block, { shell: true });
    case "cs":
      return runCode(s.csPath, s.csArgs, s.csFileExtension, block, { shell: true });
    case "haskell":
      return s.useGhci ? runCode(s.ghciPath, "", "hs", block, { shell: true }) : runCode(s.runghcPath, "-f " + s.ghcPath, "hs", block, { shell: true });
    case "mathematica":
      return runCode(s.mathematicaPath, s.mathematicaArgs, s.mathematicaFileExtension, block, { shell: true });
    case "scala":
      return runCode(s.scalaPath, s.scalaArgs, s.scalaFileExtension, block, { shell: true });
    case "swift":
      return runCode(s.swiftPath, s.swiftArgs, s.swiftFileExtension, block, { shell: true });
    case "c":
      return runCode(s.clingPath, s.clingArgs, "c", block, { shell: true });
    case "ruby":
      return runCode(s.rubyPath, s.rubyArgs, s.rubyFileExtension, block, { shell: true });
    case "sql":
      return runCode(s.sqlPath, s.sqlArgs, "sql", block, { shell: true });
    case "octave":
      return runCode(s.octavePath, s.octaveArgs, s.octaveFileExtension, block, { shell: true, transform: (code) => expandOctavePlot(code) });
    case "maxima":
      return runCode(s.maximaPath, s.maximaArgs, s.maximaFileExtension, block, { shell: true, transform: (code) => expandMaximaPlot(code) });
    case "racket":
      return runCode(s.racketPath, s.racketArgs, s.racketFileExtension, block, { shell: true });
    case "applescript":
      return runCode(s.applescriptPath, s.applescriptArgs, s.applescriptFileExtension, block, { shell: true });
    case "zig":
      return runCode(s.zigPath, s.zigArgs, "zig", block, { shell: true });
    case "ocaml":
      return runCode(s.ocamlPath, s.ocamlArgs, "ocaml", block, { shell: true });
    case "php":
      return runCode(s.phpPath, s.phpArgs, s.phpFileExtension, block, { shell: true });
    case "latex":
      const outputPath = await retrieveFigurePath(block.srcCode, s.latexFigureTitlePattern, block.markdownFile, s);
      const invokeCompiler = [s.latexTexfotArgs, s.latexCompilerPath, s.latexCompilerArgs].join(" ");
      return !s.latexDoFilter ? runCode(s.latexCompilerPath, s.latexCompilerArgs, outputPath, block, { transform: (code) => modifyLatexCode(code, s) }) : runCode(s.latexTexfotPath, invokeCompiler, outputPath, block, { transform: (code) => modifyLatexCode(code, s) });
    default:
      break;
  }
}
function addInOpenFiles(plugin) {
  const workspace = plugin.app.workspace;
  workspace.iterateRootLeaves((leaf) => {
    if (leaf.view instanceof import_obsidian47.MarkdownView) {
      addToAllCodeBlocks(leaf.view.contentEl, leaf.view.file.path, leaf.view, plugin);
    }
  });
}
function addToAllCodeBlocks(element, file, view, plugin) {
  Array.from(element.getElementsByTagName("code")).forEach((codeBlock) => addToCodeBlock(codeBlock, file, view, plugin));
}
function addToCodeBlock(codeBlock, file, view, plugin) {
  if (codeBlock.className.match(/^language-\{\w+/i)) {
    codeBlock.className = codeBlock.className.replace(/^language-\{(\w+)/i, "language-$1 {");
    codeBlock.parentElement.className = codeBlock.className;
  }
  const language = codeBlock.className.toLowerCase();
  if (!language || !language.contains("language-"))
    return;
  const pre = codeBlock.parentElement;
  const parent = pre.parentElement;
  const srcCode = codeBlock.getText();
  let sanitizedClassList = sanitizeClassListOfCodeBlock(codeBlock);
  const canonicalLanguage = getLanguageAlias(
    supportedLanguages.find((lang) => sanitizedClassList.contains(`language-${lang}`))
  );
  const isLanguageSupported = canonicalLanguage !== void 0;
  const hasBlockBeenButtonifiedAlready = parent.classList.contains(codeBlockHasButtonClass);
  if (!isLanguageSupported || hasBlockBeenButtonifiedAlready)
    return;
  const outputter = new Outputter(codeBlock, plugin.settings, view, plugin.app, file);
  parent.classList.add(codeBlockHasButtonClass);
  const button = createButton();
  pre.appendChild(button);
  const block = {
    srcCode,
    language: canonicalLanguage,
    markdownFile: file,
    button,
    outputter,
    executors: plugin.executors
  };
  button.addEventListener("click", () => handleExecution(block));
}
function sanitizeClassListOfCodeBlock(codeBlock) {
  let sanitizedClassList = Array.from(codeBlock.classList);
  return sanitizedClassList.map((c) => c.toLowerCase());
}
function createButton() {
  console.debug("Add run button");
  const button = document.createElement("button");
  button.classList.add(buttonClass);
  button.setText(buttonText);
  return button;
}
function runCode(cmd, cmdArgs, ext, block, options) {
  const useShell = (options == null ? void 0 : options.shell) ? options.shell : false;
  if (options == null ? void 0 : options.transform)
    block.srcCode = options.transform(block.srcCode);
  if (!useShell)
    block.outputter.startBlock();
  const executor = block.executors.getExecutorFor(block.markdownFile, block.language, useShell);
  executor.run(block.srcCode, block.outputter, cmd, cmdArgs, ext).then(() => {
    block.button.className = buttonClass;
    if (!useShell) {
      block.outputter.closeInput();
      block.outputter.finishBlock();
    }
  });
}

// src/runAllCodeBlocks.ts
function runAllCodeBlocks(workspace) {
  const lastActiveView = workspace.getMostRecentLeaf().view;
  if (lastActiveView instanceof import_obsidian48.TextFileView) {
    lastActiveView.containerEl.querySelectorAll("button." + buttonClass).forEach((button) => {
      button.click();
    });
  }
}

// src/ReleaseNoteModal.ts
var import_obsidian49 = require("obsidian");
var ReleaseNoteModel = class extends import_obsidian49.Modal {
  constructor(app) {
    super(app);
    this.component = new import_obsidian49.Component();
  }
  onOpen() {
    let text = "# Release Note: Execute Code Plugin v2.1.0\n\nThank you for updating to version 2.1.0! This update includes some bug fixes and improvements and brings two new features:\n- [LaTeX Support](https://github.com/twibiral/obsidian-execute-code/pull/400): You can now render LaTeX code in your code blocks. Just add the language tag `latex` to your code block.\n- New Magic command: [@content](https://github.com/twibiral/obsidian-execute-code/pull/390) allows you to load the file content of the open note into your code block.\n\n\n\n[Here you can find a detailed change log.](https://github.com/twibiral/obsidian-execute-code/blob/master/CHANGELOG.md)\n\n\nIf you enjoy using the plugin, consider supporting the development via [PayPal](https://www.paypal.com/paypalme/timwibiral) or [Buy Me a Coffee](https://www.buymeacoffee.com/twibiral).\n\n\n---\n\n\n[OLD] Release Notes v2.0.0\n\nWe are happy to announce the release of version 2.0.0. This release brings a special change: You can now make the output of your code blocks persistent.If enabled, the output of your code blocks will be saved in the markdown file and will also be exported to PDF.\n\n\nYou can enable this in the settings. Be aware that this feature is still experimental and might not work as expected. Check the [github page](https://github.com/twibiral/obsidian-execute-code) for more information.";
    this.component.load();
    import_obsidian49.MarkdownRenderer.render(this.app, text, this.contentEl, this.app.workspace.getActiveFile().path, this.component);
  }
};

// src/main.ts
var languageAliases = ["javascript", "typescript", "bash", "csharp", "wolfram", "nb", "wl", "hs", "py", "tex"];
var canonicalLanguages = [
  "js",
  "ts",
  "cs",
  "latex",
  "lean",
  "lua",
  "python",
  "cpp",
  "prolog",
  "shell",
  "groovy",
  "r",
  "go",
  "rust",
  "java",
  "powershell",
  "kotlin",
  "mathematica",
  "haskell",
  "scala",
  "swift",
  "racket",
  "fsharp",
  "c",
  "dart",
  "ruby",
  "batch",
  "sql",
  "octave",
  "maxima",
  "applescript",
  "zig",
  "ocaml",
  "php"
];
var supportedLanguages = [...languageAliases, ...canonicalLanguages];
var ExecuteCodePlugin2 = class extends import_obsidian50.Plugin {
  async onload() {
    await this.loadSettings();
    this.addSettingTab(new SettingsTab(this.app, this));
    this.executors = new ExecutorContainer(this);
    const context = {
      app: this.app,
      settings: this.settings,
      executors: this.executors
    };
    addInOpenFiles(context);
    this.registerMarkdownPostProcessor((element, _context) => {
      addToAllCodeBlocks(element, _context.sourcePath, this.app.workspace.getActiveViewOfType(import_obsidian50.MarkdownView), context);
    });
    supportedLanguages.forEach((l) => {
      console.debug(`Registering renderer for ${l}.`);
      this.registerMarkdownCodeBlockProcessor(`run-${l}`, async (src, el, _ctx) => {
        await import_obsidian50.MarkdownRenderer.render(this.app, "```" + l + "\n" + src + (src.endsWith("\n") ? "" : "\n") + "```", el, _ctx.sourcePath, new import_obsidian50.Component());
      });
    });
    this.registerView(
      EXECUTOR_MANAGER_VIEW_ID,
      (leaf) => new ExecutorManagerView(leaf, this.executors)
    );
    this.addCommand({
      id: EXECUTOR_MANAGER_OPEN_VIEW_COMMAND_ID,
      name: "Open Code Runtime Management",
      callback: () => ExecutorManagerView.activate(this.app.workspace)
    });
    this.addCommand({
      id: "run-all-code-blocks-in-file",
      name: "Run all Code Blocks in Current File",
      callback: () => runAllCodeBlocks(this.app.workspace)
    });
    if (!this.settings.releaseNote2_1_0wasShowed) {
      this.app.workspace.onLayoutReady(() => {
        new ReleaseNoteModel(this.app).open();
      });
      this.settings.releaseNote2_1_0wasShowed = true;
      this.saveSettings();
    }
    applyLatexBodyClasses(this.app, this.settings);
  }
  onunload() {
    document.querySelectorAll("pre > code").forEach((codeBlock) => {
      const pre = codeBlock.parentElement;
      const parent = pre.parentElement;
      if (parent.hasClass(codeBlockHasButtonClass)) {
        parent.removeClass(codeBlockHasButtonClass);
      }
    });
    document.querySelectorAll("." + buttonClass).forEach((button) => button.remove());
    document.querySelectorAll("." + disabledClass).forEach((button) => button.remove());
    document.querySelectorAll(".clear-button").forEach((button) => button.remove());
    document.querySelectorAll(".language-output").forEach((out) => out.remove());
    for (const executor of this.executors) {
      executor.stop().then((_) => {
      });
    }
    console.log("Unloaded plugin: Execute Code");
  }
  async loadSettings() {
    this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
    if (process.platform !== "win32") {
      this.settings.wslMode = false;
    }
  }
  async saveSettings() {
    await this.saveData(this.settings);
  }
};

/* nosourcemap */