Moved matching functionality to dedicated module

This commit is contained in:
Ozzie Gooen 2022-05-19 18:17:31 -04:00
parent c326d0b229
commit 0b85b12551

View File

@ -56,7 +56,8 @@ let rec matchInput = (input: itype, r: expressionValue): option<value> =>
| _ => None
}
module MatchSimple = {
module Matcher = {
module MatchSimple = {
type t = DifferentName | SameNameDifferentArguments | FullMatch
let isFullMatch = (match: t) =>
@ -70,9 +71,9 @@ module MatchSimple = {
| SameNameDifferentArguments => true
| _ => false
}
}
}
module Match = {
module Match = {
type t<'a, 'b> = DifferentName | SameNameDifferentArguments('a) | FullMatch('b)
let isFullMatch = (match: t<'a, 'b>): bool =>
@ -86,9 +87,9 @@ module Match = {
| SameNameDifferentArguments(_) => true
| _ => false
}
}
}
module FnDefinition = {
module FnDefinition = {
type definitionMatch = MatchSimple.t
let getArgValues = (f: fnDefinition, args: array<expressionValue>): option<array<value>> => {
@ -116,31 +117,12 @@ module FnDefinition = {
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 definitionId = int
type match = Match.t<array<definitionId>, definitionId>
let make = (~name, ~definitions): function => {
name: name,
definitions: definitions,
}
let makeDefinition = (~name, ~inputs, ~run): fnDefinition => {
name: name,
inputs: inputs,
run: run,
}
let match = (f: function, fnName: string, args: array<expressionValue>): match => {
let matchedDefinition = () =>
E.A.getIndexBy(f.definitions, r =>
@ -164,18 +146,18 @@ module Function = {
Match.DifferentName,
)
}
}
}
module RegistryMatch = {
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)) =>
@ -226,11 +208,48 @@ module Registry = {
registry
->E.A.getBy(fn => fn.name === fnName)
->E.O.bind(fn => E.A.get(fn.definitions, inputIndex))
}
}
module FnDefinition = {
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 run = (f: fnDefinition, args: array<expressionValue>) => {
let argValues = getArgValues(f, args)
switch argValues {
| Some(values) => f.run(values)
| None => Error("Impossible")
}
}
}
module Function = {
type definitionId = int
let make = (~name, ~definitions): function => {
name: name,
definitions: definitions,
}
let makeDefinition = (~name, ~inputs, ~run): fnDefinition => {
name: name,
inputs: inputs,
run: run,
}
}
module Registry = {
let matchAndRun = (r: registry, fnName: string, args: array<expressionValue>) => {
switch findMatches(r, fnName, args) {
| Match.FullMatch(m) =>
fullMatchToDef(r, m)->E.O2.fmap(r => {
switch Matcher.Registry.findMatches(r, fnName, args) {
| Matcher.Match.FullMatch(m) =>
Matcher.Registry.fullMatchToDef(r, m)->E.O2.fmap(r => {
FnDefinition.run(r, args)
})
| _ => None