UNPKG

js-slang

Version:

Javascript-based implementations of Source, written in Typescript

106 lines 4.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StepperUnaryExpression = void 0; const __1 = require("../.."); const generator_1 = require("../../generator"); const Literal_1 = require("./Literal"); class StepperUnaryExpression { constructor(operator, argument, leadingComments, trailingComments, loc, range) { this.type = 'UnaryExpression'; this.operator = operator; this.prefix = true; this.argument = argument; this.leadingComments = leadingComments; this.trailingComments = trailingComments; this.loc = loc; this.range = range; } static createLiteral(node) { // if node argument is positive literal(x) and node operator is "-", we replace them with literal(-x) instead. if (node.operator === '-' && node.argument.type === 'Literal' && typeof node.argument.value === 'number' && node.argument.value > 0) { return new Literal_1.StepperLiteral(-node.argument.value, (-node.argument.value).toString(), node.leadingComments, node.trailingComments, node.loc, node.range); } return undefined; } static create(node) { const literal = StepperUnaryExpression.createLiteral(node); if (literal) { return literal; } return new StepperUnaryExpression(node.operator, (0, generator_1.convert)(node.argument), node.leadingComments, node.trailingComments, node.loc, node.range); } isContractible() { if (this.argument.type !== 'Literal') return false; const valueType = typeof this.argument.value; const markContractible = () => { __1.redex.preRedex = [this]; return true; }; switch (this.operator) { case '!': if (valueType === 'boolean') { return markContractible(); } else { throw new Error(`Line ${this.loc?.start.line || 0}: Expected boolean, got ${valueType}.`); } case '-': if (valueType === 'number') { return markContractible(); } else { throw new Error(`Line ${this.loc?.start.line || 0}: Expected number, got ${valueType}.`); } default: return false; } } isOneStepPossible() { return this.isContractible() || this.argument.isOneStepPossible(); } contract() { __1.redex.preRedex = [this]; if (this.argument.type !== 'Literal') throw new Error(); const operand = this.argument.value; if (this.operator === '!') { const ret = new Literal_1.StepperLiteral(!operand, undefined, this.leadingComments, this.trailingComments, this.loc, this.range); __1.redex.postRedex = [ret]; return ret; } else if (this.operator === '-') { const ret = new Literal_1.StepperLiteral(-operand, (-operand).toString(), this.leadingComments, this.trailingComments, this.loc, this.range); __1.redex.postRedex = [ret]; return ret; } throw new Error(); } oneStep() { if (this.isContractible()) { return this.contract(); } const res = new StepperUnaryExpression(this.operator, this.argument.oneStep(), this.leadingComments, this.trailingComments, this.loc, this.range); const literal = StepperUnaryExpression.createLiteral(res); return literal ? literal : res; } substitute(id, value) { const res = new StepperUnaryExpression(this.operator, this.argument.substitute(id, value), this.leadingComments, this.trailingComments, this.loc, this.range); const literal = StepperUnaryExpression.createLiteral(res); return literal ? literal : res; } freeNames() { return this.argument.freeNames(); } allNames() { return this.argument.allNames(); } rename(before, after) { return new StepperUnaryExpression(this.operator, this.argument.rename(before, after), this.leadingComments, this.trailingComments, this.loc, this.range); } } exports.StepperUnaryExpression = StepperUnaryExpression; //# sourceMappingURL=UnaryExpression.js.map