Skip to content

Commit

Permalink
feat: add support for async/sync interpreters on same context
Browse files Browse the repository at this point in the history
This commit refactors the whole codebase to better support sync/async execution.
Some important changes:
- add support for nested param resolution through @orioro/typing typeSpec
  utilities
- remove function and null ParamResolvers in favor of aforementioned typeSpecs
- separate interpreter functions into sub-modules (withtin dir src/interpreter)
- fix isExpression method to check whether the interpreterId is actually a
  string before attempting to get the interpterter function (previous versions
  were unintentionally using JS type casting which transformed the array
  `[['$$value']]` into a string `'$$value'`)
- modify interpreterList format to support sync/async evaluation on the same
  context object allowing expression interpreters to evaluate synchronoushly
  even if they were called in async mode (introduced to support
  Array.prototype.sort(customComparatorExp))

BREAKING CHANGE: `context.interpreters` format modified
  • Loading branch information
simonfan committed Mar 14, 2021
1 parent bde0238 commit 81609cc
Show file tree
Hide file tree
Showing 46 changed files with 2,654 additions and 2,240 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ node_modules
dist
coverage
tmp
yarn-error.log
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ TODO
- [`$arrayLength(array)`](#arraylengtharray)
- [`$arrayReduce(reduceExp, start, array)`](#arrayreducereduceexp-start-array)
- [`$arrayMap(mapExp, array)`](#arraymapmapexp-array)
- [`$arrayEvery(everyExp, array)`](#arrayeveryeveryexp-array)
- [`$arrayEvery(testExp, array)`](#arrayeverytestexp-array)
- [`$arraySome(someExp, array)`](#arraysomesomeexp-array)
- [`$arrayFilter(queryExp, array)`](#arrayfilterqueryexp-array)
- [`$arrayFindIndex(queryExp, array)`](#arrayfindindexqueryexp-array)
Expand Down Expand Up @@ -169,7 +169,7 @@ any of the searched values is in the array.
- `mapExp` {[Expression](#expression)}
- `array` {Array}

##### `$arrayEvery(everyExp, array)`
##### `$arrayEvery(testExp, array)`

`Array.prototype.every`

Expand All @@ -178,7 +178,7 @@ Result is similar to logical operator `$and`. Main difference
$arrayEvery exposes array iteration variables:
`$$PARENT_SCOPE`, `$$VALUE`, `$$INDEX`, `$$ARRAY`

- `everyExp` {[Expression](#expression)}
- `testExp` {[Expression](#expression)}
- `array` {Array}

##### `$arraySome(someExp, array)`
Expand Down Expand Up @@ -727,14 +727,14 @@ through Catastrophic backtracking, for future study and reference:

## Value

- [`$value(pathExp, defaultExp)`](#valuepathexp-defaultexp)
- [`$value(path, defaultExp)`](#valuepath-defaultexp)
- [`$literal(value)`](#literalvalue)
- [`$evaluate(expExp, scopeExp)`](#evaluateexpexp-scopeexp)
- [`$evaluate(expression, scope)`](#evaluateexpression-scope)


##### `$value(pathExp, defaultExp)`
##### `$value(path, defaultExp)`

- `pathExp` {String}
- `path` {String}
- `defaultExp` {*}
- Returns: `value` {*}

Expand All @@ -743,8 +743,8 @@ through Catastrophic backtracking, for future study and reference:
- `value` {*}
- Returns: {*}

##### `$evaluate(expExp, scopeExp)`
##### `$evaluate(expression, scope)`

- `expExp` {[Expression](#expression)}
- `scopeExp` {Object | null}
- `expression` {[Expression](#expression)}
- `scope` {Object}
- Returns: {*}
15 changes: 14 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@

- $and | Add 'strict' mode option (src/expressions/logical.ts)
- array | $arrayEvery write tests with async conditions (src/expressions/array.ts)
- array | $arraySome write tests with async conditions (src/expressions/array.ts)
- array | Make it possible for the same set of expression interpreters
to be called synchronously or asynchronously. E.g. sort comparator
expression should only support Synchronous (src/expressions/array.ts)
- asyncParamResolver | ONE_OF_TYPES: handle complex cases, e.g.
oneOfTypes(['string', objectType({ key1: 'string', key2: 'number '})]) (src/interpreter/asyncParamResolver.ts)
- logical | Write test to ensure delayed evaluation (src/expressions/logical.ts)
- syncInterpreter | Handle nested object param typeSpec (src/interpreter/syncParamResolver.ts)
- syncInterpreter | Study better ways at validating evlauation results for
tupleType and indefiniteArrayOfType. Currently validation is highly redundant. (src/interpreter/syncParamResolver.ts)
- syncInterpreter | Update Interpreter type: remove function (src/interpreter/syncInterpreter.ts)
- value | Consider adding 'expression' type (src/expressions/value.ts)
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"@babel/core": "^7.11.5",
"@babel/preset-env": "^7.11.5",
"@babel/preset-typescript": "^7.10.4",
"@orioro/jest-util": "^1.3.0",
"@orioro/jest-util": "^1.5.0",
"@orioro/readme": "^1.0.1",
"@rollup/plugin-babel": "^5.2.0",
"@rollup/plugin-commonjs": "^15.0.0",
Expand All @@ -64,7 +64,7 @@
"typescript": "^4.0.2"
},
"dependencies": {
"@orioro/typing": "^3.0.0",
"@orioro/typing": "^4.2.0",
"lodash": "^4.17.20"
},
"config": {
Expand Down
64 changes: 64 additions & 0 deletions spec/specUtil.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { evaluate, evaluateAsync } from '../src/evaluate'
import { interpreterList } from '../src/interpreter/interpreter'
import {
testCases,
asyncResult,
valueLabel,
resultLabel,
variableName,
VariableName,
} from '@orioro/jest-util'

const _evLabel = ([value, expression], result) =>
`${valueLabel(value)} | ${valueLabel(expression)} -> ${resultLabel(result)}`

export const _prepareEvaluateTestCases = (interpreterSpecs) => {
const interpreters = interpreterList(interpreterSpecs)

const testSyncCases = (cases) => {
testCases(
cases,
(value, expression) =>
evaluate(
{
interpreters,
scope: { $$VALUE: value },
},
expression
),
([value, expression], result) =>
`sync - ${_evLabel([value, expression], result)}`
)
}

const testAsyncCases = cases => {
testCases(
cases.map((_case) => {
const result = _case[_case.length - 1]
const args = _case.slice(0, -1)

return [...args, asyncResult(result)]
}),
(value, expression) =>
evaluateAsync(
{
interpreters,
scope: { $$VALUE: value },
},
expression
),
([value, expression], result) =>
`async - ${_evLabel([value, expression], result)}`
)
}

const testSyncAndAsync = (cases) => {
testSyncCases(cases)
testAsyncCases(cases)
}

testSyncAndAsync.testSyncCases = testSyncCases
testSyncAndAsync.testAsyncCases = testAsyncCases

return testSyncAndAsync
}
149 changes: 77 additions & 72 deletions src/__snapshots__/index.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,113 +2,118 @@

exports[`public api 1`] = `
Array [
"ALL_EXPRESSIONS",
"$$INDEX",
"$$ARRAY",
"$$ACC",
"$$ARRAY",
"$$INDEX",
"$$SORT_A",
"$$SORT_B",
"$$VALUE",
"$and",
"$arrayAddAt",
"$arrayAt",
"$arrayEvery",
"$arrayFilter",
"$arrayFilterAsyncParallel",
"$arrayFilterAsyncSerial",
"$arrayFind",
"$arrayFindIndex",
"$arrayIncludes",
"$arrayIncludesAll",
"$arrayIncludesAny",
"$arrayIndexOf",
"$arrayJoin",
"$arrayLength",
"$arrayReduce",
"$arrayMap",
"$arrayEvery",
"$arraySome",
"$arrayFilter",
"$arrayFindIndex",
"$arrayIndexOf",
"$arrayFind",
"$arrayReverse",
"$arraySort",
"$arrayPush",
"$arrayPop",
"$arrayUnshift",
"$arrayPush",
"$arrayReduce",
"$arrayRemoveAt",
"$arrayReplace",
"$arrayReverse",
"$arrayShift",
"$arraySlice",
"$arrayReplace",
"$arrayAddAt",
"$arrayRemoveAt",
"$arrayJoin",
"$arrayAt",
"ARRAY_EXPRESSIONS",
"$arraySome",
"$arraySort",
"$arrayUnshift",
"$boolean",
"BOOLEAN_EXPRESSIONS",
"$eq",
"$notEq",
"$in",
"$notIn",
"$evaluate",
"$gt",
"$gte",
"$if",
"$in",
"$isType",
"$literal",
"$lt",
"$lte",
"$matches",
"COMPARISON_EXPRESSIONS",
"$pipe",
"FUNCTIONAL_EXPRESSIONS",
"$and",
"$or",
"$not",
"$nor",
"$xor",
"$if",
"$switch",
"$switchKey",
"LOGICAL_EXPRESSIONS",
"$mathSum",
"$mathSub",
"$mathMult",
"$mathDiv",
"$mathMod",
"$mathPow",
"$mathAbs",
"$mathCeil",
"$mathDiv",
"$mathFloor",
"$mathMax",
"$mathMin",
"$mathMod",
"$mathMult",
"$mathPow",
"$mathRound",
"$mathFloor",
"$mathCeil",
"MATH_EXPRESSIONS",
"$numberInt",
"$mathSub",
"$mathSum",
"$nor",
"$not",
"$notEq",
"$notIn",
"$numberFloat",
"NUMBER_EXPRESSIONS",
"$objectMatches",
"$objectFormat",
"$objectDefaults",
"$numberInt",
"$objectAssign",
"$objectDefaults",
"$objectFormat",
"$objectKeys",
"OBJECT_EXPRESSIONS",
"$objectMatches",
"$or",
"$pipe",
"$string",
"$stringStartsWith",
"$stringLength",
"$stringSubstr",
"$stringConcat",
"$stringTrim",
"$stringPadStart",
"$stringInterpolate",
"$stringLength",
"$stringPadEnd",
"$stringToUpperCase",
"$stringPadStart",
"$stringStartsWith",
"$stringSubstr",
"$stringToLowerCase",
"$stringInterpolate",
"STRING_EXPRESSIONS",
"CORE_TYPES",
"typeExpressions",
"$stringToUpperCase",
"$stringTrim",
"$switch",
"$switchKey",
"$type",
"$isType",
"TYPE_EXPRESSIONS",
"$$VALUE",
"$value",
"$literal",
"$evaluate",
"$xor",
"ALL_EXPRESSIONS",
"ARRAY_EXPRESSIONS",
"BOOLEAN_EXPRESSIONS",
"COMPARISON_EXPRESSIONS",
"CORE_TYPES",
"FUNCTIONAL_EXPRESSIONS",
"LOGICAL_EXPRESSIONS",
"MATH_EXPRESSIONS",
"NUMBER_EXPRESSIONS",
"OBJECT_EXPRESSIONS",
"STRING_EXPRESSIONS",
"TYPE_EXPRESSIONS",
"VALUE_EXPRESSIONS",
"TypeAlternatives",
"TypeMap",
"isExpression",
"asyncInterpreter",
"asyncParamResolver",
"evaluate",
"evaluateAsync",
"evaluateSync",
"evaluateTyped",
"evaluateTypedAsync",
"evaluateTypedSync",
"interpreter",
"interpreterList",
"isExpression",
"syncInterpreter",
"syncInterpreterList",
"asyncInterpreter",
"asyncInterpreterList",
"syncParamResolver",
"typeExpressions",
]
`;
Loading

0 comments on commit 81609cc

Please sign in to comment.