github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/equity/compiler/stack.go (about)

     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  }