Moved matching functionality to dedicated module
This commit is contained in:
parent
c326d0b229
commit
0b85b12551
|
@ -56,41 +56,162 @@ let rec matchInput = (input: itype, r: expressionValue): option<value> =>
|
||||||
| _ => None
|
| _ => None
|
||||||
}
|
}
|
||||||
|
|
||||||
module MatchSimple = {
|
module Matcher = {
|
||||||
type t = DifferentName | SameNameDifferentArguments | FullMatch
|
module MatchSimple = {
|
||||||
|
type t = DifferentName | SameNameDifferentArguments | FullMatch
|
||||||
|
|
||||||
let isFullMatch = (match: t) =>
|
let isFullMatch = (match: t) =>
|
||||||
switch match {
|
switch match {
|
||||||
| FullMatch => true
|
| FullMatch => true
|
||||||
| _ => false
|
| _ => false
|
||||||
|
}
|
||||||
|
|
||||||
|
let isNameMatchOnly = (match: t) =>
|
||||||
|
switch match {
|
||||||
|
| SameNameDifferentArguments => true
|
||||||
|
| _ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module Match = {
|
||||||
|
type t<'a, 'b> = DifferentName | SameNameDifferentArguments('a) | FullMatch('b)
|
||||||
|
|
||||||
|
let isFullMatch = (match: t<'a, 'b>): bool =>
|
||||||
|
switch match {
|
||||||
|
| FullMatch(_) => true
|
||||||
|
| _ => false
|
||||||
|
}
|
||||||
|
|
||||||
|
let isNameMatchOnly = (match: t<'a, 'b>) =>
|
||||||
|
switch match {
|
||||||
|
| SameNameDifferentArguments(_) => true
|
||||||
|
| _ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module FnDefinition = {
|
||||||
|
type definitionMatch = MatchSimple.t
|
||||||
|
|
||||||
|
let getArgValues = (f: fnDefinition, args: array<expressionValue>): option<array<value>> => {
|
||||||
|
let mainInputTypes = f.inputs
|
||||||
|
if E.A.length(f.inputs) !== E.A.length(args) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
E.A.zip(mainInputTypes, args)
|
||||||
|
->E.A2.fmap(((input, arg)) => matchInput(input, arg))
|
||||||
|
->E.A.O.openIfAllSome
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let isNameMatchOnly = (match: t) =>
|
let matchAssumingSameName = (f: fnDefinition, args: array<expressionValue>) => {
|
||||||
switch match {
|
switch getArgValues(f, args) {
|
||||||
| SameNameDifferentArguments => true
|
| Some(_) => MatchSimple.FullMatch
|
||||||
| _ => false
|
| None => MatchSimple.SameNameDifferentArguments
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
module Match = {
|
|
||||||
type t<'a, 'b> = DifferentName | SameNameDifferentArguments('a) | FullMatch('b)
|
|
||||||
|
|
||||||
let isFullMatch = (match: t<'a, 'b>): bool =>
|
|
||||||
switch match {
|
|
||||||
| FullMatch(_) => true
|
|
||||||
| _ => false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let isNameMatchOnly = (match: t<'a, 'b>) =>
|
let match = (f: fnDefinition, fnName: string, args: array<expressionValue>) => {
|
||||||
switch match {
|
if f.name !== fnName {
|
||||||
| SameNameDifferentArguments(_) => true
|
MatchSimple.DifferentName
|
||||||
| _ => false
|
} else {
|
||||||
|
matchAssumingSameName(f, args)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module Function = {
|
||||||
|
type definitionId = int
|
||||||
|
type match = Match.t<array<definitionId>, definitionId>
|
||||||
|
|
||||||
|
let match = (f: function, fnName: string, args: array<expressionValue>): match => {
|
||||||
|
let matchedDefinition = () =>
|
||||||
|
E.A.getIndexBy(f.definitions, r =>
|
||||||
|
MatchSimple.isFullMatch(FnDefinition.match(r, fnName, args))
|
||||||
|
) |> E.O.fmap(r => Match.FullMatch(r))
|
||||||
|
let getMatchedNameOnlyDefinition = () => {
|
||||||
|
let nameMatchIndexes =
|
||||||
|
f.definitions
|
||||||
|
->E.A2.fmapi((index, r) =>
|
||||||
|
MatchSimple.isNameMatchOnly(FnDefinition.match(r, fnName, args)) ? Some(index) : None
|
||||||
|
)
|
||||||
|
->E.A.O.concatSomes
|
||||||
|
switch nameMatchIndexes {
|
||||||
|
| [] => None
|
||||||
|
| elements => Some(Match.SameNameDifferentArguments(elements))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
E.A.O.firstSomeFnWithDefault(
|
||||||
|
[matchedDefinition, getMatchedNameOnlyDefinition],
|
||||||
|
Match.DifferentName,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module RegistryMatch = {
|
||||||
|
type match = {
|
||||||
|
fnName: string,
|
||||||
|
inputIndex: int,
|
||||||
|
}
|
||||||
|
type t = Match.t<array<match>, match>
|
||||||
|
let makeMatch = (fnName: string, inputIndex: int) => {fnName: fnName, inputIndex: inputIndex}
|
||||||
|
}
|
||||||
|
|
||||||
|
module Registry = {
|
||||||
|
let findExactMatches = (r: registry, fnName: string, args: array<expressionValue>) => {
|
||||||
|
let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args)))
|
||||||
|
let getFullMatch = E.A.getBy(functionMatchPairs, ((_, match: Function.match)) =>
|
||||||
|
Match.isFullMatch(match)
|
||||||
|
)
|
||||||
|
let fullMatch: option<RegistryMatch.match> = getFullMatch->E.O.bind(((fn, match)) =>
|
||||||
|
switch match {
|
||||||
|
| FullMatch(index) => Some(RegistryMatch.makeMatch(fn.name, index))
|
||||||
|
| _ => None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
fullMatch
|
||||||
|
}
|
||||||
|
|
||||||
|
let findNameMatches = (r: registry, fnName: string, args: array<expressionValue>) => {
|
||||||
|
let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args)))
|
||||||
|
let getNameMatches =
|
||||||
|
functionMatchPairs
|
||||||
|
->E.A2.fmap(((fn, match)) => Match.isNameMatchOnly(match) ? Some((fn, match)) : None)
|
||||||
|
->E.A.O.concatSomes
|
||||||
|
let matches =
|
||||||
|
getNameMatches
|
||||||
|
->E.A2.fmap(((fn, match)) =>
|
||||||
|
switch match {
|
||||||
|
| SameNameDifferentArguments(indexes) =>
|
||||||
|
indexes->E.A2.fmap(index => RegistryMatch.makeMatch(fn.name, index))
|
||||||
|
| _ => []
|
||||||
|
}
|
||||||
|
)
|
||||||
|
->Belt.Array.concatMany
|
||||||
|
E.A.toNoneIfEmpty(matches)
|
||||||
|
}
|
||||||
|
|
||||||
|
let findMatches = (r: registry, fnName: string, args: array<expressionValue>) => {
|
||||||
|
switch findExactMatches(r, fnName, args) {
|
||||||
|
| Some(r) => Match.FullMatch(r)
|
||||||
|
| None =>
|
||||||
|
switch findNameMatches(r, fnName, args) {
|
||||||
|
| Some(r) => Match.SameNameDifferentArguments(r)
|
||||||
|
| None => Match.DifferentName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let fullMatchToDef = (registry: registry, {fnName, inputIndex}: RegistryMatch.match): option<
|
||||||
|
fnDefinition,
|
||||||
|
> =>
|
||||||
|
registry
|
||||||
|
->E.A.getBy(fn => fn.name === fnName)
|
||||||
|
->E.O.bind(fn => E.A.get(fn.definitions, inputIndex))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module FnDefinition = {
|
module FnDefinition = {
|
||||||
type definitionMatch = MatchSimple.t
|
|
||||||
|
|
||||||
let getArgValues = (f: fnDefinition, args: array<expressionValue>): option<array<value>> => {
|
let getArgValues = (f: fnDefinition, args: array<expressionValue>): option<array<value>> => {
|
||||||
let mainInputTypes = f.inputs
|
let mainInputTypes = f.inputs
|
||||||
if E.A.length(f.inputs) !== E.A.length(args) {
|
if E.A.length(f.inputs) !== E.A.length(args) {
|
||||||
|
@ -101,22 +222,6 @@ module FnDefinition = {
|
||||||
->E.A.O.openIfAllSome
|
->E.A.O.openIfAllSome
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let matchAssumingSameName = (f: fnDefinition, args: array<expressionValue>) => {
|
|
||||||
switch getArgValues(f, args) {
|
|
||||||
| Some(_) => MatchSimple.FullMatch
|
|
||||||
| None => MatchSimple.SameNameDifferentArguments
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let match = (f: fnDefinition, fnName: string, args: array<expressionValue>) => {
|
|
||||||
if f.name !== fnName {
|
|
||||||
MatchSimple.DifferentName
|
|
||||||
} else {
|
|
||||||
matchAssumingSameName(f, args)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let run = (f: fnDefinition, args: array<expressionValue>) => {
|
let run = (f: fnDefinition, args: array<expressionValue>) => {
|
||||||
let argValues = getArgValues(f, args)
|
let argValues = getArgValues(f, args)
|
||||||
switch argValues {
|
switch argValues {
|
||||||
|
@ -128,8 +233,6 @@ module FnDefinition = {
|
||||||
|
|
||||||
module Function = {
|
module Function = {
|
||||||
type definitionId = int
|
type definitionId = int
|
||||||
type match = Match.t<array<definitionId>, definitionId>
|
|
||||||
|
|
||||||
let make = (~name, ~definitions): function => {
|
let make = (~name, ~definitions): function => {
|
||||||
name: name,
|
name: name,
|
||||||
definitions: definitions,
|
definitions: definitions,
|
||||||
|
@ -140,97 +243,13 @@ module Function = {
|
||||||
inputs: inputs,
|
inputs: inputs,
|
||||||
run: run,
|
run: run,
|
||||||
}
|
}
|
||||||
|
|
||||||
let match = (f: function, fnName: string, args: array<expressionValue>): match => {
|
|
||||||
let matchedDefinition = () =>
|
|
||||||
E.A.getIndexBy(f.definitions, r =>
|
|
||||||
MatchSimple.isFullMatch(FnDefinition.match(r, fnName, args))
|
|
||||||
) |> E.O.fmap(r => Match.FullMatch(r))
|
|
||||||
let getMatchedNameOnlyDefinition = () => {
|
|
||||||
let nameMatchIndexes =
|
|
||||||
f.definitions
|
|
||||||
->E.A2.fmapi((index, r) =>
|
|
||||||
MatchSimple.isNameMatchOnly(FnDefinition.match(r, fnName, args)) ? Some(index) : None
|
|
||||||
)
|
|
||||||
->E.A.O.concatSomes
|
|
||||||
switch nameMatchIndexes {
|
|
||||||
| [] => None
|
|
||||||
| elements => Some(Match.SameNameDifferentArguments(elements))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
E.A.O.firstSomeFnWithDefault(
|
|
||||||
[matchedDefinition, getMatchedNameOnlyDefinition],
|
|
||||||
Match.DifferentName,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module RegistryMatch = {
|
|
||||||
type match = {
|
|
||||||
fnName: string,
|
|
||||||
inputIndex: int,
|
|
||||||
}
|
|
||||||
type t = Match.t<array<match>, match>
|
|
||||||
let makeMatch = (fnName: string, inputIndex: int) => {fnName: fnName, inputIndex: inputIndex}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module Registry = {
|
module Registry = {
|
||||||
let findExactMatches = (r: registry, fnName: string, args: array<expressionValue>) => {
|
|
||||||
let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args)))
|
|
||||||
let getFullMatch = E.A.getBy(functionMatchPairs, ((_, match: Function.match)) =>
|
|
||||||
Match.isFullMatch(match)
|
|
||||||
)
|
|
||||||
let fullMatch: option<RegistryMatch.match> = getFullMatch->E.O.bind(((fn, match)) =>
|
|
||||||
switch match {
|
|
||||||
| FullMatch(index) => Some(RegistryMatch.makeMatch(fn.name, index))
|
|
||||||
| _ => None
|
|
||||||
}
|
|
||||||
)
|
|
||||||
fullMatch
|
|
||||||
}
|
|
||||||
|
|
||||||
let findNameMatches = (r: registry, fnName: string, args: array<expressionValue>) => {
|
|
||||||
let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args)))
|
|
||||||
let getNameMatches =
|
|
||||||
functionMatchPairs
|
|
||||||
->E.A2.fmap(((fn, match)) => Match.isNameMatchOnly(match) ? Some((fn, match)) : None)
|
|
||||||
->E.A.O.concatSomes
|
|
||||||
let matches =
|
|
||||||
getNameMatches
|
|
||||||
->E.A2.fmap(((fn, match)) =>
|
|
||||||
switch match {
|
|
||||||
| SameNameDifferentArguments(indexes) =>
|
|
||||||
indexes->E.A2.fmap(index => RegistryMatch.makeMatch(fn.name, index))
|
|
||||||
| _ => []
|
|
||||||
}
|
|
||||||
)
|
|
||||||
->Belt.Array.concatMany
|
|
||||||
E.A.toNoneIfEmpty(matches)
|
|
||||||
}
|
|
||||||
|
|
||||||
let findMatches = (r: registry, fnName: string, args: array<expressionValue>) => {
|
|
||||||
switch findExactMatches(r, fnName, args) {
|
|
||||||
| Some(r) => Match.FullMatch(r)
|
|
||||||
| None =>
|
|
||||||
switch findNameMatches(r, fnName, args) {
|
|
||||||
| Some(r) => Match.SameNameDifferentArguments(r)
|
|
||||||
| None => Match.DifferentName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let fullMatchToDef = (registry: registry, {fnName, inputIndex}: RegistryMatch.match): option<
|
|
||||||
fnDefinition,
|
|
||||||
> =>
|
|
||||||
registry
|
|
||||||
->E.A.getBy(fn => fn.name === fnName)
|
|
||||||
->E.O.bind(fn => E.A.get(fn.definitions, inputIndex))
|
|
||||||
|
|
||||||
let matchAndRun = (r: registry, fnName: string, args: array<expressionValue>) => {
|
let matchAndRun = (r: registry, fnName: string, args: array<expressionValue>) => {
|
||||||
switch findMatches(r, fnName, args) {
|
switch Matcher.Registry.findMatches(r, fnName, args) {
|
||||||
| Match.FullMatch(m) =>
|
| Matcher.Match.FullMatch(m) =>
|
||||||
fullMatchToDef(r, m)->E.O2.fmap(r => {
|
Matcher.Registry.fullMatchToDef(r, m)->E.O2.fmap(r => {
|
||||||
FnDefinition.run(r, args)
|
FnDefinition.run(r, args)
|
||||||
})
|
})
|
||||||
| _ => None
|
| _ => None
|
||||||
|
|
Loading…
Reference in New Issue
Block a user