Cleaned up FunctionRegistry to use Match type

This commit is contained in:
Ozzie Gooen 2022-05-18 17:27:36 -04:00
parent f7f94cbcb1
commit b67c90eb06

View File

@ -55,59 +55,80 @@ let rec matchInput = (input: itype, r: expressionValue): option<value> =>
| _ => None | _ => None
} }
module FnDefinition = { module MatchSimple = {
type definitionMatch = type t = DifferentName | SameNameDifferentArguments | FullMatch
DifferentName | SameNameDifferentArguments(string) | Match(string, array<value>)
let isFullMatch = (match: definitionMatch) => let isFullMatch = (match: t) =>
switch match { switch match {
| Match(_, _) => true | FullMatch => true
| _ => false | _ => false
} }
let isNameMatchOnly = (match: definitionMatch) => 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 { switch match {
| SameNameDifferentArguments(_) => true | SameNameDifferentArguments(_) => true
| _ => false | _ => false
} }
}
let matchSingleSameName = (f: fnDefinition, args: array<expressionValue>) => { module FnDefinition = {
type definitionMatch = MatchSimple.t
let getArgValues = (f: fnDefinition, args: array<expressionValue>): option<array<value>> => {
let inputTypes = f.inputs let inputTypes = f.inputs
if E.A.length(f.inputs) !== E.A.length(args) { if E.A.length(f.inputs) !== E.A.length(args) {
SameNameDifferentArguments(f.name) None
} else { } else {
let foo =
E.A.zip(inputTypes, args) E.A.zip(inputTypes, args)
->E.A2.fmap(((input, arg)) => matchInput(input, arg)) ->E.A2.fmap(((input, arg)) => matchInput(input, arg))
->E.A.O.arrSomeToSomeArr ->E.A.O.arrSomeToSomeArr
switch foo {
| Some(r) => Match(f.name, r)
| None => SameNameDifferentArguments(f.name)
} }
} }
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>) => { let match = (f: fnDefinition, fnName: string, args: array<expressionValue>) => {
if f.name !== fnName { if f.name !== fnName {
DifferentName MatchSimple.DifferentName
} else { } else {
matchSingleSameName(f, args) matchAssumingSameName(f, args)
}
}
let run = (f: fnDefinition, args: array<expressionValue>) => {
let argValues = getArgValues(f, args)
switch argValues {
| Some(values) => f.run(values)
| None => Error("Impossible")
} }
} }
} }
module Function = { module Function = {
type match = [#FullMatch(int) | #NameMatchOnly(array<int>) | #NoMatch] type definitionId = int
let isFullMatch = (t: match) => type match = Match.t<array<definitionId>, definitionId>
switch t {
| #FullMatch(_) => true
| _ => false
}
let isNameOnlyMatch = (t: match) =>
switch t {
| #NameMatchOnly(_) => true
| _ => false
}
let make = (name, definitions): function => { let make = (name, definitions): function => {
name: name, name: name,
definitions: definitions, definitions: definitions,
@ -121,22 +142,25 @@ module Function = {
let match = (f: function, fnName: string, args: array<expressionValue>): match => { let match = (f: function, fnName: string, args: array<expressionValue>): match => {
let matchedDefinition = () => let matchedDefinition = () =>
E.A.getIndexBy(f.definitions, r => E.A.getIndexBy(f.definitions, r =>
FnDefinition.isFullMatch(FnDefinition.match(r, fnName, args)) MatchSimple.isFullMatch(FnDefinition.match(r, fnName, args))
) |> E.O.fmap(r => #FullMatch(r)) ) |> E.O.fmap(r => Match.FullMatch(r))
let getMatchedNameOnlyDefinition = () => { let getMatchedNameOnlyDefinition = () => {
let nameMatchIndexes = let nameMatchIndexes =
f.definitions f.definitions
->E.A2.fmapi((index, r) => ->E.A2.fmapi((index, r) =>
FnDefinition.isNameMatchOnly(FnDefinition.match(r, fnName, args)) ? Some(index) : None MatchSimple.isNameMatchOnly(FnDefinition.match(r, fnName, args)) ? Some(index) : None
) )
->E.A.O.concatSomes ->E.A.O.concatSomes
switch nameMatchIndexes { switch nameMatchIndexes {
| [] => None | [] => None
| elements => Some(#NameMatchOnly(elements)) | elements => Some(Match.SameNameDifferentArguments(elements))
} }
} }
E.A.O.firstSomeFnWithDefault([matchedDefinition, getMatchedNameOnlyDefinition], #NoMatch) E.A.O.firstSomeFnWithDefault(
[matchedDefinition, getMatchedNameOnlyDefinition],
Match.DifferentName,
)
} }
} }
@ -145,27 +169,19 @@ module RegistryMatch = {
fnName: string, fnName: string,
inputIndex: int, inputIndex: int,
} }
type t = [#FullMatch(match) | #NameMatchOnly(array<match>) | #NoMatch] type t = Match.t<array<match>, match>
let makeMatch = (fnName: string, inputIndex: int) => {fnName: fnName, inputIndex: inputIndex} let makeMatch = (fnName: string, inputIndex: int) => {fnName: fnName, inputIndex: inputIndex}
let isFullMatch = (t: t) =>
switch t {
| #FullMatch(_) => true
| _ => false
}
let isNameOnlyMatch = (t: t) =>
switch t {
| #NameMatchOnly(_) => true
| _ => false
}
} }
module Registry = { module Registry = {
let findExactMatches = (r: registry, fnName: string, args: array<expressionValue>) => { let findExactMatches = (r: registry, fnName: string, args: array<expressionValue>) => {
let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args))) let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args)))
let getFullMatch = E.A.getBy(functionMatchPairs, ((_, match)) => Function.isFullMatch(match)) let getFullMatch = E.A.getBy(functionMatchPairs, ((_, match: Function.match)) =>
Match.isFullMatch(match)
)
let fullMatch: option<RegistryMatch.match> = getFullMatch->E.O.bind(((fn, match)) => let fullMatch: option<RegistryMatch.match> = getFullMatch->E.O.bind(((fn, match)) =>
switch match { switch match {
| #FullMatch(index) => Some(RegistryMatch.makeMatch(fn.name, index)) | FullMatch(index) => Some(RegistryMatch.makeMatch(fn.name, index))
| _ => None | _ => None
} }
) )
@ -176,13 +192,13 @@ module Registry = {
let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args))) let functionMatchPairs = r->E.A2.fmap(l => (l, Function.match(l, fnName, args)))
let getNameMatches = let getNameMatches =
functionMatchPairs functionMatchPairs
->E.A2.fmap(((fn, match)) => Function.isNameOnlyMatch(match) ? Some((fn, match)) : None) ->E.A2.fmap(((fn, match)) => Match.isNameMatchOnly(match) ? Some((fn, match)) : None)
->E.A.O.concatSomes ->E.A.O.concatSomes
let matches = let matches =
getNameMatches getNameMatches
->E.A2.fmap(((fn, match)) => ->E.A2.fmap(((fn, match)) =>
switch match { switch match {
| #NameMatchOnly(indexes) => | SameNameDifferentArguments(indexes) =>
indexes->E.A2.fmap(index => RegistryMatch.makeMatch(fn.name, index)) indexes->E.A2.fmap(index => RegistryMatch.makeMatch(fn.name, index))
| _ => [] | _ => []
} }
@ -193,11 +209,11 @@ module Registry = {
let findMatches = (r: registry, fnName: string, args: array<expressionValue>) => { let findMatches = (r: registry, fnName: string, args: array<expressionValue>) => {
switch findExactMatches(r, fnName, args) { switch findExactMatches(r, fnName, args) {
| Some(r) => #FullMatch(r) | Some(r) => Match.FullMatch(r)
| None => | None =>
switch findNameMatches(r, fnName, args) { switch findNameMatches(r, fnName, args) {
| Some(r) => #NameMatchOnly(r) | Some(r) => Match.SameNameDifferentArguments(r)
| None => #NoMatch | None => Match.DifferentName
} }
} }
} }
@ -209,16 +225,9 @@ module Registry = {
->E.A.getBy(fn => fn.name === fnName) ->E.A.getBy(fn => fn.name === fnName)
->E.O.bind(fn => E.A.get(fn.definitions, inputIndex)) ->E.O.bind(fn => E.A.get(fn.definitions, inputIndex))
let runDef = (fnDefinition: fnDefinition, args: array<expressionValue>) => {
switch FnDefinition.matchSingleSameName(fnDefinition, args) {
| Match(_, values) => fnDefinition.run(values)
| _ => Error("Impossible")
}
}
let matchAndRun = (r: registry, fnName: string, args: array<expressionValue>) => { let matchAndRun = (r: registry, fnName: string, args: array<expressionValue>) => {
switch findMatches(r, fnName, args) { switch findMatches(r, fnName, args) {
| #FullMatch(m) => fullMatchToDef(r, m)->E.O2.fmap(runDef(_, args)) | Match.FullMatch(m) => fullMatchToDef(r, m)->E.O2.fmap(FnDefinition.run(_, args))
| _ => None | _ => None
} }
} }