diff --git a/base/gdb/gdb.go b/base/gdb/gdb.go index 9bc21fd2..da7d7ddd 100644 --- a/base/gdb/gdb.go +++ b/base/gdb/gdb.go @@ -28,6 +28,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) { for { select { case <-time.Tick(t): + m.Option(ice.LOG_DISABLE, ice.TRUE) m.Cmd(TIMER, HAPPEN) case s, ok := <-f.s: if !ok { diff --git a/base/gdb/timer.go b/base/gdb/timer.go index 0cd9a72f..bb18f3a9 100644 --- a/base/gdb/timer.go +++ b/base/gdb/timer.go @@ -13,6 +13,7 @@ func _timer_action(m *ice.Message, now time.Time, arg ...string) { if value[mdb.COUNT] == "0" || value[mdb.TIME] > now.Format(ice.MOD_TIME) { return } + m.Option(ice.LOG_DISABLE, ice.FALSE) m.Cmd(ROUTINE, mdb.CREATE, mdb.NAME, value[mdb.NAME], kit.Keycb(ROUTINE), value[ice.CMD]) mdb.HashModify(m, mdb.HASH, value[mdb.HASH], mdb.COUNT, kit.Int(value[mdb.COUNT])-1, mdb.TIME, m.Time(value[INTERVAL])) }) diff --git a/base/lex/split.go b/base/lex/split.go index 303a2599..f01a14ab 100644 --- a/base/lex/split.go +++ b/base/lex/split.go @@ -25,17 +25,15 @@ func _split_tab(text string) (tab int) { func _split_deep(stack []int, text string) ([]int, int) { tab := _split_tab(text) for i := len(stack) - 1; i >= 0; i-- { - if tab <= stack[i] { - stack = stack[:len(stack)-1] - } + kit.If(tab <= stack[i], func() { stack = stack[:len(stack)-1] }) } stack = append(stack, tab) return stack, len(stack) } func _split_list(m *ice.Message, file string, arg ...string) ice.Map { - const DEEP = "_deep" - stack, deep := []int{}, 0 - list, line := kit.List(kit.Data(DEEP, -1)), "" + const INDENT = "_indent" + stack, indent := []int{}, 0 + list, line := kit.List(kit.Data(INDENT, -1)), "" m.Cmd(nfs.CAT, file, func(text string) { if strings.TrimSpace(text) == "" { return @@ -46,19 +44,19 @@ func _split_list(m *ice.Message, file string, arg ...string) ice.Map { if strings.HasPrefix(strings.TrimSpace(text), "# ") { return } - stack, deep = _split_deep(stack, text) - data := kit.Data(DEEP, deep) + stack, indent = _split_deep(stack, text) + data := kit.Data(INDENT, indent) ls := kit.Split(text, m.Option(SPLIT_SPACE), m.Option(SPLIT_BLOCK), m.Option(SPLIT_QUOTE), m.Option(SPLIT_TRANS)) switch cb := m.OptionCB(SPLIT).(type) { case func(int, []string): - cb(deep, ls) + cb(indent, ls) case func(int, []string) []string: - ls = cb(deep, ls) + ls = cb(indent, ls) case func(int, []string, ice.Map, ice.Map): root, _ := kit.Value(list[0], "list.0").(ice.Map) - cb(deep, ls, data, root) + cb(indent, ls, data, root) case func(int, []string, ice.Map) []string: - ls = cb(deep, ls, data) + ls = cb(indent, ls, data) case func([]string, ice.Map) []string: ls = cb(ls, data) case func([]string) []string: @@ -69,16 +67,13 @@ func _split_list(m *ice.Message, file string, arg ...string) ice.Map { default: m.ErrorNotImplement(cb) } - for _, k := range arg { - if kit.Value(data, kit.Keym(k), kit.Select("", ls, 0)); len(ls) > 0 { - ls = ls[1:] - } - } - for i := 0; i < len(ls)-1; i += 2 { - kit.Value(data, kit.Keym(ls[i]), ls[i+1]) - } + kit.For(arg, func(k string) { + kit.Value(data, kit.Keym(k), kit.Select("", ls, 0)) + kit.If(len(ls) > 0, func() { ls = ls[1:] }) + }) + kit.For(ls, func(k, v string) { kit.Value(data, kit.Keym(k), v) }) for i := len(list) - 1; i >= 0; i-- { - if deep > kit.Int(kit.Value(list[i], kit.Keym(DEEP))) { + if indent > kit.Int(kit.Value(list[i], kit.Keym(INDENT))) { kit.Value(list[i], kit.Keys(mdb.LIST, "-2"), data) list = append(list, data) break @@ -109,6 +104,3 @@ func init() { }}, }) } -func Split(m *ice.Message, arg ...string) ice.Map { - return kit.Value(_split_list(m, arg[0], arg[1:]...), kit.Keys(mdb.LIST, "0")).(ice.Map) -} diff --git a/base/web/serve.go b/base/web/serve.go index f23fb748..1abdd777 100644 --- a/base/web/serve.go +++ b/base/web/serve.go @@ -78,7 +78,6 @@ func _serve_handle(key string, cmd *ice.Command, m *ice.Message, w http.Response default: r.ParseMultipartForm(kit.Int64(kit.Select("4096", r.Header.Get(ContentLength)))) kit.For(r.PostForm, func(k string, v []string) { _log(FORM, k, kit.Join(v, ice.SP)).Optionv(k, v) }) - kit.For(r.PostForm, func(k string, v []string) { _log(FORM, k, kit.Join(v, ice.SP)).Optionv(k, v) }) } kit.For(r.Cookies(), func(k, v string) { m.Optionv(k, v) }) m.OptionDefault(ice.MSG_HEIGHT, "480", ice.MSG_WIDTH, "320") diff --git a/base/yac/stack.go b/base/yac/stack.go new file mode 100644 index 00000000..ea0e9a2f --- /dev/null +++ b/base/yac/stack.go @@ -0,0 +1,247 @@ +package yac + +import ( + "io" + "path" + "strings" + + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/nfs" + kit "shylinux.com/x/toolkits" +) + +type Func struct { + line int +} +type Frame struct { + key string + value ice.Map + status int + line int + pop func() +} +type Stack struct { + frame []*Frame + last *Frame + rest []string + list []string + line int +} + +func (s *Stack) peekf(m *ice.Message) *Frame { return s.frame[len(s.frame)-1] } +func (s *Stack) pushf(m *ice.Message, key string) *Frame { + f := &Frame{key: key, value: kit.Dict(), status: s.peekf(m).status, line: s.line} + s.frame = append(s.frame, f) + return f +} +func (s *Stack) popf(m *ice.Message) *Frame { + f := s.frame[len(s.frame)-1] + kit.If(len(s.frame) > 1, func() { s.frame = s.frame[:len(s.frame)-1] }) + return f +} +func (s *Stack) value(m *ice.Message, key string, arg ...ice.Any) ice.Any { + for i := len(s.frame) - 1; i >= 0; i-- { + if f := s.frame[i]; f.value[key] != nil { + kit.If(len(arg) > 0, func() { f.value[key] = arg[0] }) + return f.value[key] + } + } + f := s.frame[len(s.frame)-1] + kit.If(len(arg) > 0, func() { f.value[key] = arg[0] }) + return f.value[key] +} +func (s *Stack) parse(m *ice.Message, p string) *Stack { + nfs.Open(m, p, func(r io.Reader) { + s.peekf(m).key = p + kit.For(r, func(text string) { + s.list = append(s.list, text) + for s.line = len(s.list) - 1; s.line < len(s.list); s.line++ { + if text = s.list[s.line]; text == "" || strings.HasPrefix(text, "#") { + continue + } + for s.rest = kit.Split(text, "\t ", "<=>+-*/;"); len(s.rest) > 0; { + ls := s.rest + switch s.rest = []string{}; v := s.value(m, ls[0]).(type) { + case *Func: + f, line := s.pushf(m, ls[0]), s.line + f.pop, s.line = func() { s.rest, s.line, _ = nil, line+1, s.popf(m) }, v.line + default: + if _, ok := m.Target().Commands[ls[0]]; ok { + m.Options(STACK, s).Cmdy(ls) + } else { + m.Options(STACK, s).Cmdy(CMD, ls) + } + } + } + } + }) + }) + return s +} +func (s *Stack) show(m *ice.Message) (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("frame: %v %v: %v", i, k, v)) }) + } + return +} +func _parse_split(m *ice.Message, split string, arg ...string) ([]string, []string) { + if i := kit.IndexOf(arg, split); i == -1 { + return arg, nil + } else { + return arg[:i], arg[i+1:] + } +} +func NewStack(m *ice.Message) *Stack { return &Stack{frame: []*Frame{&Frame{value: kit.Dict()}}} } + +const ( + PARSE = "parse" + CMD = "cmd" + LET = "let" + IF = "if" + FOR = "for" + FUNC = "func" + TYPE = "type" + RETURN = "return" + EXPR = "expr" +) +const STACK = "stack" + +func init() { + Index.MergeCommands(ice.Commands{ + STACK: {Name: "stack path auto parse", Actions: ice.Actions{ + PARSE: {Hand: func(m *ice.Message, arg ...string) {}}, + }, Hand: func(m *ice.Message, arg ...string) { + m.Options(nfs.DIR_ROOT, nfs.SRC).Cmdy(nfs.CAT, arg) + if len(m.Result()) == 0 { + return + } + m.Echo(ice.NL).Echo("output:" + ice.NL) + s := NewStack(m).parse(m, path.Join(nfs.SRC, path.Join(arg...))) + m.Echo(ice.NL).Echo("script:" + ice.NL) + m.Echo(strings.Join(s.show(m), ice.NL)) + }}, + CMD: {Name: "cmd", Hand: func(m *ice.Message, arg ...string) { + s := m.Optionv(STACK).(*Stack) + arg, s.rest = _parse_split(m, "}", arg...) + if f := s.peekf(m); f.status >= 0 { + m.Cmdy(arg) + m.Echo(ice.NL) + } + }}, + LET: {Name: "let a = 1", Hand: func(m *ice.Message, arg ...string) { + s := m.Optionv(STACK).(*Stack) + f := s.peekf(m) + kit.If(f.status > -1, func() { s.value(m, arg[0], m.Cmdx(EXPR, arg[2:])) }) + }}, + IF: {Name: "if a > 1", Hand: func(m *ice.Message, arg ...string) { + s := m.Optionv(STACK).(*Stack) + f := s.pushf(m, m.CommandKey()) + arg, s.rest = _parse_split(m, "{", arg...) + kit.If(f.status < 0 || m.Cmdx(EXPR, arg) == ice.FALSE, func() { f.status = -1 }) + }}, + FOR: {Name: "for a > 1", Hand: func(m *ice.Message, arg ...string) { + s := m.Optionv(STACK).(*Stack) + arg, s.rest = _parse_split(m, "{", arg...) + f := s.pushf(m, m.CommandKey()) + kit.If(f.status < 0 || m.Cmdx(EXPR, arg) == ice.FALSE, func() { f.status = -1 }) + line := s.line + f.pop = func() { + kit.If(f.status > -1, func() { s.line = line - 1 }) + s.popf(m) + } + }}, + FUNC: {Name: "func show", Hand: func(m *ice.Message, arg ...string) { + s := m.Optionv(STACK).(*Stack) + arg, s.rest = _parse_split(m, "{", arg...) + fun := &Func{line: s.line} + s.value(m, arg[0], fun) + f := s.pushf(m, m.CommandKey()) + f.status = -1 + }}, + RETURN: {Name: "return show", Hand: func(m *ice.Message, arg ...string) { + s := m.Optionv(STACK).(*Stack) + f := s.peekf(m) + f.status = -2 + }}, + "}": {Name: "}", Hand: func(m *ice.Message, arg ...string) { + s := m.Optionv(STACK).(*Stack) + if f := s.peekf(m); f.pop == nil { + s.last = s.peekf(m) + s.popf(m) + } else { + f.pop() + } + }}, + EXPR: {Name: "expr a = 1", Hand: func(m *ice.Message, arg ...string) { + s := m.Optionv(STACK).(*Stack) + level := map[string]int{ + "*": 30, "/": 30, + "+": 20, "-": 20, + "<": 10, ">": 10, "<=": 10, ">=": 10, "==": 10, "!=": 10, + } + list := kit.List() + get := func(p int) ice.Any { + if p+len(list) >= 0 { + return list[p+len(list)] + } + return "" + } + gets := func(p int) string { + k := kit.Format(get(p)) + if v := s.value(m, k); v != nil { + return kit.Format(v) + } + return k + } + getl := func(p int) int { return level[kit.Format(get(p))] } + push := func(v ice.Any) { list = append(list, v) } + pop := func(n int) { list = list[:len(list)-n] } + ops := func() { + bin := func(v ice.Any) { + pop(3) + push(kit.Format(v)) + } + switch a, b := kit.Int(gets(-3)), kit.Int(gets(-1)); 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) + } + } + kit.For(arg, func(k string) { + if level[k] > 0 { + for level[k] <= getl(-2) { + ops() + } + } + push(k) + }) + for len(list) > 1 { + ops() + } + m.Echo(kit.Format(list[0])) + m.Debug("expr %s", m.Result()) + }}, + }) +} diff --git a/base/yac/yac.go b/base/yac/yac.go index 52b1bd5a..7d0ecd4e 100644 --- a/base/yac/yac.go +++ b/base/yac/yac.go @@ -6,4 +6,4 @@ const YAC = "yac" var Index = &ice.Context{Name: YAC, Help: "语法模块"} -func init() { ice.Index.Register(Index, nil) } +func init() { ice.Index.Register(Index, nil, STACK) } diff --git a/core/code/shy.go b/core/code/shy.go index dd045756..72dd5225 100644 --- a/core/code/shy.go +++ b/core/code/shy.go @@ -9,6 +9,7 @@ import ( "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/web" + "shylinux.com/x/icebergs/base/yac" kit "shylinux.com/x/toolkits" ) @@ -21,7 +22,7 @@ func init() { ctx.ProcessCommand(m, web.WIKI_WORD, kit.Simple(path.Join(arg[2], arg[1]))) }}, mdb.ENGINE: {Hand: func(m *ice.Message, arg ...string) { - ctx.ProcessCommand(m, web.WIKI_WORD, kit.Simple(path.Join(arg[2], arg[1]))) + ctx.ProcessCommand(m, yac.STACK, kit.Simple(arg[1])) }}, TEMPLATE: {Hand: func(m *ice.Message, arg ...string) { m.Echo(nfs.Template(m, "demo.shy"), path.Base(path.Dir(path.Join(arg[2], arg[1])))) diff --git a/misc/lex/lex.go b/misc/lex/lex.go new file mode 100644 index 00000000..9a56d49e --- /dev/null +++ b/misc/lex/lex.go @@ -0,0 +1,9 @@ +package lex + +import ice "shylinux.com/x/icebergs" + +const LEX = "lex" + +var Index = &ice.Context{Name: LEX, Help: "词法模块"} + +func init() { ice.Index.Register(Index, nil, SPLIT) } diff --git a/base/lex/matrix.go b/misc/lex/matrix.go similarity index 84% rename from base/lex/matrix.go rename to misc/lex/matrix.go index 7722fdd7..15f4c091 100644 --- a/base/lex/matrix.go +++ b/misc/lex/matrix.go @@ -437,75 +437,7 @@ func init() { }) m.ProcessInner() }}, - "location": {Hand: func(m *ice.Message, arg ...string) { - m.ProcessLocation("https://baidu.com") - }}, - "replace": {Hand: func(m *ice.Message, arg ...string) { - m.ProcessReplace("https://baidu.com") - }}, - "history": {Hand: func(m *ice.Message, arg ...string) { - m.ProcessHistory() - }}, - "confirms": {Hand: func(m *ice.Message, arg ...string) { - m.Option("hi", "hello") - m.ProcessConfirm("hello world") - }}, - "refresh": {Hand: func(m *ice.Message, arg ...string) { - m.ProcessRefresh("3s") - }}, - "rewrite": {Hand: func(m *ice.Message, arg ...string) { - m.ProcessRewrite("hash", "1", "npage", "2") - }}, - "display": {Hand: func(m *ice.Message, arg ...string) { - m.Push("value", 1) - m.Push("value", 2) - m.ProcessDisplay("/plugin/story/pie.js") - }}, - // "field": {Hand: func(m *ice.Message, arg ...string) { - // m.ProcessCommand("cli.system", []string{"pwd"}, arg...) - // }}, - "inner": {Hand: func(m *ice.Message, arg ...string) { - m.Push("value", 1) - m.Push("value", 2) - m.Push("good", 2) - m.Push("good", 2) - m.ProcessInner() - }}, - "hold": {Hand: func(m *ice.Message, arg ...string) { - m.ProcessHold() - }}, - "back": {Hand: func(m *ice.Message, arg ...string) { - m.ProcessBack() - }}, - "rich": {Hand: func(m *ice.Message, arg ...string) { - m.Push("hi", "hello") - m.Push("he", "world") - m.Push("value", "good") - m.ProcessRich("hello world\n") - }}, - "grow": {Hand: func(m *ice.Message, arg ...string) { - m.ProcessGrow("hello world\n") - }}, - "open": {Hand: func(m *ice.Message, arg ...string) { - m.ProcessOpen("https://baidu.com") - }}, }, Hand: func(m *ice.Message, arg ...string) { - m.Action( - "location", "replace", "history", - "confirms", "refresh", "rewrite", "display", "field", "inner", - "hold", "back", "rich", "grow", "open", - "openLocation", "getLocation", "getClipboardData", - ) - m.Push("hi", "hello") - m.Push("he", "world") - m.Push("value", "good") - m.Echo("hello world") - m.StatusTimeCount() - m.EchoButton("clear") - m.PushButton("close") - m.EchoButton("upload") - m.EchoButton("actions") - return if m.Action(mdb.CREATE); len(arg) == 0 { // 矩阵列表 m.Fields(len(arg), "time,hash,npage,nhash") m.Cmdy(mdb.SELECT, m.PrefixKey(), "", mdb.HASH) diff --git a/misc/lex/regexp.go b/misc/lex/regexp.go new file mode 100644 index 00000000..8aa7dc63 --- /dev/null +++ b/misc/lex/regexp.go @@ -0,0 +1,11 @@ +package lex + +const ( + PATTERN = "pattern" + REGEXP = "regexp" + PREFIX = "prefix" + SUFFIX = "suffix" + + SPACE = "space" + OPERATOR = "operator" +) diff --git a/misc/lex/split.go b/misc/lex/split.go new file mode 100644 index 00000000..f01a14ab --- /dev/null +++ b/misc/lex/split.go @@ -0,0 +1,106 @@ +package lex + +import ( + "strings" + + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/mdb" + "shylinux.com/x/icebergs/base/nfs" + kit "shylinux.com/x/toolkits" +) + +func _split_tab(text string) (tab int) { + for _, c := range text { + switch c { + case '\t': + tab += 4 + case ' ': + tab++ + default: + break + } + } + return +} +func _split_deep(stack []int, text string) ([]int, int) { + tab := _split_tab(text) + for i := len(stack) - 1; i >= 0; i-- { + kit.If(tab <= stack[i], func() { stack = stack[:len(stack)-1] }) + } + stack = append(stack, tab) + return stack, len(stack) +} +func _split_list(m *ice.Message, file string, arg ...string) ice.Map { + const INDENT = "_indent" + stack, indent := []int{}, 0 + list, line := kit.List(kit.Data(INDENT, -1)), "" + m.Cmd(nfs.CAT, file, func(text string) { + if strings.TrimSpace(text) == "" { + return + } + if line += text; strings.Count(text, "`")%2 == 1 { + return + } + if strings.HasPrefix(strings.TrimSpace(text), "# ") { + return + } + stack, indent = _split_deep(stack, text) + data := kit.Data(INDENT, indent) + ls := kit.Split(text, m.Option(SPLIT_SPACE), m.Option(SPLIT_BLOCK), m.Option(SPLIT_QUOTE), m.Option(SPLIT_TRANS)) + switch cb := m.OptionCB(SPLIT).(type) { + case func(int, []string): + cb(indent, ls) + case func(int, []string) []string: + ls = cb(indent, ls) + case func(int, []string, ice.Map, ice.Map): + root, _ := kit.Value(list[0], "list.0").(ice.Map) + cb(indent, ls, data, root) + case func(int, []string, ice.Map) []string: + ls = cb(indent, ls, data) + case func([]string, ice.Map) []string: + ls = cb(ls, data) + case func([]string) []string: + ls = cb(ls) + case func([]string): + cb(ls) + case nil: + default: + m.ErrorNotImplement(cb) + } + kit.For(arg, func(k string) { + kit.Value(data, kit.Keym(k), kit.Select("", ls, 0)) + kit.If(len(ls) > 0, func() { ls = ls[1:] }) + }) + kit.For(ls, func(k, v string) { kit.Value(data, kit.Keym(k), v) }) + for i := len(list) - 1; i >= 0; i-- { + if indent > kit.Int(kit.Value(list[i], kit.Keym(INDENT))) { + kit.Value(list[i], kit.Keys(mdb.LIST, "-2"), data) + list = append(list, data) + break + } + list = list[:len(list)-1] + } + line = "" + }) + return list[0].(ice.Map) +} + +const ( + SPLIT_SPACE = "split.space" + SPLIT_BLOCK = "split.block" + SPLIT_QUOTE = "split.quote" + SPLIT_TRANS = "split.trans" +) +const SPLIT = "split" + +func init() { + Index.MergeCommands(ice.Commands{ + SPLIT: {Name: "split path key auto", Help: "分词", Hand: func(m *ice.Message, arg ...string) { + if len(arg) == 0 || strings.HasSuffix(arg[0], ice.PS) { + m.Cmdy(nfs.DIR, arg) + return + } + m.Echo(kit.Format(_split_list(m, arg[0], kit.Split(kit.Join(arg[1:]))...))) + }}, + }) +} diff --git a/base/yac/matrix.go b/misc/yac/matrix.go similarity index 100% rename from base/yac/matrix.go rename to misc/yac/matrix.go diff --git a/base/yac/script.go b/misc/yac/script.go similarity index 100% rename from base/yac/script.go rename to misc/yac/script.go diff --git a/misc/yac/yac.go b/misc/yac/yac.go new file mode 100644 index 00000000..52b1bd5a --- /dev/null +++ b/misc/yac/yac.go @@ -0,0 +1,9 @@ +package yac + +import ice "shylinux.com/x/icebergs" + +const YAC = "yac" + +var Index = &ice.Context{Name: YAC, Help: "语法模块"} + +func init() { ice.Index.Register(Index, nil) }