1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
package hm
import (
"fmt"
)
// Type represents all the possible type constructors.
type Type interface {
Substitutable
Name() string // Name is the name of the constructor
Normalize(TypeVarSet, TypeVarSet) (Type, error) // Normalize normalizes all the type variable names in the type
Types() Types // If the type is made up of smaller types, then it will return them
Eq(Type) bool // equality operation
fmt.Formatter
fmt.Stringer
}
// Substitutable is any type that can have a set of substitutions applied on it, as well as being able to know what its free type variables are
type Substitutable interface {
Apply(Subs) Substitutable
FreeTypeVar() TypeVarSet
}
// TypeConst are the default implementation of a constant type. Feel free to implement your own. TypeConsts should be immutable (so no pointer types plz)
type TypeConst string
func (t TypeConst) Name() string { return string(t) }
func (t TypeConst) Apply(Subs) Substitutable { return t }
func (t TypeConst) FreeTypeVar() TypeVarSet { return nil }
func (t TypeConst) Normalize(k, v TypeVarSet) (Type, error) { return t, nil }
func (t TypeConst) Types() Types { return nil }
func (t TypeConst) String() string { return string(t) }
func (t TypeConst) Format(s fmt.State, c rune) { fmt.Fprintf(s, "%s", string(t)) }
func (t TypeConst) Eq(other Type) bool { return other == t }
// Record is a basic record/tuple type. It takes an optional name.
type Record struct {
ts []Type
name string
}
// NewRecordType creates a new Record Type
func NewRecordType(name string, ts ...Type) *Record {
return &Record{
ts: ts,
name: name,
}
}
func (t *Record) Apply(subs Subs) Substitutable {
ts := make([]Type, len(t.ts))
for i, v := range t.ts {
ts[i] = v.Apply(subs).(Type)
}
return NewRecordType(t.name, ts...)
}
func (t *Record) FreeTypeVar() TypeVarSet {
var tvs TypeVarSet
for _, v := range t.ts {
tvs = v.FreeTypeVar().Union(tvs)
}
return tvs
}
func (t *Record) Name() string {
if t.name != "" {
return t.name
}
return t.String()
}
func (t *Record) Normalize(k, v TypeVarSet) (Type, error) {
ts := make([]Type, len(t.ts))
var err error
for i, tt := range t.ts {
if ts[i], err = tt.Normalize(k, v); err != nil {
return nil, err
}
}
return NewRecordType(t.name, ts...), nil
}
func (t *Record) Types() Types {
ts := BorrowTypes(len(t.ts))
copy(ts, t.ts)
return ts
}
func (t *Record) Eq(other Type) bool {
if ot, ok := other.(*Record); ok {
if len(ot.ts) != len(t.ts) {
return false
}
for i, v := range t.ts {
if !v.Eq(ot.ts[i]) {
return false
}
}
return true
}
return false
}
func (t *Record) Format(f fmt.State, c rune) {
f.Write([]byte("("))
for i, v := range t.ts {
if i < len(t.ts)-1 {
fmt.Fprintf(f, "%v, ", v)
} else {
fmt.Fprintf(f, "%v)", v)
}
}
}
func (t *Record) String() string { return fmt.Sprintf("%v", t) }
// Clone implements Cloner
func (t *Record) Clone() interface{} {
retVal := new(Record)
ts := BorrowTypes(len(t.ts))
for i, tt := range t.ts {
if c, ok := tt.(Cloner); ok {
ts[i] = c.Clone().(Type)
} else {
ts[i] = tt
}
}
retVal.ts = ts
retVal.name = t.name
return retVal
}
|