llparse
Version:
Compile incremental parsers to C code
58 lines • 2.22 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MulAdd = void 0;
const assert = require("assert");
const constants_1 = require("../constants");
const field_1 = require("./field");
class MulAdd extends field_1.Field {
doBuild(ctx, out) {
const options = this.ref.options;
const ty = ctx.getFieldType(this.ref.field);
let field = this.field(ctx);
if (options.signed) {
assert(constants_1.SIGNED_TYPES.has(ty), `Unexpected mulAdd type "${ty}"`);
const targetTy = constants_1.SIGNED_TYPES.get(ty);
out.push(`${targetTy}* field = (${targetTy}*) &${field};`);
field = '(*field)';
}
const match = ctx.matchVar();
const limits = options.signed ? constants_1.SIGNED_LIMITS : constants_1.UNSIGNED_LIMITS;
assert(limits.has(ty), `Unexpected mulAdd type "${ty}"`);
const [min, max] = limits.get(ty);
const mulMax = `${max} / ${options.base}`;
const mulMin = `${min} / ${options.base}`;
out.push('/* Multiplication overflow */');
out.push(`if (${field} > ${mulMax}) {`);
out.push(' return 1;');
out.push('}');
if (options.signed) {
out.push(`if (${field} < ${mulMin}) {`);
out.push(' return 1;');
out.push('}');
}
out.push('');
out.push(`${field} *= ${options.base};`);
out.push('');
out.push('/* Addition overflow */');
out.push(`if (${match} >= 0) {`);
out.push(` if (${field} > ${max} - ${match}) {`);
out.push(' return 1;');
out.push(' }');
out.push('} else {');
out.push(` if (${field} < ${min} - ${match}) {`);
out.push(' return 1;');
out.push(' }');
out.push('}');
out.push(`${field} += ${match};`);
if (options.max !== undefined) {
out.push('');
out.push('/* Enforce maximum */');
out.push(`if (${field} > ${options.max}) {`);
out.push(' return 1;');
out.push('}');
}
out.push('return 0;');
}
}
exports.MulAdd = MulAdd;
//# sourceMappingURL=mul-add.js.map