UNPKG

clvm_tools

Version:

Javascript implementation of clvm_tools

136 lines (135 loc) 5.26 kB
"use strict"; 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;