silphius/app/astride/evaluators/assignment.test.js
2024-06-22 10:47:17 -05:00

272 lines
7.9 KiB
JavaScript

import {expect, test} from 'vitest';
import evaluate from '@/astride/evaluate.js';
import expression from '@/astride/test/expression.js';
const scopeTest = test.extend({
scope: async ({}, use) => {
await use({
S: {O: {}},
get(k) { return this.S[k]; },
set(k, v) { return this.S[k] = v; }
});
},
});
scopeTest('evaluates =', async ({scope}) => {
expect(evaluate(await expression('x = 4'), {scope}))
.to.deep.include({value: 4});
expect(scope.get('x'))
.to.equal(4);
expect(evaluate(await expression('O.x = 8'), {scope}))
.to.deep.include({value: 8});
expect(scope.get('O').x)
.to.equal(8);
expect(evaluate(await expression('O["y"] = 16'), {scope}))
.to.deep.include({value: 16});
expect(scope.get('O').y)
.to.equal(16);
});
scopeTest('evaluates +=', async ({scope}) => {
scope.set('x', 1);
expect(evaluate(await expression('x += 4'), {scope}))
.to.deep.include({value: 5});
expect(scope.get('x'))
.to.equal(5);
scope.set('O', {x: 1});
expect(evaluate(await expression('O.x += 4'), {scope}))
.to.deep.include({value: 5});
expect(scope.get('O').x)
.to.equal(5);
});
scopeTest('evaluates -=', async ({scope}) => {
scope.set('x', 5);
expect(evaluate(await expression('x -= 4'), {scope}))
.to.deep.include({value: 1});
expect(scope.get('x'))
.to.equal(1);
scope.set('O', {x: 5});
expect(evaluate(await expression('O.x -= 4'), {scope}))
.to.deep.include({value: 1});
expect(scope.get('O').x)
.to.equal(1);
});
scopeTest('evaluates *=', async ({scope}) => {
scope.set('x', 5);
expect(evaluate(await expression('x *= 4'), {scope}))
.to.deep.include({value: 20});
expect(scope.get('x'))
.to.equal(20);
scope.set('O', {x: 5});
expect(evaluate(await expression('O.x *= 4'), {scope}))
.to.deep.include({value: 20});
expect(scope.get('O').x)
.to.equal(20);
});
scopeTest('evaluates /=', async ({scope}) => {
scope.set('x', 25);
expect(evaluate(await expression('x /= 5'), {scope}))
.to.deep.include({value: 5});
expect(scope.get('x'))
.to.equal(5);
scope.set('O', {x: 25});
expect(evaluate(await expression('O.x /= 5'), {scope}))
.to.deep.include({value: 5});
expect(scope.get('O').x)
.to.equal(5);
});
scopeTest('evaluates %=', async ({scope}) => {
scope.set('x', 5);
expect(evaluate(await expression('x %= 2'), {scope}))
.to.deep.include({value: 1});
expect(scope.get('x'))
.to.equal(1);
scope.set('O', {x: 5});
expect(evaluate(await expression('O.x %= 2'), {scope}))
.to.deep.include({value: 1});
expect(scope.get('O').x)
.to.equal(1);
});
scopeTest('evaluates **=', async ({scope}) => {
scope.set('x', 5);
expect(evaluate(await expression('x **= 3'), {scope}))
.to.deep.include({value: 125});
expect(scope.get('x'))
.to.equal(125);
scope.set('O', {x: 5});
expect(evaluate(await expression('O.x **= 3'), {scope}))
.to.deep.include({value: 125});
expect(scope.get('O').x)
.to.equal(125);
});
scopeTest('evaluates <<=', async ({scope}) => {
scope.set('x', 2);
expect(evaluate(await expression('x <<= 1'), {scope}))
.to.deep.include({value: 4});
expect(scope.get('x'))
.to.equal(4);
scope.set('O', {x: 2});
expect(evaluate(await expression('O.x <<= 1'), {scope}))
.to.deep.include({value: 4});
expect(scope.get('O').x)
.to.equal(4);
});
scopeTest('evaluates >>=', async ({scope}) => {
scope.set('x', 8);
expect(evaluate(await expression('x >>= 2'), {scope}))
.to.deep.include({value: 2});
expect(scope.get('x'))
.to.equal(2);
scope.set('O', {x: 8});
expect(evaluate(await expression('O.x >>= 2'), {scope}))
.to.deep.include({value: 2});
expect(scope.get('O').x)
.to.equal(2);
});
scopeTest('evaluates >>>=', async ({scope}) => {
scope.set('x', -1);
expect(evaluate(await expression('x >>>= 1'), {scope}))
.to.deep.include({value: 2147483647});
expect(scope.get('x'))
.to.equal(2147483647);
scope.set('O', {x: -1});
expect(evaluate(await expression('O.x >>>= 1'), {scope}))
.to.deep.include({value: 2147483647});
expect(scope.get('O').x)
.to.equal(2147483647);
});
scopeTest('evaluates |=', async ({scope}) => {
scope.set('x', 3);
expect(evaluate(await expression('x |= 5'), {scope}))
.to.deep.include({value: 7});
expect(scope.get('x'))
.to.equal(7);
scope.set('O', {x: 3});
expect(evaluate(await expression('O.x |= 5'), {scope}))
.to.deep.include({value: 7});
expect(scope.get('O').x)
.to.equal(7);
});
scopeTest('evaluates ^=', async ({scope}) => {
scope.set('x', 7);
expect(evaluate(await expression('x ^= 2'), {scope}))
.to.deep.include({value: 5});
expect(scope.get('x'))
.to.equal(5);
scope.set('O', {x: 7});
expect(evaluate(await expression('O.x ^= 2'), {scope}))
.to.deep.include({value: 5});
expect(scope.get('O').x)
.to.equal(5);
});
scopeTest('evaluates &=', async ({scope}) => {
scope.set('x', 5);
expect(evaluate(await expression('x &= 3'), {scope}))
.to.deep.include({value: 1});
expect(scope.get('x'))
.to.equal(1);
scope.set('O', {x: 5});
expect(evaluate(await expression('O.x &= 3'), {scope}))
.to.deep.include({value: 1});
expect(scope.get('O').x)
.to.equal(1);
});
scopeTest('evaluates ||=', async ({scope}) => {
scope.set('x', false);
expect(evaluate(await expression('x ||= true'), {scope}))
.to.deep.include({value: true});
expect(scope.get('x'))
.to.equal(true);
scope.set('O', {x: false});
expect(evaluate(await expression('O.x ||= true'), {scope}))
.to.deep.include({value: true});
expect(scope.get('O').x)
.to.equal(true);
});
scopeTest('evaluates &&=', async ({scope}) => {
scope.set('x', true);
expect(evaluate(await expression('x &&= true'), {scope}))
.to.deep.include({value: true});
expect(scope.get('x'))
.to.equal(true);
expect(evaluate(await expression('x &&= false'), {scope}))
.to.deep.include({value: false});
expect(scope.get('x'))
.to.equal(false);
scope.set('O', {x: true});
expect(evaluate(await expression('O.x &&= true'), {scope}))
.to.deep.include({value: true});
expect(scope.get('O').x)
.to.equal(true);
expect(evaluate(await expression('O.x &&= false'), {scope}))
.to.deep.include({value: false});
expect(scope.get('O').x)
.to.equal(false);
});
scopeTest('evaluates ??=', async ({scope}) => {
scope.set('x', null);
expect(evaluate(await expression('x ??= 2'), {scope}))
.to.deep.include({value: 2});
expect(scope.get('x'))
.to.equal(2);
expect(evaluate(await expression('x ??= 4'), {scope}))
.to.deep.include({value: 2});
expect(scope.get('x'))
.to.equal(2);
scope.set('O', {x: null});
expect(evaluate(await expression('O.x ??= 2'), {scope}))
.to.deep.include({value: 2});
expect(scope.get('O').x)
.to.equal(2);
expect(evaluate(await expression('O.x ??= 4'), {scope}))
.to.deep.include({value: 2});
expect(scope.get('O').x)
.to.equal(2);
});
scopeTest('evaluates promised assignment', async ({scope}) => {
const evaluated = evaluate(await expression('x = await 4'), {scope});
expect(evaluated.async)
.to.equal(true);
expect(await evaluated.value)
.to.equal(4);
expect(await scope.get('x'))
.to.equal(4);
const evaluatedComputedObject = evaluate(await expression('O["x"] = await 4'), {scope});
expect(evaluatedComputedObject.async)
.to.equal(true);
expect(await evaluatedComputedObject.value)
.to.equal(4);
expect(await scope.get('O').x)
.to.equal(4);
const evaluatedObject = evaluate(await expression('O.x = await 4'), {scope});
expect(evaluatedObject.async)
.to.equal(true);
expect(await evaluatedObject.value)
.to.equal(4);
expect(await scope.get('O').x)
.to.equal(4);
const evaluatedPromisedObject = evaluate(await expression('(await O).x = await 4'), {scope});
expect(evaluatedPromisedObject.async)
.to.equal(true);
expect(await evaluatedPromisedObject.value)
.to.equal(4);
expect(await scope.get('O').x)
.to.equal(4);
});