You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
1.8 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package vm
  2. import (
  3. "fmt"
  4. )
  5. // Not goroutine safe
  6. type Stack struct {
  7. data []Word
  8. ptr int
  9. gas *uint64
  10. err *error
  11. }
  12. func NewStack(capacity int, gas *uint64, err *error) *Stack {
  13. return &Stack{
  14. data: make([]Word, capacity),
  15. ptr: 0,
  16. gas: gas,
  17. err: err,
  18. }
  19. }
  20. func (st *Stack) useGas(gasToUse uint64) {
  21. if *st.gas > gasToUse {
  22. *st.gas -= gasToUse
  23. } else {
  24. st.setErr(ErrInsufficientGas)
  25. }
  26. }
  27. func (st *Stack) setErr(err error) {
  28. if *st.err != nil {
  29. *st.err = err
  30. }
  31. }
  32. func (st *Stack) Push(d Word) {
  33. st.useGas(GasStackOp)
  34. if st.ptr == cap(st.data) {
  35. st.setErr(ErrDataStackOverflow)
  36. return
  37. }
  38. st.data[st.ptr] = d
  39. st.ptr++
  40. }
  41. func (st *Stack) PushBytes(bz []byte) {
  42. if len(bz) != 32 {
  43. panic("Invalid bytes size: expected 32")
  44. }
  45. st.Push(BytesToWord(bz))
  46. }
  47. func (st *Stack) Push64(i uint64) {
  48. st.Push(Uint64ToWord(i))
  49. }
  50. func (st *Stack) Pop() Word {
  51. st.useGas(GasStackOp)
  52. if st.ptr == 0 {
  53. st.setErr(ErrDataStackUnderflow)
  54. return Zero
  55. }
  56. st.ptr--
  57. return st.data[st.ptr]
  58. }
  59. func (st *Stack) PopBytes() []byte {
  60. return st.Pop().Bytes()
  61. }
  62. func (st *Stack) Pop64() uint64 {
  63. return GetUint64(st.Pop())
  64. }
  65. func (st *Stack) Len() int {
  66. return st.ptr
  67. }
  68. func (st *Stack) Swap(n int) {
  69. st.useGas(GasStackOp)
  70. if st.ptr < n {
  71. st.setErr(ErrDataStackUnderflow)
  72. return
  73. }
  74. st.data[st.ptr-n], st.data[st.ptr-1] = st.data[st.ptr-1], st.data[st.ptr-n]
  75. return
  76. }
  77. func (st *Stack) Dup(n int) {
  78. st.useGas(GasStackOp)
  79. if st.ptr < n {
  80. st.setErr(ErrDataStackUnderflow)
  81. return
  82. }
  83. st.Push(st.data[st.ptr-n])
  84. return
  85. }
  86. // Not an opcode, costs no gas.
  87. func (st *Stack) Peek() Word {
  88. return st.data[st.ptr-1]
  89. }
  90. func (st *Stack) Print() {
  91. fmt.Println("### stack ###")
  92. if st.ptr > 0 {
  93. for i, val := range st.data {
  94. fmt.Printf("%-3d %v\n", i, val)
  95. }
  96. } else {
  97. fmt.Println("-- empty --")
  98. }
  99. fmt.Println("#############")
  100. }