js-slang
Version:
Javascript-based implementations of Source, written in Typescript
82 lines • 3.66 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StepperLogicalExpression = void 0;
const __1 = require("../..");
const generator_1 = require("../../generator");
const Literal_1 = require("./Literal");
class StepperLogicalExpression {
constructor(operator, left, right, leadingComments, trailingComments, loc, range) {
this.type = 'LogicalExpression';
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 StepperLogicalExpression(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') {
const leftType = typeof this.left.value;
if (leftType !== 'boolean') {
throw new Error(`Line ${this.loc?.start.line || 0}: Expected boolean on left hand side of operation, got ${leftType}.`);
}
__1.redex.preRedex = [this];
return true;
}
return false;
}
isOneStepPossible() {
return this.isContractible() || this.left.isOneStepPossible() || this.right.isOneStepPossible();
}
contract() {
__1.redex.preRedex = [this];
if (this.left.type !== 'Literal')
throw new Error('Left operand must be a literal to contract');
const leftValue = this.left.value;
if (this.operator === '&&' && !leftValue) {
let ret = new Literal_1.StepperLiteral(false, undefined, this.leadingComments, this.trailingComments, this.loc, this.range);
__1.redex.postRedex = [ret];
return ret;
}
else if (this.operator === '||' && leftValue) {
let ret = new Literal_1.StepperLiteral(true, undefined, this.leadingComments, this.trailingComments, this.loc, this.range);
__1.redex.postRedex = [ret];
return ret;
}
else {
return this.right;
}
}
oneStep() {
if (this.isContractible()) {
return this.contract();
}
else if (this.left.isOneStepPossible()) {
return new StepperLogicalExpression(this.operator, this.left.oneStep(), this.right, this.leadingComments, this.trailingComments, this.loc, this.range);
}
else if (this.right.isOneStepPossible()) {
return new StepperLogicalExpression(this.operator, this.left, this.right.oneStep(), this.leadingComments, this.trailingComments, this.loc, this.range);
}
else {
throw new Error('No step possible');
}
}
substitute(id, value) {
return new StepperLogicalExpression(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 StepperLogicalExpression(this.operator, this.left.rename(before, after), this.right.rename(before, after), this.leadingComments, this.trailingComments, this.loc, this.range);
}
}
exports.StepperLogicalExpression = StepperLogicalExpression;
//# sourceMappingURL=LogicalExpression.js.map