Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.

Commit 55e8e65

Browse files
committed
Monomorphize treelist.go
1 parent 7ad8903 commit 55e8e65

5 files changed

Lines changed: 419 additions & 42 deletions

File tree

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// Copyright 2015 Google Inc. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package jvm
16+
17+
// This class represents a list as a persistent n-ary tree
18+
// This has much slower access and updates than a real list but has the advantage
19+
// of sharing memory with previous versions of the list when only a few elements
20+
// are changed. See http://en.wikipedia.org/wiki/Persistent_data_structure//Trees
21+
// Also, default values are not stored, so this is good for sparse arrays
22+
type ImmutableTreeListᐸElementTᐳ struct {
23+
missing ElementT
24+
direct [16]ElementT
25+
children [16]*ImmutableTreeListᐸElementTᐳ
26+
}
27+
28+
func newTreeListᐸElementTᐳ(missing ElementT) *ImmutableTreeListᐸElementTᐳ {
29+
self := ImmutableTreeListᐸElementTᐳ{missing: missing}
30+
for i := 0; i < 16; i++ {
31+
self.direct[i] = missing
32+
}
33+
// Subtrees allocated lazily
34+
return &self
35+
}
36+
37+
func (self *ImmutableTreeListᐸElementTᐳ) get(i uint16) ElementT {
38+
if i < 16 {
39+
return self.direct[i]
40+
}
41+
i -= 16
42+
43+
ci := i % 16
44+
i = i / 16
45+
child := self.children[ci]
46+
if child == nil {
47+
return self.missing
48+
}
49+
return child.get(i)
50+
}
51+
52+
func (self *ImmutableTreeListᐸElementTᐳ) set(i uint16, val ElementT) *ImmutableTreeListᐸElementTᐳ {
53+
if i < 16 {
54+
if val == self.direct[i] {
55+
return self
56+
}
57+
58+
temp := self.direct
59+
temp[i] = val
60+
return &ImmutableTreeListᐸElementTᐳ{self.missing, temp, self.children}
61+
}
62+
63+
i -= 16
64+
65+
ci := i % 16
66+
i = i / 16
67+
child := self.children[ci]
68+
69+
if child == nil {
70+
if val == self.missing {
71+
return self
72+
}
73+
child = newTreeListᐸElementTᐳ(self.missing).set(i, val)
74+
} else {
75+
if val == child.get(i) {
76+
return self
77+
}
78+
child = child.set(i, val)
79+
}
80+
81+
temp := self.children
82+
temp[ci] = child
83+
return &ImmutableTreeListᐸElementTᐳ{self.missing, self.direct, temp}
84+
}
85+
86+
func (left *ImmutableTreeListᐸElementTᐳ) merge(right *ImmutableTreeListᐸElementTᐳ, f func(ElementT, ElementT) ElementT) *ImmutableTreeListᐸElementTᐳ {
87+
// Effectively computes [func(x, y) for x, y in zip(left, right)]
88+
// Assume func(x, x) == x
89+
if left == right {
90+
return left
91+
}
92+
93+
if left == nil {
94+
left, right = right, left
95+
}
96+
97+
missing := left.missing
98+
direct := [16]ElementT{}
99+
children := [16]*ImmutableTreeListᐸElementTᐳ{}
100+
101+
if right == nil {
102+
for i, x := range left.direct {
103+
direct[i] = f(x, missing)
104+
}
105+
for i, child := range left.children {
106+
children[i] = child.merge(nil, f)
107+
}
108+
} else {
109+
for i, x := range left.direct {
110+
direct[i] = f(x, right.direct[i])
111+
}
112+
for i, child := range left.children {
113+
children[i] = child.merge(right.children[i], f)
114+
}
115+
116+
if direct == right.direct && children == right.children {
117+
return right
118+
}
119+
}
120+
121+
if direct == left.direct && children == left.children {
122+
return left
123+
}
124+
return &ImmutableTreeListᐸElementTᐳ{missing, direct, children}
125+
}
Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,69 +11,66 @@
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
14-
package jvm
1514

16-
// The first SIZE elements are stored directly, the rest are stored in one of SPLIT subtrees
17-
const SIZE = 16
18-
const SPLIT = 16
15+
package jvm
1916

2017
// This class represents a list as a persistent n-ary tree
2118
// This has much slower access and updates than a real list but has the advantage
2219
// of sharing memory with previous versions of the list when only a few elements
2320
// are changed. See http://en.wikipedia.org/wiki/Persistent_data_structure//Trees
2421
// Also, default values are not stored, so this is good for sparse arrays
25-
type ImmutableTreeList struct {
26-
missing interface{}
27-
direct [SIZE]interface{}
28-
children [SPLIT]*ImmutableTreeList
22+
type ImmutableTreeListᐸArrayTᐳ struct {
23+
missing ArrayT
24+
direct [16]ArrayT
25+
children [16]*ImmutableTreeListᐸArrayTᐳ
2926
}
3027

31-
func newTreeList(missing interface{}) *ImmutableTreeList {
32-
self := ImmutableTreeList{missing: missing}
33-
for i := 0; i < SIZE; i++ {
28+
func newTreeListᐸArrayTᐳ(missing ArrayT) *ImmutableTreeListᐸArrayTᐳ {
29+
self := ImmutableTreeListᐸArrayTᐳ{missing: missing}
30+
for i := 0; i < 16; i++ {
3431
self.direct[i] = missing
3532
}
3633
// Subtrees allocated lazily
3734
return &self
3835
}
3936

40-
func (self *ImmutableTreeList) get(i uint16) interface{} {
41-
if i < SIZE {
37+
func (self *ImmutableTreeListᐸArrayTᐳ) get(i uint16) ArrayT {
38+
if i < 16 {
4239
return self.direct[i]
4340
}
44-
i -= SIZE
41+
i -= 16
4542

46-
ci := i % SPLIT
47-
i = i / SPLIT
43+
ci := i % 16
44+
i = i / 16
4845
child := self.children[ci]
4946
if child == nil {
5047
return self.missing
5148
}
5249
return child.get(i)
5350
}
5451

55-
func (self *ImmutableTreeList) set(i uint16, val interface{}) *ImmutableTreeList {
56-
if i < SIZE {
52+
func (self *ImmutableTreeListᐸArrayTᐳ) set(i uint16, val ArrayT) *ImmutableTreeListᐸArrayTᐳ {
53+
if i < 16 {
5754
if val == self.direct[i] {
5855
return self
5956
}
6057

6158
temp := self.direct
6259
temp[i] = val
63-
return &ImmutableTreeList{self.missing, temp, self.children}
60+
return &ImmutableTreeListᐸArrayTᐳ{self.missing, temp, self.children}
6461
}
6562

66-
i -= SIZE
63+
i -= 16
6764

68-
ci := i % SPLIT
69-
i = i / SPLIT
65+
ci := i % 16
66+
i = i / 16
7067
child := self.children[ci]
7168

7269
if child == nil {
7370
if val == self.missing {
7471
return self
7572
}
76-
child = newTreeList(self.missing).set(i, val)
73+
child = newTreeListᐸArrayTᐳ(self.missing).set(i, val)
7774
} else {
7875
if val == child.get(i) {
7976
return self
@@ -83,10 +80,10 @@ func (self *ImmutableTreeList) set(i uint16, val interface{}) *ImmutableTreeList
8380

8481
temp := self.children
8582
temp[ci] = child
86-
return &ImmutableTreeList{self.missing, self.direct, temp}
83+
return &ImmutableTreeListᐸArrayTᐳ{self.missing, self.direct, temp}
8784
}
8885

89-
func (left *ImmutableTreeList) merge(right *ImmutableTreeList, f func(interface{}, interface{}) interface{}) *ImmutableTreeList {
86+
func (left *ImmutableTreeListᐸArrayTᐳ) merge(right *ImmutableTreeListᐸArrayTᐳ, f func(ArrayT, ArrayT) ArrayT) *ImmutableTreeListᐸArrayTᐳ {
9087
// Effectively computes [func(x, y) for x, y in zip(left, right)]
9188
// Assume func(x, x) == x
9289
if left == right {
@@ -98,8 +95,8 @@ func (left *ImmutableTreeList) merge(right *ImmutableTreeList, f func(interface{
9895
}
9996

10097
missing := left.missing
101-
direct := [SIZE]interface{}{}
102-
children := [SPLIT]*ImmutableTreeList{}
98+
direct := [16]ArrayT{}
99+
children := [16]*ImmutableTreeListᐸArrayTᐳ{}
103100

104101
if right == nil {
105102
for i, x := range left.direct {
@@ -124,5 +121,5 @@ func (left *ImmutableTreeList) merge(right *ImmutableTreeList, f func(interface{
124121
if direct == left.direct && children == left.children {
125122
return left
126123
}
127-
return &ImmutableTreeList{missing, direct, children}
124+
return &ImmutableTreeListᐸArrayTᐳ{missing, direct, children}
128125
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// Copyright 2015 Google Inc. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package jvm
16+
17+
// This class represents a list as a persistent n-ary tree
18+
// This has much slower access and updates than a real list but has the advantage
19+
// of sharing memory with previous versions of the list when only a few elements
20+
// are changed. See http://en.wikipedia.org/wiki/Persistent_data_structure//Trees
21+
// Also, default values are not stored, so this is good for sparse arrays
22+
type ImmutableTreeListᐸboolᐳ struct {
23+
missing bool
24+
direct [16]bool
25+
children [16]*ImmutableTreeListᐸboolᐳ
26+
}
27+
28+
func newTreeListᐸboolᐳ(missing bool) *ImmutableTreeListᐸboolᐳ {
29+
self := ImmutableTreeListᐸboolᐳ{missing: missing}
30+
for i := 0; i < 16; i++ {
31+
self.direct[i] = missing
32+
}
33+
// Subtrees allocated lazily
34+
return &self
35+
}
36+
37+
func (self *ImmutableTreeListᐸboolᐳ) get(i uint16) bool {
38+
if i < 16 {
39+
return self.direct[i]
40+
}
41+
i -= 16
42+
43+
ci := i % 16
44+
i = i / 16
45+
child := self.children[ci]
46+
if child == nil {
47+
return self.missing
48+
}
49+
return child.get(i)
50+
}
51+
52+
func (self *ImmutableTreeListᐸboolᐳ) set(i uint16, val bool) *ImmutableTreeListᐸboolᐳ {
53+
if i < 16 {
54+
if val == self.direct[i] {
55+
return self
56+
}
57+
58+
temp := self.direct
59+
temp[i] = val
60+
return &ImmutableTreeListᐸboolᐳ{self.missing, temp, self.children}
61+
}
62+
63+
i -= 16
64+
65+
ci := i % 16
66+
i = i / 16
67+
child := self.children[ci]
68+
69+
if child == nil {
70+
if val == self.missing {
71+
return self
72+
}
73+
child = newTreeListᐸboolᐳ(self.missing).set(i, val)
74+
} else {
75+
if val == child.get(i) {
76+
return self
77+
}
78+
child = child.set(i, val)
79+
}
80+
81+
temp := self.children
82+
temp[ci] = child
83+
return &ImmutableTreeListᐸboolᐳ{self.missing, self.direct, temp}
84+
}
85+
86+
func (left *ImmutableTreeListᐸboolᐳ) merge(right *ImmutableTreeListᐸboolᐳ, f func(bool, bool) bool) *ImmutableTreeListᐸboolᐳ {
87+
// Effectively computes [func(x, y) for x, y in zip(left, right)]
88+
// Assume func(x, x) == x
89+
if left == right {
90+
return left
91+
}
92+
93+
if left == nil {
94+
left, right = right, left
95+
}
96+
97+
missing := left.missing
98+
direct := [16]bool{}
99+
children := [16]*ImmutableTreeListᐸboolᐳ{}
100+
101+
if right == nil {
102+
for i, x := range left.direct {
103+
direct[i] = f(x, missing)
104+
}
105+
for i, child := range left.children {
106+
children[i] = child.merge(nil, f)
107+
}
108+
} else {
109+
for i, x := range left.direct {
110+
direct[i] = f(x, right.direct[i])
111+
}
112+
for i, child := range left.children {
113+
children[i] = child.merge(right.children[i], f)
114+
}
115+
116+
if direct == right.direct && children == right.children {
117+
return right
118+
}
119+
}
120+
121+
if direct == left.direct && children == left.children {
122+
return left
123+
}
124+
return &ImmutableTreeListᐸboolᐳ{missing, direct, children}
125+
}

0 commit comments

Comments
 (0)