Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(let): refactor let #526

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
a938eed
Default issue template, proposed by Github
dastin-sandura Oct 25, 2020
ce1de3c
Merge pull request #1 from dastin-sandura/feature-request-issue-template
dastin-sandura Oct 25, 2020
3856a6e
Update feature request issue template
dastin-sandura Oct 25, 2020
2b2c992
Merge pull request #3 from dastin-sandura/feature-request-issute-temp…
dastin-sandura Oct 25, 2020
58a8383
Merge pull request #4 from xFAANG/master
dastin-sandura Oct 28, 2020
7dd2b2b
Changes
dastin-sandura Oct 28, 2020
b0220a7
remove logs, unused function, and check if code === const
dastin-sandura Oct 28, 2020
8905c13
change 'let' test retrieval of a let variable value instead of checki…
dastin-sandura Oct 28, 2020
a3c350c
remove code which runs when using 'assign' from let.ts
dastin-sandura Oct 28, 2020
299c9a8
remove condition on assign, add flag to decide when to throw 'unknown…
dastin-sandura Oct 29, 2020
7a7b517
remove commented code from assign.ts
dastin-sandura Oct 29, 2020
1112880
Test for 'assign' which makes sure that you cannot assign value to a …
dastin-sandura Oct 29, 2020
8fe68fd
Change test naming
dastin-sandura Oct 29, 2020
4b63579
const.test for making sure that const is Object.isFrozen()
dastin-sandura Oct 29, 2020
2962a05
assign test for throwing when assigning value to an undeclared variable
dastin-sandura Oct 29, 2020
f3b4822
assign test for checking assignment to reserved keyword variables
dastin-sandura Oct 29, 2020
6bd4b58
change if to proper jest expect assertion
dastin-sandura Oct 30, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions src/askvm/resources/core/__test__/assign.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { runUntyped } from '../../..';
import { parse } from '../../../../askcode';
import * as core from '../../core';
import { assignRes } from '../assign';

const values = {};

function ask(code: string) {
return runUntyped(
{
resources: { ...core, assignRes },
values,
},
parse(code)
);
}

describe(`assign`, function () {
it(`Should assign a value to a 'let' variable with the assign resource.`, async function () {
const initialValue = 6;
const assignedValue = 4;
const resolvedValue = await ask(
`ask(let('a',${initialValue}),assign('a',${assignedValue}))`
);
expect(resolvedValue).toEqual(assignedValue);
});

it(`Should throw when assigning a value to a constant variable.`, async function () {
const constantName = 'favoriteConst';
await expect(
ask(
`ask(const('${constantName}','Coconut'),assign('${constantName}','Wallnut'))`
)
).rejects.toThrow(
`Cannot assign to a constant variable "${constantName}" because it is a constant.`
);
});

it(`Should throw when assigning a value to a non-declared variable.`, async function () {
await expect(ask(`ask(assign('unrealisticCoco','Nut'))`)).rejects.toThrow(
`Cannot assign to an unknown variable "unrealisticCoco"`
);
});

it(`Should throw when assigning a value to a reserved keyword variable.`, async function () {
const reservedWord = 'resources';
await expect(
ask(`ask(assign('${reservedWord}','CocoResource'))`)
).rejects.toThrow(
`Key "resources" is a reserved keyword and cannot be assigned to.`
);
});
});
44 changes: 44 additions & 0 deletions src/askvm/resources/core/__test__/const.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { runUntyped } from '../../..';
import { parse } from '../../../../askcode';
import * as core from '../../core';
import { constRes } from '../const';

const values = {};

function ask(code: string) {
return runUntyped(
{
resources: { ...core, constRes },
values,
},
parse(code)
);
}

describe(`const`, function () {
it(`should assign value to a const variable on initialization`, async function () {
const value = 6;
await expect(
ask(`ask(const('a',${value}),call(get('get'), 'a'))`)
).resolves.toEqual(value);
});

it(`Creating a const should create a Javascript variable object which is Object.isFrozen()`, async function () {
const value = 6;
const constantVariable = await expect(
ask(`ask(const('a',${value}),call(get('get'), 'a'))`)
).resolves.toEqual(value);
expect(Object.isFrozen(constantVariable)).toBe(true);
});

const reservedWords = ['resources'];

it(`should not allow reserved words as constant name`, async function () {
for (let i = 0; i < reservedWords.length; i++) {
const reservedWord = reservedWords[i];
await expect(ask(`ask(const('resources',6))`)).rejects.toThrow(
`Key "${reservedWord}" cannot be redeclared`
);
}
});
});
20 changes: 2 additions & 18 deletions src/askvm/resources/core/__test__/let.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,13 @@ function ask(code: string) {
}

describe(`let`, function () {
it(`should throw when trying to assign to const`, async function () {
it(`should assign value to a let variable on initialization`, async function () {
const value = 6;
await expect(
ask(`ask(const('a',${value}),call(get('get'),assign('a',4),'a'))`)
).rejects.toThrow(`Cannot assign to a constant variable "a"`);
});

it(`should assign value on initialization`, async function () {
const value = 6;
await expect(
ask(`ask(let('a',${value}),call(get('get'), 'a'))`)
ask(`ask(let('cocoCount',${value}),get('cocoCount'))`)
).resolves.toEqual(value);
});

it(`should assign value with the assign resource`, async function () {
const initialValue = 6;
const assignedValue = 4;
const resolvedValue = await ask(
`ask(let('a',${initialValue}),assign('a',${assignedValue}))`
);
expect(resolvedValue).toEqual(assignedValue);
});

const reservedWords = ['resources'];

it(`should not allow reserved words as variable name`, async function () {
Expand Down
57 changes: 57 additions & 0 deletions src/askvm/resources/core/assign.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import {
any,
resource,
run,
runUntyped,
Options,
TypedValue,
JSONable,
} from '../../lib';

function assignValue(
valueObject: { [key: string]: any },
key: string,
assignedValue: any
) {
if (Object.isFrozen(valueObject[key]))
throw new Error(
`Cannot assign to a constant variable "${key}" because it is a constant.`
);
valueObject[key] = assignedValue;
}

export const assignRes = resource({
type: any,
async compute(options, code, args): Promise<TypedValue<JSONable>> {
const { params: children = [] } = code;

const key: any = await runUntyped(options, children[0]); // FIXME any
dastin-sandura marked this conversation as resolved.
Show resolved Hide resolved
const value = await run(options, children[1]);

if (key === 'resources') {
dastin-sandura marked this conversation as resolved.
Show resolved Hide resolved
throw new Error(
`Key "resources" is a reserved keyword and cannot be assigned to.`
);
}

let keyFound = false;
for (
let prototype: Options | undefined = options;
prototype;
prototype = prototype?.prototype
) {
const { values = {} } = prototype;
if (Object.prototype.hasOwnProperty.call(values, key)) {
assignValue(values, key, value);
keyFound = true;
return value;
}
}
if (keyFound === false)
dastin-sandura marked this conversation as resolved.
Show resolved Hide resolved
throw new Error(`Cannot assign to an unknown variable "${key}"`);

options.values![key] = value;

return value;
},
});
25 changes: 25 additions & 0 deletions src/askvm/resources/core/const.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {
any,
resource,
run,
runUntyped,
TypedValue,
JSONable,
} from '../../lib';

export const constRes = resource({
type: any,
async compute(options, code, args): Promise<TypedValue<JSONable>> {
const { params: children = [] } = code;

const key: any = await runUntyped(options, children[0]); // FIXME any
const value = await run(options, children[1]);

if (key === 'resources') {
throw new Error(`Key "resources" cannot be redeclared`);
}
options.values![key] = value;
Object.freeze(options.values![key]);
dastin-sandura marked this conversation as resolved.
Show resolved Hide resolved
return value;
},
});
4 changes: 3 additions & 1 deletion src/askvm/resources/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ export * from './fun';
export * from './get';
export { ifRes as if } from './if';
export * from './is';
export { letRes as let, letRes as const, letRes as assign } from './let';
export { letRes as let } from './let';
export { constRes as const } from './const';
export { assignRes as assign } from './assign';
export * from './list';
export * from './logicalOr';
export * from './not';
Expand Down
18 changes: 0 additions & 18 deletions src/askvm/resources/core/let.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,8 @@ export const letRes = resource({
throw new Error(`Key "resources" cannot be redeclared`);
}

if (code.name === 'assign') {
for (
let prototype: Options | undefined = options;
prototype;
prototype = prototype?.prototype
) {
const { values = {} } = prototype;
if (Object.prototype.hasOwnProperty.call(values, key)) {
assignValue(values, key, value);
return value;
}
}
throw new Error(`Cannot assign to an unknown variable "${key}"`);
}

options.values![key] = value;

if (code.name === 'const') {
Object.freeze(options.values![key]);
}
dastin-sandura marked this conversation as resolved.
Show resolved Hide resolved
return value;
},
});