diff --git a/.github/workflows/deno.yml b/.github/workflows/deno.yml index 8820aeb..c741868 100644 --- a/.github/workflows/deno.yml +++ b/.github/workflows/deno.yml @@ -11,6 +11,8 @@ name: Deno on: push: branches-ignore: [] + tags: + - '**' pull_request: branches-ignore: [] diff --git a/deno.json b/deno.json index 6152bef..c0d485e 100644 --- a/deno.json +++ b/deno.json @@ -1,11 +1,5 @@ { "tasks": { "build_npm": "deno run -A scripts/build_npm.ts" - }, - "imports": { - "ts-pattern": "npm:ts-pattern@5.0.5", - "iteruyo": "https://deno.land/x/iteruyo@v0.3.0/mod.ts", - "std/assert": "https://deno.land/std@0.201.0/assert/mod.ts", - "util/": "./src/util/" } } \ No newline at end of file diff --git a/deps.ts b/deps.ts new file mode 100644 index 0000000..2ba8fb3 --- /dev/null +++ b/deps.ts @@ -0,0 +1,9 @@ +export { + match, + P, +} from "npm:ts-pattern@5.0.5" +export { $ as Iter } from "https://deno.land/x/iteruyo@v0.3.0/mod.ts" +export { + assertEquals, + assertNotEquals, +} from "https://deno.land/std@0.201.0/assert/mod.ts" \ No newline at end of file diff --git a/mod.ts b/mod.ts new file mode 100644 index 0000000..8b096c3 --- /dev/null +++ b/mod.ts @@ -0,0 +1 @@ +export * from "./src/mod.ts" \ No newline at end of file diff --git a/src/Expr.ts b/src/Expr.ts index d3b96e7..2d3cd00 100644 --- a/src/Expr.ts +++ b/src/Expr.ts @@ -1,11 +1,16 @@ export type Expr = | {ref: string} - | {literal: string} - | {def: [string, Expr]} - | {join: [Expr, Expr]} + | {literal: string | number} + | {def: [Expr, Expr]} | {or: [Expr, Expr]} | {and: [Expr, Expr]} | {symbol: string} | {call: [Expr, Expr]} + | {arrow: [Expr, Expr]} + | {capture: [string, Expr]} + | {guard: Expr} + | {js_arrow: (x: Expr) => Expr} + | {f: string, args: [Expr, Expr]} -export const any = {symbol: "any"} \ No newline at end of file +export const any = {symbol: "any"} +export const non = {symbol: "non"} \ No newline at end of file diff --git a/src/expand.ts b/src/expand.ts index be62f54..38ac9fe 100644 --- a/src/expand.ts +++ b/src/expand.ts @@ -1,10 +1,10 @@ import { Expr } from "./Expr.ts" -import { call, join } from "./func/mod.ts" +import { call, expandable } from "./func/mod.ts" -import { match, P } from "ts-pattern" -import { $ as Iter } from "iteruyo" -import { $a, $b } from "util/select.ts" -export * from "iteruyo" +import { match, P } from "../deps.ts" +import { Iter } from "../deps.ts" +import { $, $a, $b, f } from "./util/mod.ts" +export * from "../deps.ts" class LazyArray { memory: T[] = [] @@ -46,11 +46,11 @@ export const expand = (query: Expr) => function*(expr: Expr): Generator function*(expr: Expr): Generator { + .with({f: $("f"), args: [$a, $b]}, ({f, a, b}) => { const aStash = new LazyArray(expand(a)(expr)) const bStash = new LazyArray(expand(b)(expr)) return Iter(fill(x => !aStash.at(x), y => !bStash.at(y))) - .map(([x, y]) => join(aStash.at(x), bStash.at(y))) + .map(([x, y]) => expandable[f](aStash.at(x), bStash.at(y))) }) .otherwise(x => [x]) } diff --git a/src/func/and.ts b/src/func/and.ts index 5f7e19f..e684ca3 100644 --- a/src/func/and.ts +++ b/src/func/and.ts @@ -1,10 +1,40 @@ -import { Expr, any } from "../Expr.ts" +import { Expr, any, non } from "../Expr.ts" -import { match } from "ts-pattern" -import { $_ } from "util/select.ts" +import { match, P } from "../../deps.ts" +import { $, $a, $b, commu } from "../util/mod.ts" + +import { call } from "./call.ts" +import { or } from "./or.ts" export const and = (a: Expr, b: Expr): Expr => match([a, b]) - .with([$_, any], x => x) - .with([any, $_], x => x) + .with( + commu([ + {or: [$("a1"), $("a2")] as const}, + $b, + ]), + ({a1, a2, b}) => { + return or( + and(a1!, b!), + and(a2!, b!), + ) + } + ) + .with( + [{literal: $a}, {literal: $b}], + ({a, b}) => { + return a === b + ? {literal: a} + : non + } + ) + .with( + commu([ + {guard: $a}, + $b, + ]), + ({a, b}) => call(a!, b!) + ) + .with(commu([P.any, non]), () => non) + .with(commu([$a, any]), ({a}) => a!) .otherwise(_ => ({and: [a, b]})) \ No newline at end of file diff --git a/src/func/basic.ts b/src/func/basic.ts new file mode 100644 index 0000000..49c201c --- /dev/null +++ b/src/func/basic.ts @@ -0,0 +1,29 @@ +import { Expr } from "../Expr.ts"; + +export const literal = + (value: string | number) => + ({literal: value}) + +export const ref = + (name: string) => + ({ref: name}) + +export const def = + (name: Expr, expr: Expr): Expr => + ({def: [name, expr]}) + +export const arrow = + (from: Expr, to: Expr): Expr => + ({arrow: [from, to]}) + +export const capture = + (name: string, type: Expr): Expr => + ({capture: [name, type]}) + +export const guard = + (f: Expr) => + ({guard: f}) + +export const js_arrow = + (f: (x: Expr) => Expr) => + ({js_arrow: f}) \ No newline at end of file diff --git a/src/func/call.ts b/src/func/call.ts index a3d0d08..b49855c 100644 --- a/src/func/call.ts +++ b/src/func/call.ts @@ -1,27 +1,83 @@ -import { Expr, any } from "../Expr.ts" +import { Expr, any, non } from "../Expr.ts" import { and } from "./and.ts" +import { or } from "./or.ts" import { join } from "./join.ts" +import { + add, + sub, + mul, + div, +} from "./math.ts" -import { match, P } from "ts-pattern" -import { $_, $a, $b } from "util/select.ts" +import { match, P } from "../../deps.ts" +import { $, $_, $a, $b, commu } from "../util/mod.ts" export const call = (query: Expr, expr: Expr): Expr => { - return match(query) - .with({ref: $_}, name => - match(expr) - .with({def: [name, $_]}, value => { - return value - }) - .with({and: [$a, $b]}, ({a, b}) => { - return and( + return match([query, expr]) + .with([P.any, non], () => any) + .with( + [$("q"), {or: [$a, $b]}], + ({a, b, q}) => or(call(q, a), call(q, b)) + ) + .with( + [{ref: P.any}, {def: [{ref: P.any}, $_]}], + ([{ref}, {def: [{ref: name}, _val]}]) => ref == name, + val => val + ) + .with( + [{ref: $("name")}, {and: [$a, $b]}], + ({name, a, b}) => + and( call({ref: name}, a), call({ref: name}, b), ) - }) + ) + .with([{ref: P.any}, P.any], () => any) + .with( + [{arrow: [{literal: P.any}, $_]}, {literal: P.any}], + ([{arrow: [{literal: a1}, _]}, {literal: a2}]) => a1 == a2, + val => val + ) + .with( + [{arrow: [{capture: $a}, $b]}, P.any], + ({a: [name, type], b}) => // TODO: Type Checking + match(expr) + .with($_, () => call(b, {def: [ + {ref: name}, + and(expr, type), + ]})) .otherwise(() => any) ) - .with({join: [$a, $b]}, ({a, b}) => { - return join(call(a, expr), call(b, expr)) - }) - .otherwise(q => q) + .with([{arrow: P.any}, P.any], () => any) + .with([{call: [$a, $b]}, P.any], ({a, b}) => call( + call(a, expr), + call(b, expr), + )) + .with([{and: [$a, $b]}, P.any], ({a, b}) => and( + call(a, expr), + call(b, expr), + )) + .with( + [{f: P.any, args: commu([non, P.any])}, P.any], + () => any + ) + .with( + [{f: $("name"), args: $("args")}, P.any], + ({name, args}) => { + return { + join, + add, + sub, + mul, + div, + }[name as "join"]( + ...args.map(arg => call(arg, expr)) as typeof args + ) + } + ) + .with( + [{js_arrow: $("f")}, $a], + ({f, a}) => f(a) + ) + .otherwise(_ => query) } \ No newline at end of file diff --git a/src/func/join.ts b/src/func/join.ts index bddb7c6..b519589 100644 --- a/src/func/join.ts +++ b/src/func/join.ts @@ -1,12 +1,12 @@ import { Expr } from "../Expr.ts" -import { match } from "ts-pattern" -import { $a, $b } from "util/select.ts" +import { match } from "../../deps.ts" +import { f, str$a, str$b } from "../util/mod.ts" export const join = (a: Expr, b: Expr): Expr => match([a, b]) .with( - [{literal: $a}, {literal: $b}], + [{literal: str$a}, {literal: str$b}], ({a, b}) => ({literal: a + b}), ) - .otherwise(() => ({join: [a, b]})) \ No newline at end of file + .otherwise(() => f({join: [a, b]})) \ No newline at end of file diff --git a/src/func/math.ts b/src/func/math.ts new file mode 100644 index 0000000..86be446 --- /dev/null +++ b/src/func/math.ts @@ -0,0 +1,23 @@ +import { Expr, non, any } from "../Expr.ts" + +import { P, match } from "../../deps.ts" +import { num$a, num$b, commu } from "../util/mod.ts" + +const math = + (name: string, func: (a: number, b: number) => number) => + (a: Expr, b: Expr): Expr => + match([a, b]) + .with( + commu([non, P.any]), + () => any + ) + .with( + [{literal: num$a}, {literal: num$b}], + ({a, b}) => ({literal: func(a, b)}) + ) + .otherwise(() => ({f: name, args: [a, b]})) + +export const add = math("add", (a, b) => a + b) +export const sub = math("sub", (a, b) => a - b) +export const mul = math("mul", (a, b) => a * b) +export const div = math("div", (a, b) => a / b) \ No newline at end of file diff --git a/src/func/mod.ts b/src/func/mod.ts index 92c6283..88b464e 100644 --- a/src/func/mod.ts +++ b/src/func/mod.ts @@ -1,3 +1,13 @@ export * from "./and.ts" export * from "./call.ts" -export * from "./join.ts" \ No newline at end of file +export * from "./join.ts" +export * from "./basic.ts" +export * from "./math.ts" +export * from "./or.ts" + +import { join, or, add, sub, mul, div } from "./mod.ts" + +import { Expr } from "../Expr.ts" + +export const expandable: Record Expr> = + { join, or, add, sub, mul, div } \ No newline at end of file diff --git a/src/func/or.ts b/src/func/or.ts new file mode 100644 index 0000000..0b0b39d --- /dev/null +++ b/src/func/or.ts @@ -0,0 +1,10 @@ +import { Expr, any, non } from "../Expr.ts" + +import { match, P } from "../../deps.ts" +import { $a, commu } from "../util/mod.ts" + +export const or = (a: Expr, b: Expr): Expr => + match([a, b]) + .with(commu([$a, non]), ({a}) => a!) + .with(commu([P.any, any]), () => any) + .otherwise(_ => ({or: [a, b]})) \ No newline at end of file diff --git a/src/mod.ts b/src/mod.ts index 8dcb9c1..a082437 100644 --- a/src/mod.ts +++ b/src/mod.ts @@ -1,4 +1,7 @@ export * from "./func/mod.ts" +export * from "./std/mod.ts" export * from "./expand.ts" export * from "./Expr.ts" -export * from "./run.ts" \ No newline at end of file +export * from "./run.ts" + +export * from "./util/f.ts" diff --git a/src/run.ts b/src/run.ts index 0e033d1..c698fa9 100644 --- a/src/run.ts +++ b/src/run.ts @@ -1,8 +1,8 @@ import { Expr } from "./Expr.ts" import { and, call } from "./func/mod.ts" -import { match, P } from "ts-pattern" -import { $, $a, $b } from "util/select.ts" +import { match, P } from "../deps.ts" +import { $, $a, $b } from "./util/mod.ts" export const run = (expr: Expr): Expr => { return match(expr) diff --git a/src/std/mod.ts b/src/std/mod.ts new file mode 100644 index 0000000..76b3f03 --- /dev/null +++ b/src/std/mod.ts @@ -0,0 +1,22 @@ +import { guard, js_arrow } from "../func/basic.ts" +import { Expr, non } from "../Expr.ts" + +const predicate = + (check: (x: Expr) => boolean) => + guard( + js_arrow( + x => check(x) ? x : non + ) + ) + +export const num = + predicate(x => + "literal" in x && + typeof x?.literal == "number" + ) + +export const str = + predicate(x => + "literal" in x && + typeof x?.literal == "string" + ) \ No newline at end of file diff --git a/src/util/f.ts b/src/util/f.ts new file mode 100644 index 0000000..bbafe23 --- /dev/null +++ b/src/util/f.ts @@ -0,0 +1,11 @@ +import { Expr } from "../Expr.ts" + +export const f = + < + T extends string, + Es extends [unknown] | [unknown, unknown] + > + (o: {[k in T]: Es}) => { + const [[f, args]] = Object.entries(o) + return {f, args} as {f: T, args: Es} + } \ No newline at end of file diff --git a/src/util/mod.ts b/src/util/mod.ts new file mode 100644 index 0000000..3088073 --- /dev/null +++ b/src/util/mod.ts @@ -0,0 +1,2 @@ +export * from "./f.ts" +export * from "./select.ts" diff --git a/src/util/select.ts b/src/util/select.ts index 2dcbbde..4320edc 100644 --- a/src/util/select.ts +++ b/src/util/select.ts @@ -1,6 +1,17 @@ -import { P } from "ts-pattern" +import { P } from "../../deps.ts" export const $ = P.select export const $_ = $() export const $a = $("a") -export const $b = $("b") \ No newline at end of file +export const $b = $("b") +export const str$a = $("a", P.string) +export const str$b = $("b", P.string) +export const num$a = $("a", P.number) +export const num$b = $("b", P.number) +export const commu = + + ([a, b]: [A, B]) => + P.union( + [a, b], + [b, a], + ) \ No newline at end of file diff --git a/test/arrow.test.ts b/test/arrow.test.ts new file mode 100644 index 0000000..3305ad5 --- /dev/null +++ b/test/arrow.test.ts @@ -0,0 +1,113 @@ +import { + assertEquals, + assertNotEquals, +} from "../deps.ts" + +import { + call, + any, + + and, + arrow, + capture, + mul, + ref, + def, + literal, + or, + + num, + str, +} from "../src/mod.ts" +import { f } from "../src/util/mod.ts" + +Deno.test("Arrow - Match Literal", () => { + assertEquals( + call( + arrow( + literal("hello"), + literal("bye"), + ), + literal("hello"), + ), + literal("bye"), + ) + assertNotEquals( + call( + arrow( + literal("hello"), + literal("bye"), + ), + literal("hell"), + ), + literal("bye"), + ) +}) + +Deno.test("Arrow - Multiple Match", () => { + assertEquals( + call( + and( + arrow( + literal("1"), + literal("2"), + ), + arrow( + literal("2"), + literal("4"), + ), + ), + literal("2"), + ), + literal("4"), + ) +}) + +Deno.test("Arrow - Capture", () => { + assertEquals( + call( + arrow( + capture("n", any), + mul(ref("n"), literal(2)), + ), + literal(123), + ), + literal(246), + ) +}) + +Deno.test("Arrow - Junction", () => { + assertEquals( + call( + arrow( + capture("n", any), + mul(ref("n"), literal(2)), + ), + or(literal(10), literal(20)), + ), + or(literal(20), literal(40)), + ) +}) + +Deno.test("Arrow - Typed Capture", () => { + assertEquals( + call( + arrow( + capture("n", num), + mul(ref("n"), literal(2)), + ), + literal(123), + ), + literal(246), + ) + assertEquals( + call( + arrow( + capture("n", str), + mul(ref("n"), literal(2)), + ), + literal(123), + ), + any, + ) +}) diff --git a/test/call.test.ts b/test/call.test.ts index 109ac28..3b9358d 100644 --- a/test/call.test.ts +++ b/test/call.test.ts @@ -1,51 +1,107 @@ -import { assertEquals } from "std/assert" +import { + assertEquals, + assertNotEquals, +} from "../deps.ts" +import { mul } from "../mod.ts"; -import { call } from "../src/mod.ts" +import { + call, + any, + + and, + ref, + def, + join, + literal, +} from "../src/mod.ts" +import { f } from "../src/util/mod.ts" Deno.test("Call - Ref - And", () => { assertEquals( - call({ref: "a"}, { - and: [ - {def: ["a", {literal: "hello"}]}, - {def: ["b", {literal: "world"}]}, - ] - }), - {literal: "hello"}, + call( + ref("a"), + and( + def(ref("a"), literal("hello")), + def(ref("b"), literal("world")), + ) + ), + literal("hello"), ) assertEquals( - call({ref: "b"}, { - and: [ - {def: ["a", {literal: "hello"}]}, - {def: ["b", {literal: "world"}]}, - ] - }), - {literal: "world"}, + call( + ref("b"), + and( + def(ref("a"), literal("hello")), + def(ref("b"), literal("world")), + ) + ), + literal("world"), ) }) Deno.test("Call - Ref - Nested And", () => { assertEquals( - call({ref: "b"}, { - and: [ - {def: ["a", {literal: "hello"}]}, - {and: [ - {def: ["b", {literal: "world"}]}, - {def: ["c", {literal: "1234"}]}, - ]} - ] - }), - {literal: "world"}, + call( + ref("b"), + and( + def(ref("a"), literal("hello")), + and( + def(ref("b"), literal("world")), + def(ref("c"), literal("1234")), + ) + ) + ), + literal("world"), + ) +}) + +Deno.test("Call - Ref - Nested Complex", () => { + assertEquals( + call( + {call: [ref("area"), ref("square")]}, + and( + def( + ref("square"), + and( + def(ref("w"), literal(12)), + def(ref("h"), literal(5)), + ) + ), + def( + ref("area"), + mul( + ref("w"), + ref("h"), + ) + ) + ) + ), + literal(60), ) }) Deno.test("Call - Join", () => { assertEquals( - call({join: [{ref: "a"}, {ref: "b"}]}, { - and: [ - {def: ["a", {literal: "hello"}]}, - {def: ["b", {literal: "world"}]}, - ] - }), - {literal: "helloworld"}, + call( + join(ref("a"), ref("b")), + and( + def(ref("a"), literal("hello")), + def(ref("b"), literal("world")), + ) + ), + literal("helloworld"), + ) +}) + +Deno.test("Call - Math", () => { + assertEquals( + call( + mul(ref("a"), ref("b")), + and( + def(ref("a"), literal(12)), + def(ref("b"), literal(5)), + ) + ), + literal(60), ) }) \ No newline at end of file diff --git a/test/expand.test.ts b/test/expand.test.ts index 8c15b0c..7d2de51 100644 --- a/test/expand.test.ts +++ b/test/expand.test.ts @@ -1,27 +1,45 @@ -import { assertEquals } from "std/assert" +import { assertEquals } from "../deps.ts" +import { and } from "../mod.ts"; -import { Expr, expand, $ as Iter, any } from "../src/mod.ts" +import { + Expr, + expand, + Iter, + any, + + add, + arrow, + call, + capture, + join, + literal, + sub, + or, + ref, + def, +} from "../src/mod.ts" +import { f } from "../src/util/mod.ts" Deno.test("Expand - Literal", () => { assertEquals( [...expand( - {literal: "a"} + literal("a") )(any)], - [{literal: "a"}], + [literal("a")], ) }) Deno.test("Expand - Or", () => { assertEquals( [...expand( - {or: [ - {literal: "a"}, - {literal: "b"}, - ]} + or( + literal("a"), + literal("b"), + ) )(any)], [ - {literal: "a"}, - {literal: "b"}, + literal("a"), + literal("b"), ], ) }) @@ -29,92 +47,251 @@ Deno.test("Expand - Or", () => { Deno.test("Expand - Join", () => { assertEquals( [...expand( - { - join: [ - {or: [ - {literal: "1"}, - {literal: "2"}, - ]}, - {or: [ - {literal: "3"}, - {literal: "4"}, - ]}, - ] - } + join( + or( + literal("1"), + literal("2"), + ), + or( + literal("3"), + literal("4"), + ), + ) )(any)], [ - {literal: "13"}, - {literal: "23"}, - {literal: "14"}, - {literal: "24"}, + literal("13"), + literal("23"), + literal("14"), + literal("24"), ], ) }) Deno.test("Expand - Recursion", () => { - const pat: Expr = - {or: [ - {literal: ""}, - {or: [ - {join: [ - {join: - [ - {literal: "("}, - {ref: "pat"}, - ] - }, - {literal: ")"}, - ]}, - {join: [ - {ref: "pat"}, - {or: [ - {literal: "x"}, - {literal: "-"}, - ]}, - ]}, - ]}, - ]} - assertEquals( - Iter(expand({ref: "pat"})({def: ["pat", pat]})).take(10).toArray(), - [ - { literal: "" }, - { literal: "()" }, - { literal: "x" }, - { literal: "(())" }, - { literal: "()x" }, - { literal: "(x)" }, - { literal: "-" }, - { literal: "((()))" }, - { literal: "()-" }, - { literal: "(()x)" }, - ], + const pat = + or( + literal(""), + or( + join( + join( + literal("("), + ref("pat"), + ), + literal(")"), + ), + join( + ref("pat"), + or( + literal("x"), + literal("-"), + ), + ), + ), ) + assertEquals( + Iter(expand(ref("pat"))(def(ref("pat"), pat))).take(10).toArray(), + [ + literal(""), + literal("()"), + literal("x"), + literal("(())"), + literal("()x"), + literal("(x)"), + literal("-"), + literal("((()))"), + literal("()-"), + literal("(()x)"), + ], + ) }) +Deno.test("Expand - Recursion With External Function", () => { + const paren = + arrow( + capture("pat", any), + join( + join( + literal("("), + ref("pat"), + ), + literal(")"), + ) + ) + const pat = + or( + literal(""), + or( + join( + join( + literal("("), + ref("pat"), + ), + literal(")"), + ), + join( + ref("pat"), + or( + literal("x"), + literal("-"), + ), + ), + ), + ) + const expr = + and( + def( + ref("pat"), + pat, + ), + def( + ref("paren"), + paren, + ), + ) + assertEquals( + Iter(expand(ref("pat"))(expr)).take(10).toArray(), + [ + literal(""), + literal("()"), + literal("x"), + literal("(())"), + literal("()x"), + literal("(x)"), + literal("-"), + literal("((()))"), + literal("()-"), + literal("(()x)"), + ], + ) +}) +/* +Deno.test("Expand - Recursion", () => { + const pat_0 = + arrow( + literal(1), + literal(""), + ) + const pat_n = + arrow( + capture("n", any), + or( + join( + join( + literal("("), + call( + ref("pat"), + sub(ref("n"), literal(1)) + ), + ), + literal(")"), + ), + join( + call( + ref("pat"), + sub(ref("n"), literal(1)) + ), + or( + literal("x"), + literal("-"), + ), + ), + ), + ) + const pat = and( + pat_0, + pat_n, + ) + const result = + Iter( + expand + ( + call( + ref("pat"), + literal("0"), + ) + ) + (def(ref("pat"), pat)) + ).toArray() + + assertEquals( + result, + [ + literal(""), + literal("()"), + literal("x"), + literal("(())"), + literal("()x"), + literal("(x)"), + literal("-"), + literal("((()))"), + literal("()-"), + literal("(()x)"), + ], + ) +}) +*/ Deno.test("Expand - Join Refs", () => { assertEquals( [...expand( - { - join: [ - {ref: "a"}, - {ref: "b"}, - ] - } - )({and: [ - {def: ["a", {or: [ - {literal: "1"}, - {literal: "2"}, - ]}]}, - {def: ["b", {or: [ - {literal: "3"}, - {literal: "4"}, - ]}]}, - ]})], + join( + ref("a"), + ref("b"), + ) + )(and( + def(ref("a"), or( + literal("1"), + literal("2"), + )), + def(ref("b"), or( + literal("3"), + literal("4"), + )), + ))], + [ + literal("13"), + literal("23"), + literal("14"), + literal("24"), + ], + ) +}) + +Deno.test("Expand - Recursive Math", () => { + assertEquals( + Iter(expand(ref("nat"))(def( + ref("nat"), + or( + literal(1), + add( + ref("nat"), + literal(1) + ) + ) + ))).take(3).toArray(), [ - {literal: "13"}, - {literal: "23"}, - {literal: "14"}, - {literal: "24"}, + literal(1), + literal(2), + literal(3), ], ) +}) + +Deno.test("Expand - Logic", () => { + assertEquals( + Iter( + expand( + and( + or( + literal(1), + literal(2), + ), + or( + literal(2), + literal(3), + ), + ) + )(any) + ).toArray(), + [literal(2)] + ) }) \ No newline at end of file diff --git a/test/guard.test.ts b/test/guard.test.ts new file mode 100644 index 0000000..070f56a --- /dev/null +++ b/test/guard.test.ts @@ -0,0 +1,35 @@ +import { + assertEquals, + assertNotEquals, +} from "../deps.ts" + +import { + call, + any, + + and, + arrow, + capture, + mul, + ref, + def, + literal, + or, + js_arrow, + guard, + non, + num, +} from "../src/mod.ts" + +Deno.test("Guard - Number", () => { + assertEquals( + and( + num, + or( + literal(123), + literal("456"), + ) + ), + literal(123), + ) +}) \ No newline at end of file