55 lines
1.2 KiB
Go
55 lines
1.2 KiB
Go
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))
|
|
}
|
|
}
|