-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbootstrap.go
More file actions
104 lines (94 loc) · 2.74 KB
/
Copy pathbootstrap.go
File metadata and controls
104 lines (94 loc) · 2.74 KB
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
package analysis
import (
"github.com/ProCode-Software/klar/internal/klarerrs"
)
// bootstrapType is a type that is used to bootstrap the typechecker.
// It wraps a type and a kind, so the typechecker allows operations
// for the provided kind on the wrapped type.
//
// Example: If the builtin module declares `type List`, allow list
// operations on the `List` type (such as iteration).
type bootstrapType struct {
asDeclared Type // Most likely a struct
kind Kind // The kind the type represents
withKind Type // Type if it actually had the kind
MethodSet // TODO: Is this needed?
}
func (bt *bootstrapType) Kind() Kind { return bt.kind }
func (bt *bootstrapType) Underlying() Type { return bt.withKind }
func (bt *bootstrapType) String() string { return bt.kind.String() }
var _ interface {
SupportsMethods
Indexer
} = &bootstrapType{}
func (c *Checker) wrapBootstrapTypes() {
for declaredName, ct := range compositeTypes {
obj := c.module.Context.Lookup(declaredName)
if obj == nil || !obj.IsTypeName() {
continue
}
tn := obj.TypeName()
tn.Type = &bootstrapType{
asDeclared: tn.Type,
kind: ct.kind,
withKind: ct.asKind(c.module.Context), // Root context to lookup generics
}
}
// Int, String, etc.
for name, kind := range primitives {
obj := c.module.Context.Lookup(name)
if obj == nil || !obj.IsTypeName() {
continue
}
tn := obj.TypeName()
tn.Type = &bootstrapType{
asDeclared: tn.Type,
kind: kind,
withKind: kind,
}
}
}
func (c *Checker) wrapBootstrappedTypeName(tn *TypeName, recv *Object) *TypeName {
if kind, ok := primitives[recv.Name]; ok {
return &TypeName{Name: tn.Name, Type: &bootstrapType{
asDeclared: recv.TypeName().Type,
kind: kind,
withKind: kind,
}}
}
if ct, ok := compositeTypes[recv.Name]; ok {
return &TypeName{Name: tn.Name, Type: &bootstrapType{
asDeclared: recv.TypeName().Type,
kind: ct.kind,
withKind: ct.asKind(c.module.Context),
}}
}
return tn
}
func (bt *bootstrapType) IndexComputed(i Type, t *Expr) *klarerrs.Error {
if indexer, ok := Underlying(bt.withKind).(ComputedIndexer); ok {
return indexer.IndexComputed(i, t)
}
if indexer, ok := Underlying(bt.asDeclared).(ComputedIndexer); ok {
return indexer.IndexComputed(i, t)
}
return nil
}
func (bt *bootstrapType) Index(i string, t *Expr) *klarerrs.Error {
indexer, ok := bt.withKind.(Indexer)
if !ok {
return nil
}
return indexer.Index(i, t)
/* if indexer, ok := Underlying(bt.asDeclared).(Indexer); ok {
return indexer.Index(i, t)
}
return nil */
}
func (bt *bootstrapType) CanIndex() bool {
_, ok := Underlying(bt.asDeclared).(Indexer)
return ok
}
func lookupBootstrap(name string) *Object {
return builtinModule.Context.Lookup(name)
}