-
-
Notifications
You must be signed in to change notification settings - Fork 13
/
visibility.go
90 lines (71 loc) · 2.06 KB
/
visibility.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
package core
import (
"errors"
"github.com/inoxlang/inox/internal/parse"
cmap "github.com/orcaman/concurrent-map/v2"
)
const (
VISIBILITY_KEY = "_visibility_"
)
var (
visibilityMap = cmap.NewWithCustomShardingFunction[VisibilityId, *ValueVisibility](
func(key VisibilityId) uint32 {
return uint32(key % 16)
},
)
nextVisibilityId = VisibilityId(1)
ErrNotVisible = errors.New("not visible by context")
)
type VisibilityId uint64
func (v VisibilityId) HasVisibility() bool {
return v > 0
}
// A ValueVisibility specifies what parts of an Inox value are 'visible' during serialization.
type ValueVisibility struct {
publicKeys []string
selfVisibleKeys []string
}
func GetVisibility(id VisibilityId) (*ValueVisibility, bool) {
return visibilityMap.Get(id)
}
func initializeVisibilityMetaproperty(v *Object, block *parse.InitializationBlock) {
visibility := &ValueVisibility{}
objLiteral := block.Statements[0].(*parse.ObjectLiteral)
//TODO: return error if invalid keys or if there are metaproperties
for _, prop := range objLiteral.Properties {
if prop.HasImplicitKey() {
continue
}
switch prop.Name() {
case "public":
keyList := prop.Value.(*parse.KeyListExpression)
visibility.publicKeys = make([]string, len(keyList.Keys))
for i, n := range keyList.Names() {
visibility.publicKeys[i] = n.Name
}
case "visible_by":
dict := prop.Value.(*parse.DictionaryLiteral)
for _, entry := range dict.Entries {
switch keyNode := entry.Key.(type) {
case *parse.UnambiguousIdentifierLiteral:
switch keyNode.Name {
case "self":
keyList := entry.Value.(*parse.KeyListExpression)
visibility.selfVisibleKeys = make([]string, len(keyList.Keys))
for i, n := range keyList.Names() {
visibility.selfVisibleKeys[i] = n.Name
}
}
}
}
}
}
initializeObjectVisibility(v, visibility)
}
func initializeObjectVisibility(v *Object, visibility *ValueVisibility) {
id := nextVisibilityId
nextVisibilityId++
visibilityMap.Set(id, visibility)
v.ensureAdditionalFields()
v.visibilityId = id
}