ton-assembly
Version:
TON assembler and disassembler
436 lines • 15.9 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.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