From 3edc006f07f6e6c5ef4c7310d82daad432c3bac2 Mon Sep 17 00:00:00 2001 From: shylinux Date: Fri, 31 Mar 2023 13:01:27 +0800 Subject: [PATCH] opt yac --- base/log/debug.go | 37 +- base/mdb/mdb.go | 1 + base/yac/stack.go | 838 ++++++++++++++++++++++++++-------------------- logs.go | 2 +- 4 files changed, 494 insertions(+), 384 deletions(-) diff --git a/base/log/debug.go b/base/log/debug.go index 210fa16f..c58aa224 100644 --- a/base/log/debug.go +++ b/base/log/debug.go @@ -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) + 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]) diff --git a/base/mdb/mdb.go b/base/mdb/mdb.go index fde0eb92..7e5284de 100644 --- a/base/mdb/mdb.go +++ b/base/mdb/mdb.go @@ -120,6 +120,7 @@ const ( REVERT = "revert" RANDOM = "random" OFFEND = "offend" + OFFSET = "offset" PAGE = "page" NEXT = "next" diff --git a/base/yac/stack.go b/base/yac/stack.go index a640b669..119307eb 100644 --- a/base/yac/stack.go +++ b/base/yac/stack.go @@ -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 ( - EXPR = "expr" - OPS = "(,){;}!=<>+-*/" + PWD = "pwd" + CMD = "cmd" + LET = "let" + IF = "if" + FOR = "for" + FUNC = "func" + CALL = "call" + RETURN = "return" + EXPR = "expr" +) +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("%s", 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 + 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 } + return k } -func (s *Expr) setv(k string, v ice.Any) { - kit.If(s.s.runable(), func() { s.s.value(k, v) }) +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) + } + }) + 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) + } + for len(s.list) > 1 { + 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 } - s.pop(1) - s.push(ice.Pulse.Cmdx(list...)) - continue } - case CLOSE: - if len(s.list) > 1 { + 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) + for i := 0; i < len(s.list); i += 2 { + list = append(list, s.getv(m, i)) } - } else { - if level[k] > 0 { - for level[k] <= s.getl(-2) { - s.ops() + 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)) + } } - } else if len(s.list) > 0 && s.getl(-1) == 0 { - return s.End(arg[:i]...), i + } + s.list = kit.List(&Value{list}) + } + } + if !s.s.runable(m) { + return arg + } + if len(s.list) > 0 { + return s.list[0] + } + return nil +} + +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 SPLIT, BEGIN: + return true + case END: + s.s.skip-- + return true + } + 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 { + s.pop(1).push(op) + } + } else if level[k] > 0 { + for level[k] >= 9 && level[k] <= s.getl(-2) { + s.ops(m) + } + if k == CLOSE { + if s.gets(-2) == OPEN { + v := s.get(-1) + s.pop(2).push(v) + return false + } + return true } s.push(k) + } else { + s.push(k) } - } - return s.End(arg...), len(arg) + return false + }) + return s.end(m, arg...) } -func (s *Expr) End(arg ...string) ice.Any { - ice.Pulse.Debug("what %v", s.list) - for len(s.list) > 1 { - s.ops() +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) } - if s.s.runable() { - if len(s.list) > 0 { - return s.list[0] + 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 } - 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:] - } - switch k { - case BEGIN: - return arg[:i+1], arg[i+1:] - case END: - return arg[:i], arg[i:] - } - } - 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]) - } else { - kit.For(s.last.value, func(k string, v ice.Any) { f.value[k] = v }) - } - res = m.Cmdx(EXPR, list[1]) - } - 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 - } - } - }}, - 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)) - } else { - m.Resultv(v) - } - m.Debug("expr %s %v", m.Result(), s.value(m.Result())) - }}, - }) } +func NewExpr(m *ice.Message, s *Stack) *Expr { return &Expr{kit.List(), s, m} } diff --git a/logs.go b/logs.go index b4dc8194..34f06173 100644 --- a/logs.go +++ b/logs.go @@ -25,7 +25,7 @@ func (m *Message) join(arg ...Any) (string, []Any) { i-- continue case []string: - list = append(list, kit.JoinKV(DF, SP, v...)) + list = append(list, kit.JoinKV(DF+SP, SP, v...)) i-- continue }