UNPKG

ton-assembly

Version:

TON assembler and disassembler

436 lines 15.9 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.dictpushArg = exports.debugstrArg = exports.sliceArg = exports.ifBitArgs = exports.ifElseBitArgs = exports.twoCodeSliceArgs = exports.codeSliceArg = exports.threeStackArgs = exports.threeIntegerArgs = exports.twoStackArgs = exports.twoIntegerArgs = exports.singleBigIntArg = exports.singleControlArg = exports.singleStackArg = exports.singleIntegerArg = exports.processInstructions = exports.createLoc = exports.ParseError = void 0; const util_1 = require("../runtime/util"); const i = __importStar(require("../runtime")); const convert_1 = require("./convert"); const core_1 = require("@ton/core"); class ParseError extends Error { loc; msg; constructor(loc, msg) { super(msg); this.name = "ParseError"; this.loc = loc; this.msg = msg; } toString() { return `${this.name}: ${this.msg} at ${this.loc.file}:${this.loc.line}`; } } exports.ParseError = ParseError; const offsetToLine = (lines, searchOffset) => { let offset = 0; let index = 0; for (const line of lines) { offset += line.length + 1; if (searchOffset < offset) { return index; } index++; } return lines.length - 1; }; const createLoc = (ctx, loc) => { if (loc.$ === "empty") { return { file: ctx.filepath, line: offsetToLine(ctx.lines, loc.at), }; } return { file: ctx.filepath, line: offsetToLine(ctx.lines, loc.start), }; }; exports.createLoc = createLoc; const processInstructions = (ctx, instructions) => { return instructions.map(it => { const loc = (0, exports.createLoc)(ctx, it.loc); try { if (it.$ === "ExplicitRef") { return i.PSEUDO_PUSHREF(i.util.code((0, exports.processInstructions)(ctx, it.code.instructions)), loc); } if (it.$ === "EmbedSlice") { return i.PSEUDO_PUSHSLICE(parseDataLiteral(it.data), loc); } if (it.$ === "Exotic") { if (it.lib.$ === "DefaultExotic") { return i.PSEUDO_EXOTIC((0, util_1.DefaultExoticCell)(parseDataLiteral(it.lib.data).asCell())); } return i.PSEUDO_EXOTIC((0, util_1.LibraryCell)(parseDataLiteral(it.lib.data)), loc); } return (0, convert_1.convertInstruction)(ctx, it, loc); } catch (error) { if (typeof error === "string") { throw new ParseError(loc, error); } if (error instanceof Error) { throw new ParseError(loc, error.message); } throw error; } }); }; exports.processInstructions = processInstructions; const singleIntegerArg = (instr) => { const [arg0raw] = instr.args; if (!arg0raw) { throw new Error(`Expected 1 argument`); } const arg = arg0raw.expression; if (arg.$ !== "IntegerLiteral") { throw new Error(`Expected integer literal argument, got ${arg.$}`); } return parseNumber(arg); }; exports.singleIntegerArg = singleIntegerArg; const singleStackArg = (instr) => { const [arg0raw] = instr.args; if (!arg0raw) { throw new Error(`Expected 1 argument`); } const arg = arg0raw.expression; if (arg.$ !== "StackElement") { throw new Error(`Expected stack element argument, got ${arg.$}`); } return parseStackElement(arg); }; exports.singleStackArg = singleStackArg; const singleControlArg = (instr) => { const [arg0raw] = instr.args; if (!arg0raw) { throw new Error(`Expected 1 argument`); } const arg = arg0raw.expression; if (arg.$ !== "ControlRegister") { throw new Error(`Expected control register argument, got ${arg.$}`); } const number = Number.parseInt(arg.value.slice(1)); if (number === 6) { throw new Error(`c6 doesn't exist`); } return number; }; exports.singleControlArg = singleControlArg; const singleBigIntArg = (instr) => { const [arg0raw] = instr.args; if (!arg0raw) { throw new Error(`Expected 1 argument`); } const arg = arg0raw.expression; if (arg.$ !== "IntegerLiteral") { throw new Error(`Expected integer literal argument, got ${arg.$}`); } return parseBigNum(arg); }; exports.singleBigIntArg = singleBigIntArg; const twoIntegerArgs = (instr) => { const [arg0raw, arg1raw] = instr.args; if (!arg0raw || !arg1raw) { throw new Error(`Expected 2 arguments`); } const arg = arg0raw.expression; if (arg.$ !== "IntegerLiteral") { throw new Error(`Expected integer literal argument 1, got ${arg.$}`); } const arg2 = arg1raw.expression; if (arg2.$ !== "IntegerLiteral") { throw new Error(`Expected integer literal argument 2, got ${arg2.$}`); } return [parseNumber(arg), parseNumber(arg2)]; }; exports.twoIntegerArgs = twoIntegerArgs; const twoStackArgs = (instr) => { const [arg0raw, arg1raw] = instr.args; if (!arg0raw || !arg1raw) { throw new Error(`Expected 2 arguments`); } const arg = arg0raw.expression; if (arg.$ !== "StackElement") { throw new Error(`Expected stack element argument 1, got ${arg.$}`); } const arg2 = arg1raw.expression; if (arg2.$ !== "StackElement") { throw new Error(`Expected stack element argument 2, got ${arg2.$}`); } return [parseStackElement(arg), parseStackElement(arg2)]; }; exports.twoStackArgs = twoStackArgs; const threeIntegerArgs = (instr) => { const [arg0raw, arg1raw, arg2raw] = instr.args; if (!arg0raw || !arg1raw || !arg2raw) { throw new Error(`Expected 3 arguments`); } const arg = arg0raw.expression; if (arg.$ !== "IntegerLiteral") { throw new Error(`Expected integer literal argument 1, got ${arg.$}`); } const arg2 = arg1raw.expression; if (arg2.$ !== "IntegerLiteral") { throw new Error(`Expected integer literal argument 2, got ${arg2.$}`); } const arg3 = arg2raw.expression; if (arg3.$ !== "IntegerLiteral") { throw new Error(`Expected integer literal argument 3, got ${arg3.$}`); } return [parseNumber(arg), parseNumber(arg2), parseNumber(arg3)]; }; exports.threeIntegerArgs = threeIntegerArgs; const threeStackArgs = (instr) => { const [arg0raw, arg1raw, arg2raw] = instr.args; if (!arg0raw || !arg1raw || !arg2raw) { throw new Error(`Expected 3 arguments`); } const arg = arg0raw.expression; if (arg.$ !== "StackElement") { throw new Error(`Expected stack element argument 1, got ${arg.$}`); } const arg2 = arg1raw.expression; if (arg2.$ !== "StackElement") { throw new Error(`Expected stack element argument 2, got ${arg2.$}`); } const arg3 = arg2raw.expression; if (arg3.$ !== "StackElement") { throw new Error(`Expected stack element argument 3, got ${arg3.$}`); } return [parseStackElement(arg), parseStackElement(arg2), parseStackElement(arg3)]; }; exports.threeStackArgs = threeStackArgs; const codeSliceArg = (ctx, instr) => { const [arg0raw] = instr.args; if (!arg0raw) { throw new Error(`Expected 1 argument`); } const arg = arg0raw.expression; if (arg.$ !== "Code" && arg.$ !== "DataLiteral") { throw new Error(`Expected code or data literal argument, got ${arg.$}`); } if (arg.$ === "DataLiteral") { return processRawSliceCode(arg); } return (0, util_1.decompiledCode)((0, exports.processInstructions)(ctx, arg.instructions)); }; exports.codeSliceArg = codeSliceArg; const twoCodeSliceArgs = (ctx, instr) => { const [arg0raw, arg1raw] = instr.args; if (!arg0raw || !arg1raw) { throw new Error(`Expected 2 arguments`); } const arg = arg0raw.expression; if (arg.$ !== "Code" && arg.$ !== "DataLiteral") { throw new Error(`Expected code or data literal argument 1, got ${arg.$}`); } const arg1 = arg1raw.expression; if (arg1.$ !== "Code" && arg1.$ !== "DataLiteral") { throw new Error(`Expected code or data literal argument 2, got ${arg1.$}`); } const first = arg.$ === "DataLiteral" ? processRawSliceCode(arg) : (0, util_1.decompiledCode)((0, exports.processInstructions)(ctx, arg.instructions)); const second = arg1.$ === "DataLiteral" ? processRawSliceCode(arg1) : (0, util_1.decompiledCode)((0, exports.processInstructions)(ctx, arg1.instructions)); return [first, second]; }; exports.twoCodeSliceArgs = twoCodeSliceArgs; const ifElseBitArgs = (ctx, instr) => { const [arg0raw, arg1raw, arg2raw] = instr.args; if (!arg0raw || !arg1raw || !arg2raw) { throw new Error(`Expected 3 arguments`); } const arg0 = arg0raw.expression; if (arg0.$ !== "IntegerLiteral") { throw new Error(`Expected integer literal argument 1, got ${arg0.$}`); } const arg1 = arg1raw.expression; if (arg1.$ !== "Code" && arg1.$ !== "DataLiteral") { throw new Error(`Expected code or data literal argument 2, got ${arg1.$}`); } const arg2 = arg2raw.expression; if (arg2.$ !== "Code" && arg2.$ !== "DataLiteral") { throw new Error(`Expected code or data literal argument 3, got ${arg2.$}`); } const second = arg1.$ === "DataLiteral" ? processRawSliceCode(arg1) : (0, util_1.decompiledCode)((0, exports.processInstructions)(ctx, arg1.instructions)); const third = arg2.$ === "DataLiteral" ? processRawSliceCode(arg2) : (0, util_1.decompiledCode)((0, exports.processInstructions)(ctx, arg2.instructions)); return [parseNumber(arg0), second, third]; }; exports.ifElseBitArgs = ifElseBitArgs; const ifBitArgs = (ctx, instr) => { const [arg0raw, arg1raw] = instr.args; if (!arg0raw || !arg1raw) { throw new Error(`Expected 2 arguments`); } const arg = arg0raw.expression; if (arg.$ !== "IntegerLiteral") { throw new Error(`Expected integer literal argument 1, got ${arg.$}`); } const arg1 = arg1raw.expression; if (arg1.$ !== "Code" && arg1.$ !== "DataLiteral") { throw new Error(`Expected code or data literal argument 2, got ${arg1.$}`); } const second = arg1.$ === "DataLiteral" ? processRawSliceCode(arg1) : (0, util_1.decompiledCode)((0, exports.processInstructions)(ctx, arg1.instructions)); return [parseNumber(arg), second]; }; exports.ifBitArgs = ifBitArgs; const sliceArg = (instr) => { const [arg0raw] = instr.args; if (!arg0raw) { throw new Error(`Expected 1 argument`); } const arg = arg0raw.expression; if (arg.$ !== "DataLiteral") { throw new Error(`Expected hex, bin or boc literal argument 1, got ${arg.$}`); } return parseDataLiteral(arg); }; exports.sliceArg = sliceArg; const debugstrArg = (instr) => { const [arg0raw] = instr.args; if (!arg0raw) { throw new Error(`Expected 1 argument`); } const arg = arg0raw.expression; if (arg.$ !== "DataLiteral") { throw new Error(`Expected hex, bin or string literal argument 1, got ${arg.$}`); } return parseDataLiteral(arg); }; exports.debugstrArg = debugstrArg; const dictpushArg = (ctx, instr) => { const [arg0raw, arg1raw] = instr.args; if (!arg0raw || !arg1raw) { throw new Error(`Expected 2 arguments`); } const arg0 = arg0raw.expression; if (arg0.$ !== "IntegerLiteral") { throw new Error(`Expected integer argument 1, got ${arg0.$}`); } const keyLength = parseNumber(arg0); const arg1 = arg1raw.expression; if (arg1.$ === "DataLiteral") { const slice = parseDataLiteral(arg1); return [keyLength, i.util.rawDict(slice)]; } if (arg1.$ !== "Dictionary") { throw new Error(`Expected dictionary argument 2, got ${arg1.$}`); } const methods = arg1.entries.map((entry) => { const id = entry.id; const code = entry.code; return { $: "DecompiledMethod", id: parseNumber(id), instructions: (0, exports.processInstructions)(ctx, code.instructions), }; }); return [keyLength, i.util.decompiledDict(methods)]; }; exports.dictpushArg = dictpushArg; const parseDataLiteral = (literal) => { const arg = literal.value; if (arg.$ === "StringLiteral") { return (0, core_1.beginCell)().storeBuffer(Buffer.from(arg.value)).asSlice(); } if (arg.$ === "HexLiteral") { return (0, util_1.hex)(arg.content); } if (arg.$ === "BocLiteral") { return (0, util_1.boc)(arg.content); } return (0, util_1.bin)(arg.content); }; const parseStackElement = (arg) => { const number = arg.value.slice(1); if (number.startsWith("(")) { // (-1) return Number.parseInt(number.slice(1, -1)); } return Number.parseInt(number); }; const parseNumber = (literal) => { const bigNum = parseBigNum(literal); if (bigNum > Number.MAX_SAFE_INTEGER) { throw new Error(`Number argument is too big, max value is ${Number.MAX_SAFE_INTEGER}, but ${bigNum} given`); } if (literal.value.$ === "IntegerLiteralOct") { // special handle for 0o777 const val = Number.parseInt(normalizeUnderscores(literal.value.digits.slice(2)), 8); if (literal.op === "-") { return -val; } return val; } if (literal.value.$ === "IntegerLiteralBin") { // special handle for 0b1111 const val = Number.parseInt(normalizeUnderscores(literal.value.digits.slice(2)), 2); if (literal.op === "-") { return -val; } return val; } const val = Number.parseInt(normalizeUnderscores(literal.value.digits)); if (literal.op === "-") { return -val; } return val; }; const parseBigNum = (literal) => { const val = BigInt(normalizeUnderscores(literal.value.digits)); if (literal.op === "-") { return -val; } return val; }; const normalizeUnderscores = (input) => input.replaceAll("_", ""); const processRawSliceCode = (literal) => { const slice = parseDataLiteral(literal); try { const decompiled = i.decompileCell(slice.asCell()); return (0, util_1.code)(decompiled); } catch { return (0, util_1.rawCode)(slice); } }; //# sourceMappingURL=util.js.map