Skip to content

Commit

Permalink
fix workflow
Browse files Browse the repository at this point in the history
rename namelist to chain
chain works for array, string and object
  • Loading branch information
chientrm committed Jan 5, 2022
1 parent 4ee3301 commit a2bb2f0
Show file tree
Hide file tree
Showing 17 changed files with 130 additions and 80 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Node.js Package
name: Publish to NPM

on:
release:
Expand All @@ -9,14 +9,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm i
- run: npm run lint
- run: npm test
- run: npm run cleanForPublish
- uses: actions/setup-node@v2
with:
node-version: 16
registry-url: https://registry.npmjs.org/
- run: npm i
- run: npm run lint
- run: npm test
- run: npm run removeDocsAndTests
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@chientrm/es",
"type": "module",
"version": "0.0.12-alpha15",
"version": "0.0.12-alpha16",
"description": "",
"main": "index.js",
"directories": {
Expand All @@ -16,7 +16,7 @@
"testLoc": "find src/*.test.js src/**/*.test.js | xargs wc -l",
"lcov": "npx c8 -r lcovonly npm test",
"coverage": "npx c8 npm test",
"removeDocsAndTests": "rm -rf docs src/*.test.js src/**/*.test.js"
"cleanForPublish": "rm -rf docs src/*.test.js src/**/*.test.js .github"
},
"author": "Chien Tran",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion src/components/EArray.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe("EArray", () => {
"alice",
]);
});
it("name list", () => {
it("chain", () => {
expect(
run(
[{ a: { b: 1 } }],
Expand Down
37 changes: 37 additions & 0 deletions src/components/EChain.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { invalidChain } from "../core/error.js";
import { EName } from "./EName.js";
import { EReference } from "./EReference.js";
import { eRun } from "./utils.js";

export class EChain extends EName {
constructor(names) {
super({ names });
}
getNameKey(i) {
const name = this.names[i];
name instanceof EName || invalidChain(name);
return [name, name.name];
}
run(contexts) {
let result = eRun(contexts, this.names[0]);
if (this.names.length > 1)
for (let i = 1; i < this.names.length; i++) {
const [name, key] = this.getNameKey(i);
result = name.run([...contexts, { [key]: result[key] }], result);
}
return result;
}
assign(contexts, value) {
if (this.names.length > 1) {
let result = eRun(contexts, this.names[0]);
for (let i = 1; i < this.names.length - 1; i++) {
const [name, key] = this.getNameKey(i);
result = name.run([...contexts, { [key]: result[key] }], result);
}
const [name, key] = this.getNameKey(this.names.length - 1);
return name instanceof EReference
? (result[key] = value)
: name.assign([...contexts, { [key]: result[key] }], value);
} else return this.names[0].assign(contexts, value);
}
}
49 changes: 39 additions & 10 deletions src/components/ENameList.test.js → src/components/EChain.test.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,46 @@
import { expect } from "chai";
import { describe, it } from "mocha";
import { EIndexing } from "./EIndexing.js";
import { ENameList } from "./ENameList.js";
import { EInvoke } from "./EInvoke.js";
import { EChain } from "./EChain.js";
import { EReference } from "./EReference.js";

describe("ENameList", () => {
describe("EChain", () => {
describe("run", () => {
const run = (contexts, names) => new ENameList(names).run(contexts);
const run = (contexts, names) => new EChain(names).run(contexts);
it("invalid", () => {
expect(() => run([{}], [[], 1])).to.throw("Unknown chain 1");
});
it("undefined", () => {
expect(run([{}], [new EReference("a")])).to.be.undefined;
expect(run([{ a: 1 }], [new EReference("a"), new EReference("b")])).to.be
.undefined;
expect(() =>
run([{}], [new EReference("a"), new EReference("b")])
).to.throw("read properties of undefined (reading 'b')");
});
it("string", () => {
expect(run([{}], ["abc", new EInvoke("includes", ["a"])])).to.be.true;
expect(
run(
[{ s: "abc" }],
[new EReference("s"), new EInvoke("includes", ["a"])]
)
).to.be.true;
});
it("array", () => {
expect(
run(
[{ f: (a) => a * 2 }],
[[2, 3], new EInvoke("map", [new EReference("f")])]
)
).to.deep.equal([4, 6]);
expect(
run(
[{ a: [2, 3], f: (i) => i * 2 }],
[new EReference("a"), new EInvoke("map", [new EReference("f")])]
)
).to.deep.equal([4, 6]);
});
it("1 reference", () => {
const contexts = [{ a: 1 }];
expect(run(contexts, [new EReference("a")])).to.equal(1);
Expand All @@ -27,17 +53,20 @@ describe("ENameList", () => {
});
describe("assign", () => {
const assign = (contexts, names, value) =>
new ENameList(names).assign(contexts, value);
new EChain(names).assign(contexts, value);
it("undefined", () => {
const contexts = [{}];
expect(() =>
assign(contexts, [new EReference("a"), new EReference("b")], 1)
).to.throw("Cannot read properties of undefined (reading 'b')");
).to.throw("Cannot set properties of undefined (setting 'b')");
});
it("1 reference", () => {
const contexts = [{}];
expect(assign(contexts, [new EReference("a")], 1)).to.equal(1);
expect(contexts).to.deep.equal([{ a: 1 }]);
it("string", () => {
expect(() => assign([{}], ["", new EReference("a")], 1)).to.throw(
"Cannot create property 'a' on string ''"
);
});
it("array", () => {
expect(assign([{}], [[], new EReference("a")], 1)).to.equal(1);
});
it("2 references", () => {
const contexts = [{ a: {} }];
Expand Down
4 changes: 2 additions & 2 deletions src/components/EExpression.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EObject } from "./EObject.js";
import { operators as funcs } from "./operators.js";
import { invalidOperator } from "../core/index.js";
import { ENameList } from "./ENameList.js";
import { EChain } from "./EChain.js";

class Node extends EObject {
constructor(left, right, func) {
Expand Down Expand Up @@ -46,7 +46,7 @@ export class EExpression extends EObject {
: stack.push(p)
);
let result = stack.pop();
result instanceof ENameList && (result = result.run(ctxs));
result instanceof EChain && (result = result.run(ctxs));
return result;
}
}
7 changes: 5 additions & 2 deletions src/components/EInvoke.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ export class EInvoke extends EName {
constructor(name, operands) {
super({ name, operands });
}
run(ctxs) {
run(ctxs, _this) {
const func = search(ctxs, this.name);
isFunction(func) || invalidFunction(this.name);
return func(...this.operands.map((o) => eRun(ctxs, eRun(ctxs, o))));
return func.apply(
_this,
this.operands.map((o) => eRun(ctxs, eRun(ctxs, o)))
);
}
assign() {
invalidLvalue(`invoke ${this.name}`);
Expand Down
32 changes: 0 additions & 32 deletions src/components/ENameList.js

This file was deleted.

6 changes: 1 addition & 5 deletions src/components/ESet.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ENameList } from "./ENameList.js";
import { EObject } from "./EObject.js";

export class ESet extends EObject {
Expand All @@ -8,10 +7,7 @@ export class ESet extends EObject {
run(contexts) {
const result = {};
contexts = [...contexts, result];
this.operands.forEach((operand) => {
const _result = operand.run(contexts);
_result instanceof ENameList && _result.run(contexts);
});
this.operands.forEach((operand) => operand.run(contexts));
return result;
}
}
2 changes: 1 addition & 1 deletion src/components/ESet.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ describe("ESet", () => {
)
).to.deep.equal({ a: 1, b: 3 });
});
it("name list", () => {
it("chain", () => {
expect(
run(
[{ o: { f: () => 1 } }],
Expand Down
6 changes: 1 addition & 5 deletions src/components/ETuple.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ENameList } from "./ENameList.js";
import { EObject } from "./EObject.js";

export class ETuple extends EObject {
Expand All @@ -7,10 +6,7 @@ export class ETuple extends EObject {
}
run(contexts) {
let result = undefined;
this.operands.forEach((operand) => {
result = operand.run(contexts);
result instanceof ENameList && (result = result.run(contexts));
});
this.operands.forEach((operand) => (result = operand.run(contexts)));
return result;
}
}
2 changes: 1 addition & 1 deletion src/components/ETuple.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe("ETuple", () => {
)
).to.equal(3);
});
it("name list", () => {
it("chain", () => {
expect(
run(
[{ o: { f: () => 1 } }],
Expand Down
10 changes: 5 additions & 5 deletions src/components/operators.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { invalidLvalue, invalidParam, notImplemented } from "../core/error.js";
import { EArray } from "./EArray.js";
import { EName } from "./EName.js";
import { ENameList } from "./ENameList.js";
import { EObject } from "./EObject.js";
import { EChain } from "./EChain.js";
import { EReference } from "./EReference.js";
import { eRun, isObject } from "./utils.js";

export const operators = {
".": {
i: -2,
f: (_, b, a) =>
a instanceof EName && b instanceof EName
? new ENameList([...(a instanceof ENameList ? a.names : [a]), b])
: `${a}.${b}` * 1,
typeof a === "number"
? `${a}.${b}` * 1
: new EChain([...(a instanceof EChain ? a.names : [a]), b]),
},
"=>": {
i: -1,
Expand Down Expand Up @@ -62,7 +62,7 @@ export const operators = {
"=": {
i: 10,
f: (ctxs, b, a) => {
a instanceof ENameList || (a = new ENameList([a]));
a instanceof EChain || (a = new EChain([a]));
a.names.forEach((name) => name instanceof EName || invalidLvalue(a));
return a.assign(ctxs, eRun(ctxs, b));
},
Expand Down
23 changes: 16 additions & 7 deletions src/components/operators.test.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,36 @@
import { expect } from "chai";
import { describe, it } from "mocha";
import { EArray } from "./EArray.js";
import { EChain } from "./EChain.js";
import { EExpression } from "./EExpression.js";
import { EIndexing } from "./EIndexing.js";
import { EInvoke } from "./EInvoke.js";
import { ENameList } from "./ENameList.js";
import { EReference } from "./EReference.js";
import { ETuple } from "./ETuple.js";
import { operators } from "./operators.js";

describe("operators", () => {
const run = (operator, ctxs, a, b) => operators[operator].f(ctxs, b, a);

describe(". name list", () => {
describe(". chain", () => {
it("number", () => {
expect(run(".", [{}], 0, 14)).to.equal(0.14);
});
it("NaN", () => {
expect(run(".", [{}], 0, {})).to.be.NaN;
expect(run(".", [{}], 0, new EReference())).to.be.NaN;
expect(run(".", [{}], new EReference()), 0).to.be.NaN;
});
it("name list", () => {
it("string", () => {
expect(run(".", [{}], "abc", new EReference("length"))).to.deep.equal({
names: ["abc", { name: "length" }],
});
});
it("array", () => {
expect(run(".", [{}], [], new EReference("length"))).to.deep.equal({
names: [[], { name: "length" }],
});
});
it("chain", () => {
expect(
run(".", [{}], new EReference("a"), new EReference("b"))
).to.deep.equal({
Expand All @@ -31,7 +40,7 @@ describe("operators", () => {
run(
".",
[{}],
new ENameList([new EReference("a"), new EReference("b")]),
new EChain([new EReference("a"), new EReference("b")]),
new EReference("c")
)
).to.deep.equal({
Expand Down Expand Up @@ -134,12 +143,12 @@ describe("operators", () => {
it("l-value indexing", () => {
expect(run("=", [{ a: [1] }], new EIndexing("a", [0]), 2)).to.equal(2);
});
it("l-value name list", () => {
it("l-value chain", () => {
expect(() =>
run(
"=",
[{}],
new ENameList([new EReference("a"), new EReference("b")]),
new EChain([new EReference("a"), new EReference("b")]),
1
).to.throw("Cannot read properties of undefined (reading 'b')")
);
Expand Down
4 changes: 4 additions & 0 deletions src/core/error.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ export const syntaxExpected = (filename, lineNo, what) => {
throw new SyntaxError(`${filename}:${lineNo}\n${what} is expected`);
};

export const invalidChain = (name) => {
throw new Error(`Unknown chain ${name}`);
};

export const invalidFunction = (name) => {
throw new Error(`Unknown function ${name}`);
};
Expand Down
Loading

0 comments on commit a2bb2f0

Please sign in to comment.