UNPKG

js-slang

Version:

Javascript-based implementations of Source, written in Typescript

122 lines 5.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StepperBinaryExpression = void 0; const __1 = require("../.."); const generator_1 = require("../../generator"); const Literal_1 = require("./Literal"); class StepperBinaryExpression { constructor(operator, left, right, leadingComments, trailingComments, loc, range) { this.type = 'BinaryExpression'; this.operator = operator; this.left = left; this.right = right; this.leadingComments = leadingComments; this.trailingComments = trailingComments; this.loc = loc; this.range = range; } static create(node) { return new StepperBinaryExpression(node.operator, (0, generator_1.convert)(node.left), (0, generator_1.convert)(node.right), node.leadingComments, node.trailingComments, node.loc, node.range); } isContractible() { if (this.left.type !== 'Literal' || this.right.type !== 'Literal') { return false; } const leftType = typeof this.left.value; const rightType = typeof this.right.value; const markContractible = () => { __1.redex.preRedex = [this]; return true; }; if (leftType === 'boolean') { throw new Error(`Line ${this.loc?.start.line || 0}: Expected number or string on left hand side of operation, got ${leftType}.`); } if (leftType === 'string' && rightType === 'string') { if (['+', '===', '!==', '<', '>', '<=', '>='].includes(this.operator)) { return markContractible(); } else { throw new Error(`Line ${this.loc?.start.line || 0}: Expected number on left hand side of operation, got ${leftType}.`); } } if (leftType === 'string') { if (['+', '===', '!==', '<', '>', '<=', '>='].includes(this.operator)) { throw new Error(`Line ${this.loc?.start.line || 0}: Expected string on right hand side of operation, got ${rightType}.`); } else { throw new Error(`Line ${this.loc?.start.line || 0}: Expected number on left hand side of operation, got ${leftType}.`); } } if (leftType === 'number' && rightType === 'number') { if (['*', '+', '/', '-', '===', '!==', '<', '>', '<=', '>=', '%'].includes(this.operator)) { return markContractible(); } } if (leftType === 'number') { throw new Error(`Line ${this.loc?.start.line || 0}: Expected number on right hand side of operation, got ${rightType}.`); } return false; } isOneStepPossible() { return this.isContractible() || this.left.isOneStepPossible() || this.right.isOneStepPossible(); } contract() { __1.redex.preRedex = [this]; if (this.left.type !== 'Literal' || this.right.type !== 'Literal') throw new Error(); const left = this.left.value; const right = this.right.value; const op = this.operator; const value = this.operator === '&&' ? left && right : op === '||' ? left || right : op === '+' && typeof left === 'number' && typeof right === 'number' ? left + right : op === '+' && typeof left === 'string' && typeof right === 'string' ? left + right : op === '-' ? left - right : op === '*' ? left * right : op === '%' ? left % right : op === '/' ? left / right : op === '===' ? left === right : op === '!==' ? left !== right : op === '<' ? left < right : op === '<=' ? left <= right : op === '>=' ? left >= right : left > right; let ret = new Literal_1.StepperLiteral(value, value !== null ? value.toString() : 'null', undefined, undefined, this.loc, this.range); __1.redex.postRedex = [ret]; return ret; } oneStep() { return this.isContractible() ? this.contract() : this.left.isOneStepPossible() ? new StepperBinaryExpression(this.operator, this.left.oneStep(), this.right) : new StepperBinaryExpression(this.operator, this.left, this.right.oneStep()); } substitute(id, value) { return new StepperBinaryExpression(this.operator, this.left.substitute(id, value), this.right.substitute(id, value), this.leadingComments, this.trailingComments, this.loc, this.range); } freeNames() { return Array.from(new Set([this.left.freeNames(), this.right.freeNames()].flat())); } allNames() { return Array.from(new Set([this.left.allNames(), this.right.allNames()].flat())); } rename(before, after) { return new StepperBinaryExpression(this.operator, this.left.rename(before, after), this.right.rename(before, after), this.leadingComments, this.trailingComments, this.loc, this.range); } } exports.StepperBinaryExpression = StepperBinaryExpression; //# sourceMappingURL=BinaryExpression.js.map