mirror of
https://shylinux.com/x/icebergs
synced 2025-06-26 10:27:31 +08:00
opt yac
This commit is contained in:
parent
ca064bcc17
commit
3edc006f07
@ -2,6 +2,7 @@ package log
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
@ -13,52 +14,48 @@ import (
|
||||
|
||||
const DEBUG = "debug"
|
||||
|
||||
func _debug_file(k string) string { return ice.VAR_LOG + k + ".log" }
|
||||
|
||||
func init() {
|
||||
Index.MergeCommands(ice.Commands{
|
||||
DEBUG: {Name: "debug level=error,bench,debug,error,watch offset filter auto reset doc", Help: "后台日志", Actions: ice.Actions{
|
||||
DEBUG: {Name: "debug level=error,bench,debug,error,watch offset limit filter auto reset doc", Help: "后台日志", Actions: ice.Actions{
|
||||
"doc": {Help: "文档", Hand: func(m *ice.Message, arg ...string) { m.ProcessOpen("https://pkg.go.dev/std") }},
|
||||
"reset": {Help: "文档", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmd(nfs.CAT, ice.VAR_LOG+arg[0]+".log", func(line string, index int) {
|
||||
m.ProcessRewrite("offset", index+2)
|
||||
})
|
||||
m.Cmd(nfs.CAT, _debug_file(arg[0]), func(line string, index int) { m.ProcessRewrite(mdb.OFFSET, index+2, mdb.LIMIT, 1000) })
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, arg ...string) {
|
||||
offset, stats := kit.Int(kit.Select("0", arg, 1)), map[string]int{}
|
||||
offset, limit, stats := kit.Int(kit.Select("0", arg, 1)), kit.Int(kit.Select("1000", arg, 2)), map[string]int{}
|
||||
switch arg[0] {
|
||||
case BENCH, ERROR, DEBUG:
|
||||
m.Cmd(nfs.CAT, ice.VAR_LOG+arg[0]+".log", func(line string, index int) {
|
||||
if len(arg) > 2 && !strings.Contains(line, arg[2]) || index < offset {
|
||||
m.Cmd(nfs.CAT, _debug_file(arg[0]), func(line string, index int) {
|
||||
if index < offset || index >= offset+limit || !strings.Contains(line, kit.Select("", arg, 3)) {
|
||||
return
|
||||
}
|
||||
ls := strings.SplitN(line, ice.SP, 6)
|
||||
if len(ls) < 6 {
|
||||
if _, e := time.Parse(kit.Split(ice.MOD_TIMES)[0], ls[0]); e != nil || len(ls) < 6 {
|
||||
m.Push(mdb.TIME, "").Push(mdb.ID, "")
|
||||
m.Push(nfs.PATH, "").Push(nfs.FILE, "").Push(nfs.LINE, "")
|
||||
m.Push(ctx.SHIP, "").Push(ctx.ACTION, "").Push(nfs.CONTENT, line)
|
||||
return
|
||||
}
|
||||
m.Push(mdb.TIME, ls[0]+ice.SP+ls[1]).Push(mdb.ID, ls[2])
|
||||
i := strings.LastIndex(ls[5], ice.SP)
|
||||
if strings.HasPrefix(ls[5][i+1:], ice.BASE) || strings.HasPrefix(ls[5][i+1:], ice.CORE) || strings.HasPrefix(ls[5][i+1:], ice.MISC) {
|
||||
m.Push(nfs.PATH, ice.USR_ICEBERGS)
|
||||
if i := strings.LastIndex(ls[5], ice.SP); strings.HasPrefix(ls[5][i+1:], ice.BASE) || strings.HasPrefix(ls[5][i+1:], ice.CORE) || strings.HasPrefix(ls[5][i+1:], ice.MISC) {
|
||||
m.Push(nfs.FILE, strings.TrimSpace(strings.Split(ls[5][i:], ice.DF)[0]))
|
||||
m.Push(nfs.LINE, strings.TrimSpace(strings.Split(ls[5][i:], ice.DF)[1]))
|
||||
ls[5] = ls[5][:i]
|
||||
} else if strings.HasPrefix(ls[5][i+1:], ice.USR_ICEBERGS) {
|
||||
m.Push(nfs.PATH, ice.USR_ICEBERGS)
|
||||
m.Push(nfs.FILE, strings.TrimPrefix(strings.TrimSpace(strings.Split(ls[5][i:], ice.DF)[0]), ice.USR_ICEBERGS))
|
||||
m.Push(nfs.LINE, strings.TrimSpace(strings.Split(ls[5][i:], ice.DF)[1]))
|
||||
ls[5] = ls[5][:i]
|
||||
} else {
|
||||
m.Push(nfs.PATH, ice.USR_ICEBERGS)
|
||||
m.Push(nfs.FILE, "init.go")
|
||||
m.Push(nfs.LINE, "90")
|
||||
m.Push(nfs.FILE, "base/web/serve.go").Push(nfs.LINE, "62")
|
||||
}
|
||||
if ls[4] == ice.LOG_CMDS {
|
||||
_ls := strings.SplitN(ls[5], ice.SP, 2)
|
||||
ls[4] = _ls[0]
|
||||
ls[5] = _ls[1]
|
||||
if !unicode.IsDigit(rune(ls[5][0])) {
|
||||
if ls[4], ls[5] = _ls[0], _ls[1]; !unicode.IsDigit(rune(ls[5][0])) {
|
||||
_ls := strings.SplitN(ls[5], ice.SP, 2)
|
||||
ls[4] += ice.SP + _ls[0]
|
||||
ls[5] = _ls[1]
|
||||
ls[4], ls[5] = ls[4]+ice.SP+_ls[0], _ls[1]
|
||||
}
|
||||
}
|
||||
m.Push(ctx.SHIP, ls[3]).Push(ctx.ACTION, ls[4]).Push(nfs.CONTENT, ls[5])
|
||||
|
@ -120,6 +120,7 @@ const (
|
||||
REVERT = "revert"
|
||||
RANDOM = "random"
|
||||
OFFEND = "offend"
|
||||
OFFSET = "offset"
|
||||
|
||||
PAGE = "page"
|
||||
NEXT = "next"
|
||||
|
@ -1,18 +1,327 @@
|
||||
package yac
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/log"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
type Value struct{ list []ice.Any }
|
||||
|
||||
func (s *Value) MarshalJSON() ([]byte, error) { return json.Marshal(s.list) }
|
||||
|
||||
type Func struct {
|
||||
obj []string
|
||||
arg []string
|
||||
res []string
|
||||
Position
|
||||
}
|
||||
type Frame struct {
|
||||
key string
|
||||
value ice.Map
|
||||
status int
|
||||
Position
|
||||
pop func()
|
||||
}
|
||||
type Stack struct {
|
||||
last *Frame
|
||||
frame []*Frame
|
||||
input chan string
|
||||
list []string
|
||||
rest []string
|
||||
Position
|
||||
}
|
||||
type Position struct{ line, skip int }
|
||||
|
||||
func (s *Stack) peekf(m *ice.Message) *Frame {
|
||||
kit.If(len(s.frame) == 0, func() { s.pushf(m, "") })
|
||||
return s.frame[len(s.frame)-1]
|
||||
}
|
||||
func (s *Stack) pushf(m *ice.Message, key string) *Frame {
|
||||
f := &Frame{key: kit.Select(m.CommandKey(), key), value: kit.Dict(), Position: s.Position}
|
||||
kit.If(len(s.frame) > 0, func() { f.status = s.peekf(m).status })
|
||||
m.Debug("stack push %#v", f)
|
||||
s.frame = append(s.frame, f)
|
||||
return f
|
||||
}
|
||||
func (s *Stack) popf(m *ice.Message) *Frame {
|
||||
f := s.peekf(m)
|
||||
m.Debug("stack pop %#v", f)
|
||||
kit.If(len(s.frame) > 1, func() { s.frame = s.frame[:len(s.frame)-1] })
|
||||
return f
|
||||
}
|
||||
func (s *Stack) stack(cb ice.Any) {
|
||||
for i := len(s.frame) - 1; i >= 0; i-- {
|
||||
switch cb := cb.(type) {
|
||||
case func(*Frame, int) bool:
|
||||
if cb(s.frame[i], i) {
|
||||
return
|
||||
}
|
||||
case func(*Frame, int):
|
||||
cb(s.frame[i], i)
|
||||
case func(*Frame):
|
||||
cb(s.frame[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
func (s *Stack) value(m *ice.Message, key string, arg ...ice.Any) ice.Any {
|
||||
f := s.peekf(m)
|
||||
s.stack(func(_f *Frame, i int) bool {
|
||||
if _f.value[key] != nil {
|
||||
f = _f
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
kit.If(len(arg) > 0, func() {
|
||||
m.Debug("value set %v %#v", key, arg[0])
|
||||
switch v := arg[0].(type) {
|
||||
case *Value:
|
||||
f.value[key] = v.list[0]
|
||||
default:
|
||||
f.value[key] = arg[0]
|
||||
}
|
||||
})
|
||||
// m.Debug("value get %v %v", key, f.value[key])
|
||||
return f.value[key]
|
||||
}
|
||||
func (s *Stack) runable(m *ice.Message) bool { return s.peekf(m).status > DISABLE }
|
||||
func (s *Stack) read(m *ice.Message) (text string, ok bool) {
|
||||
isvoid := func(text string) bool {
|
||||
return strings.TrimSpace(text) == "" || strings.HasPrefix(strings.TrimSpace(text), "#")
|
||||
}
|
||||
for s.line++; s.line < len(s.list); s.line++ {
|
||||
if isvoid(s.list[s.line]) {
|
||||
continue
|
||||
}
|
||||
return s.list[s.line], true
|
||||
}
|
||||
for {
|
||||
if text, ok = <-s.input; !ok {
|
||||
break
|
||||
}
|
||||
m.Debug("input read %v", text)
|
||||
if s.list = append(s.list, text); isvoid(text) {
|
||||
continue
|
||||
}
|
||||
s.line = len(s.list) - 1
|
||||
break
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *Stack) reads(m *ice.Message, cb func(i int, k string) bool) (arg []string) {
|
||||
i := 0
|
||||
for {
|
||||
if s.skip++; s.skip < len(s.rest) {
|
||||
arg = append(arg, s.rest[s.skip])
|
||||
if cb(i, s.rest[s.skip]) {
|
||||
break
|
||||
}
|
||||
i++
|
||||
} else if text, ok := s.read(m); ok {
|
||||
s.rest, s.skip = kit.Split(text, "\t ", OPS), -1
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
func (s *Stack) call(m *ice.Message) {
|
||||
s.reads(m, func(i int, k string) bool {
|
||||
if k == SPLIT {
|
||||
|
||||
} else if k == END {
|
||||
kit.If(s.peekf(m).pop != nil, func() { s.peekf(m).pop() })
|
||||
s.last = s.popf(m)
|
||||
} else if _, ok := m.Target().Commands[k]; ok {
|
||||
m.Cmdy(k)
|
||||
} else {
|
||||
s.skip--
|
||||
m.Cmdy(EXPR)
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
func (s *Stack) parse(m *ice.Message, r io.Reader) *ice.Message {
|
||||
s.input = make(chan string, 100)
|
||||
m.Options(STACK, s)
|
||||
kit.For(r, func(text string) { s.input <- text })
|
||||
close(s.input)
|
||||
|
||||
// s.input = make(chan string)
|
||||
// m.Options(STACK, s).Go(func() {
|
||||
// defer func() { kit.If(s.input != nil, func() { close(s.input) }) }()
|
||||
// kit.For(r, func(text string) { s.input <- text })
|
||||
// })
|
||||
s.peekf(m)
|
||||
s.call(m)
|
||||
return m
|
||||
}
|
||||
func (s *Stack) token(m *ice.Message) string {
|
||||
if s.skip < len(s.rest) {
|
||||
return s.rest[s.skip]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
func (s *Stack) expr(m *ice.Message, pos Position) string {
|
||||
s.Position = pos
|
||||
return m.Cmdx(EXPR)
|
||||
}
|
||||
func NewStack() *Stack { return &Stack{} }
|
||||
func _parse_stack(m *ice.Message) *Stack { return m.Optionv(STACK).(*Stack) }
|
||||
func _parse_frame(m *ice.Message) (*Stack, *Frame) {
|
||||
return _parse_stack(m), _parse_stack(m).pushf(m, "")
|
||||
}
|
||||
|
||||
const (
|
||||
PWD = "pwd"
|
||||
CMD = "cmd"
|
||||
LET = "let"
|
||||
IF = "if"
|
||||
FOR = "for"
|
||||
FUNC = "func"
|
||||
CALL = "call"
|
||||
RETURN = "return"
|
||||
EXPR = "expr"
|
||||
OPS = "(,){;}!=<>+-*/"
|
||||
)
|
||||
const STACK = "stack"
|
||||
|
||||
func init() {
|
||||
Index.MergeCommands(ice.Commands{
|
||||
PWD: {Name: "pwd", Hand: func(m *ice.Message, arg ...string) {
|
||||
s := _parse_stack(m)
|
||||
res := []string{kit.Format("%d:%d", s.line, s.skip)}
|
||||
s.stack(func(f *Frame, i int) {
|
||||
kit.If(i > 0, func() {
|
||||
res = append(res, kit.Format("%d:%d %s %v", f.line, f.skip, f.key, kit.Select(ice.FALSE, ice.TRUE, f.status > DISABLE)))
|
||||
})
|
||||
})
|
||||
m.Echo(strings.Join(res, " / ")).Echo(ice.NL)
|
||||
}},
|
||||
CMD: {Name: "cmd", Hand: func(m *ice.Message, arg ...string) {
|
||||
s := _parse_stack(m)
|
||||
kit.If(s.runable(m), func() {
|
||||
m.Cmdy(s.rest[s.skip+1:])
|
||||
m.EchoLine("")
|
||||
})
|
||||
s.skip = len(s.rest)
|
||||
}},
|
||||
LET: {Name: "let a, b = 1, 2", Hand: func(m *ice.Message, arg ...string) { m.Cmd(EXPR) }},
|
||||
IF: {Name: "if a = 1; a > 1 {", Hand: func(m *ice.Message, arg ...string) {
|
||||
s, f := _parse_frame(m)
|
||||
res := m.Cmdx(EXPR)
|
||||
kit.If(s.token(m) == SPLIT, func() { res = m.Cmdx(EXPR) })
|
||||
kit.If(res == ice.FALSE, func() { f.status = DISABLE })
|
||||
}},
|
||||
FOR: {Name: "for a = 1; a < 10; a++ {", Hand: func(m *ice.Message, arg ...string) {
|
||||
s, f := _parse_frame(m)
|
||||
list, status := []Position{s.Position}, f.status
|
||||
for f.status = DISABLE; s.token(m) != BEGIN; {
|
||||
m.Cmd(EXPR)
|
||||
list = append(list, s.Position)
|
||||
}
|
||||
f.status = status
|
||||
res := ice.TRUE
|
||||
if len(list) < 3 {
|
||||
res = s.expr(m, list[0])
|
||||
} else {
|
||||
if s.last == nil || s.last.line != s.line {
|
||||
res = s.expr(m, list[0])
|
||||
} else {
|
||||
kit.For(s.last.value, func(k string, v ice.Any) { f.value[k] = v })
|
||||
}
|
||||
res = s.expr(m, list[1])
|
||||
}
|
||||
kit.If(res == ice.FALSE, func() { f.status = DISABLE })
|
||||
s.Position, f.pop = list[len(list)-1], func() {
|
||||
if s.runable(m) {
|
||||
kit.If(len(list) > 3, func() { s.expr(m, list[2]) })
|
||||
s.Position = list[0]
|
||||
s.Position.skip--
|
||||
}
|
||||
}
|
||||
}},
|
||||
FUNC: {Name: "func show(a, b) (c, d)", Hand: func(m *ice.Message, arg ...string) {
|
||||
s := _parse_stack(m)
|
||||
list, key, kind := [][]string{[]string{}}, "", ""
|
||||
push := func() { kit.If(key, func() { list[len(list)-1], key, kind = append(list[len(list)-1], key), "", "" }) }
|
||||
s.reads(m, func(i int, k string) bool {
|
||||
switch k {
|
||||
case OPEN:
|
||||
defer kit.If(i > 0, func() { list = append(list, []string{}) })
|
||||
case FIELD, CLOSE:
|
||||
case BEGIN:
|
||||
return true
|
||||
default:
|
||||
kit.If(key, func() { kind = k }, func() { key = k })
|
||||
return false
|
||||
}
|
||||
push()
|
||||
return false
|
||||
})
|
||||
kit.If(len(list) < 2, func() { list = append(list, []string{}) })
|
||||
kit.If(len(list) < 3, func() { list = append(list, []string{}) })
|
||||
s.value(m, kit.Select("", list[0], -1), &Func{obj: list[0], arg: list[1], res: list[2], Position: s.Position})
|
||||
s.pushf(m, "").status = DISABLE
|
||||
}},
|
||||
CALL: {Name: "call show", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Echo("%v", NewExpr(m, _parse_stack(m)).call(m, arg[0]))
|
||||
}},
|
||||
RETURN: {Name: "return show", Hand: func(m *ice.Message, arg ...string) {
|
||||
s := _parse_stack(m)
|
||||
if len(s.frame) == 1 {
|
||||
close(s.input)
|
||||
s.input = nil
|
||||
}
|
||||
f := s.peekf(m)
|
||||
f.status = DISABLE
|
||||
}},
|
||||
STACK: {Name: "stack path auto parse", Hand: func(m *ice.Message, arg ...string) {
|
||||
if m.Options(nfs.DIR_ROOT, nfs.SRC).Cmdy(nfs.CAT, arg); len(m.Result()) == 0 {
|
||||
return
|
||||
}
|
||||
nfs.Open(m, path.Join(nfs.SRC, path.Join(arg...)), func(r io.Reader) {
|
||||
msg := NewStack().parse(m.Spawn(), r)
|
||||
if m.SetResult(); m.Option(log.DEBUG) != ice.TRUE {
|
||||
m.Copy(msg)
|
||||
return
|
||||
}
|
||||
s := _parse_stack(msg)
|
||||
m.EchoLine("script: %s", arg[0])
|
||||
span := func(s, k, t string) string {
|
||||
return strings.ReplaceAll(s, k, kit.Format("<span class='%s'>%s</span>", t, k))
|
||||
}
|
||||
kit.For(s.list, func(i int, s string) {
|
||||
kit.For([]string{"let", "if", "for", "func"}, func(k string) { s = span(s, k, "keyword") })
|
||||
kit.For([]string{"pwd", "cmd"}, func(k string) { s = span(s, k, "function") })
|
||||
m.EchoLine("%2d: %s", i, s)
|
||||
})
|
||||
m.EchoLine("").EchoLine("output: %s", arg[0]).Copy(msg)
|
||||
})
|
||||
}},
|
||||
EXPR: {Name: "expr a = 1", Hand: func(m *ice.Message, arg ...string) {
|
||||
s := _parse_stack(m)
|
||||
arg = s.rest
|
||||
if v := NewExpr(m, s).cals(m); !s.runable(m) {
|
||||
m.Resultv(v)
|
||||
} else if v != nil {
|
||||
m.Echo(kit.Format(v))
|
||||
} else if s.token(m) == BEGIN {
|
||||
m.Echo(ice.TRUE)
|
||||
}
|
||||
m.Debug("expr value %v %v", m.Result(), arg)
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
||||
const (
|
||||
OPS = "(,){;}*/+-!=<>&|"
|
||||
OPEN = "("
|
||||
FIELD = ","
|
||||
CLOSE = ")"
|
||||
@ -23,401 +332,204 @@ const (
|
||||
)
|
||||
|
||||
var level = map[string]int{
|
||||
"++": 100,
|
||||
"+": 20, "-": 20, "*": 30, "/": 30,
|
||||
"<": 10, ">": 10, "<=": 10, ">=": 10, "==": 10, "!=": 10,
|
||||
"(": 2, ")": 2,
|
||||
"=": 1,
|
||||
"++": 100, "--": 100, "!": 90,
|
||||
"*": 40, "/": 40, "+": 30, "-": 30,
|
||||
"==": 20, "!=": 20, "<=": 20, ">=": 20, "<": 20, ">": 20, "&&": 10, "||": 10,
|
||||
"=": 2, ",": 2, "(": 1, ")": 1,
|
||||
}
|
||||
|
||||
type Expr struct {
|
||||
list ice.List
|
||||
|
||||
s *Stack
|
||||
m *ice.Message
|
||||
}
|
||||
|
||||
func (s *Expr) push(v ice.Any) { s.list = append(s.list, v) }
|
||||
func (s *Expr) pop(n int) { s.list = s.list[:len(s.list)-n] }
|
||||
func (s *Expr) push(v ice.Any) *Expr {
|
||||
s.list = append(s.list, v)
|
||||
return s
|
||||
}
|
||||
func (s *Expr) pop(n int) *Expr {
|
||||
s.list = s.list[:len(s.list)-n]
|
||||
return s
|
||||
}
|
||||
func (s *Expr) get(p int) (v ice.Any) {
|
||||
kit.If(p+len(s.list) >= 0, func() { v = s.list[p+len(s.list)] })
|
||||
kit.If(0 <= p+len(s.list) && p+len(s.list) < len(s.list), func() { v = s.list[p+len(s.list)] })
|
||||
kit.If(0 <= p && p < len(s.list), func() { v = s.list[p] })
|
||||
return
|
||||
}
|
||||
func (s *Expr) gets(p int) string { return kit.Format(s.get(p)) }
|
||||
func (s *Expr) getl(p int) int { return level[kit.Format(s.get(p))] }
|
||||
func (s *Expr) getv(p int) (v ice.Any) {
|
||||
func (s *Expr) getl(p int) int { return level[s.gets(p)] }
|
||||
func (s *Expr) getv(m *ice.Message, p int) (v ice.Any) {
|
||||
if !s.s.runable(m) {
|
||||
return nil
|
||||
}
|
||||
k := s.get(p)
|
||||
if v = s.s.value(kit.Format(k)); v != nil {
|
||||
if v = s.s.value(m, kit.Format(k)); v != nil {
|
||||
return v
|
||||
} else {
|
||||
}
|
||||
return k
|
||||
}
|
||||
func (s *Expr) setv(m *ice.Message, k string, v ice.Any) *Expr {
|
||||
kit.If(s.s.runable(m), func() {
|
||||
switch v := v.(type) {
|
||||
case *Value:
|
||||
s.s.value(m, k, v.list[0])
|
||||
default:
|
||||
s.s.value(m, k, v)
|
||||
}
|
||||
func (s *Expr) setv(k string, v ice.Any) {
|
||||
kit.If(s.s.runable(), func() { s.s.value(k, v) })
|
||||
})
|
||||
return s
|
||||
}
|
||||
func (s *Expr) ops() {
|
||||
switch s.gets(-2) {
|
||||
case "=":
|
||||
s.setv(s.gets(-3), s.getv(-1))
|
||||
s.pop(2)
|
||||
return
|
||||
}
|
||||
bin := func(v ice.Any) {
|
||||
s.pop(3)
|
||||
s.push(v)
|
||||
}
|
||||
switch a, b := kit.Int(s.getv(-3)), kit.Int(s.getv(-1)); s.gets(-2) {
|
||||
case "==":
|
||||
bin(a == b)
|
||||
case "!=":
|
||||
bin(a != b)
|
||||
case "<=":
|
||||
bin(a <= b)
|
||||
case ">=":
|
||||
bin(a >= b)
|
||||
case ">":
|
||||
bin(a > b)
|
||||
case "<":
|
||||
bin(a < b)
|
||||
case "+":
|
||||
bin(a + b)
|
||||
case "-":
|
||||
bin(a - b)
|
||||
func (s *Expr) ops(m *ice.Message) {
|
||||
m.Debug("expr ops %v", s.list)
|
||||
bin := func(v ice.Any) { s.pop(3).push(v) }
|
||||
switch a, b := kit.Int(s.getv(m, -3)), kit.Int(s.getv(m, -1)); s.gets(-2) {
|
||||
case "*":
|
||||
bin(a * b)
|
||||
case "/":
|
||||
bin(a / b)
|
||||
case "+":
|
||||
bin(a + b)
|
||||
case "-":
|
||||
bin(a - b)
|
||||
case ">":
|
||||
bin(a > b)
|
||||
case "<":
|
||||
bin(a < b)
|
||||
case "<=":
|
||||
bin(a <= b)
|
||||
case ">=":
|
||||
bin(a >= b)
|
||||
case "!=":
|
||||
bin(a != b)
|
||||
case "==":
|
||||
bin(a == b)
|
||||
}
|
||||
}
|
||||
func (s *Expr) Cals(arg ...string) (ice.Any, int) {
|
||||
ice.Pulse.Debug("what %d %v", s.s.line, arg)
|
||||
for i := 0; i < len(arg); i++ {
|
||||
k := arg[i]
|
||||
switch k {
|
||||
case OPEN:
|
||||
if s.getl(-1) == 0 {
|
||||
list := kit.List(s.gets(-1))
|
||||
for {
|
||||
v, n := NewExpr(s.s).Cals(arg[i+1:]...)
|
||||
list = append(list, v)
|
||||
if i += 1 + n; arg[i] == CLOSE {
|
||||
i++
|
||||
break
|
||||
} else if arg[i] == FIELD {
|
||||
|
||||
} else {
|
||||
i--
|
||||
}
|
||||
}
|
||||
func (s *Expr) end(m *ice.Message, arg ...string) ice.Any {
|
||||
if s.gets(-1) == CLOSE {
|
||||
s.pop(1)
|
||||
s.push(ice.Pulse.Cmdx(list...))
|
||||
continue
|
||||
}
|
||||
case CLOSE:
|
||||
if len(s.list) > 1 {
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
case BEGIN, SPLIT, FIELD:
|
||||
s.s.rest = arg[i:]
|
||||
return s.End(arg[:i]...), i
|
||||
}
|
||||
if op := s.gets(-1) + k; level[op] > 0 {
|
||||
if op == "++" {
|
||||
s.setv(s.gets(-2), kit.Int(s.s.value(s.gets(-2)))+1)
|
||||
s.pop(1)
|
||||
} else {
|
||||
s.pop(1)
|
||||
s.push(op)
|
||||
}
|
||||
} else {
|
||||
if level[k] > 0 {
|
||||
for level[k] <= s.getl(-2) {
|
||||
s.ops()
|
||||
}
|
||||
} else if len(s.list) > 0 && s.getl(-1) == 0 {
|
||||
return s.End(arg[:i]...), i
|
||||
}
|
||||
s.push(k)
|
||||
}
|
||||
}
|
||||
return s.End(arg...), len(arg)
|
||||
}
|
||||
func (s *Expr) End(arg ...string) ice.Any {
|
||||
ice.Pulse.Debug("what %v", s.list)
|
||||
for len(s.list) > 1 {
|
||||
s.ops()
|
||||
switch s.ops(m); s.gets(-2) {
|
||||
case ",":
|
||||
list := kit.List()
|
||||
for i := len(s.list) - 2; i > 0; i -= 2 {
|
||||
if s.list[i] == "=" {
|
||||
for j := 0; j < i; j += 2 {
|
||||
s.setv(m, s.gets(j), s.getv(m, j+i+1))
|
||||
list = append(list, s.getv(m, j))
|
||||
}
|
||||
s.list = kit.List(&Value{list: list})
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(s.list) == 1 {
|
||||
break
|
||||
}
|
||||
for i := 0; i < len(s.list); i += 2 {
|
||||
list = append(list, s.getv(m, i))
|
||||
}
|
||||
s.list = kit.List(&Value{list: list})
|
||||
case "=":
|
||||
if len(s.list) == 3 {
|
||||
s.setv(m, s.gets(-3), s.getv(m, -1)).pop(2)
|
||||
break
|
||||
}
|
||||
list := kit.List()
|
||||
switch v := s.getv(m, -1).(type) {
|
||||
case *Value:
|
||||
for i := 0; i < len(s.list)-1; i += 2 {
|
||||
if i/2 < len(v.list) {
|
||||
s.setv(m, s.gets(i), v.list[i/2])
|
||||
list = append(list, s.getv(m, i))
|
||||
}
|
||||
}
|
||||
}
|
||||
s.list = kit.List(&Value{list})
|
||||
}
|
||||
}
|
||||
if !s.s.runable(m) {
|
||||
return arg
|
||||
}
|
||||
if s.s.runable() {
|
||||
if len(s.list) > 0 {
|
||||
return s.list[0]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return arg
|
||||
}
|
||||
func NewExpr(s *Stack) *Expr { return &Expr{kit.List(), s} }
|
||||
|
||||
type Func struct {
|
||||
line int
|
||||
arg []string
|
||||
res []string
|
||||
}
|
||||
type Frame struct {
|
||||
key string
|
||||
value ice.Map
|
||||
status int
|
||||
line int
|
||||
pop func()
|
||||
}
|
||||
type Stack struct {
|
||||
key string
|
||||
last *Frame
|
||||
frame []*Frame
|
||||
rest []string
|
||||
list []string
|
||||
line int
|
||||
|
||||
input chan string
|
||||
}
|
||||
|
||||
func (s *Stack) peekf() *Frame {
|
||||
kit.If(len(s.frame) == 0, func() { s.pushf("") })
|
||||
return s.frame[len(s.frame)-1]
|
||||
}
|
||||
func (s *Stack) pushf(key string) *Frame {
|
||||
f := &Frame{key: key, value: kit.Dict(), line: s.line}
|
||||
kit.If(len(s.frame) > 0, func() { f.status = s.peekf().status })
|
||||
s.frame = append(s.frame, f)
|
||||
return f
|
||||
}
|
||||
func (s *Stack) popf() *Frame {
|
||||
f := s.peekf()
|
||||
kit.If(len(s.frame) > 1, func() { s.frame = s.frame[:len(s.frame)-1] })
|
||||
return f
|
||||
}
|
||||
func (s *Stack) stack(cb ice.Any) {
|
||||
for i := len(s.frame) - 1; i >= 0; i-- {
|
||||
switch cb := cb.(type) {
|
||||
case func(*Frame, int):
|
||||
cb(s.frame[i], i)
|
||||
case func(*Frame):
|
||||
cb(s.frame[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var n = 0
|
||||
|
||||
func (s *Stack) value(key string, arg ...ice.Any) ice.Any {
|
||||
|
||||
f := s.peekf()
|
||||
for i := len(s.frame) - 1; i >= 0; i-- {
|
||||
if _f := s.frame[i]; _f.value[key] != nil {
|
||||
f = _f
|
||||
}
|
||||
}
|
||||
n++
|
||||
if n > 1000 {
|
||||
panic(n)
|
||||
}
|
||||
kit.If(len(arg) > 0, func() {
|
||||
f.value[key] = arg[0]
|
||||
ice.Pulse.Debug("set value %v %v %v", f.key, key, arg[0])
|
||||
}, func() {
|
||||
ice.Pulse.Debug("get value %v %v", f.key, key)
|
||||
})
|
||||
return f.value[key]
|
||||
}
|
||||
func (s *Stack) runable() bool { return s.peekf().status > DISABLE }
|
||||
func (s *Stack) read() (text string, ok bool) {
|
||||
for {
|
||||
if text, ok = <-s.input; !ok {
|
||||
return
|
||||
}
|
||||
if s.list = append(s.list, text); text == "" || strings.HasPrefix(text, "#") {
|
||||
continue
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
func (s *Stack) parse(m *ice.Message, p string) *Stack {
|
||||
s.input = make(chan string)
|
||||
m.Options(STACK, s).Go(func() {
|
||||
nfs.Open(m, p, func(r io.Reader) {
|
||||
defer close(s.input)
|
||||
kit.For(r, func(text string) { s.input <- text })
|
||||
})
|
||||
})
|
||||
s.key, s.peekf().key = p, p
|
||||
for {
|
||||
if _, ok := s.read(); !ok {
|
||||
break
|
||||
}
|
||||
for s.line = len(s.list) - 1; s.line < len(s.list); s.line++ {
|
||||
for s.rest = kit.Split(s.list[s.line], "\t ", OPS); len(s.rest) > 0; {
|
||||
if s.rest[0] == END {
|
||||
rest := s.rest[1:]
|
||||
kit.If(s.peekf().pop != nil, func() { s.peekf().pop() })
|
||||
s.last, s.rest = s.popf(), rest
|
||||
continue
|
||||
}
|
||||
ls, rest := _parse_rest("", s.rest...)
|
||||
if len(ls) == 0 {
|
||||
s.rest = rest
|
||||
continue
|
||||
}
|
||||
switch s.rest = []string{}; v := s.value(ls[0]).(type) {
|
||||
case *Func:
|
||||
f, line := s.pushf(ls[0]), s.line
|
||||
f.pop, s.line = func() { s.rest, s.line = rest, line+1 }, v.line
|
||||
continue
|
||||
default:
|
||||
if _, ok := m.Target().Commands[ls[0]]; ok {
|
||||
m.Cmdy(ls)
|
||||
} else if s.runable() {
|
||||
m.Cmdy(CMD, ls)
|
||||
}
|
||||
}
|
||||
s.rest = append(s.rest, rest...)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
func (s *Stack) show() (res []string) {
|
||||
for i, l := range s.list {
|
||||
res = append(res, kit.Format("%2d: ", i)+l)
|
||||
}
|
||||
res = append(res, "")
|
||||
for i, f := range s.frame {
|
||||
res = append(res, kit.Format("frame: %v line: %v %v %v", i, f.line, f.key, f.status))
|
||||
kit.For(f.value, func(k string, v ice.Any) { res = append(res, kit.Format(" %v %v: %v", i, k, v)) })
|
||||
}
|
||||
return
|
||||
}
|
||||
func NewStack() *Stack { return &Stack{} }
|
||||
|
||||
func _parse_stack(m *ice.Message) *Stack { return m.Optionv(STACK).(*Stack) }
|
||||
func _parse_frame(m *ice.Message) (*Stack, *Frame) { return _parse_stack(m), _parse_stack(m).peekf() }
|
||||
func _parse_rest(split string, arg ...string) ([]string, []string) {
|
||||
for i, k := range arg {
|
||||
if split != "" && split == k {
|
||||
return arg[:i], arg[i+1:]
|
||||
}
|
||||
func (s *Expr) cals(m *ice.Message) ice.Any {
|
||||
m.Debug("expr calcs %d %v", s.s.line, s.s.rest[s.s.skip:])
|
||||
arg := s.s.reads(m, func(i int, k string) bool {
|
||||
switch k {
|
||||
case BEGIN:
|
||||
return arg[:i+1], arg[i+1:]
|
||||
case SPLIT, BEGIN:
|
||||
return true
|
||||
case END:
|
||||
return arg[:i], arg[i:]
|
||||
s.s.skip--
|
||||
return true
|
||||
}
|
||||
}
|
||||
return arg, nil
|
||||
}
|
||||
|
||||
const (
|
||||
PWD = "pwd"
|
||||
CMD = "cmd"
|
||||
LET = "let"
|
||||
IF = "if"
|
||||
FOR = "for"
|
||||
FUNC = "func"
|
||||
TYPE = "type"
|
||||
SOURCE = "source"
|
||||
RETURN = "return"
|
||||
)
|
||||
const STACK = "stack"
|
||||
|
||||
func init() {
|
||||
Index.MergeCommands(ice.Commands{
|
||||
CMD: {Name: "cmd", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(arg)
|
||||
}},
|
||||
LET: {Name: "let a = 1", Hand: func(m *ice.Message, arg ...string) {
|
||||
s := _parse_stack(m)
|
||||
kit.If(s.runable(), func() { s.value(arg[0], m.Cmdx(EXPR, arg[2:])) })
|
||||
}},
|
||||
IF: {Name: "if a = 1; a > 1 {", Hand: func(m *ice.Message, arg ...string) {
|
||||
s := _parse_stack(m)
|
||||
f := s.pushf(m.CommandKey())
|
||||
res := m.Cmdx(EXPR, arg)
|
||||
kit.If(s.rest[0] == SPLIT, func() { res = m.Cmdx(EXPR, s.rest[1:]) })
|
||||
kit.If(res == ice.FALSE, func() { f.status = DISABLE })
|
||||
s.rest = s.rest[1:]
|
||||
}},
|
||||
FOR: {Name: "for a = 1; a < 10; a++ {", Hand: func(m *ice.Message, arg ...string) {
|
||||
s := _parse_stack(m)
|
||||
f := s.pushf(m.CommandKey())
|
||||
list, status := [][]string{}, f.status
|
||||
for f.status, s.rest = DISABLE, arg; s.rest[0] != BEGIN; {
|
||||
if list = append(list, m.Cmd(EXPR, s.rest).Resultv()); s.rest[0] == SPLIT {
|
||||
s.rest = s.rest[1:]
|
||||
}
|
||||
}
|
||||
f.status, s.rest = status, s.rest[1:]
|
||||
res := ice.TRUE
|
||||
if len(list) == 1 {
|
||||
res = m.Cmdx(EXPR, list[0])
|
||||
} else if len(list) > 1 {
|
||||
if s.last == nil || s.last.line != s.line {
|
||||
res = m.Cmdx(EXPR, list[0])
|
||||
if level[k] == 0 && len(s.list) > 0 && s.getl(-1) == 0 {
|
||||
s.s.skip--
|
||||
return true
|
||||
} else if k == OPEN && len(s.list) > 0 && s.getl(-1) == 0 {
|
||||
value := s.call(m, s.get(-1))
|
||||
s.pop(1).push(value)
|
||||
} else if op := s.gets(-1) + k; level[op] > 0 && s.getl(-1) > 0 {
|
||||
if op == "++" {
|
||||
s.setv(m, s.gets(-2), kit.Int(s.s.value(m, s.gets(-2)))+1).pop(1)
|
||||
} else {
|
||||
kit.For(s.last.value, func(k string, v ice.Any) { f.value[k] = v })
|
||||
s.pop(1).push(op)
|
||||
}
|
||||
res = m.Cmdx(EXPR, list[1])
|
||||
} else if level[k] > 0 {
|
||||
for level[k] >= 9 && level[k] <= s.getl(-2) {
|
||||
s.ops(m)
|
||||
}
|
||||
kit.If(res == ice.FALSE, func() { f.status = DISABLE })
|
||||
f.pop = func() {
|
||||
if s.runable() {
|
||||
kit.If(len(list) > 2, func() { m.Cmd(EXPR, list[2]) })
|
||||
s.line = f.line - 1
|
||||
if k == CLOSE {
|
||||
if s.gets(-2) == OPEN {
|
||||
v := s.get(-1)
|
||||
s.pop(2).push(v)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}},
|
||||
FUNC: {Name: "func show", Hand: func(m *ice.Message, arg ...string) {
|
||||
s := _parse_stack(m)
|
||||
s.value(arg[0], &Func{line: s.line, arg: arg[1:]})
|
||||
f := s.pushf(m.CommandKey())
|
||||
f.status = DISABLE
|
||||
}},
|
||||
RETURN: {Name: "return show", Hand: func(m *ice.Message, arg ...string) {
|
||||
s := _parse_stack(m)
|
||||
if len(s.frame) == 1 {
|
||||
close(s.input)
|
||||
s.line = len(s.list)
|
||||
}
|
||||
f := s.peekf()
|
||||
f.status = DISABLE
|
||||
}},
|
||||
PWD: {Name: "pwd", Hand: func(m *ice.Message, arg ...string) {
|
||||
s := _parse_stack(m)
|
||||
kit.If(s.runable(), func() {
|
||||
res := []string{kit.Format(s.line)}
|
||||
s.stack(func(f *Frame, i int) { kit.If(i > 0, func() { res = append(res, kit.Format("%v:%v", f.line, f.key)) }) })
|
||||
m.Echo(strings.Join(res, " / ")).Echo(ice.NL)
|
||||
})
|
||||
}},
|
||||
STACK: {Name: "stack path auto parse", Hand: func(m *ice.Message, arg ...string) {
|
||||
if m.Options(nfs.DIR_ROOT, nfs.SRC).Cmdy(nfs.CAT, arg); len(m.Result()) == 0 {
|
||||
return
|
||||
}
|
||||
m.SetResult()
|
||||
m.Echo(ice.NL).Echo("output: %s\n", arg[0])
|
||||
s := NewStack().parse(m, path.Join(nfs.SRC, path.Join(arg...)))
|
||||
m.Echo(ice.NL).Echo("script: %s\n", arg[0])
|
||||
m.Echo(strings.Join(s.show(), ice.NL))
|
||||
}},
|
||||
EXPR: {Name: "expr a = 1", Hand: func(m *ice.Message, arg ...string) {
|
||||
s := _parse_stack(m)
|
||||
v, n := NewExpr(s).Cals(arg...)
|
||||
s.rest = arg[n:]
|
||||
if s.runable() {
|
||||
m.Echo(kit.Format(v))
|
||||
s.push(k)
|
||||
} else {
|
||||
m.Resultv(v)
|
||||
s.push(k)
|
||||
}
|
||||
m.Debug("expr %s %v", m.Result(), s.value(m.Result()))
|
||||
}},
|
||||
return false
|
||||
})
|
||||
return s.end(m, arg...)
|
||||
}
|
||||
func (s *Expr) call(m *ice.Message, name ice.Any) (v ice.Any) {
|
||||
m.Debug("call %v", name)
|
||||
list := kit.List(name)
|
||||
switch v = NewExpr(m, s.s).cals(m); v := v.(type) {
|
||||
case *Value:
|
||||
list = append(list, v.list...)
|
||||
default:
|
||||
list = append(list, v)
|
||||
}
|
||||
m.Debug("call %v", list)
|
||||
switch v := s.s.value(m, kit.Format(name)).(type) {
|
||||
case *Func:
|
||||
f := s.s.pushf(m, "")
|
||||
kit.For(v.res, func(k string) { f.value[k] = "" })
|
||||
kit.For(v.arg, func(k string) { f.value[k] = "" })
|
||||
kit.For(v.arg, func(i int, k string) { kit.If(i+1 < len(list), func() { f.value[k] = list[i+1] }) })
|
||||
value, pos := &Value{list: kit.List()}, s.s.Position
|
||||
f.pop, s.s.Position = func() {
|
||||
kit.For(v.res, func(k string) { value.list = append(value.list, f.value[k]) })
|
||||
s.s.Position = pos
|
||||
}, v.Position
|
||||
m.Debug("call %#v", f)
|
||||
s.s.call(m)
|
||||
m.Debug("call %#v", value)
|
||||
return value
|
||||
default:
|
||||
if s.s.runable(m) {
|
||||
return m.Cmdx(list...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
func NewExpr(m *ice.Message, s *Stack) *Expr { return &Expr{kit.List(), s, m} }
|
||||
|
Loading…
x
Reference in New Issue
Block a user