/
registries.go
102 lines (78 loc) · 1.76 KB
/
registries.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
package def
import (
"errors"
rtu "github.com/wrmsr/bane/core/runtime"
)
//
type RegistryError struct {
err error
}
func (e RegistryError) Error() string { return e.err.Error() }
func (e RegistryError) Unwrap() error { return e.err }
var (
RegistrySealedError = RegistryError{errors.New("registry sealed")}
)
//
var _thisPackage = func() string { return rtu.GetCaller(0).Pkg }()
func X_defPackageName() string {
return _thisPackage
}
func getCallingPackage() string {
pkg := rtu.GetCaller(2).Pkg
if pkg == _thisPackage {
panic(RegistryError{errors.New("must not call from this package")})
}
return pkg
}
//
type packageRegistry struct {
name string
defs []PackageDef
_spec *PackageSpec
}
func newPackageRegistry(name string) *packageRegistry {
return &packageRegistry{
name: name,
}
}
func (r *packageRegistry) addDef(def PackageDef) {
if r._spec != nil {
panic(RegistrySealedError)
}
r.defs = append(r.defs, def)
}
func (r *packageRegistry) spec() *PackageSpec {
if r._spec == nil {
r._spec = NewPackageSpec(r.name, r.defs)
}
return r._spec
}
//
type registry struct {
packages map[string]*packageRegistry
}
func newRegistry() *registry {
return ®istry{
packages: make(map[string]*packageRegistry),
}
}
func (r *registry) getPackage(name string) *packageRegistry {
if p, ok := r.packages[name]; ok {
return p
}
p := newPackageRegistry(name)
r.packages[name] = p
return p
}
//
var globalRegistry = newRegistry()
func addPackageDef[T PackageDef](r *registry, pkg string, def T) T {
r.getPackage(pkg).addDef(def)
return def
}
func X_addPackageDef(def PackageDef) {
globalRegistry.getPackage(getCallingPackage()).addDef(def)
}
func X_getPackageSpec() *PackageSpec {
return globalRegistry.getPackage(getCallingPackage()).spec()
}