ginger/lang/match.go

55 lines
1.2 KiB
Go
Raw Permalink Normal View History

package lang
import "fmt"
// Match is used to pattern match an arbitrary Term against a pattern. A pattern
// is a 2-tuple of the type (as an atom, e.g. AAtom, AConst) and a matching
// value.
//
// If the value is AUnder the pattern will match all Terms of the type,
// regardless of their value. If the pattern's type and value are both AUnder
// the pattern will match all Terms.
//
// If the pattern's value is a Tuple or a List, each of its values will be used
// as a sub-pattern to match against the corresponding value in the value.
func Match(pat Tuple, t Term) bool {
if len(pat) != 2 {
return false
}
pt, pv := pat[0], pat[1]
switch pt {
case AAtom:
a, ok := t.(Atom)
return ok && (Equal(pv, AUnder) || Equal(pv, a))
case AConst:
c, ok := t.(Const)
return ok && (Equal(pv, AUnder) || Equal(pv, c))
case ATuple:
tt, ok := t.(Tuple)
if !ok {
return false
} else if Equal(pv, AUnder) {
return true
}
pvt := pv.(Tuple)
if len(tt) != len(pvt) {
return false
}
for i := range tt {
pvti, ok := pvt[i].(Tuple)
if !ok || !Match(pvti, tt[i]) {
return false
}
}
return true
case AList:
panic("TODO")
case AUnder:
return true
default:
panic(fmt.Sprintf("unknown type %T", pt))
}
}