OSDN Git Service

Merge pull request #41 from Bytom/dev
[bytom/vapor.git] / equity / compiler / stack.go
1 package compiler
2
3 type (
4         stack struct {
5                 *stackEntry
6         }
7         stackEntry struct {
8                 str  string
9                 prev *stackEntry
10         }
11 )
12
13 func (stk stack) isEmpty() bool {
14         return stk.stackEntry == nil
15 }
16
17 func (stk stack) top() string {
18         if stk.isEmpty() {
19                 return ""
20         }
21         return stk.str
22 }
23
24 func (stk stack) add(str string) stack {
25         e := &stackEntry{
26                 str:  str,
27                 prev: stk.stackEntry,
28         }
29         return stack{e}
30 }
31
32 func (stk stack) addFromStack(other stack) stack {
33         if other.isEmpty() {
34                 return stk
35         }
36         res := stk.addFromStack(other.drop())
37         return res.add(other.top())
38 }
39
40 func (stk stack) drop() stack {
41         if !stk.isEmpty() {
42                 stk = stack{stk.prev}
43         }
44         return stk
45 }
46
47 func (stk stack) dropN(n int) stack {
48         for n > 0 {
49                 stk = stk.drop()
50                 n--
51         }
52         return stk
53 }
54
55 func (stk stack) recurFind(str string) int {
56         if stk.isEmpty() {
57                 return -1
58         }
59         if stk.str == str {
60                 return 0
61         }
62         res := stk.drop().recurFind(str)
63         if res < 0 {
64                 return res
65         }
66         return res + 1
67 }
68
69 func (stk stack) count() map[string]int {
70         if stk.isEmpty() {
71                 return nil
72         }
73         stackCounts := make(map[string]int)
74         for {
75                 stackCounts[stk.str]++
76                 stk = stack{stk.prev}
77                 if stk.stackEntry == nil {
78                         break
79                 }
80         }
81         return stackCounts
82 }
83
84 func (stk stack) find(str string) int {
85         stackCounts := stk.count()
86         if stk.isEmpty() || stackCounts[str] == 0 {
87                 return -1
88         }
89
90         var pos int
91         for {
92                 if stk.str == str {
93                         if stackCounts[str] == 1 {
94                                 break
95                         }
96                         stackCounts[str]--
97                 }
98                 stk = stack{stk.prev}
99                 if stk.stackEntry == nil {
100                         break
101                 }
102                 pos++
103         }
104         return pos
105 }
106
107 func (stk stack) roll(n int) stack {
108         var x func(stack, int) (stack, string)
109         x = func(stk stack, n int) (stack, string) {
110                 if n == 0 {
111                         return stk.drop(), stk.top()
112                 }
113                 stk2, entry := x(stk.drop(), n-1)
114                 return stk2.add(stk.top()), entry
115         }
116         stk, entry := x(stk, n)
117         return stk.add(entry)
118 }
119
120 func (stk stack) swap() stack {
121         a := stk.top()
122         stk = stk.drop()
123         b := stk.top()
124         stk = stk.drop()
125         return stk.add(a).add(b)
126 }
127
128 func (stk stack) dup() stack {
129         return stk.add(stk.top())
130 }
131
132 func (stk stack) over() stack {
133         t := stk.drop().top()
134         return stk.add(t)
135 }
136
137 func (stk stack) pick(n int) stack {
138         t := stk.dropN(n).top()
139         return stk.add(t)
140 }
141
142 func (stk stack) String() string {
143         if stk.stackEntry == nil {
144                 return "[]"
145         }
146         var x func(stk stack) string
147         x = func(stk stack) string {
148                 if stk.stackEntry == nil {
149                         return ""
150                 }
151                 return x(stk.drop()) + " " + stk.stackEntry.str
152         }
153         return "[..." + x(stk) + "]"
154 }