aboutsummaryrefslogtreecommitdiff
path: root/compiler/symbol_position.go
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/symbol_position.go')
-rw-r--r--compiler/symbol_position.go79
1 files changed, 53 insertions, 26 deletions
diff --git a/compiler/symbol_position.go b/compiler/symbol_position.go
index 1b400bd..d35dfde 100644
--- a/compiler/symbol_position.go
+++ b/compiler/symbol_position.go
@@ -52,17 +52,26 @@ func (p symbolPosition) describe() (uint16, bool) {
return v, false
}
-type symbolPositionSet map[symbolPosition]struct{}
+type symbolPositionSet struct {
+ // `s` represents a set of symbol positions.
+ // However, immediately after adding a symbol position, the elements may be duplicated.
+ // When you need an aligned set with no duplicates, you can get such value via the set function.
+ s []symbolPosition
+ sorted bool
+}
-func newSymbolPositionSet() symbolPositionSet {
- return map[symbolPosition]struct{}{}
+func newSymbolPositionSet() *symbolPositionSet {
+ return &symbolPositionSet{
+ s: []symbolPosition{},
+ sorted: false,
+ }
}
-func (s symbolPositionSet) String() string {
- if len(s) <= 0 {
+func (s *symbolPositionSet) String() string {
+ if len(s.s) <= 0 {
return "{}"
}
- ps := s.sort()
+ ps := s.sortAndRemoveDuplicates()
var b strings.Builder
fmt.Fprintf(&b, "{")
for i, p := range ps {
@@ -76,22 +85,27 @@ func (s symbolPositionSet) String() string {
return b.String()
}
-func (s symbolPositionSet) add(pos symbolPosition) symbolPositionSet {
- s[pos] = struct{}{}
+func (s *symbolPositionSet) set() []symbolPosition {
+ s.sortAndRemoveDuplicates()
+ return s.s
+}
+
+func (s *symbolPositionSet) add(pos symbolPosition) *symbolPositionSet {
+ s.s = append(s.s, pos)
+ s.sorted = false
return s
}
-func (s symbolPositionSet) merge(t symbolPositionSet) symbolPositionSet {
- for p := range t {
- s.add(p)
- }
+func (s *symbolPositionSet) merge(t *symbolPositionSet) *symbolPositionSet {
+ s.s = append(s.s, t.s...)
+ s.sorted = false
return s
}
-func (s symbolPositionSet) intersect(set symbolPositionSet) symbolPositionSet {
+func (s *symbolPositionSet) intersect(set *symbolPositionSet) *symbolPositionSet {
in := newSymbolPositionSet()
- for p1 := range s {
- for p2 := range set {
+ for _, p1 := range s.s {
+ for _, p2 := range set.s {
if p1 != p2 {
continue
}
@@ -101,11 +115,11 @@ func (s symbolPositionSet) intersect(set symbolPositionSet) symbolPositionSet {
return in
}
-func (s symbolPositionSet) hash() string {
- if len(s) <= 0 {
+func (s *symbolPositionSet) hash() string {
+ if len(s.s) <= 0 {
return ""
}
- sorted := s.sort()
+ sorted := s.sortAndRemoveDuplicates()
var buf []byte
for _, p := range sorted {
b := make([]byte, 8)
@@ -118,15 +132,28 @@ func (s symbolPositionSet) hash() string {
return string(buf)
}
-func (s symbolPositionSet) sort() []symbolPosition {
- sorted := make([]symbolPosition, len(s))
- i := 0
- for p := range s {
- sorted[i] = p
- i++
+func (s *symbolPositionSet) sortAndRemoveDuplicates() []symbolPosition {
+ if s.sorted {
+ return s.s
}
- sortSymbolPositions(sorted, 0, len(sorted)-1)
- return sorted
+
+ sortSymbolPositions(s.s, 0, len(s.s)-1)
+
+ // Remove duplicates.
+ lastV := s.s[0]
+ nextIdx := 1
+ for _, v := range s.s[1:] {
+ if v == lastV {
+ continue
+ }
+ s.s[nextIdx] = v
+ nextIdx++
+ lastV = v
+ }
+ s.s = s.s[:nextIdx]
+ s.sorted = true
+
+ return s.s
}
// sortSymbolPositions sorts a slice of symbol positions as it uses quick sort.