UNPKG

ton-assembly

Version:

TON assembler and disassembler

197 lines 6.86 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.decompileCell = exports.decompile = exports.compileCellWithMapping = exports.compileCell = exports.compile = exports.DEFAULT_STORE_OPTIONS = exports.parseExotic = exports.codeType = exports.instr = void 0; const $ = __importStar(require("./util")); const G = __importStar(require("@ton/core")); const c = __importStar(require("./constructors")); const constructors_1 = require("./constructors"); const instr_gen_1 = require("./instr-gen"); const builder_1 = require("./builder"); const compile_1 = require("./compile"); exports.instr = { store: (b, t, options) => { if (t.$ === "PSEUDO_PUSHREF") { $.PSEUDO_PUSHREF.store(b, t, options); return; } if (t.$ === "PSEUDO_PUSHSLICE") { $.PSEUDO_PUSHSLICE.store(b, t, options); return; } if (t.$ === "PSEUDO_EXOTIC") { $.PSEUDO_EXOTIC.store(b, t, options); return; } const store = instr_gen_1.storeMapping.get(t.$); if (!store) { throw new Error("unknown instruction"); } store(b, t, options); }, load: getLoadInstr(instr_gen_1.rangeToType), }; const codeType = () => { const processCell = (cell) => { if (cell.isExotic) { return [(0, exports.parseExotic)(cell)]; } return (0, exports.codeType)().load(cell.asSlice()); }; return { load: slice => { const arr = []; const sliceBackup = slice.clone(); while (slice.remainingBits > 0) { try { arr.push(exports.instr.load(slice)); } catch { return [c.PSEUDO_PUSHSLICE(sliceBackup)]; } } while (slice.remainingRefs > 0) { const source = slice.loadRef(); const instructions = processCell(source); arr.push(c.PSEUDO_PUSHREF($.decompiledCode(instructions))); } return arr; }, store(b, t, options) { (0, compile_1.compileInstructions)(b, t, options); }, }; }; exports.codeType = codeType; function DummyOpcode(min, max) { return { min, max, load: s => { throw new Error(`invalid opcode, slice: ${s.asCell().toString()}`); }, }; } function getLoadInstr(instructionList) { const list = []; const MAX_OPCODE_BITS = 24; const top_opcode = 1 << MAX_OPCODE_BITS; const sorted = instructionList.sort((a, b) => a.min - b.min); let upto = 0; for (const instruction of sorted) { const { min, max } = instruction; if (min === max && min === 0) continue; // skip pseudo instructions assert(min < max); assert(min >= upto); assert(max <= top_opcode); if (upto < min) { list.push(DummyOpcode(upto, min)); } list.push(instruction); upto = max; } if (upto < top_opcode) { list.push(DummyOpcode(upto, top_opcode)); } return (s) => { const bits = Math.min(s.remainingBits, 24); const opcode = s.preloadUint(bits) << (24 - bits); let i = 0; let j = list.length; while (j - i > 1) { const k = (j + i) >> 1; const kElement = list[k]; if (kElement === undefined) break; if (kElement.min <= opcode) { i = k; } else { j = k; } } const instr = list[i]; if (bits < 8) { throw new Error(`invalid opcode, not enough bits, expected at least 8 bits, but got ${bits}`); } if (!instr) { throw new Error(`invalid opcode, slice: ${s.asCell().toString()}`); } return instr.load(s); }; } const parseExotic = (cell) => { const slice = cell.beginParse(true); return (0, constructors_1.PSEUDO_EXOTIC)($.exotic.load(slice)); }; exports.parseExotic = parseExotic; exports.DEFAULT_STORE_OPTIONS = { skipRefs: false }; const compile = (instructions, options = exports.DEFAULT_STORE_OPTIONS) => { return (0, exports.compileCell)(instructions, options).toBoc(); }; exports.compile = compile; const compileCell = (instructions, options = exports.DEFAULT_STORE_OPTIONS) => { const b = new builder_1.CodeBuilder(); (0, exports.codeType)().store(b, instructions, options); return b.asCell(); }; exports.compileCell = compileCell; const compileCellWithMapping = (instructions, options = exports.DEFAULT_STORE_OPTIONS, isDictionaryCell = false, offset = 0) => { const b = new builder_1.CodeBuilder(isDictionaryCell, offset); (0, exports.codeType)().store(b, instructions, options); return b.build(); }; exports.compileCellWithMapping = compileCellWithMapping; const decompile = (buffer) => { const boc = G.Cell.fromBoc(buffer)[0]; if (!boc) return []; return (0, exports.decompileCell)(boc); }; exports.decompile = decompile; const decompileCell = (cell) => { if (cell.isExotic) { return [(0, exports.parseExotic)(cell)]; } return (0, exports.codeType)().load(cell.asSlice()); }; exports.decompileCell = decompileCell; function assert(cond) { if (!cond) { throw new Error("assertion failed"); } } //# sourceMappingURL=instr.js.map