File: functionType.go

package info (click to toggle)
golang-github-chewxy-hm 1.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 216 kB
  • sloc: makefile: 2
file content (124 lines) | stat: -rw-r--r-- 2,853 bytes parent folder | download
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
}