clvm_tools
Version:
Javascript implementation of clvm_tools
136 lines (135 loc) • 5.26 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.assemble = exports.disassemble = exports.disassemble_to_ir = exports.type_for_atom = exports.assemble_from_ir = void 0;
const clvm_1 = require("clvm");
const reader_1 = require("../ir/reader");
const writer_1 = require("../ir/writer");
const utils_1 = require("../ir/utils");
const Type_1 = require("../ir/Type");
function isPrintable(s) {
// eslint-disable-next-line no-control-regex
const regex = /^[0-9a-zA-Z!"#$%&'()*+,-./:;<=>?@\\[\]^_`{|}~ \t\n\r\x0b\x0c]+$/;
return regex.test(s);
}
// In order to reduce stack memory consumed, I made `assemble_from_ir` fully flatten from the previous recursive function callstack.
function assemble_from_ir(ir_sexp) {
const input_stack = []; // [depth, SExp]
const return_value_stack = []; // [depth, SExp]
let last_return_value;
input_stack.push([0, ir_sexp]);
while (input_stack.length || return_value_stack.length) {
while (return_value_stack.length >= 2) {
if (return_value_stack[return_value_stack.length - 1][0] !== return_value_stack[return_value_stack.length - 2][0]) {
break;
}
const sexp_1 = return_value_stack.pop();
const sexp_2 = return_value_stack.pop();
last_return_value = sexp_1[1].cons(sexp_2[1]);
return_value_stack.push([sexp_1[0] - 1, last_return_value]);
}
if (!input_stack.length) {
if (return_value_stack.length === 1) {
break;
}
continue;
}
const depth_and_sexp = input_stack.pop();
ir_sexp = depth_and_sexp[1];
let keyword = utils_1.ir_as_symbol(ir_sexp);
if (keyword) {
if (keyword[0] === "#") {
keyword = keyword.substring(1);
}
const atom = clvm_1.KEYWORD_TO_ATOM[keyword];
if (atom) {
last_return_value = clvm_1.SExp.to(clvm_1.h(atom));
return_value_stack.push([depth_and_sexp[0], last_return_value]);
continue;
}
else {
last_return_value = utils_1.ir_val(ir_sexp);
return_value_stack.push([depth_and_sexp[0], last_return_value]);
continue;
}
// Original code raises an Error, which never reaches.
// throw new SyntaxError(`can't parse ${keyrowd} at ${ir_sexp._offset}`);
}
if (!utils_1.ir_listp(ir_sexp)) {
last_return_value = utils_1.ir_val(ir_sexp);
return_value_stack.push([depth_and_sexp[0], last_return_value]);
continue;
}
if (utils_1.ir_nullp(ir_sexp)) {
last_return_value = clvm_1.SExp.to([]);
return_value_stack.push([depth_and_sexp[0], last_return_value]);
continue;
}
// handle "q"
const first = utils_1.ir_first(ir_sexp);
keyword = utils_1.ir_as_symbol(first);
if (keyword === "q") {
// pass;
}
const depth = depth_and_sexp[0] + 1;
input_stack.push([depth, first]);
input_stack.push([depth, utils_1.ir_rest(ir_sexp)]);
}
return last_return_value;
}
exports.assemble_from_ir = assemble_from_ir;
function type_for_atom(atom) {
if (atom.length > 2) {
try {
const v = atom.decode();
if (isPrintable(v)) {
return Type_1.Type.QUOTES.i;
}
}
catch (e) {
// do nothing
}
return Type_1.Type.HEX.i;
}
if (clvm_1.int_to_bytes(clvm_1.int_from_bytes(atom, { signed: true }), { signed: true }).equal_to(atom)) {
return Type_1.Type.INT.i;
}
return Type_1.Type.HEX.i;
}
exports.type_for_atom = type_for_atom;
function disassemble_to_ir(sexp, keyword_from_atom, allow_keyword) {
if (utils_1.is_ir(sexp) && allow_keyword !== false) {
return utils_1.ir_cons(utils_1.ir_symbol("ir"), sexp);
}
if (sexp.listp()) {
if (sexp.first().listp() || allow_keyword !== false) {
allow_keyword = true;
}
const v0 = disassemble_to_ir(sexp.first(), keyword_from_atom, allow_keyword);
const v1 = disassemble_to_ir(sexp.rest(), keyword_from_atom, false);
return utils_1.ir_cons(v0, v1);
}
const as_atom = sexp.atom;
if (allow_keyword) {
const v = keyword_from_atom[as_atom.hex()];
if (v && v !== ".") {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return utils_1.ir_symbol(v); // @todo Find a good way not to use `ts-ignore`
}
}
if (sexp.nullp()) {
return utils_1.ir_null();
}
return clvm_1.SExp.to(clvm_1.t(type_for_atom(as_atom), as_atom));
}
exports.disassemble_to_ir = disassemble_to_ir;
function disassemble(sexp, keyword_from_atom = clvm_1.KEYWORD_FROM_ATOM) {
const symbols = disassemble_to_ir(sexp, keyword_from_atom);
return writer_1.write_ir(symbols);
}
exports.disassemble = disassemble;
function assemble(s) {
const symbols = reader_1.read_ir(s);
return assemble_from_ir(symbols);
}
exports.assemble = assemble;