From c8ca9c7c6369f41a10aadcc0a01894139fd6c288 Mon Sep 17 00:00:00 2001 From: shylinux Date: Thu, 6 Apr 2023 15:35:09 +0800 Subject: [PATCH] add yac.type --- base/cli/runtime.go | 8 +- base/ctx/command.go | 12 +- base/ctx/ctx.go | 13 +- base/nfs/cat.go | 8 +- base/yac/expr.go | 318 +++++++++++++++++++-------- base/yac/import.go | 61 ++++++ base/yac/stack.go | 520 +++++++++++++++++++++++++++++++------------- base/yac/stmt.go | 109 ++++++---- base/yac/type.go | 99 +++++++++ base/yac/value.go | 175 +++++++++++---- conf.go | 4 +- core/chat/favor.go | 2 +- core/code/code.go | 3 + core/code/shy.go | 8 +- core/wiki/refer.go | 6 +- logs.go | 8 +- type.go | 5 +- type.shy | 76 +++++++ 18 files changed, 1079 insertions(+), 356 deletions(-) create mode 100644 base/yac/import.go create mode 100644 base/yac/type.go create mode 100644 type.shy diff --git a/base/cli/runtime.go b/base/cli/runtime.go index c6cecc4b..d65a7320 100644 --- a/base/cli/runtime.go +++ b/base/cli/runtime.go @@ -130,7 +130,7 @@ const RUNTIME = "runtime" func init() { Index.MergeCommands(ice.Commands{ - RUNTIME: {Name: "runtime info=bootinfo,ifconfig,diskinfo,hostinfo,userinfo,procinfo,bootinfo,api,cli,cmd,env,path,chain auto", Help: "运行环境", Actions: ice.MergeActions(ice.Actions{ + RUNTIME: {Name: "runtime info=bootinfo,ifconfig,diskinfo,hostinfo,userinfo,procinfo,bootinfo,api,cli,cmd,mod,env,path,chain auto", Help: "运行环境", Actions: ice.MergeActions(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { _runtime_init(m) }}, IFCONFIG: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy("tcp.host") }}, DISKINFO: {Hand: func(m *ice.Message, arg ...string) { _runtime_diskinfo(m) }}, @@ -164,6 +164,12 @@ func init() { m.OptionFields(ctx.INDEX, mdb.NAME, mdb.HELP, nfs.FILE) m.Cmdy(ctx.COMMAND, mdb.SEARCH, ctx.COMMAND).StatusTimeCount() }}, + "mod": {Hand: func(m *ice.Message, arg ...string) { + kit.For(ice.Info.Gomod, func(k string, v ice.Any) { + m.Push("mod", k) + m.Push("url", v) + }) + }}, ENV: {Hand: func(m *ice.Message, arg ...string) { kit.For(os.Environ(), func(v string) { ls := strings.SplitN(v, ice.EQ, 2) diff --git a/base/ctx/command.go b/base/ctx/command.go index 971feb38..c1d4674c 100644 --- a/base/ctx/command.go +++ b/base/ctx/command.go @@ -8,7 +8,6 @@ import ( "shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" - "shylinux.com/x/icebergs/base/yac" kit "shylinux.com/x/toolkits" ) @@ -32,9 +31,6 @@ func _command_list(m *ice.Message, name string) *ice.Message { m.Push(mdb.META, kit.Format(cmd.Meta)) m.Push(mdb.LIST, kit.Format(cmd.List)) }) - if m.Length() == 0 && yac.ExistsFile(m, name) { - m.Cmdy(yac.STACK, ice.CMD, name) - } return m } func _command_search(m *ice.Message, kind, name, text string) { @@ -95,13 +91,7 @@ func PodCmd(m *ice.Message, arg ...ice.Any) bool { return false } func Run(m *ice.Message, arg ...string) { - kit.If(!PodCmd(m, arg) && aaa.Right(m, arg), func() { - if yac.ExistsFile(m, arg[0]) { - m.Cmdy(yac.STACK, ice.RUN, arg) - } else { - m.Cmdy(arg) - } - }) + kit.If(!PodCmd(m, arg) && aaa.Right(m, arg), func() { m.Cmdy(arg) }) } func CmdHandler(args ...ice.Any) ice.Handler { return func(m *ice.Message, arg ...string) { m.Cmdy(args...) } diff --git a/base/ctx/ctx.go b/base/ctx/ctx.go index 74c8d082..82bbf9cc 100644 --- a/base/ctx/ctx.go +++ b/base/ctx/ctx.go @@ -1,9 +1,18 @@ package ctx -import ice "shylinux.com/x/icebergs" +import ( + ice "shylinux.com/x/icebergs" + kit "shylinux.com/x/toolkits" +) const CTX = "ctx" var Index = &ice.Context{Name: CTX, Help: "标准模块"} -func init() { ice.Index.Register(Index, nil, CONTEXT, COMMAND, CONFIG) } +func init() { + ice.Index.Register(Index, nil, CONTEXT, COMMAND, CONFIG) + ice.Info.Stack[Prefix()] = func(m *ice.Message, key string, arg ...ice.Any) ice.Any { + return nil + } +} +func Prefix(arg ...string) string { return kit.Keys(CTX, arg) } diff --git a/base/nfs/cat.go b/base/nfs/cat.go index 48e9c2c7..71bb0939 100644 --- a/base/nfs/cat.go +++ b/base/nfs/cat.go @@ -145,13 +145,19 @@ func OptionLoad(m *ice.Message, p string) *ice.Message { return m } func Open(m *ice.Message, p string, cb ice.Any) { - if strings.HasSuffix(p, PS) { + if p == "" { + return + } else if strings.HasSuffix(p, PS) { if ls, e := ReadDir(m, p); !m.Warn(e) { switch cb := cb.(type) { case func([]os.FileInfo): cb(ls) case func(os.FileInfo): kit.For(ls, cb) + case func(io.Reader, string): + kit.For(ls, func(s os.FileInfo) { + kit.If(!s.IsDir(), func() { Open(m, path.Join(p, s.Name()), cb) }) + }) default: m.ErrorNotImplement(cb) } diff --git a/base/yac/expr.go b/base/yac/expr.go index 3f06298e..5348523f 100644 --- a/base/yac/expr.go +++ b/base/yac/expr.go @@ -26,19 +26,23 @@ const ( END = "}" ) -var keyword = regexp.MustCompile("[_a-zA-Z][_a-zA-Z0-9]*") +var keyword = regexp.MustCompile(`[_a-zA-Z][_a-zA-Z0-9\.]*`) var level = map[string]int{ "//": 200, "/*": 200, "*/": 200, - "!": 100, "++": 100, "--": 100, "[": 100, "]": 100, + "&": 100, // "*": 100, "!": 100, + "[": 100, "]": 100, "++": 100, "--": 100, "*": 40, "/": 40, "+": 30, "-": 30, "<": 20, ">": 20, ">=": 20, "<=": 20, "!=": 20, "==": 20, "&&": 10, "||": 10, - DEFINE: 2, ASSIGN: 2, FIELD: 2, OPEN: 1, CLOSE: 1, + DEFS: 2, DEFINE: 2, ASSIGN: 2, FIELD: 2, OPEN: 1, CLOSE: 1, } type Expr struct { list ice.List - s *Stack + p string + t Any + n int + *Stack } func (s *Expr) push(v Any) *Expr { @@ -46,7 +50,11 @@ func (s *Expr) push(v Any) *Expr { return s } func (s *Expr) pop(n int) *Expr { - s.list = s.list[:len(s.list)-n] + if n <= len(s.list) { + s.list = s.list[:len(s.list)-n] + } else { + s.list = s.list[:0] + } return s } func (s *Expr) pops(n int, v Any) *Expr { return s.pop(n).push(v) } @@ -60,30 +68,30 @@ func (s *Expr) getl(p int) int { return level[s.gets(p)] } func (s *Expr) getv(m *ice.Message, p int) (v Any) { switch v := s.get(p); v := v.(type) { case string: - return s.s.value(m, v) + return s.value(m, v) default: return v } } func (s *Expr) setv(m *ice.Message, p int, op string, v Any) Any { - if !s.s.runable() { + if !s.runable() { return nil } switch k := s.gets(p); v := v.(type) { case string: - return s.s.value(m, k, s.s.value(m, v), op) + return s.value(m, k, s.value(m, v), op) case Value: if len(v.list) > 0 { - return s.s.value(m, k, v.list[0], op) + return s.value(m, k, v.list[0], op) } else { - return s.s.value(m, k) + return s.value(m, k, nil, op) } default: - return s.s.value(m, k, v, op) + return s.value(m, k, v, op) } } func (s *Expr) opv(m *ice.Message, p int, op string, v Any) Any { - if !s.s.runable() { + if !s.runable() { return s.getv(m, p) } if obj, ok := s.getv(m, p).(Operater); ok { @@ -92,18 +100,17 @@ func (s *Expr) opv(m *ice.Message, p int, op string, v Any) Any { return s.getv(m, p) } func (s *Expr) ops(m *ice.Message) { - if !s.s.runable() || s.getl(-2) < 10 { + if !s.runable() || s.getl(-2) < 10 { return } s.pops(3, s.opv(m, -3, s.gets(-2), s.getv(m, -1))) } func (s *Expr) end(m *ice.Message) Any { - if !s.s.runable() || len(s.list) == 0 { + if !s.runable() || len(s.list) == 0 { return nil } else if len(s.list) == 1 { return s.getv(m, 0) } - m.Debug("expr ops %v", s.list) for i := 0; i < 100 && len(s.list) > 1; i++ { switch s.ops(m); s.gets(-2) { case DEFINE, ASSIGN: @@ -136,75 +143,203 @@ func (s *Expr) end(m *ice.Message) Any { } } } - m.Debug("expr ops %v", s.list) return s.getv(m, 0) } -func (s *Expr) cals(m *ice.Message) Any { - line := s.s.line - if s.s.skip == -1 { - m.Debug("expr calcs %v %s:%d", s.s.rest, s.s.name, s.s.line) - } else { - m.Debug("expr calcs %v %s:%d", s.s.rest[s.s.skip:], s.s.name, s.s.line) +func (s *Expr) isop(k Any) bool { + switch k := k.(type) { + case int: + return level[s.gets(k)] > 0 + case string: + return level[k] > 0 } - s.s.reads(m, func(k string) bool { - if op := s.gets(-1) + k; level[op] > 0 && s.getl(-1) > 0 { - s.pop(1) - k = op + return false +} + +func (s *Expr) sub(m *ice.Message) *Expr { + sub := NewExpr(s.Stack) + sub.n = s.n + 1 + return sub +} +func (s *Expr) ktv(m *ice.Message, ismap bool, t Any, p string) map[string]Any { + data := kit.Dict() + for s.token() != END { + k := "" + kit.If(ismap, func() { + sub := s.sub(m) + if k = kit.Format(trans(sub.cals(m, DEFS, END))); k == "" { + k = _parse_const(m, sub.gets(0)) + } + }, func() { k, _ = s.next(m), s.next(m) }) + kit.If(s.token() == DEFS, func() { + sub := s.sub(m) + if sub.p = p; ismap { + sub.t = t + } else { + switch t := t.(type) { + case Struct: + if field, ok := t.index[k].(Field); ok { + sub.t = field.kind + } + } + } + m.Debug("field %d %#v %#v", sub.n, k, data[k]) + data[k] = sub.cals(m, FIELD, END) + }) + } + return data +} +func (s *Expr) ntv(m *ice.Message, t Any, p string) []Any { + data := kit.List() + for !kit.IsIn(s.token(), SUPS, END) { + sub := s.sub(m) + sub.t, sub.p = t, p + if v := sub.cals(m, FIELD, SUPS, END); v != nil { + m.Debug("field %d %d %#v", sub.n, len(data), v) + data = append(data, v) + } + } + return data +} +func (s *Expr) cals(m *ice.Message, arg ...string) Any { + if s.skip == -1 { + m.Debug("calcs %d %v %v", s.n, s.rest, arg) + } else { + m.Debug("calcs %d %v %v", s.n, s.rest[s.skip:], arg) + } + line := s.line + s.reads(m, func(k string) bool { + switch s.get(-1).(type) { + case string: + if op := s.gets(-1) + k; s.isop(op) { + s.pop(1) + k = op + } + } + if kit.IsIn(k, arg...) { + return true } switch k { - case DEFS, SUPS, BEGIN, SPLIT: + case SPLIT: return true - case END: - s.s.skip-- - return true - case CLOSE: - if s.gets(-2) == OPEN { - s.pops(2, s.get(-1)) + case BEGIN: + p := "" + kit.If(strings.Contains(s.gets(-1), ice.PT), func() { p = kit.Split(s.gets(-1), ice.PT)[0] }) + switch t := s.getv(m, -1).(type) { + case Map: + s.pops(1, Dict{s.ktv(m, true, s.value(m, kit.Keys(p, t.value)), p)}) + return false + case Slice: + s.pops(1, List{s.ntv(m, t, p)}) + return false + case Struct: + s.pops(1, Object{Dict{s.ktv(m, false, t, p)}, t}) + return false + } + switch t := s.t.(type) { + case Map: + s.pops(0, Dict{s.ktv(m, true, s.value(m, kit.Keys(s.p, t.value)), s.p)}) + return false + case Slice: + s.pops(0, List{s.ntv(m, t, s.p)}) + return false + case Struct: + s.pops(0, Object{Dict{s.ktv(m, false, t, s.p)}, t}) + return false + } + if kit.IsIn(s.gets(-1), DEFINE) || len(s.list) == 0 && len(arg) > 0 { + s.pops(0, Dict{s.ktv(m, true, nil, "")}) return false } return true + case END: + s.skip-- + return true + case MAP: + s.next(m) + key := s.next(m) + s.next(m) + value := s.next(m) + v := Map{key: key, value: value} + name := kit.Format("map[%s]%s", v.key, v.value) + s.value(m, name, v) + s.push(name) + return false + case SUBS: + if s.peek(m) == SUPS { + pos := s.Position + if s.next(m); !s.isop(s.peek(m)) { + v := Slice{value: s.next(m)} + name := kit.Format("[]%s", v.value) + s.value(m, name, v) + s.push(name) + return false + } + s.Position = pos + } + if kit.IsIn(s.gets(-1), DEFINE) || len(s.list) == 0 && len(arg) > 0 { + s.push(List{s.ntv(m, nil, "")}) + return false + } + case STRUCT, INTERFACE: + s.skip-- + name := s.show() + s.rest[s.skip] = name + s.skip-- + m.Cmd(TYPE) + s.push(name) + return false + case FUNC: + s.push(s.value(m, s.funcs(m))) + return false } - if len(s.list) > 0 && s.getl(-1) == 0 { + if len(s.list) > 0 && !s.isop(-1) { switch k { + case SUBS: + switch v := s.sub(m).cals(m, SUPS); s.get(-1).(type) { + case string: + s.pops(1, kit.Keys(s.gets(-1), kit.Format(trans(v)))) + default: + s.pops(1, s.opv(m, -1, SUBS, v)) + } + return false + case OPEN: + switch k := s.get(-1).(type) { + case string: + s.pops(1, s.call(m, s.Stack, k)) + default: + s.pops(1, s.call(m, k, "")) + } + return false + case CLOSE: + kit.If(s.gets(-2) == OPEN, func() { s.pops(2, s.get(-1)) }) + return false case "++", "--": s.pops(1, s.setv(m, -1, ASSIGN, s.opv(m, -1, k, nil))) return false - case SUBS: - s.pops(1, s.opv(m, -1, SUBS, s.s.cals(m))) - return false - case OPEN: - if s.gets(-1) == FUNC && s.s.skip > 1 { - s.s.skip-- - s.pops(1, s.s.value(m, s.s.funcs(m))) - } else { - switch k := s.get(-1).(type) { - case string: - s.pops(1, s.call(m, s.s, k)) - default: - s.pops(1, s.call(m, k, "")) + } + if !s.isop(k) { + if strings.HasPrefix(k, ice.PT) { + if kit.Select("", s.rest, s.skip+1) == OPEN { + s.skip++ + s.pops(1, s.call(m, s.getv(m, -1), strings.TrimPrefix(k, ice.PT))) + return false + } else if !s.isop(-1) && len(s.list) > 0 { + s.pops(1, s.gets(-1)+k) + return false } } - return false - } - if level[k] == 0 { - if strings.HasPrefix(k, ice.PT) && kit.Select("", s.s.rest, s.s.skip+1) == OPEN { - s.s.skip++ - s.pops(1, s.call(m, s.getv(m, -1), strings.TrimPrefix(k, ice.PT))) - return false - } else { - s.s.skip-- - return true - } + s.skip-- + return true } } - if level[k] > 0 { + if s.isop(k) { for 9 <= level[k] && level[k] <= s.getl(-2) && level[k] < 100 { s.ops(m) } s.push(k) } else { - if s.push(s.trans(m, k)); s.gets(-2) == "!" { - s.pops(2, s.opv(m, -1, "!", nil)) + if s.push(s.trans(m, k)); s.getl(-2) > 0 && (s.getl(-3) > 0 || len(s.list) == 2) { + s.pops(2, s.opv(m, -1, s.gets(-2), nil)) } } return false @@ -227,48 +362,36 @@ func (s *Expr) trans(m *ice.Message, k string) Any { return Number{value: k} } } -func (s *Expr) cmds(m *ice.Message, line int) bool { - if cmds := false; len(s.list) == 1 && s.s.skip < 2 { +func (s *Expr) cmds(m *ice.Message, line int) (done bool) { + if len(s.list) == 1 && s.skip < 2 { m.Search(s.gets(0), func(key string, cmd *ice.Command) { - if cmds = true; s.s.line == line { - args := kit.List(s.gets(0)) - for { - s := NewExpr(s.s) - s.cals(m) - if v := s.getv(m, 0); v != nil { - args = append(args, trans(v)) + args := kit.List(s.gets(0)) + for done = true; s.line == line; { + sub := s.sub(m) + switch sub.cals(m); v := sub.get(0).(type) { + case string: + if _v := s.value(m, v); _v != nil { + args = append(args, kit.Format(trans(_v))) } else { args = append(args, v) } - if s.s.line != line { - break - } + default: + args = append(args, kit.Format(trans(v))) } - m.Cmdy(args...) - } else { - m.Cmdy(s.gets(0)) } + m.Cmdy(args...) }) - if cmds { - return true - } } - return false + return } func (s *Expr) call(m *ice.Message, obj Any, key string) Any { - list := kit.List() - switch v := s.s.cals(m).(type) { - case Value: - list = append(list, v.list...) - default: - list = append(list, v) + if arg := _parse_res(m, s.sub(m).cals(m, CLOSE)); s.runable() { + return s.calls(m, obj, key, nil, arg...) + } else { + return nil } - if !s.s.runable() { - return list - } - return s.s.call(m, obj, key, nil, list...) } -func NewExpr(s *Stack) *Expr { return &Expr{kit.List(), s} } +func NewExpr(s *Stack) *Expr { return &Expr{list: kit.List(), Stack: s} } const EXPR = "expr" @@ -276,15 +399,20 @@ func init() { Index.MergeCommands(ice.Commands{ EXPR: {Name: "expr a, b = 1, 2", Hand: func(m *ice.Message, arg ...string) { s := _parse_stack(m) - arg = s.rest - if v := s.cals(m); !s.runable() { + if arg, v := s.rest, s.cals(m); !s.runable() { return } else if v != nil { - m.Echo(kit.Format(trans(v))) + m.Debug("value %#v <- %v", v, arg) + switch v := trans(v).(type) { + case Message: + case Value: + kit.If(len(v.list) > 0, func() { m.Echo(kit.Format(v.list[0])) }) + default: + m.Echo(kit.Format(v)) + } } else if s.token() == BEGIN { m.Echo(ice.TRUE) } - m.Debug("expr value %s %v %s:%d", m.Result(), arg, s.name, s.line) }}, }) } diff --git a/base/yac/import.go b/base/yac/import.go new file mode 100644 index 00000000..13618196 --- /dev/null +++ b/base/yac/import.go @@ -0,0 +1,61 @@ +package yac + +import ( + "io" + "net/url" + "path" + "strings" + + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/nfs" + kit "shylinux.com/x/toolkits" +) + +const ( + PACKAGE = "package" + IMPORT = "import" +) + +func init() { + Index.MergeCommands(ice.Commands{ + PACKAGE: {Name: "package main", Hand: func(m *ice.Message, arg ...string) { + s := _parse_stack(m) + s.skip = len(s.rest) + }}, + IMPORT: {Name: "import ice shylinux.com/x/icebergs", Hand: func(m *ice.Message, arg ...string) { + load := func(pre string, u *url.URL, p string, r io.Reader) { + if kit.Ext(p) == nfs.SHY { + s, f := _parse_frame(m) + defer s.popf(m) + kit.For(u.Query(), func(k string, v []string) { f.value[k] = v[0] }) + sub := s.parse(m, p, r) + kit.If(pre != "_", func() { kit.For(sub.peekf().value, func(k string, v Any) { s.frame[0].value[kit.Keys(pre, k)] = v }) }) + } + } + find := func(pre, url string) { + u := kit.ParseURL(strings.TrimSuffix(strings.TrimPrefix(url, "\""), "\"")) + pre = kit.Select(path.Base(u.Path), pre) + kit.If(pre == ice.PT, func() { pre = "" }) + if ls := kit.Split(u.Path, ice.PS); path.Join(kit.Slice(ls, 0, 3)...) == ice.Info.Make.Module && nfs.Exists(m, path.Join(kit.Slice(ls, 3)...)) { + nfs.Open(m, path.Join(kit.Slice(ls, 3)...)+ice.PS, func(r io.Reader, p string) { load(pre, u, p, r) }) + } else if p := path.Join(ice.USR_REQUIRE, u.Path) + ice.PS; nfs.Exists(m, p) { + nfs.Open(m, p, func(r io.Reader, p string) { load(pre, u, p, r) }) + } else if p := nfs.USR + path.Join(kit.Slice(ls, 2)...) + ice.PS; nfs.Exists(m, p) { + nfs.Open(m, p, func(r io.Reader, p string) { load(pre, u, p, r) }) + } + } + s := _parse_stack(m) + if p := s.next(m); p == OPEN { + for s.token() != CLOSE { + if list := s.nextLine(m); s.token() != CLOSE { + pos := s.Position + find(kit.Select("", list[0], len(list) > 1), kit.Select("", list, -1)) + s.Position = pos + } + } + } else { + find(kit.Select("", s.rest[1], len(s.rest) > 2), kit.Select("", s.rest, -1)) + } + }}, + }) +} diff --git a/base/yac/stack.go b/base/yac/stack.go index 00695b67..15445920 100644 --- a/base/yac/stack.go +++ b/base/yac/stack.go @@ -4,6 +4,7 @@ import ( "bufio" "io" "path" + "strconv" "strings" ice "shylinux.com/x/icebergs" @@ -13,10 +14,11 @@ import ( ) type Function struct { - obj []string - arg []string - res []string + obj []Field + arg []Field + res []Field Position + object Object } type Frame struct { key string @@ -29,7 +31,6 @@ type Stack struct { last *Frame frame []*Frame Position - n int } type Position struct { rest []string @@ -47,7 +48,7 @@ func (s *Stack) peekf() *Frame { 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().status }) - m.Debug("stack push %d %v %s:%d", len(s.frame), f.key, f.name, f.line) + m.Debug("stack %d push %s %s", len(s.frame), f.key, s.show()) s.frame = append(s.frame, f) return f } @@ -56,7 +57,7 @@ func (s *Stack) popf(m *ice.Message) *Frame { for i := len(f.defers) - 1; i >= 0; i-- { f.defers[i]() } - m.Debug("stack pop %d %v %s:%d", len(s.frame)-1, f.key, f.name, f.line) + m.Debug("stack %d pop %s %s", len(s.frame)-1, f.key, s.show()) kit.If(len(s.frame) > 0, func() { s.frame = s.frame[:len(s.frame)-1] }) s.last = f return f @@ -79,22 +80,72 @@ func (s *Stack) value(m *ice.Message, key string, arg ...Any) Any { return false }) } + keys := strings.Split(key, ice.PT) + kit.If(strings.Contains(key, ice.PS), func() { keys = []string{key} }) kit.If(len(arg) > 0, func() { - m.Debug("value set %d %v %#v", n, key, arg[0]) - f.value[key] = arg[0] + var v Any = Dict{f.value} + for i := 0; i < len(keys); i++ { + switch k := keys[i]; _v := v.(type) { + case Operater: + if i == len(keys)-1 { + m.Debug("value %d:%s set %v %#v", n, f.key, key, arg[0]) + _v.Operate(k, arg[0]) + } else { + if v = _v.Operate(SUBS, k); v == nil { + if _, e := strconv.ParseInt(keys[i+1], 10, 32); e == nil { + v = _v.Operate(k, List{}) + } else { + v = _v.Operate(k, Dict{kit.Dict()}) + } + } + } + default: + v = nil + } + } }) - if v, ok := f.value[key]; ok { + v, ok := f.value[key] + if ok { return v - } - if k := kit.Select(key, strings.Split(key, ice.PT), -1); strings.ToUpper(k) == k { - if c, ok := ice.Info.Index[strings.ToLower(k)].(*ice.Context); ok && (key == k || key == c.Prefix(k)) { - return strings.ToLower(key) + } else { + if s.stack(func(_f *Frame, i int) bool { + v, ok = _f.value[key] + return ok + }); ok { + return v } } - return nil + v = s + kit.For(keys, func(k string) { + switch _v := v.(type) { + case Operater: + v = _v.Operate(SUBS, k) + case *Stack: + v = nil + _v.stack(func(_f *Frame, i int) bool { + v, ok = _f.value[k] + return ok + }) + default: + v = nil + } + }) + if v != nil { + return v + } + return _parse_const(m, key) } func (s *Stack) runable() bool { return s.peekf().status > STATUS_DISABLE } func (s *Stack) token() string { return kit.Select("", s.rest, s.skip) } +func (s *Stack) show() string { + if s.Buffer == nil { + return "" + } else if s.skip == -1 { + return kit.Format("%s:%d", s.name, s.line+1) + } else { + return kit.Format("%s:%d:%d", s.name, s.line+1, s.skip) + } +} 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), "#") @@ -107,17 +158,37 @@ func (s *Stack) read(m *ice.Message) (text string, ok bool) { } for s.input != nil && s.input.Scan() { text = s.input.Text() - m.Debug("input read %d \"%s\" %s:%d", len(s.list), text, s.name, len(s.list)) if s.line, s.list = len(s.list), append(s.list, text); isvoid(text) { continue } + m.Debug("input %d read \"%s\" %s", len(s.list), text, s.show()) return text, true } return } func (s *Stack) reads(m *ice.Message, cb func(k string) bool) { + block, last := []string{}, 0 for { if s.skip++; s.skip < len(s.rest) { + if k := s.rest[s.skip]; k == "`" { + if len(block) > 0 { + kit.If(s.line != last, func() { block, last = append(block, ice.NL), s.line }) + block = append(block, k) + cb(strings.Join(block, ice.SP)) + block = block[:0] + } else { + block = append(block, k) + } + continue + } else if len(block) > 0 { + kit.If(s.line != last, func() { block, last = append(block, ice.NL), s.line }) + block = append(block, k) + continue + } + if s.rest[s.skip] == ice.PS && kit.Select("", s.rest, s.skip+1) == ice.PS { + s.skip = len(s.rest) + continue + } if cb(s.rest[s.skip]) { break } @@ -129,97 +200,147 @@ func (s *Stack) reads(m *ice.Message, cb func(k string) bool) { } } } +func (s *Stack) nextLine(m *ice.Message) []string { + s.skip = len(s.rest) + s.reads(m, func(string) bool { return true }) + return s.rest +} +func (s *Stack) next(m *ice.Message) string { + s.reads(m, func(k string) bool { return true }) + return s.token() +} +func (s *Stack) peek(m *ice.Message) string { + pos := s.Position + defer func() { s.Position = pos }() + s.reads(m, func(k string) bool { return true }) + return s.token() +} +func (s *Stack) pos(m *ice.Message, pos Position, n int) { + s.Position = pos + s.skip += n +} func (s *Stack) run(m *ice.Message) { begin := len(s.frame) s.reads(m, func(k string) bool { - if s.n++; s.n > 300 { - panic(s.n) - } if k == SPLIT { } else if k == END { if s.last = s.popf(m); len(s.frame) < begin { return true } + } else if _, ok := m.Source().Commands[k]; ok { + m.Cmdy(k, kit.Slice(s.rest, s.skip+1)) } else if _, ok := m.Target().Commands[k]; ok { m.Cmdy(k, kit.Slice(s.rest, s.skip+1)) } else { - s.skip-- - m.Cmdy(EXPR, kit.Slice(s.rest, s.skip)) + if s.skip--; s.skip == -1 { + m.Cmd(EXPR, s.rest, ice.SP, s.show()) + } else { + m.Cmd(EXPR, kit.Slice(s.rest, s.skip), ice.SP, s.show()) + } } return false }) } -func (s *Stack) call(m *ice.Message, obj Any, key Any, cb func(*Frame, Function), arg ...Any) Any { - if _k, ok := key.(string); ok { - kit.For(kit.Split(_k, ice.PT), func(k string) { - switch v := obj.(type) { - case *Stack: - if v := v.value(m, _k); v != nil { - obj = v - break - } - obj, key = v.value(m, k), strings.TrimPrefix(_k, k+ice.PT) - } - }) - } - m.Debug("expr call %T %s %v", obj, key, kit.Format(arg)) - switch obj := obj.(type) { - case Function: - f := s.pushf(m, CALL) - kit.For(obj.res, func(k string) { f.value[k] = "" }) - kit.For(obj.arg, func(i int, k string) { - kit.If(i < len(arg), func() { f.value[k] = arg[i] }, func() { f.value[k] = "" }) - }) - value, pos := Value{list: kit.List()}, s.Position - f.value["_return"] = func(arg ...Any) { - if len(obj.res) > 0 { - kit.For(obj.res, func(i int, k string) { - kit.If(i < len(arg), func() { value.list = append(value.list, f.value[k]) }, func() { value.list = append(value.list, "") }) - }) - } else { - value.list = arg - } - } - f.defers, s.Position = append(f.defers, func() { - if len(obj.res) > 0 && len(value.list) == 0 { - kit.For(obj.res, func(i int, k string) { value.list = append(value.list, f.value[k]) }) - } - s.Position = pos - }), obj.Position - kit.If(cb != nil, func() { cb(f, obj) }) - s.run(m.Options(STACK, s)) - return value - case Caller: - return obj.Call(kit.Format(key), arg...) - case func(*ice.Message, string, ...Any) Any: - kit.For(arg, func(i int, v Any) { arg[i] = trans(arg[i]) }) - return wrap(obj(m, kit.Format(key), arg...)) - case func(string, ...Any) Any: - return obj(kit.Format(key), arg...) - case func(): - obj() - return nil - default: - args := kit.List(key) - for _, v := range arg { - switch v := v.(type) { - case Value: - args = append(args, v.list...) - default: - args = append(args, trans(v)) - } - } - return Message{m.Cmd(args...)} - } -} -func (s *Stack) cals(m *ice.Message) Any { return NewExpr(s).cals(m) } func (s *Stack) expr(m *ice.Message, pos ...Position) string { kit.If(len(pos) > 0, func() { s.Position = pos[0] }) return m.Cmdx(EXPR, kit.Slice(s.rest, s.skip)) } +func (s *Stack) cals(m *ice.Message, arg ...string) Any { + sub := NewExpr(s) + return sub.cals(m, arg...) +} +func (s *Stack) cals0(m *ice.Message, arg ...string) string { + sub := NewExpr(s) + sub.cals(m, arg...) + return sub.gets(0) +} +func (s *Stack) types(m *ice.Message) Any { + for ; s.skip < len(s.rest); s.skip++ { + switch s.token() { + case "*": + case MAP: + s.skip += 2 + key := s.types(m) + s.skip += 2 + return Map{key: key, value: s.types(m)} + case SUBS: + s.skip += 2 + return Slice{value: s.types(m)} + case STRUCT: + key, t := []string{}, Struct{index: map[string]Any{}} + for s.next(m); s.next(m) != END; { + if key = append(key, s.token()); s.next(m) == FIELD { + continue + } + types := s.types(m) + kit.For(key, func(key string) { + field := Field{key, types} + t.field = append(t.field, field) + t.index[key] = field + }) + key, s.skip = key[:0], len(s.rest) + } + return t + case INTERFACE: + t := Interface{index: map[string]Function{}} + for s.next(m); s.next(m) != END; { + name := s.token() + field, list := Field{}, [][]Field{} + for s.skip++; s.skip < len(s.rest); s.skip++ { + switch s.token() { + case OPEN: + list = append(list, []Field{}) + case "*": + case FIELD, CLOSE: + list[len(list)-1] = append(list[len(list)-1], field) + field = Field{} + default: + switch t := s.types(m).(type) { + case string: + kit.If(field.name == "", func() { field.name = t }, func() { field.kind = t }) + default: + field.kind = s.types(m) + } + } + } + kit.If(len(list) == 1, func() { list = append(list, []Field{}) }) + t.index[name] = Function{arg: list[0], res: list[1]} + s.skip = len(s.rest) + } + return t + case FUNC: + field, list := Field{}, [][]Field{} + for s.skip++; s.skip < len(s.rest); s.skip++ { + switch s.token() { + case OPEN: + list = append(list, []Field{}) + case "*": + case FIELD, CLOSE: + list[len(list)-1] = append(list[len(list)-1], field) + field = Field{} + default: + switch t := s.types(m).(type) { + case string: + kit.If(field.name == "", func() { field.name = t }, func() { field.kind = t }) + default: + field.kind = s.types(m) + } + } + } + kit.If(len(list) == 1, func() { list = append(list, []Field{}) }) + return Function{arg: list[0], res: list[1]} + default: + // if t := s.value(m, s.token()); t != nil && t != "" { + // return t + // } + return s.token() + } + } + return "" +} func (s *Stack) funcs(m *ice.Message) string { - name := kit.Format("%s:%d:%d", s.name, s.line, s.skip) + name := s.show() s.rest[s.skip], s.skip = name, s.skip-1 m.Cmd(FUNC, name) f := s.peekf() @@ -229,30 +350,120 @@ func (s *Stack) funcs(m *ice.Message) string { s.run(m) return name } -func (s *Stack) parse(m *ice.Message, name string, r io.Reader, cb func(*Frame)) *Stack { - s.Buffer = &Buffer{name: name, input: bufio.NewScanner(r)} - s.load(m, cb).run(m) +func (s *Stack) calls(m *ice.Message, obj Any, key Any, cb func(*Frame, Function), arg ...Any) Any { + if _k, ok := key.(string); ok && _k != "" { + kit.For(kit.Split(_k, ice.PT), func(k string) { + switch v := obj.(type) { + case Operater: + obj = v.Operate(SUBS, k) + case *Stack: + if _v := v.value(m, _k); _v != nil { + obj, key = _v, "" + } else { + obj, key = v.value(m, k), strings.TrimPrefix(_k, k+ice.PT) + } + } + }) + } + switch obj := obj.(type) { + case Function: + m.Debug("stack %d call %T %s %#v", len(s.frame)-1, obj, kit.Select("", obj.obj, -1), arg) + f := s.pushf(m, CALL) + for _, field := range obj.res { + f.value[field.name] = nil + } + for i, field := range obj.arg { + kit.If(i < len(arg), func() { f.value[field.name] = arg[i] }, func() { f.value[field.name] = nil }) + } + kit.If(len(obj.obj) > 1, func() { f.value[obj.obj[0].name] = obj.object }) + value, pos := Value{list: kit.List()}, s.Position + f.value["_return"] = func(arg ...Any) { + if len(obj.res) > 0 { + for i, field := range obj.res { + kit.If(i < len(arg), func() { value.list = append(value.list, f.value[field.name]) }, func() { value.list = append(value.list, nil) }) + } + } else { + value.list = arg + } + } + s.Position, f.defers = obj.Position, append(f.defers, func() { + if len(obj.res) > 0 && len(value.list) == 0 { + for _, field := range obj.res { + value.list = append(value.list, f.value[field.name]) + } + } + s.Position = pos + }) + kit.If(cb != nil, func() { cb(f, obj) }) + s.run(m.Options(STACK, s)) + return value + case Caller: + m.Debug("stack %d call %T %s %#v", len(s.frame)-1, obj, key, arg) + kit.For(arg, func(i int, v Any) { arg[i] = trans(arg[i]) }) + return wrap(obj.Call(kit.Format(key), arg...)) + case func(*ice.Message, string, ...Any) Any: + m.Debug("stack %d call %T %s %#v", len(s.frame)-1, obj, key, arg) + kit.For(arg, func(i int, v Any) { arg[i] = trans(arg[i]) }) + return wrap(obj(m, kit.Format(key), arg...)) + case func(): + obj() + return nil + default: + args := kit.List(key) + kit.For(arg, func(i int, v Any) { args = append(args, trans(v)) }) + return Message{m.Cmd(args...)} + } +} +func (s *Stack) action(m *ice.Message, obj Any, key Any, arg ...string) *ice.Message { + s.calls(m, obj, key, func(f *Frame, v Function) { + i := 0 + for _, field := range v.arg { + switch field.name { + case "m", "msg": + f.value[field.name] = Message{m} + case ice.ARG: + list := kit.List() + kit.For(arg, func(v string) { list = append(list, String{v}) }) + f.value[field.name] = Value{list} + default: + f.value[field.name], i = String{m.Option(field.name, kit.Select(m.Option(field.name), arg, i))}, i+1 + } + } + }) + return m +} +func (s *Stack) parse(m *ice.Message, name string, r io.Reader) *Stack { + pos := s.Position + defer func() { s.Position = pos }() + s.Position = Position{Buffer: &Buffer{name: name, input: bufio.NewScanner(r)}} + s.peekf().Position = s.Position + m.Debug("stack %d parse %s", len(s.frame)-1, s.show()) + s.run(m) + return s +} +func NewStack(m *ice.Message, cb func(*Frame)) *Stack { + s := &Stack{} + s.pushf(m.Options(STACK, s), STACK) + s.load(m, cb) return s } -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, "") } -func _parse_cache(m *ice.Message, name string) *Stack { - key := kit.Keys(m.PrefixKey(), name) - s := mdb.Cache(m, key, func() (v Any) { - nfs.Open(m, existsFile(m, name), func(r io.Reader, p string) { - v = NewStack().parse(m.Spawn(), p, r, nil) - }) - return - }).(*Stack) - kit.If(m.Option(ice.DEBUG) == ice.TRUE, func() { mdb.Cache(m, key, nil) }) - return s +func _parse_const(m *ice.Message, key string) string { + if k := kit.Select(key, strings.Split(key, ice.PT), -1); kit.IsUpper(k) { + if c, ok := ice.Info.Index[strings.ToLower(k)].(*ice.Context); ok && (key == k || key == c.Prefix(k)) { + return strings.ToLower(k) + } + } + return "" } func _parse_res(m *ice.Message, v Any) []Any { switch v := v.(type) { + case nil: + return nil case Value: return v.list default: @@ -269,64 +480,71 @@ const STACK = "stack" func init() { Index.MergeCommands(ice.Commands{ STACK: {Name: "stack path auto parse", Actions: ice.Actions{ - ice.CMD: {Hand: func(m *ice.Message, arg ...string) { - s := _parse_cache(m, arg[0]) - meta := kit.Dict() - kit.For(s.peekf().value, func(k string, v Any) { - switch v := v.(type) { - case Function: - list := kit.List() - kit.For(v.arg, func(k string) { - if !kit.IsIn(k, "m", ice.ARG) { - list = append(list, kit.Dict(mdb.NAME, k, mdb.TYPE, mdb.TEXT, mdb.VALUE, "")) - } - }) - kit.If(k == mdb.LIST, func() { list = append(list, kit.Dict(mdb.NAME, mdb.LIST, mdb.TYPE, "button", mdb.ACTION, ice.AUTO)) }) - meta[k] = list - } - }) - m.Push(ice.INDEX, arg[0]) - m.Push(mdb.NAME, arg[0]) - m.Push(mdb.HELP, arg[0]) - m.Push(mdb.LIST, kit.Format(meta[mdb.LIST])) - m.Push(mdb.META, kit.Format(meta)) - }}, - ice.RUN: {Hand: func(m *ice.Message, arg ...string) { - s := _parse_cache(m, arg[0]) - action, i := mdb.LIST, 0 - if len(arg) > 2 && arg[1] == ice.ACTION && s.value(m, arg[2]) != nil { - action, arg = arg[2], arg[3:] - } else { - arg = arg[1:] - } - s.call(m.StatusTime(), s, action, func(f *Frame, v Function) { - kit.For(v.arg, func(k string) { - switch k { - case "m": - f.value[k] = Message{m} - case ice.ARG: - list := kit.List() - kit.For(arg, func(v string) { list = append(list, String{v}) }) - f.value[k] = Value{list} - default: - f.value[k], i = String{m.Option(k, kit.Select(m.Option(k), arg, i))}, i+1 - } - }) - }) - }}, + "start": {Hand: func(m *ice.Message, arg ...string) {}}, + ice.CMD: {Hand: func(m *ice.Message, arg ...string) {}}, + ice.RUN: {Hand: func(m *ice.Message, arg ...string) {}}, }, Hand: func(m *ice.Message, arg ...string) { - if m.Options(nfs.DIR_ROOT, nfs.SRC).Cmdy(nfs.CAT, arg); len(m.Result()) == 0 { + if len(arg) == 0 || strings.HasSuffix(arg[0], ice.PS) { + m.Options(nfs.DIR_ROOT, nfs.SRC).Cmdy(nfs.CAT, arg) return } - nfs.Open(m, path.Join(nfs.SRC, path.Join(arg...)), func(r io.Reader, p string) { - if NewStack().parse(m, p, r, nil); m.Option(ice.DEBUG) == ice.TRUE { - m.EchoLine("").EchoLine("stack: %s", arg[0]).Cmdy(INFO) + nfs.Open(m, path.Join(nfs.SRC, strings.TrimPrefix(path.Join(arg...), nfs.SRC)), func(r io.Reader, p string) { + if NewStack(m, nil).parse(m, p, r); m.Option(ice.DEBUG) == ice.TRUE { + m.Cmdy(INFO, arg) } }) }}, }) + loaded := kit.Dict() + ice.AddMergeAction(func(c *ice.Context, key string, cmd *ice.Command, sub string, action *ice.Action) (init ice.Handler) { + kit.IfNoKey(loaded, ice.SRC_SCRIPT+c.Prefix(key)+ice.PS, func(p string) { kit.If(nfs.Exists(ice.Pulse, p), func() { init = StackHandler }) }) + return + }) } -func existsFile(m *ice.Message, p string) string { - return nfs.SRC + strings.Replace(p, ice.PT, ice.PS, -1) + ice.PT + nfs.SHY + +func StackHandler(m *ice.Message, arg ...string) { + s := NewStack(m, nil) + script := []string{} + nfs.Open(m, ice.SRC_SCRIPT+m.PrefixKey()+ice.PS, func(r io.Reader, p string) { + kit.If(kit.Ext(p) == nfs.SHY, func() { + if strings.HasPrefix(path.Base(p), "on") { + script = append(script, kit.Format("Volcanos(\"%s\", {", kit.TrimExt(path.Base(p), nfs.SHY))) + kit.For(r, func(s string) { + if strings.HasPrefix(s, FUNC) { + script = append(script, ice.TB+strings.Replace(strings.TrimPrefix(s, FUNC+ice.SP), "(", ": function(", 1)) + } else if strings.HasPrefix(s, END) { + script = append(script, ice.TB+"},") + } else { + script = append(script, ice.TB+s) + } + }) + script = append(script, "})") + } else { + s.parse(m.Spawn(Index).Spawn(m.Target()), p, r) + } + }) + }) + if len(script) > 0 { + p := ice.USR_SCRIPT + m.PrefixKey() + ice.PS + "list.js" + s.value(m, "_script", "/require/"+p) + m.Cmd(nfs.SAVE, p, kit.Dict(nfs.CONTENT, strings.Join(script, ice.NL))) + } + cmd := m.Commands("") + kit.For(s.peekf().value, func(k string, v Any) { + switch v := v.(type) { + case Function: + list := kit.List() + for _, field := range v.arg { + kit.If(!kit.IsIn(field.name, "m", "msg", ice.ARG), func() { list = append(list, kit.Dict(mdb.NAME, field.name, mdb.TYPE, mdb.TEXT, mdb.VALUE, "")) }) + } + kit.If(k == mdb.LIST, func() { list = append(list, kit.Dict(mdb.NAME, mdb.LIST, mdb.TYPE, "button", mdb.ACTION, ice.AUTO)) }) + h := func(m *ice.Message, arg ...string) { m.Copy(s.action(m.Spawn(Index).Spawn(m.Target()), s, k, arg...)) } + if k == mdb.LIST { + cmd.Hand, cmd.List = h, list + } else { + cmd.Actions[k], cmd.Meta[k] = &ice.Action{Hand: h}, list + } + } + }) } -func ExistsFile(m *ice.Message, p string) bool { return nfs.Exists(m, existsFile(m, p)) } +func StackAction() ice.Actions { return ice.Actions{ice.CTX_INIT: {Hand: StackHandler}} } diff --git a/base/yac/stmt.go b/base/yac/stmt.go index 4a35b1f1..fa17a0b0 100644 --- a/base/yac/stmt.go +++ b/base/yac/stmt.go @@ -13,12 +13,14 @@ const ( IF = "if" ELSE = "else" FOR = "for" + RANGE = "range" BREAK = "break" CONTINUE = "continue" SWITCH = "switch" CASE = "case" DEFAULT = "default" FUNC = "func" + INIT = "init" CALL = "call" DEFER = "defer" RETURN = "return" @@ -42,9 +44,9 @@ func init() { ELSE: {Name: "else if a = 1; a > 1 {", Hand: func(m *ice.Message, arg ...string) { s, f := _parse_frame(m) if s.last.status == STATUS_DISABLE { - f.status = 0 + f.status = STATUS_NORMAL } else { - f.status, f.defers = STATUS_DISABLE, append(f.defers, func() { f.status = 0 }) + f.status, f.defers = STATUS_DISABLE, append(f.defers, func() { f.status = STATUS_NORMAL }) } s.reads(m, func(k string) bool { if k == IF { @@ -57,6 +59,27 @@ func init() { }}, FOR: {Name: "for a = 1; a < 10; a++ {", Hand: func(m *ice.Message, arg ...string) { s, f := _parse_frame(m) + if strings.Contains(s.list[s.line], RANGE) { + pos, key, list := s.Position, []string{}, []Any{} + kit.If(s.last != nil && s.last.line == s.line, func() { list, _ = s.last.value["_range"].([]Any) }) + for { // for k, v := range value { + if k := s.cals0(m, FIELD, DEFS, ASSIGN); k == RANGE { + if obj, ok := s.cals(m).(Operater); ok { + if _list, ok := obj.Operate(RANGE, list).([]Any); ok { + kit.For(key, func(i int, k string) { f.value[k] = _list[i] }) + f.value["_range"] = _list + break + } + } + f.status = STATUS_DISABLE + break + } else if k != "" { + key = append(key, k) + } + } + f.defers = append(f.defers, func() { kit.If(s.runable(), func() { s.pos(m, pos, -1) }) }) + return + } list, status := []Position{s.Position}, f.status for f.status = STATUS_DISABLE; s.token() != BEGIN; list = append(list, s.Position) { s.expr(m) @@ -91,8 +114,7 @@ func init() { } s.stack(func(f *Frame, i int) bool { f.status = STATUS_DISABLE - defer s.popf(m) - switch f.key { + switch s.popf(m); f.key { case FOR, SWITCH: return true default: @@ -106,8 +128,7 @@ func init() { return } s.stack(func(f *Frame, i int) bool { - defer s.popf(m) - switch f.key { + switch s.popf(m); f.key { case FOR: return true default: @@ -124,7 +145,7 @@ func init() { CASE: {Name: "case b:", Hand: func(m *ice.Message, arg ...string) { s := _parse_stack(m) f := s.peekf() - f.status = 0 + f.status = STATUS_NORMAL v := s.cals(m) f.status = STATUS_DISABLE if res, ok := v.(Operater); ok { @@ -136,19 +157,21 @@ func init() { DEFAULT: {Name: "default:", Hand: func(m *ice.Message, arg ...string) { s := _parse_stack(m) f := s.peekf() - if f.status = 0; f.value["_case"] == "done" { + if f.status = STATUS_NORMAL; f.value["_case"] == "done" { f.status = STATUS_DISABLE } s.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), "", "" }) } + list, key, kind := [][]Field{[]Field{}}, "", "" + push := func() { + kit.If(key, func() { list[len(list)-1], key, kind = append(list[len(list)-1], Field{name: key, kind: kind}), "", "" }) + } s.reads(m, func(k string) bool { switch k { case OPEN: - defer kit.If(key != "" || len(list) > 1, func() { list = append(list, []string{}) }) + defer kit.If(key != "" || len(list) > 1, func() { list = append(list, []Field{}) }) case FIELD, CLOSE: case BEGIN: return true @@ -159,47 +182,50 @@ func init() { 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), Function{obj: list[0], arg: list[1], res: list[2], Position: s.Position}) - s.pushf(m, "").status = STATUS_DISABLE + kit.If(len(list) < 2, func() { list = append(list, []Field{}) }) + kit.If(len(list) < 3, func() { list = append(list, []Field{}) }) + name, fun := list[0][len(list[0])-1].name, Function{obj: list[0], arg: list[1], res: list[2], Position: s.Position} + if len(list[0]) > 1 { + st := list[0][0].kind.(Struct) + st.method = append(st.method, fun) + st.index[name] = fun + } else { + kit.If(name != INIT, func() { s.value(m, name, fun) }) + } + if f := s.pushf(m, ""); name == INIT { + f.key = CALL + } else { + f.status = STATUS_DISABLE + } }}, DEFER: {Name: "defer func() {} ()", Hand: func(m *ice.Message, arg ...string) { s := _parse_stack(m) - s.reads(m, func(k string) bool { - kit.If(k == FUNC, func() { k = s.funcs(m) }) - s.skip++ - v := s.cals(m) - if !s.runable() { + k := s.next(m) + kit.If(k == FUNC, func() { k = s.funcs(m) }) + s.skip++ + args := _parse_res(m, s.cals(m)) + if !s.runable() { + return + } + s.stack(func(f *Frame, i int) bool { + if f.key == CALL { + f.defers = append(f.defers, func() { s.calls(m, s, k, nil, args...) }) return true } - if vv, ok := v.(Value); ok { - v = vv.list - } else { - v = []Any{v} - } - s.stack(func(f *Frame, i int) bool { - if f.key == CALL { - f.defers = append(f.defers, func() { s.call(m, s, k, nil, v.([]Any)...) }) - return true - } - return false - }) - return true + return false }) }}, RETURN: {Name: "return show", Hand: func(m *ice.Message, arg ...string) { s := _parse_stack(m) - v := s.cals(m) + args := _parse_res(m, s.cals(m)) s.stack(func(f *Frame, i int) bool { f.status = STATUS_DISABLE switch f.key { case FUNC: - case CALL: switch cb := f.value["_return"].(type) { case func(...Any): - cb(_parse_res(m, v)...) + cb(args...) } case SOURCE: s.input = nil @@ -215,17 +241,24 @@ func init() { s := _parse_stack(m) u := kit.ParseURL(s.expr(m)) nfs.Open(m, u.Path, func(r io.Reader, p string) { - f := s.parse(m, p, r, func(f *Frame) { kit.For(u.Query(), func(k string, v []string) { f.value[k] = v[0] }) }).popf(m) - s.Position = f.Position + s.parse(m, p, r) s.skip = len(s.rest) }) }}, INFO: {Name: "info", Hand: func(m *ice.Message, arg ...string) { + m.EchoLine("").EchoLine("stack: %s", arg[0]) _parse_stack(m).stack(func(f *Frame, i int) bool { m.EchoLine("frame: %s %v:%v:%v", f.key, f.name, f.line, f.skip) kit.For(f.value, func(k string, v Any) { m.EchoLine(" %s: %#v", k, v) }) return false }) + m.EchoLine("stmt: %s", arg[0]) + for key, cmd := range m.Target().Commands { + if strings.HasPrefix(key, "_") || strings.HasPrefix(key, "/") { + continue + } + m.EchoLine(" %s: %#v", key, cmd.Name) + } }}, PWD: {Name: "pwd", Hand: func(m *ice.Message, arg ...string) { s := _parse_stack(m) diff --git a/base/yac/type.go b/base/yac/type.go new file mode 100644 index 00000000..1cfba13f --- /dev/null +++ b/base/yac/type.go @@ -0,0 +1,99 @@ +package yac + +import ( + ice "shylinux.com/x/icebergs" + kit "shylinux.com/x/toolkits" +) + +const ( + CONST = "const" + TYPE = "type" + VAR = "var" + + STRING = "string" + INT = "int" + MAP = "map" + SLICE = "slice" + STRUCT = "struct" + INTERFACE = "interface" +) + +type Map struct { + key Any + value Any +} +type Slice struct { + value Any +} +type Interface struct { + index map[string]Function +} +type Struct struct { + index map[string]Any + method []Function + field []Field +} +type Field struct { + name string + kind Any +} +type Object struct { + value Operater + index Struct +} + +func (s Object) Operate(op string, v Any) Any { + switch op { + case "&", "*": + return s + case SUBS: + switch v := s.index.index[kit.Format(v)].(type) { + case Function: + v.object = s + return v + } + fallthrough + default: + return s.value.Operate(op, v) + } + return nil +} + +func init() { + Index.MergeCommands(ice.Commands{ + CONST: {Name: "const a = 1", Hand: func(m *ice.Message, arg ...string) { + if s := _parse_stack(m); s.next(m) == OPEN { + for s.token() != CLOSE { + s.nextLine(m) + s.skip-- + s.cals(m, CLOSE) + } + } else { + s.skip-- + s.cals(m) + } + }}, + TYPE: {Name: "type student struct {", Hand: func(m *ice.Message, arg ...string) { + s := _parse_stack(m) + switch name := s.next(m); s.next(m) { + case ASSIGN: + s.next(m) + fallthrough + default: + s.value(m, name, s.types(m)) + } + }}, + VAR: {Name: "var a = 1", Hand: func(m *ice.Message, arg ...string) { + if s := _parse_stack(m); s.next(m) == OPEN { + for s.token() != CLOSE { + s.nextLine(m) + s.skip-- + s.cals(m, CLOSE) + } + } else { + s.skip-- + s.cals(m) + } + }}, + }) +} diff --git a/base/yac/value.go b/base/yac/value.go index f72a766e..40b20f64 100644 --- a/base/yac/value.go +++ b/base/yac/value.go @@ -2,7 +2,9 @@ package yac import ( "encoding/json" + "strconv" "strings" + "time" ice "shylinux.com/x/icebergs" kit "shylinux.com/x/toolkits" @@ -20,7 +22,6 @@ type Operater interface{ Operate(string, Any) Any } func (s Dict) MarshalJSON() ([]byte, error) { return json.Marshal(s.value) } func (s List) MarshalJSON() ([]byte, error) { return json.Marshal(s.value) } -func (s Value) MarshalJSON() ([]byte, error) { return json.Marshal(s.list) } func (s String) MarshalJSON() ([]byte, error) { return json.Marshal(s.value) } func (s Number) MarshalJSON() ([]byte, error) { return json.Marshal(s.value) } func (s Boolean) MarshalJSON() ([]byte, error) { return json.Marshal(s.value) } @@ -49,9 +50,10 @@ func trans(v Any) Any { return v.value case Value: if len(v.list) > 0 { - return v.list[0] + return trans(v.list[0]) + } else { + return nil } - return nil case String: return v.value case Number: @@ -64,23 +66,57 @@ func trans(v Any) Any { } func (s Dict) Operate(op string, v Any) Any { switch op { + case RANGE: + switch list := v.(type) { + case []Any: + if key := kit.SortedKey(s.value); list != nil && len(list) > 2 { + if i := kit.Int(list[2]) + 1; i < len(key) { + return []Any{key[i], s.value[key[i]], i} + } + } else { + if len(key) > 0 { + return []Any{key[0], s.value[key[0]], 0} + } + } + } + return nil case SUBS: return wrap(kit.Value(s.value, kit.Format(v))) + default: + s.value[op] = v + return v } return nil } func (s List) Operate(op string, v Any) Any { switch op { + case RANGE: + switch list := v.(type) { + case []Any: + if list != nil && len(list) > 1 { + if i := kit.Int(list[0]) + 1; i < len(s.value) { + return []Any{i, s.value[i]} + } + } else { + if len(s.value) > 0 { + return []Any{0, s.value[0]} + } + } + } + return nil case SUBS: return wrap(kit.Value(s.value, kit.Format(v))) - } - return nil -} -func (s Value) Operate(op string, v Any) Any { - switch op { - case SUBS: - if i := kit.Int(v); i < len(s.list) { - return s.list[i] + default: + if i, e := strconv.ParseInt(op, 10, 32); e == nil { + switch (int(i)+2+len(s.value)+2)%(len(s.value)+2) - 2 { + case -1: + s.value = append([]Any{v}, s.value...) + case -2: + s.value = append(s.value, v) + default: + s.value[i] = v + } + return v } } return nil @@ -149,56 +185,99 @@ func (s Boolean) Operate(op string, v Any) Any { return nil } } - -type Message struct{ *ice.Message } - -func (m Message) Call(cmd string, arg ...Any) Any { - args := []Any{} - kit.For(arg, func(i int, v Any) { args = append(args, trans(v)) }) - str := func(v Any) string { return kit.Format(trans(v)) } - switch cmd { - case "Option": - return String{m.Option(str(args[0]), args[1:]...)} - case "Cmd": - return Message{m.Cmd(args...)} - case "Cmdy": - m.Cmdy(args...) - case "Copy": - m.Copy(args[0].(Message).Message, kit.Simple(args[1:]...)...) - case "Push": - m.Push(str(args[0]), args[1], args[2:]...) - case "Echo": - m.Echo(str(args[0]), args[1:]...) - case "Action": - m.Action(args...) - case "Sleep": - m.Sleep(str(args[0])) - case "Table": - s := _parse_stack(m.Message) - m.Table(func(val ice.Maps) { s.call(m.Message, arg[0], nil, nil, Dict{kit.Dict(val)}) }) - default: - m.ErrorNotImplement(cmd) - } - return m -} func (s *Stack) load(m *ice.Message, cb func(*Frame)) *Stack { - f := s.pushf(m.Options(STACK, s), "") + f := s.peekf() f.value["kit"] = func(m *ice.Message, key string, arg ...Any) Any { - kit.For(arg, func(i int, v Any) { arg[i] = trans(v) }) switch key { case "Dict": - return Dict{kit.Dict(arg...)} + return kit.Dict(arg...) case "List": - return List{kit.List(arg...)} + return kit.List(arg...) + case "Format": + return kit.Format(arg[0], arg[1:]...) + case "Formats": + return kit.Formats(arg[0]) default: m.ErrorNotImplement(key) return nil } } + f.value["ice.MergeActions"] = func(m *ice.Message, key string, arg ...Any) Any { + s := _parse_stack(m) + _actions := ice.Actions{} + for _, v := range arg { + actions := ice.Actions{} + kit.For(v, func(k string, v Any) { + action := &ice.Action{} + kit.For(v, func(k string, v Any) { + switch k { + case "Name": + action.Name = kit.Format(trans(v)) + case "Help": + action.Help = kit.Format(trans(v)) + case "Hand": + action.Hand = func(m *ice.Message, arg ...string) { s.action(m, v, nil, arg...) } + } + }) + actions[k] = action + }) + ice.MergeActions(_actions, actions) + } + return _actions + } for k, v := range ice.Info.Stack { f.value[k] = v } f.value["m"] = Message{m} - kit.If(cb != nil, func() { cb(s.peekf()) }) + kit.If(cb != nil, func() { cb(f) }) return s } + +func (m Message) Call(cmd string, arg ...Any) Any { + str := func(v Any) string { return kit.Format(trans(v)) } + switch cmd { + case "Option": + return m.Option(str(arg[0]), arg[1:]...) + case "Cmd": + return Message{m.Cmd(arg...)} + case "Cmdy": + m.Cmdy(arg...) + case "Copy": + m.Copy(arg[0].(Message).Message, kit.Simple(arg[1:]...)...) + case "Push": + m.Push(str(arg[0]), arg[1], arg[2:]...) + case "Echo": + m.Echo(str(arg[0]), arg[1:]...) + case "Action": + m.Action(arg...) + case "Display": + if len(arg) > 0 { + m.ProcessDisplay(arg...) + } else { + m.ProcessDisplay(kit.Format("%s?_t=%d", trans(_parse_stack(m.Message).value(m.Message, "_script")), time.Now().Unix())) + } + case "StatusTime": + m.StatusTime(arg...) + case "DebugStack": + s := _parse_stack(m.Message) + list := []string{} + s.stack(func(f *Frame, i int) bool { + list = append(list, kit.Format("stack: %s", f.key)) + kit.For(f.value, func(k string, v Any) { + list = append(list, kit.Format("stack: %s %s:%#v", f.key, k, v)) + }) + return false + }) + m.Debug(ice.NL + strings.Join(list, ice.NL)) + case "Sleep": + m.Sleep(str(arg[0])) + case "Table": + s := _parse_stack(m.Message) + m.Table(func(val ice.Maps) { s.calls(m.Message, arg[0], nil, nil, Dict{kit.Dict(val)}) }) + default: + m.ErrorNotImplement(cmd) + } + return m +} + +type Message struct{ *ice.Message } diff --git a/conf.go b/conf.go index 52ae578e..d437eda9 100644 --- a/conf.go +++ b/conf.go @@ -103,6 +103,7 @@ const ( // DIR ISH_PLUGED = ".ish/pluged/" USR_MODULES = "usr/node_modules/" + USR_SCRIPT = "usr/script/" USR_INSTALL = "usr/install/" USR_REQUIRE = "usr/require/" USR_PUBLISH = "usr/publish/" @@ -143,7 +144,6 @@ const ( // DIR SRC_HELP = "src/help/" SRC_DEBUG = "src/debug/" SRC_RELEASE = "src/release/" - SRC_TEMPLATE = "src/template/" SRC_MAIN_SHY = "src/main.shy" SRC_MAIN_SH = "src/main.sh" SRC_MAIN_JS = "src/main.js" @@ -151,6 +151,8 @@ const ( // DIR SRC_WEBVIEW_GO = "src/webview.go" SRC_VERSION_GO = "src/version.go" SRC_BINPACK_GO = "src/binpack.go" + SRC_TEMPLATE = "src/template/" + SRC_SCRIPT = "src/script/" README_MD = "README.md" MAKEFILE = "Makefile" LICENSE = "LICENSE" diff --git a/core/chat/favor.go b/core/chat/favor.go index 9bbf4e07..784c3a80 100644 --- a/core/chat/favor.go +++ b/core/chat/favor.go @@ -34,7 +34,7 @@ const FAVOR = "favor" func init() { Index.MergeCommands(ice.Commands{ - FAVOR: {Name: "favor hash auto create getClipboardData getLocation scanQRCode record1 record2 upload", Help: "收藏夹", Actions: ice.MergeActions(ice.Actions{ + FAVOR: {Name: "favor hash auto create getClipboardData getLocation scanQRCode record1 record2 upload demo", Help: "收藏夹", Actions: ice.MergeActions(ice.Actions{ mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) { if arg[0] == mdb.FOREACH { m.Cmd("", ice.OptionFields("")).Table(func(value ice.Maps) { diff --git a/core/code/code.go b/core/code/code.go index b0ce0ce7..0fa6a72d 100644 --- a/core/code/code.go +++ b/core/code/code.go @@ -16,6 +16,9 @@ func init() { VIMER, INNER, XTERM, PPROF, BENCH, C, SH, SHY, PY, GO, JS, CSS, HTML, ) + ice.Info.Stack[CODE] = func(m *ice.Message, key string, arg ...ice.Any) ice.Any { + return nil + } } func Prefix(arg ...string) string { return web.Prefix(CODE, kit.Keys(arg)) } diff --git a/core/code/shy.go b/core/code/shy.go index cecd7d51..f8e78719 100644 --- a/core/code/shy.go +++ b/core/code/shy.go @@ -21,7 +21,13 @@ func init() { mdb.RENDER: {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])) - ctx.ProcessCommand(m, kit.TrimExt(arg[1], SHY), kit.Simple()) + // if ls := kit.Split(arg[1], ice.PS); ls[0] == nfs.SCRIPT { + // m.Search(ls[1], func(key string, cmd *ice.Command) { yac.StackHandler(m) }) + // ctx.ProcessCommand(m, ls[1], kit.Simple()) + // } else { + // ctx.ProcessCommand(m, kit.TrimExt(arg[1], SHY), kit.Simple()) + // } + ctx.ProcessCommand(m, yac.STACK, kit.Simple(arg[1])) }}, mdb.ENGINE: {Hand: func(m *ice.Message, arg ...string) { ctx.ProcessCommand(m, yac.STACK, kit.Simple(arg[1])) diff --git a/core/wiki/refer.go b/core/wiki/refer.go index 872cfd07..102c1875 100644 --- a/core/wiki/refer.go +++ b/core/wiki/refer.go @@ -28,6 +28,10 @@ func init() { Index.MergeCommands(ice.Commands{ REFER: {Name: "refer text", Help: "参考", Actions: WordAction( ``, - ), Hand: func(m *ice.Message, arg ...string) { _refer_show(m, arg[0], arg[1:]...) }}, + ), Hand: func(m *ice.Message, arg ...string) { + if len(arg) > 1 { + _refer_show(m, arg[0], arg[1:]...) + } + }}, }) } diff --git a/logs.go b/logs.go index 554f4ad9..b5bb7e82 100644 --- a/logs.go +++ b/logs.go @@ -147,10 +147,10 @@ func (m *Message) IsErrNotFound() bool { return m.IsErr(ErrNotFound) } func (m *Message) Debug(str string, arg ...Any) { - if m.Option("debug") == TRUE { - kit.Format(str == "", func() { str = m.FormatMeta() }) - m.log(LOG_DEBUG, str, arg...) - } + // if m.Option("debug") == TRUE || !Info.Important { + kit.Format(str == "", func() { str = m.FormatMeta() }) + m.log(LOG_DEBUG, str, arg...) + // } } func (m *Message) FormatPrefix() string { diff --git a/type.go b/type.go index 0791c9b2..9c53bf94 100644 --- a/type.go +++ b/type.go @@ -302,6 +302,8 @@ func (m *Message) Search(key string, cb Any) *Message { if key == "" { return m } + _target, _key, _cmd := m.target, m._key, m._cmd + defer func() { m.target, m._key, m._cmd = _target, _key, _cmd }() p := m.target.root if key = strings.TrimPrefix(key, "ice."); key == PT { p, key = m.target, "" @@ -336,6 +338,7 @@ func (m *Message) Search(key string, cb Any) *Message { switch cb := cb.(type) { case func(key string, cmd *Command): if cmd, ok := p.Commands[key]; ok { + m.target, m._key, m._cmd = p, key, cmd cb(key, cmd) } case func(p *Context, s *Context, key string, cmd *Command): @@ -391,5 +394,5 @@ func (m *Message) Actions(key string) *Action { return m._cmd.Actions[key] } func (m *Message) Commands(key string) *Command { - return m.Target().Commands[key] + return m.Target().Commands[kit.Select(m._key, key)] } diff --git a/type.shy b/type.shy new file mode 100644 index 00000000..a78d7f58 --- /dev/null +++ b/type.shy @@ -0,0 +1,76 @@ +type Any = interface{} +type List = []Any +type Map = map[string]Any +type Maps = map[string]string +type Handler func(m *Message, arg ...string) +type Messages = map[string]*Message +type Contexts = map[string]*Context +type Commands = map[string]*Command +type Actions = map[string]*Action +type Configs = map[string]*Config +type Caches = map[string]*Cache + +type Cache struct { + Name string + Help string + Value string +} +type Config struct { + Name string + Help string + Value Any +} +type Action struct { + Name string + Help string + Hand Handler + List List +} +type Command struct { + Name string + Help string + Actions Actions + Hand Handler + RawHand Any + List List + Meta Map +} +type Context struct { + Name string + Help string + + Caches Caches + Configs Configs + Commands Commands + + contexts Contexts + context *Context + root *Context + server Server + + id int32 +} +type Server interface { + Begin(m *Message, arg ...string) + Start(m *Message, arg ...string) + Close(m *Message, arg ...string) +} + +type Message struct { + code int + + data Map + meta map[string][]string + + root *Message + message *Message + + _source string + _target string + source *Context + target *Context + _cmd *Command + _key string + _sub string +} +