diff options
| author | Akshay Nair <phenax5@gmail.com> | 2022-01-10 21:29:42 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2022-01-10 21:29:42 +0530 |
| commit | 3581e398a2fe2f38bee7e6d13cbf609221f61672 (patch) | |
| tree | 95715115303ecb9620cbf37530e89a37c0ff5c4b /src/eval/index.ts | |
| parent | aa006086f69c827d780e6e0e69947ca7ee6e2c70 (diff) | |
| download | elxr-3581e398a2fe2f38bee7e6d13cbf609221f61672.tar.gz elxr-3581e398a2fe2f38bee7e6d13cbf609221f61672.zip | |
feat: adds matchAll function (incomplete)
Diffstat (limited to '')
| -rw-r--r-- | src/eval/index.ts | 130 |
1 files changed, 129 insertions, 1 deletions
diff --git a/src/eval/index.ts b/src/eval/index.ts index 6656743..1050295 100644 --- a/src/eval/index.ts +++ b/src/eval/index.ts @@ -1,8 +1,136 @@ import { pipe } from 'fp-ts/function' import { takeLeftWhile } from 'fp-ts/lib/Array' +import { + chain, + getOrElseW, + isSome, + map, + none, + Option, + some, +} from 'fp-ts/lib/Option' import { Expr, ListExpr } from '../types' import { match } from '../utils' +export interface MatchGroupIndexed<T = any> { + value: T + index: number +} + +export interface MatchGroupResult { + groups: MatchGroupIndexed[] +} + +const group = <T>(value: T, index: number): MatchGroupIndexed<T> => ({ + value, + index, +}) + +// :: ListExpr -> [a] -> [{ groups: [T] }] +export const matchAll = <T>( + [startO, exprs, endO]: ListExpr, + list: T[], +): MatchGroupResult => { + const check = ( + index: number, + ls: T[], + expr: Expr, + ): Option<MatchGroupIndexed[]> => { + if (ls.length === 0) return some([]) + + const [item, ...rest] = ls + + const next = + (i: number = 1) => + (cur: Option<MatchGroupIndexed[]>) => + pipe( + check(index + i, ls.slice(i), expr), + getOrElseW(() => [] as MatchGroupIndexed[]), + nextMatch => + pipe( + cur, + map(curMatch => [...curMatch, ...nextMatch]), + ), + ) + + return pipe( + expr, + match<Option<MatchGroupIndexed<any>[]>, Expr>({ + AnyItem: _ => pipe(some([group(item, index)]), next()), + AnyNumber: _ => + pipe( + typeof item === 'number' ? some([group(item, index)]) : none, + next(), + ), + AnyString: _ => + pipe( + typeof item === 'string' ? some([group(item, index)]) : none, + next(), + ), + AnyBool: _ => + pipe( + typeof item === 'boolean' ? some([group(item, index)]) : none, + next(), + ), + Truthy: _ => pipe(!!item ? some([group(item, index)]) : none, next()), + Falsey: _ => pipe(!item ? some([group(item, index)]) : none, next()), + + Group: ({ exprs }) => { + const matches = exprs.reduce( + (acc, exp) => + pipe( + acc, + chain(m => + pipe( + check(index, ls, exp), + map(ac => [...ac, ...m]), + ), + ), + ), + some([] as MatchGroupIndexed<any>[]), + ) + // console.log(matches, exprs, '---', item) + + return next()(matches) + }, + + PropertyMatch: ({ name, exprs }) => + pipe( + Object.prototype.hasOwnProperty.call(item, name) + ? check(index, [item[name]], Expr.Group({ exprs })) + : none, + next(), + ), + + OneOrMore: ({ expr }) => { + //console.log(item) + // TODO: Nested quantified expression + const matches = pipe( + ls, + takeLeftWhile(a => isSome(check(index, [a], expr))), + ) + //console.log(matches) + return pipe( + matches.length > 0 ? some([group(matches, index)]) : none, + next(matches.length || 1), + ) + }, + + _: _ => none, + }), + ) + } + + const expr = Expr.Group({ exprs }) + + return { + groups: pipe( + check(0, list, expr), + getOrElseW(() => []), + ), + } +} + export const find = <T>([startO, exprs, endO]: ListExpr, list: T[]): any => { const check = (expr: Expr) => @@ -25,7 +153,7 @@ export const find = <T>([startO, exprs, endO]: ListExpr, list: T[]): any => { list.slice(i), takeLeftWhile(x => check(expr)(x, i, list)), ) - console.log(x) + //console.log(x) return true }, |
