@ton-community/tlb-runtime
Version:
TL‑B Runtime is a library for parsing and (de)serializing data according to TL‑B schemas
113 lines (112 loc) • 4.17 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MathExprEvaluator = void 0;
const tlb_codegen_1 = require("@ton-community/tlb-codegen");
// Interpreter to evaluate TLBMathExpr at runtime
class MathExprEvaluator {
variables;
constructor(variables = new Map()) {
this.variables = variables;
}
static calculateBitsForLessThan(n) {
if (n <= 0)
return 0;
if (n === 1)
return 0;
const maxValue = n - 1;
if (maxValue === 0)
return 0;
return Math.ceil(Math.log2(maxValue + 1));
}
static calculateBitsForLessThanOrEqual(n) {
if (n < 0)
return 0;
if (n === 0)
return 0;
return Math.ceil(Math.log2(n + 1));
}
evaluate(expr) {
if (expr instanceof tlb_codegen_1.TLBNumberExpr) {
return expr.n;
}
if (expr instanceof tlb_codegen_1.TLBVarExpr) {
const value = this.variables.get(expr.x);
if (value === undefined) {
throw new Error(`Variable ${expr.x} is not defined`);
}
return value;
}
if (expr instanceof tlb_codegen_1.TLBBinaryOp) {
const left = this.evaluate(expr.left);
const right = this.evaluate(expr.right);
switch (expr.operation) {
case '+':
return left + right;
case '-':
return left - right;
case '*':
return left * right;
case '/':
return Math.floor(left / right);
case '%':
return left % right;
case '<<':
return left << right;
case '>>':
return left >> right;
case '&':
return left & right;
case '|':
return left | right;
case '^':
return left ^ right;
case '==':
return left === right ? 1 : 0;
case '!=':
return left !== right ? 1 : 0;
case '<':
return left < right ? 1 : 0;
case '<=':
return left <= right ? 1 : 0;
case '>':
return left > right ? 1 : 0;
case '>=':
return left >= right ? 1 : 0;
case '=':
return left === right ? 1 : 0;
default:
throw new Error(`Unknown operation: ${expr.operation}`);
}
}
if (expr instanceof tlb_codegen_1.TLBUnaryOp) {
const operation = expr.operation;
switch (operation) {
case '.': {
const innerExpr = expr.value;
if (innerExpr instanceof tlb_codegen_1.TLBBinaryOp && innerExpr.operation === '-') {
const left = this.evaluate(innerExpr.left);
const right = this.evaluate(innerExpr.right);
if (right === 1) {
return MathExprEvaluator.calculateBitsForLessThan(left);
}
return left - right;
}
if (innerExpr instanceof tlb_codegen_1.TLBNumberExpr) {
return MathExprEvaluator.calculateBitsForLessThanOrEqual(innerExpr.n);
}
return this.evaluate(innerExpr);
}
case '-':
return -this.evaluate(expr.value);
case '~':
return ~this.evaluate(expr.value);
case '!':
return this.evaluate(expr.value) ? 0 : 1;
default:
throw new Error(`Unknown unary operation: ${operation}`);
}
}
throw new Error(`Unsupported expression type: ${typeof expr}`);
}
}
exports.MathExprEvaluator = MathExprEvaluator;