File: scheme.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 (91 lines) | stat: -rw-r--r-- 1,814 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
package hm

import "fmt"

// Scheme represents a polytype.
// It basically says this:
//		∀TypeVariables.Type.
// What this means is for all TypeVariables enclosed in Type, those TypeVariables can be of any Type.
type Scheme struct {
	tvs TypeVarSet
	t   Type
}

func NewScheme(tvs TypeVarSet, t Type) *Scheme {
	return &Scheme{
		tvs: tvs,
		t:   t,
	}
}

func (s *Scheme) Apply(sub Subs) Substitutable {
	logf("s: %v, sub: %v", s, sub)
	if sub == nil {
		return s
	}
	sub = sub.Clone()
	defer ReturnSubs(sub)

	for _, tv := range s.tvs {
		sub = sub.Remove(tv)
	}

	s.t = s.t.Apply(sub).(Type)
	return s
}

func (s *Scheme) FreeTypeVar() TypeVarSet {
	ftvs := s.t.FreeTypeVar()
	tvs := s.tvs.Set()
	return ftvs.Difference(tvs)
}

func (s *Scheme) Clone() *Scheme {
	tvs := make(TypeVarSet, len(s.tvs))
	for i, v := range s.tvs {
		tvs[i] = v
	}
	return &Scheme{
		tvs: tvs,
		t:   s.t,
	}
}

func (s *Scheme) Format(state fmt.State, c rune) {
	state.Write([]byte("∀["))
	for i, tv := range s.tvs {
		if i < len(s.tvs)-1 {
			fmt.Fprintf(state, "%v, ", tv)
		} else {
			fmt.Fprintf(state, "%v", tv)
		}
	}
	fmt.Fprintf(state, "]: %v", s.t)
}

// Type returns the type of the scheme, as well as a boolean indicating if *Scheme represents a monotype. If it's a polytype, it'll return false
func (s *Scheme) Type() (t Type, isMonoType bool) {
	if len(s.tvs) == 0 {
		return s.t, true
	}
	return s.t, false
}

// Normalize normalizes the type variables in  a scheme, so all the names will be in alphabetical order
func (s *Scheme) Normalize() (err error) {
	tfv := s.t.FreeTypeVar()

	if len(tfv) == 0 {
		return nil
	}

	defer ReturnTypeVarSet(tfv)
	ord := BorrowTypeVarSet(len(tfv))
	for i := range tfv {
		ord[i] = TypeVariable(letters[i])
	}

	s.t, err = s.t.Normalize(tfv, ord)
	s.tvs = ord.Set()
	return
}