-
Notifications
You must be signed in to change notification settings - Fork 3
/
functionType.go
124 lines (103 loc) · 2.79 KB
/
functionType.go
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
package hm
import "fmt"
// FunctionType is a type constructor that builds function types.
type FunctionType struct {
a, b Type
}
// NewFnType creates a new FunctionType. Functions are by default right associative. This:
// NewFnType(a, a, a)
// is short hand for this:
// NewFnType(a, NewFnType(a, a))
func NewFnType(ts ...Type) *FunctionType {
if len(ts) < 2 {
panic("Expected at least 2 input types")
}
retVal := borrowFnType()
retVal.a = ts[0]
if len(ts) > 2 {
retVal.b = NewFnType(ts[1:]...)
} else {
retVal.b = ts[1]
}
return retVal
}
func (t *FunctionType) Name() string { return "→" }
func (t *FunctionType) Apply(sub Subs) Substitutable {
t.a = t.a.Apply(sub).(Type)
t.b = t.b.Apply(sub).(Type)
return t
}
func (t *FunctionType) FreeTypeVar() TypeVarSet { return t.a.FreeTypeVar().Union(t.b.FreeTypeVar()) }
func (t *FunctionType) Format(s fmt.State, c rune) { fmt.Fprintf(s, "%v → %v", t.a, t.b) }
func (t *FunctionType) String() string { return fmt.Sprintf("%v", t) }
func (t *FunctionType) Normalize(k, v TypeVarSet) (Type, error) {
var a, b Type
var err error
if a, err = t.a.Normalize(k, v); err != nil {
return nil, err
}
if b, err = t.b.Normalize(k, v); err != nil {
return nil, err
}
return NewFnType(a, b), nil
}
func (t *FunctionType) Types() Types {
retVal := BorrowTypes(2)
retVal[0] = t.a
retVal[1] = t.b
return retVal
}
func (t *FunctionType) Eq(other Type) bool {
if ot, ok := other.(*FunctionType); ok {
return ot.a.Eq(t.a) && ot.b.Eq(t.b)
}
return false
}
// Other methods (accessors mainly)
// Arg returns the type of the function argument
func (t *FunctionType) Arg() Type { return t.a }
// Ret returns the return type of a function. If recursive is true, it will get the final return type
func (t *FunctionType) Ret(recursive bool) Type {
if !recursive {
return t.b
}
if fnt, ok := t.b.(*FunctionType); ok {
return fnt.Ret(recursive)
}
return t.b
}
// FlatTypes returns the types in FunctionTypes as a flat slice of types. This allows for easier iteration in some applications
func (t *FunctionType) FlatTypes() Types {
retVal := BorrowTypes(8) // start with 8. Can always grow
retVal = retVal[:0]
if a, ok := t.a.(*FunctionType); ok {
ft := a.FlatTypes()
retVal = append(retVal, ft...)
ReturnTypes(ft)
} else {
retVal = append(retVal, t.a)
}
if b, ok := t.b.(*FunctionType); ok {
ft := b.FlatTypes()
retVal = append(retVal, ft...)
ReturnTypes(ft)
} else {
retVal = append(retVal, t.b)
}
return retVal
}
// Clone implements Cloner
func (t *FunctionType) Clone() interface{} {
retVal := new(FunctionType)
if ac, ok := t.a.(Cloner); ok {
retVal.a = ac.Clone().(Type)
} else {
retVal.a = t.a
}
if bc, ok := t.b.(Cloner); ok {
retVal.b = bc.Clone().(Type)
} else {
retVal.b = t.b
}
return retVal
}