ton-assembly
Version:
TON assembler and disassembler
197 lines • 6.86 kB
JavaScript
;
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