forked from x/ContextOS
74 lines
1.3 KiB
Go
74 lines
1.3 KiB
Go
package kit
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
type Frame struct {
|
|
Key string
|
|
Run bool
|
|
Pos int
|
|
|
|
deep int
|
|
Done bool
|
|
Data interface{}
|
|
Hash map[string]interface{}
|
|
Label map[string]int
|
|
}
|
|
|
|
func (f *Frame) String(meta string) string {
|
|
return fmt.Sprintf("%s%s%d %s %t", strings.Repeat("#", f.deep), meta, f.deep, f.Key, f.Run)
|
|
}
|
|
|
|
var bottom = &Frame{}
|
|
|
|
type Stack struct {
|
|
Target interface{}
|
|
FS []*Frame
|
|
}
|
|
|
|
func (s *Stack) Push(key string, run bool, pos int) *Frame {
|
|
s.FS = append(s.FS, &Frame{Key: key, Run: run, Pos: pos, deep: len(s.FS), Hash: map[string]interface{}{}})
|
|
return s.FS[len(s.FS)-1]
|
|
}
|
|
func (s *Stack) Peek() *Frame {
|
|
if len(s.FS) == 0 {
|
|
return bottom
|
|
}
|
|
return s.FS[len(s.FS)-1]
|
|
}
|
|
func (s *Stack) Pop() *Frame {
|
|
if len(s.FS) == 0 {
|
|
return bottom
|
|
}
|
|
f := s.FS[len(s.FS)-1]
|
|
s.FS = s.FS[:len(s.FS)-1]
|
|
return f
|
|
}
|
|
func (s *Stack) Hash(key string, val ...interface{}) (interface{}, bool) {
|
|
for i := len(s.FS) - 1; i >= 0; i-- {
|
|
if v, ok := s.FS[i].Hash[key]; ok {
|
|
if len(val) > 0 {
|
|
s.FS[i].Hash[key] = val[0]
|
|
}
|
|
return v, ok
|
|
}
|
|
}
|
|
|
|
if len(val) > 0 {
|
|
s.FS[len(s.FS)-1].Hash[key] = val[0]
|
|
return val[0], true
|
|
}
|
|
return nil, false
|
|
}
|
|
func (s *Stack) Label(key string) (int, bool) {
|
|
for i := len(s.FS) - 1; i >= 0; i-- {
|
|
if v, ok := s.FS[i].Label[key]; ok {
|
|
s.FS = s.FS[:i+1]
|
|
return v, ok
|
|
}
|
|
}
|
|
return -1, false
|
|
}
|