vm: add IterBack to the Stack to iterate bottom-to-top

And use it to build user-facing stack representation because that's the order
that C# VM uses.
This commit is contained in:
Roman Khimov 2019-11-26 19:53:30 +03:00
parent f3ed91a1f7
commit 05f3329ec0
3 changed files with 43 additions and 5 deletions

View file

@ -35,7 +35,7 @@ func appendToItems(items *[]stackItem, val StackItem, seen map[StackItem]bool) {
func stackToArray(s *Stack) []stackItem { func stackToArray(s *Stack) []stackItem {
items := make([]stackItem, 0, s.Len()) items := make([]stackItem, 0, s.Len())
seen := make(map[StackItem]bool) seen := make(map[StackItem]bool)
s.Iter(func(e *Element) { s.IterBack(func(e *Element) {
appendToItems(&items, e.value, seen) appendToItems(&items, e.value, seen)
}) })
return items return items

View file

@ -360,6 +360,17 @@ func (s *Stack) Iter(f func(*Element)) {
} }
} }
// IterBack iterates over all the elements of the stack, starting from the bottom
// of the stack.
// s.IterBack(func(elem *Element) {
// // do something with the element.
// })
func (s *Stack) IterBack(f func(*Element)) {
for e := s.Back(); e != nil; e = e.Prev() {
f(e)
}
}
// popSigElements pops keys or signatures from the stack as needed for // popSigElements pops keys or signatures from the stack as needed for
// CHECKMULTISIG. // CHECKMULTISIG.
func (s *Stack) popSigElements() ([][]byte, error) { func (s *Stack) popSigElements() ([][]byte, error) {

View file

@ -154,19 +154,46 @@ func TestIterAfterRemove(t *testing.T) {
func TestIteration(t *testing.T) { func TestIteration(t *testing.T) {
var ( var (
n = 10
s = NewStack("test") s = NewStack("test")
elems = makeElements(10) elems = makeElements(n)
) )
for _, elem := range elems { for _, elem := range elems {
s.Push(elem) s.Push(elem)
} }
assert.Equal(t, len(elems), s.Len()) assert.Equal(t, len(elems), s.Len())
i := 0 iteratedElems := make([]*Element, 0)
s.Iter(func(elem *Element) { s.Iter(func(elem *Element) {
i++ iteratedElems = append(iteratedElems, elem)
}) })
assert.Equal(t, len(elems), i) // Top to bottom order of iteration.
poppedElems := make([]*Element, 0)
for elem := s.Pop(); elem != nil; elem = s.Pop() {
poppedElems = append(poppedElems, elem)
}
assert.Equal(t, poppedElems, iteratedElems)
}
func TestBackIteration(t *testing.T) {
var (
n = 10
s = NewStack("test")
elems = makeElements(n)
)
for _, elem := range elems {
s.Push(elem)
}
assert.Equal(t, len(elems), s.Len())
iteratedElems := make([]*Element, 0)
s.IterBack(func(elem *Element) {
iteratedElems = append(iteratedElems, elem)
})
// Bottom to the top order of iteration.
assert.Equal(t, elems, iteratedElems)
} }
func TestPushVal(t *testing.T) { func TestPushVal(t *testing.T) {