diff --git a/base/yac/expr.go b/base/yac/expr.go index 29924699..cd2cfecb 100644 --- a/base/yac/expr.go +++ b/base/yac/expr.go @@ -9,24 +9,25 @@ import ( ) const ( - SPACE = "\t " - QUOTE = "\"" - TRANS = " " - BLOCK = "[:](,){;}*/+-<>!=&|" - DEFINE = ":=" - ASSIGN = "=" - SUBS = "[" - DEFS = ":" - SUPS = "]" - OPEN = "(" - FIELD = "," - CLOSE = ")" - BEGIN = "{" - SPLIT = ";" - END = "}" - DISABLE = -1 + SPACE = "\t " + QUOTE = "\"" + TRANS = " " + BLOCK = "[:](,){;}*/+-<>!=&|" + DEFINE = ":=" + ASSIGN = "=" + SUBS = "[" + DEFS = ":" + SUPS = "]" + OPEN = "(" + FIELD = "," + CLOSE = ")" + BEGIN = "{" + SPLIT = ";" + END = "}" ) +var keyword = regexp.MustCompile("[_a-zA-Z][_a-zA-Z0-9]*") + var level = map[string]int{ "//": 200, "/*": 200, "*/": 200, "!": 100, "++": 100, "--": 100, "[": 100, "]": 100, @@ -38,7 +39,6 @@ var level = map[string]int{ type Expr struct { list ice.List s *Stack - m *ice.Message n int } @@ -50,6 +50,7 @@ func (s *Expr) pop(n int) *Expr { s.list = s.list[:len(s.list)-n] return s } +func (s *Expr) pops(n int, v Any) *Expr { return s.pop(n).push(v) } func (s *Expr) get(p int) (v Any) { 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] }) @@ -66,23 +67,19 @@ func (s *Expr) getv(m *ice.Message, p int) (v Any) { } } func (s *Expr) setv(m *ice.Message, p int, op string, v Any) Any { - k := s.gets(p) - kit.If(s.s.runable(), func() { - switch v := v.(type) { - case string: - s.s.value(m, k, s.s.value(m, v), op) - case Value: - s.s.value(m, k, v.list[0], op) - default: - s.s.value(m, k, v, op) - } - }) - return s.s.value(m, k) + if !s.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) + case Value: + return s.s.value(m, k, v.list[0], op) + default: + return s.s.value(m, k, v, op) + } } func (s *Expr) opv(m *ice.Message, p int, op string, v Any) Any { - if s.n++; s.n > 100 { - panic(s.n) - } if !s.s.runable() { return s.getv(m, p) } @@ -95,12 +92,16 @@ func (s *Expr) ops(m *ice.Message) { if !s.s.runable() || s.getl(-2) < 10 { return } - v := s.opv(m, -3, s.gets(-2), s.getv(m, -1)) - s.pop(3).push(v) + if s.n++; s.n > 100 { + panic(s.n) + } + 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 { return nil + } else if len(s.list) == 1 { + return s.getv(m, 0) } m.Debug("expr ops %v", s.list) for len(s.list) > 1 { @@ -127,9 +128,7 @@ func (s *Expr) end(m *ice.Message) Any { 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) { - list = append(list, s.setv(m, i, s.gets(-2), v.list[i/2])) - } + kit.If(i/2 < len(v.list), func() { list = append(list, s.setv(m, i, s.gets(-2), v.list[i/2])) }) } default: s.setv(m, -3, s.gets(-2), s.getv(m, -1)) @@ -157,58 +156,34 @@ func (s *Expr) cals(m *ice.Message) Any { case END: s.s.skip-- return true + case CLOSE: + if s.gets(-2) == OPEN { + s.pops(2, s.get(-1)) + return false + } + return true } if len(s.list) > 0 && s.getl(-1) == 0 { switch k { - case "++": - v := s.opv(m, -1, "+", 1) - s.setv(m, -1, ASSIGN, v) - s.pop(1).push(v) - return false - case "--": - v := s.opv(m, -1, "-", 1) - s.setv(m, -1, ASSIGN, v) - s.pop(1).push(v) + case "++", "--": + s.pops(1, s.setv(m, -1, ASSIGN, s.opv(m, -1, k, nil))) return false case SUBS: - v := s.opv(m, -1, SUBS, s.s.cals(m)) - s.pop(1).push(v) + s.pops(1, s.opv(m, -1, SUBS, s.s.cals(m))) return false case OPEN: - if s.gets(-1) == FUNC { - name := kit.Format("%s:%d:%d", s.s.name, s.s.line, s.s.skip) + if s.gets(-1) == FUNC && s.s.skip > 1 { s.s.skip-- - s.s.rest[s.s.skip] = name - s.s.skip-- - m.Cmd(FUNC, name) - s.s.skip++ - sub := NewStack() - sub.Position = s.s.Position - sub.pushf(m, FUNC).status = DISABLE - sub.run(m.Options(STACK, sub)) - s.s.Position = sub.Position - m.Options(STACK, s.s) - s.s.popf(m) - s.pop(1).push(s.s.value(m, name)) + s.pops(1, s.s.value(m, s.s.funcs(m))) } else { - v := s.call(m, s.s, s.gets(-1)) - s.pop(1).push(v) + s.pops(1, s.call(m, s.s, s.gets(-1))) } return false - case CLOSE: - if s.gets(-2) == OPEN { - v := s.get(-1) - s.pop(2).push(v) - return false - } - m.Debug("what %v", k) - return true } if level[k] == 0 { if strings.HasPrefix(k, ice.PT) && kit.Select("", s.s.rest, s.s.skip+1) == OPEN { s.s.skip++ - v := s.call(m, s.getv(m, -1), strings.TrimPrefix(k, ice.PT)) - s.pop(1).push(v) + s.pops(1, s.call(m, s.getv(m, -1), strings.TrimPrefix(k, ice.PT))) return false } else { s.s.skip-- @@ -217,7 +192,7 @@ func (s *Expr) cals(m *ice.Message) Any { } } if level[k] > 0 { - for level[k] >= 9 && level[k] <= s.getl(-2) { + for level[k] >= 9 && level[k] <= s.getl(-2) && level[k] < 100 { s.ops(m) } s.push(k) @@ -228,11 +203,14 @@ func (s *Expr) cals(m *ice.Message) Any { s.push(Boolean{value: true}) } else if k == ice.FALSE { s.push(Boolean{value: false}) - } else if b, e := regexp.MatchString("[_a-zA-Z][_a-zA-Z0-9]*", k); e == nil && b { + } else if keyword.MatchString(k) { s.push(k) } else { s.push(Number{value: k}) } + if s.gets(-2) == "!" { + s.pops(2, s.opv(-1, "!")) + } } return false }) @@ -247,36 +225,11 @@ func (s *Expr) call(m *ice.Message, obj Any, key string) Any { list = append(list, v) } if !s.s.runable() { - return nil - } - kit.For(kit.Slice(kit.Split(key, ice.PT), 0, -1), func(k string) { - switch v := obj.(type) { - case *Stack: - obj, key = v.value(m, k), strings.TrimPrefix(key, k+ice.PT) - } - }) - m.Debug("expr call %T %s %v", obj, key, kit.Format(list)) - switch obj := obj.(type) { - case *Stack: - return obj.call(m, obj.value(m, key), nil, list...) - case Caller: - return obj.Call(key, list...) - case func(string, ...Any) Any: - return obj(key, list...) - default: - args := kit.List(key) - for _, v := range list { - switch v := v.(type) { - case Value: - args = append(args, v.list...) - default: - args = append(args, trans(v)) - } - } - return Message{m.Cmd(args...)} + return list } + return s.s.call(m, obj, key, nil, list...) } -func NewExpr(m *ice.Message, s *Stack) *Expr { return &Expr{kit.List(), s, m, 0} } +func NewExpr(s *Stack) *Expr { return &Expr{kit.List(), s, 0} } const EXPR = "expr" @@ -285,7 +238,6 @@ func init() { EXPR: {Name: "expr a = 1", Hand: func(m *ice.Message, arg ...string) { s := _parse_stack(m) arg = s.rest - m.Debug("what %v %d %d", s.rest[:], s.skip, s.line) if v := s.cals(m); !s.runable() { return } else if v != nil { diff --git a/base/yac/stack.go b/base/yac/stack.go index c8fb061d..0f7ac704 100644 --- a/base/yac/stack.go +++ b/base/yac/stack.go @@ -53,6 +53,11 @@ func (s *Stack) pushf(m *ice.Message, key string) *Frame { } func (s *Stack) popf(m *ice.Message) *Frame { f := s.peekf() + list := kit.List(f.value["_defer"]) + delete(f.value, "_defer") + for i := len(list) - 1; i >= 0; i-- { + list[i].(func())() + } kit.If(f.pop != nil, func() { f.pop() }) m.Debug("stack pop %d %v %s:%d", len(s.frame)-1, f.key, f.name, f.line) kit.If(len(s.frame) > 0, func() { s.frame = s.frame[:len(s.frame)-1] }) @@ -68,7 +73,7 @@ func (s *Stack) stack(cb func(*Frame, int) bool) { } func (s *Stack) value(m *ice.Message, key string, arg ...Any) Any { f, n := s.peekf(), len(s.frame)-1 - if len(arg) < 2 || arg[1] == ASSIGN { + if len(arg) < 2 || arg[1] != DEFINE { s.stack(func(_f *Frame, i int) bool { if _f.value[key] != nil { f, n = _f, i @@ -83,7 +88,7 @@ func (s *Stack) value(m *ice.Message, key string, arg ...Any) Any { }) return f.value[key] } -func (s *Stack) runable() bool { return s.peekf().status > DISABLE } +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) read(m *ice.Message) (text string, ok bool) { isvoid := func(text string) bool { @@ -120,77 +125,102 @@ func (s *Stack) reads(m *ice.Message, cb func(k string) bool) { } } func (s *Stack) run(m *ice.Message) { + begin := len(s.frame) s.reads(m, func(k string) bool { - if s.n++; s.n > 100 { - return true + if s.n++; s.n > 300 { + panic(s.n) } - if k == SPLIT { } else if k == END { - s.last = s.popf(m) + if s.last = s.popf(m); len(s.frame) < begin { + return true + } } else if _, ok := m.Target().Commands[k]; ok { m.Cmdy(k, kit.Slice(s.rest, s.skip+1)) } else { s.skip-- m.Cmd(EXPR, kit.Slice(s.rest, s.skip)) } - if len(s.frame) == 0 { - return true - } return false }) } -func (s *Stack) call(m *ice.Message, v Any, cb func(*Frame, Function), arg ...Any) Any { - switch v := v.(type) { - case Function: - f := s.pushf(m, CALL) - kit.For(v.res, func(k string) { f.value[k] = "" }) - kit.For(v.arg, func(i int, k string) { - if i < len(arg) { - f.value[k] = arg[i] - } else { - f.value[k] = "" +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) } }) - f.value["_return"], f.value["_res"] = "", v.res + } + 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.pop, s.Position = func() { - if len(v.res) == 0 { - value.list = append(value.list, f.value["_return"]) + 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 { - kit.For(v.res, func(k string) { value.list = append(value.list, f.value[k]) }) + value.list = arg + } + } + f.pop, s.Position = 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 - }, v.Position - cb(f, v) + }, obj.Position + kit.If(cb != nil, func() { cb(f, obj) }) s.run(m.Options(STACK, s)) return value - default: + case Caller: + return obj.Call(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(m, s).cals(m) } +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) load(m *ice.Message) *Stack { - f := s.pushf(m.Options(STACK, s), "") - f.value["kit"] = func(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...)} - case "List": - return List{kit.List(arg...)} - default: - m.ErrorNotImplement(key) - return nil - } - } - f.value["m"] = Message{m} - return s +func (s *Stack) funcs(m *ice.Message) string { + name := kit.Format("%s:%d:%d", s.name, s.line, s.skip) + s.rest[s.skip] = name + s.skip-- + m.Cmd(FUNC, name) + f := s.peekf() + status := f.status + defer func() { f.status = status }() + f.status = STATUS_DISABLE + 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)} @@ -206,6 +236,10 @@ func _parse_frame(m *ice.Message) (*Stack, *Frame) { return _parse_stack(m), _parse_stack(m).pushf(m, "") } +const ( + STATUS_NORMAL = 0 + STATUS_DISABLE = -1 +) const STACK = "stack" func init() { @@ -246,7 +280,7 @@ func init() { arg = arg[1:] } i := 0 - s.call(m, s.value(m, action), func(f *Frame, v Function) { + s.call(m, s, action, func(f *Frame, v Function) { kit.For(v.arg, func(k string) { switch k { case "m": @@ -268,19 +302,9 @@ func init() { return } nfs.Open(m, path.Join(nfs.SRC, path.Join(arg...)), func(r io.Reader, p string) { - s := NewStack().parse(m, p, r, nil) - if m.Option(ice.DEBUG) != ice.TRUE { + if NewStack().parse(m, p, r, nil); m.Option(ice.DEBUG) != ice.TRUE { return } - m.EchoLine("").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, INFO, SOURCE}, func(k string) { s = span(s, k, FUNCTION) }) - m.EchoLine("%2d: %s", i, s) - }) m.EchoLine("").EchoLine("stack: %s", arg[0]).Cmdy(INFO) }) diff --git a/base/yac/stmt.go b/base/yac/stmt.go index e46ab7aa..94c27bcb 100644 --- a/base/yac/stmt.go +++ b/base/yac/stmt.go @@ -10,7 +10,6 @@ import ( ) const ( - LET = "let" IF = "if" ELSE = "else" FOR = "for" @@ -21,6 +20,7 @@ const ( DEFAULT = "default" FUNC = "func" CALL = "call" + DEFER = "defer" RETURN = "return" SOURCE = "source" INFO = "info" @@ -33,25 +33,24 @@ const ( func init() { Index.MergeCommands(ice.Commands{ - 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 := s.expr(m) kit.If(s.token() == SPLIT, func() { res = s.expr(m) }) - kit.If(res == ice.FALSE, func() { f.status = DISABLE }) + kit.If(res == ice.FALSE, func() { f.status = STATUS_DISABLE }) }}, ELSE: {Name: "else if a = 1; a > 1 {", Hand: func(m *ice.Message, arg ...string) { s, f := _parse_frame(m) - if s.last.status == DISABLE { + if s.last.status == STATUS_DISABLE { f.status = 0 } else { - f.status, f.pop = DISABLE, func() { f.status = 0 } + f.status, f.pop = STATUS_DISABLE, func() { f.status = 0 } } s.reads(m, func(k string) bool { if k == IF { res := s.expr(m) kit.If(s.token() == SPLIT, func() { res = s.expr(m) }) - kit.If(res == ice.FALSE, func() { f.status = DISABLE }) + kit.If(res == ice.FALSE, func() { f.status = STATUS_DISABLE }) } return true }) @@ -59,7 +58,7 @@ func init() { 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() != BEGIN; list = append(list, s.Position) { + for f.status = STATUS_DISABLE; s.token() != BEGIN; list = append(list, s.Position) { s.expr(m) } f.status = status @@ -76,7 +75,7 @@ func init() { } res = s.expr(m, list[1]) } - kit.If(res == ice.FALSE, func() { f.status = DISABLE }) + kit.If(res == ice.FALSE, func() { f.status = STATUS_DISABLE }) s.Position, f.pop = list[len(list)-1], func() { if s.runable() { kit.If(len(list) > 3, func() { s.expr(m, list[2]) }) @@ -91,10 +90,10 @@ func init() { return } s.stack(func(f *Frame, i int) bool { - f.status = DISABLE + f.status = STATUS_DISABLE defer s.popf(m) switch f.key { - case FOR: + case FOR, SWITCH: return true default: return false @@ -127,7 +126,7 @@ func init() { f := s.peekf() f.status = 0 v := s.cals(m) - f.status = DISABLE + f.status = STATUS_DISABLE if res, ok := v.(Operater); ok { if res, ok := res.Operate("==", trans(s.value(m, "_switch"))).(Boolean); ok && res.value { f.status, f.value["_case"] = 0, "done" @@ -138,7 +137,7 @@ func init() { s := _parse_stack(m) f := s.peekf() if f.status = 0; f.value["_case"] == "done" { - f.status = DISABLE + f.status = STATUS_DISABLE } s.skip++ }}, @@ -163,33 +162,57 @@ func init() { 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 = DISABLE + s.pushf(m, "").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() { + return true + } + if vv, ok := v.(Value); ok { + v = vv.list + } else { + v = []Any{v} + } + s.stack(func(f *Frame, i int) bool { + if kit.IsIn(f.key, CALL, SOURCE, STACK) { + f.value["_defer"] = append(kit.List(f.value["_defer"]), func() { + s.call(m, s, k, nil, v.([]Any)...) + }) + return true + } + return false + }) + return true + }) + }}, RETURN: {Name: "return show", Hand: func(m *ice.Message, arg ...string) { s := _parse_stack(m) - res := kit.Simple(trans(s.value(m, "_res"))) - if v := s.cals(m); len(res) == 0 { - f := s.peekf() - f.value["_return"] = v - } else { - switch v := v.(type) { - case Value: - kit.For(res, func(i int, k string) { kit.If(i < len(v.list), func() { s.value(m, k, v.list[i]) }) }) - default: - s.value(m, kit.Select("_res", res, 0), v) - } - } + v := s.cals(m) s.stack(func(f *Frame, i int) bool { - f.status = DISABLE + f.status = STATUS_DISABLE switch f.key { case FUNC: case CALL: - - case STACK: - s.input = nil + switch cb := f.value["_return"].(type) { + case func(...Any): + switch v := v.(type) { + case Value: + cb(v.list...) + default: + cb(v) + } + } case SOURCE: s.input = nil + case STACK: + s.input = nil default: return false } @@ -219,7 +242,7 @@ func init() { res := []string{kit.Format("%d:%d", s.line, s.skip)} s.stack(func(f *Frame, i int) bool { kit.If(i > 0, func() { - res = append(res, kit.Format("%s:%d:%d %s %v", f.name, f.line, f.skip, f.key, kit.Select(ice.FALSE, ice.TRUE, f.status > DISABLE))) + res = append(res, kit.Format("%s:%d:%d %s %v", f.name, f.line, f.skip, f.key, kit.Select(ice.FALSE, ice.TRUE, f.status > STATUS_DISABLE))) }) return false }) diff --git a/base/yac/value.go b/base/yac/value.go index 9f607bdb..185c28ca 100644 --- a/base/yac/value.go +++ b/base/yac/value.go @@ -101,6 +101,10 @@ func (s String) Operate(op string, v Any) Any { } func (s Number) Operate(op string, v Any) Any { switch a, b := kit.Int(s.value), kit.Int(v); op { + case "++": + return Number{kit.Format(a + 1)} + case "--": + return Number{kit.Format(a - 1)} case "*": return Number{kit.Format(a * b)} case "/": @@ -151,8 +155,6 @@ func (m Message) Call(cmd string, arg ...Any) Any { return String{m.Option(str(args[0]), args[1:]...)} case "Cmd": return Message{m.Cmd(args...)} - case "Action": - m.Action(args...) case "Cmdy": m.Cmdy(args...) case "Copy": @@ -161,15 +163,34 @@ func (m Message) Call(cmd string, arg ...Any) Any { m.Push(str(args[0]), args[1], args[2:]...) case "Echo": m.Echo(str(args[0]), args[1:]...) - case "Sleep": - m.Sleep(str(args[0])) case "Table": s := _parse_stack(m.Message) var value Any - m.Table(func(v ice.Maps) { value = s.call(m.Message, v, nil, Dict{kit.Dict(v)}) }) + m.Table(func(val ice.Maps) { value = s.call(m.Message, arg[0], nil, nil, Dict{kit.Dict(val)}) }) return value + case "Sleep": + m.Sleep(str(args[0])) + case "Action": + m.Action(args...) default: m.ErrorNotImplement(cmd) } return m } +func (s *Stack) load(m *ice.Message) *Stack { + f := s.pushf(m.Options(STACK, s), "") + f.value["m"] = Message{m} + f.value["kit"] = func(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...)} + case "List": + return List{kit.List(arg...)} + default: + m.ErrorNotImplement(key) + return nil + } + } + return s +}