2017-02-11 17:24:02 +00:00
|
|
|
package lang
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2017-02-12 18:32:44 +00:00
|
|
|
// Commonly used Terms
|
|
|
|
var (
|
|
|
|
// Language structure types
|
|
|
|
AAtom = Atom("atom")
|
|
|
|
AConst = Atom("const")
|
|
|
|
ATuple = Atom("tup")
|
|
|
|
AList = Atom("list")
|
|
|
|
|
|
|
|
// Match shortcuts
|
|
|
|
AUnder = Atom("_")
|
|
|
|
TDblUnder = Tuple{AUnder, AUnder}
|
|
|
|
)
|
|
|
|
|
2017-02-11 17:24:02 +00:00
|
|
|
// Term is a unit of language which carries some meaning. Some Terms are
|
|
|
|
// actually comprised of multiple sub-Terms.
|
|
|
|
type Term interface {
|
|
|
|
fmt.Stringer // for debugging
|
|
|
|
|
|
|
|
// Type returns a Term which describes the type of this Term, i.e. the
|
|
|
|
// components this Term is comprised of.
|
|
|
|
Type() Term
|
|
|
|
}
|
|
|
|
|
|
|
|
// Equal returns whether or not two Terms are of equal value
|
|
|
|
func Equal(t1, t2 Term) bool {
|
|
|
|
return reflect.DeepEqual(t1, t2)
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// Atom is a constant with no other meaning than that it can be equal or not
|
|
|
|
// equal to another Atom.
|
|
|
|
type Atom string
|
|
|
|
|
|
|
|
func (a Atom) String() string {
|
|
|
|
return string(a)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Type implements the method for Term
|
|
|
|
func (a Atom) Type() Term {
|
2017-02-12 18:32:44 +00:00
|
|
|
return AAtom
|
2017-02-11 17:24:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// Const is a constant whose meaning depends on the context in which it is used
|
|
|
|
type Const string
|
|
|
|
|
|
|
|
func (a Const) String() string {
|
|
|
|
return string(a)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Type implements the method for Term
|
|
|
|
func (a Const) Type() Term {
|
2017-02-12 18:32:44 +00:00
|
|
|
return AConst
|
2017-02-11 17:24:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// Tuple is a compound Term of zero or more sub-Terms, each of which may have a
|
|
|
|
// different Type. Both the length of the Tuple and the Type of each of it's
|
|
|
|
// sub-Terms are components in the Tuple's Type.
|
|
|
|
type Tuple []Term
|
|
|
|
|
|
|
|
func (t Tuple) String() string {
|
|
|
|
ss := make([]string, len(t))
|
|
|
|
for i := range t {
|
|
|
|
ss[i] = t[i].String()
|
|
|
|
}
|
|
|
|
return "(" + strings.Join(ss, " ") + ")"
|
|
|
|
}
|
|
|
|
|
|
|
|
// Type implements the method for Term
|
|
|
|
func (t Tuple) Type() Term {
|
|
|
|
tt := make(Tuple, len(t))
|
|
|
|
for i := range t {
|
|
|
|
tt[i] = t[i].Type()
|
|
|
|
}
|
2017-02-12 18:32:44 +00:00
|
|
|
return Tuple{ATuple, tt}
|
2017-02-11 17:24:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
type list struct {
|
|
|
|
typ Term
|
|
|
|
ll []Term
|
|
|
|
}
|
|
|
|
|
|
|
|
// List is a compound Term of zero or more sub-Terms, each of which must have
|
|
|
|
// the same Type (the one given as the first argument to this function). Only
|
|
|
|
// the Type of the sub-Terms is a component in the List's Type.
|
|
|
|
func List(typ Term, elems ...Term) Term {
|
|
|
|
return list{
|
|
|
|
typ: typ,
|
|
|
|
ll: elems,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l list) String() string {
|
|
|
|
ss := make([]string, len(l.ll))
|
|
|
|
for i := range l.ll {
|
|
|
|
ss[i] = l.ll[i].String()
|
|
|
|
}
|
|
|
|
return "[" + strings.Join(ss, " ") + "]"
|
|
|
|
}
|
|
|
|
|
|
|
|
// Type implements the method for Term
|
|
|
|
func (l list) Type() Term {
|
2017-02-12 18:32:44 +00:00
|
|
|
return Tuple{AList, l.typ}
|
2017-02-11 17:24:02 +00:00
|
|
|
}
|