forked from x/icebergs
add expr
This commit is contained in:
parent
3edc006f07
commit
ec75142f96
@ -8,6 +8,7 @@ import (
|
|||||||
"shylinux.com/x/icebergs/base/aaa"
|
"shylinux.com/x/icebergs/base/aaa"
|
||||||
"shylinux.com/x/icebergs/base/mdb"
|
"shylinux.com/x/icebergs/base/mdb"
|
||||||
"shylinux.com/x/icebergs/base/nfs"
|
"shylinux.com/x/icebergs/base/nfs"
|
||||||
|
"shylinux.com/x/icebergs/base/yac"
|
||||||
kit "shylinux.com/x/toolkits"
|
kit "shylinux.com/x/toolkits"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -31,6 +32,9 @@ func _command_list(m *ice.Message, name string) *ice.Message {
|
|||||||
m.Push(mdb.META, kit.Format(cmd.Meta))
|
m.Push(mdb.META, kit.Format(cmd.Meta))
|
||||||
m.Push(mdb.LIST, kit.Format(cmd.List))
|
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
|
return m
|
||||||
}
|
}
|
||||||
func _command_search(m *ice.Message, kind, name, text string) {
|
func _command_search(m *ice.Message, kind, name, text string) {
|
||||||
@ -91,7 +95,13 @@ func PodCmd(m *ice.Message, arg ...ice.Any) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func Run(m *ice.Message, arg ...string) {
|
func Run(m *ice.Message, arg ...string) {
|
||||||
kit.If(!PodCmd(m, arg) && aaa.Right(m, arg), func() { m.Cmdy(arg) })
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
func CmdHandler(args ...ice.Any) ice.Handler {
|
func CmdHandler(args ...ice.Any) ice.Handler {
|
||||||
return func(m *ice.Message, arg ...string) { m.Cmdy(args...) }
|
return func(m *ice.Message, arg ...string) { m.Cmdy(args...) }
|
||||||
|
@ -162,6 +162,8 @@ func Open(m *ice.Message, p string, cb ice.Any) {
|
|||||||
case func(io.Reader, os.FileInfo):
|
case func(io.Reader, os.FileInfo):
|
||||||
s, _ := StatFile(m, p)
|
s, _ := StatFile(m, p)
|
||||||
cb(f, s)
|
cb(f, s)
|
||||||
|
case func(io.Reader, string):
|
||||||
|
cb(f, p)
|
||||||
case func(io.Reader):
|
case func(io.Reader):
|
||||||
cb(f)
|
cb(f)
|
||||||
case func(string):
|
case func(string):
|
||||||
|
299
base/yac/expr.go
Normal file
299
base/yac/expr.go
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
package yac
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
ice "shylinux.com/x/icebergs"
|
||||||
|
kit "shylinux.com/x/toolkits"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SPACE = "\t "
|
||||||
|
QUOTE = "\""
|
||||||
|
TRANS = " "
|
||||||
|
BLOCK = "[:](,){;}*/+-<>!=&|"
|
||||||
|
DEFINE = ":="
|
||||||
|
ASSIGN = "="
|
||||||
|
SUBS = "["
|
||||||
|
DEFS = ":"
|
||||||
|
SUPS = "]"
|
||||||
|
OPEN = "("
|
||||||
|
FIELD = ","
|
||||||
|
CLOSE = ")"
|
||||||
|
BEGIN = "{"
|
||||||
|
SPLIT = ";"
|
||||||
|
END = "}"
|
||||||
|
DISABLE = -1
|
||||||
|
)
|
||||||
|
|
||||||
|
var level = map[string]int{
|
||||||
|
"//": 200, "/*": 200, "*/": 200,
|
||||||
|
"!": 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,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Expr struct {
|
||||||
|
list ice.List
|
||||||
|
s *Stack
|
||||||
|
m *ice.Message
|
||||||
|
n int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Expr) push(v Any) *Expr {
|
||||||
|
s.list = append(s.list, v)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
func (s *Expr) pop(n int) *Expr {
|
||||||
|
s.list = s.list[:len(s.list)-n]
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
func (s *Expr) get(p int) (v 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] })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (s *Expr) gets(p int) string { return kit.Format(s.get(p)) }
|
||||||
|
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)
|
||||||
|
default:
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
if obj, ok := s.getv(m, p).(Operater); ok {
|
||||||
|
return obj.Operate(op, trans(v))
|
||||||
|
}
|
||||||
|
return s.getv(m, p)
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
func (s *Expr) end(m *ice.Message) Any {
|
||||||
|
if !s.s.runable() || len(s.list) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
m.Debug("expr ops %v", s.list)
|
||||||
|
for len(s.list) > 1 {
|
||||||
|
switch s.ops(m); s.gets(-2) {
|
||||||
|
case FIELD:
|
||||||
|
list := kit.List()
|
||||||
|
for i := len(s.list) - 2; i > 0; i -= 2 {
|
||||||
|
if s.gets(i) == ASSIGN || s.gets(i) == DEFINE {
|
||||||
|
for j := 0; j < i; j += 2 {
|
||||||
|
list = append(list, s.setv(m, j, s.gets(i), s.getv(m, j+i+1)))
|
||||||
|
}
|
||||||
|
s.list = kit.List(Value{list: list})
|
||||||
|
break
|
||||||
|
} else if i == 1 {
|
||||||
|
for i := 0; i < len(s.list); i += 2 {
|
||||||
|
list = append(list, s.getv(m, i))
|
||||||
|
}
|
||||||
|
s.list = kit.List(Value{list: list})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case ASSIGN, DEFINE:
|
||||||
|
list := kit.List()
|
||||||
|
switch v := s.getv(m, -1).(type) {
|
||||||
|
case Value:
|
||||||
|
for i := 0; i < len(s.list)-1; i += 2 {
|
||||||
|
if i/2 < len(v.list) {
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
s.list = kit.List(Value{list})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.Debug("expr ops %v", s.list)
|
||||||
|
return s.getv(m, 0)
|
||||||
|
}
|
||||||
|
func (s *Expr) cals(m *ice.Message) Any {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
switch k {
|
||||||
|
case DEFS, SUPS, BEGIN, SPLIT:
|
||||||
|
return true
|
||||||
|
case END:
|
||||||
|
s.s.skip--
|
||||||
|
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)
|
||||||
|
return false
|
||||||
|
case SUBS:
|
||||||
|
v := s.opv(m, -1, SUBS, s.s.cals(m))
|
||||||
|
s.pop(1).push(v)
|
||||||
|
return false
|
||||||
|
case OPEN:
|
||||||
|
if s.gets(-1) == FUNC {
|
||||||
|
name := kit.Format("%s:%d:%d", s.s.name, s.s.line, s.s.skip)
|
||||||
|
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))
|
||||||
|
} else {
|
||||||
|
v := s.call(m, s.s, s.gets(-1))
|
||||||
|
s.pop(1).push(v)
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
s.s.skip--
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if level[k] > 0 {
|
||||||
|
for level[k] >= 9 && level[k] <= s.getl(-2) {
|
||||||
|
s.ops(m)
|
||||||
|
}
|
||||||
|
s.push(k)
|
||||||
|
} else {
|
||||||
|
if strings.HasPrefix(k, "\"") {
|
||||||
|
s.push(String{value: k[1 : len(k)-1]})
|
||||||
|
} else if k == ice.TRUE {
|
||||||
|
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 {
|
||||||
|
s.push(k)
|
||||||
|
} else {
|
||||||
|
s.push(Number{value: k})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
return s.end(m)
|
||||||
|
}
|
||||||
|
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 !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...)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func NewExpr(m *ice.Message, s *Stack) *Expr { return &Expr{kit.List(), s, m, 0} }
|
||||||
|
|
||||||
|
const EXPR = "expr"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Index.MergeCommands(ice.Commands{
|
||||||
|
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 {
|
||||||
|
m.Echo(kit.Format(trans(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)
|
||||||
|
}},
|
||||||
|
})
|
||||||
|
}
|
@ -1,22 +1,18 @@
|
|||||||
package yac
|
package yac
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"bufio"
|
||||||
"io"
|
"io"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
ice "shylinux.com/x/icebergs"
|
ice "shylinux.com/x/icebergs"
|
||||||
"shylinux.com/x/icebergs/base/log"
|
"shylinux.com/x/icebergs/base/mdb"
|
||||||
"shylinux.com/x/icebergs/base/nfs"
|
"shylinux.com/x/icebergs/base/nfs"
|
||||||
kit "shylinux.com/x/toolkits"
|
kit "shylinux.com/x/toolkits"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Value struct{ list []ice.Any }
|
type Function struct {
|
||||||
|
|
||||||
func (s *Value) MarshalJSON() ([]byte, error) { return json.Marshal(s.list) }
|
|
||||||
|
|
||||||
type Func struct {
|
|
||||||
obj []string
|
obj []string
|
||||||
arg []string
|
arg []string
|
||||||
res []string
|
res []string
|
||||||
@ -32,66 +28,63 @@ type Frame struct {
|
|||||||
type Stack struct {
|
type Stack struct {
|
||||||
last *Frame
|
last *Frame
|
||||||
frame []*Frame
|
frame []*Frame
|
||||||
input chan string
|
|
||||||
list []string
|
|
||||||
rest []string
|
|
||||||
Position
|
Position
|
||||||
|
n int
|
||||||
|
}
|
||||||
|
type Position struct {
|
||||||
|
rest []string
|
||||||
|
skip int
|
||||||
|
line int
|
||||||
|
*Buffer
|
||||||
|
}
|
||||||
|
type Buffer struct {
|
||||||
|
name string
|
||||||
|
list []string
|
||||||
|
input *bufio.Scanner
|
||||||
}
|
}
|
||||||
type Position struct{ line, skip int }
|
|
||||||
|
|
||||||
func (s *Stack) peekf(m *ice.Message) *Frame {
|
func (s *Stack) peekf() *Frame { return s.frame[len(s.frame)-1] }
|
||||||
kit.If(len(s.frame) == 0, func() { s.pushf(m, "") })
|
|
||||||
return s.frame[len(s.frame)-1]
|
|
||||||
}
|
|
||||||
func (s *Stack) pushf(m *ice.Message, key string) *Frame {
|
func (s *Stack) pushf(m *ice.Message, key string) *Frame {
|
||||||
f := &Frame{key: kit.Select(m.CommandKey(), key), value: kit.Dict(), Position: s.Position}
|
f := &Frame{key: kit.Select(m.CommandKey(), key), value: kit.Dict(), Position: s.Position}
|
||||||
kit.If(len(s.frame) > 0, func() { f.status = s.peekf(m).status })
|
kit.If(len(s.frame) > 0, func() { f.status = s.peekf().status })
|
||||||
m.Debug("stack push %#v", f)
|
m.Debug("stack push %d %v %s:%d", len(s.frame), f.key, f.name, f.line)
|
||||||
s.frame = append(s.frame, f)
|
s.frame = append(s.frame, f)
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
func (s *Stack) popf(m *ice.Message) *Frame {
|
func (s *Stack) popf(m *ice.Message) *Frame {
|
||||||
f := s.peekf(m)
|
f := s.peekf()
|
||||||
m.Debug("stack pop %#v", f)
|
kit.If(f.pop != nil, func() { f.pop() })
|
||||||
kit.If(len(s.frame) > 1, func() { s.frame = s.frame[:len(s.frame)-1] })
|
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] })
|
||||||
|
s.last = f
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
func (s *Stack) stack(cb ice.Any) {
|
func (s *Stack) stack(cb func(*Frame, int) bool) {
|
||||||
for i := len(s.frame) - 1; i >= 0; i-- {
|
for i := len(s.frame) - 1; i >= 0; i-- {
|
||||||
switch cb := cb.(type) {
|
if cb(s.frame[i], i) {
|
||||||
case func(*Frame, int) bool:
|
return
|
||||||
if cb(s.frame[i], i) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case func(*Frame, int):
|
|
||||||
cb(s.frame[i], i)
|
|
||||||
case func(*Frame):
|
|
||||||
cb(s.frame[i])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (s *Stack) value(m *ice.Message, key string, arg ...ice.Any) ice.Any {
|
func (s *Stack) value(m *ice.Message, key string, arg ...Any) Any {
|
||||||
f := s.peekf(m)
|
f, n := s.peekf(), len(s.frame)-1
|
||||||
s.stack(func(_f *Frame, i int) bool {
|
if len(arg) < 2 || arg[1] == ASSIGN {
|
||||||
if _f.value[key] != nil {
|
s.stack(func(_f *Frame, i int) bool {
|
||||||
f = _f
|
if _f.value[key] != nil {
|
||||||
return true
|
f, n = _f, i
|
||||||
}
|
return true
|
||||||
return false
|
}
|
||||||
})
|
return false
|
||||||
|
})
|
||||||
|
}
|
||||||
kit.If(len(arg) > 0, func() {
|
kit.If(len(arg) > 0, func() {
|
||||||
m.Debug("value set %v %#v", key, arg[0])
|
m.Debug("value set %d %v %#v", n, key, arg[0])
|
||||||
switch v := arg[0].(type) {
|
f.value[key] = arg[0]
|
||||||
case *Value:
|
|
||||||
f.value[key] = v.list[0]
|
|
||||||
default:
|
|
||||||
f.value[key] = arg[0]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
// m.Debug("value get %v %v", key, f.value[key])
|
|
||||||
return f.value[key]
|
return f.value[key]
|
||||||
}
|
}
|
||||||
func (s *Stack) runable(m *ice.Message) bool { return s.peekf(m).status > DISABLE }
|
func (s *Stack) runable() bool { return s.peekf().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) {
|
func (s *Stack) read(m *ice.Message) (text string, ok bool) {
|
||||||
isvoid := func(text string) bool {
|
isvoid := func(text string) bool {
|
||||||
return strings.TrimSpace(text) == "" || strings.HasPrefix(strings.TrimSpace(text), "#")
|
return strings.TrimSpace(text) == "" || strings.HasPrefix(strings.TrimSpace(text), "#")
|
||||||
@ -102,434 +95,199 @@ func (s *Stack) read(m *ice.Message) (text string, ok bool) {
|
|||||||
}
|
}
|
||||||
return s.list[s.line], true
|
return s.list[s.line], true
|
||||||
}
|
}
|
||||||
for {
|
for s.input != nil && s.input.Scan() {
|
||||||
if text, ok = <-s.input; !ok {
|
text = s.input.Text()
|
||||||
break
|
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) {
|
||||||
m.Debug("input read %v", text)
|
|
||||||
if s.list = append(s.list, text); isvoid(text) {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
s.line = len(s.list) - 1
|
return text, true
|
||||||
break
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
func (s *Stack) reads(m *ice.Message, cb func(i int, k string) bool) (arg []string) {
|
func (s *Stack) reads(m *ice.Message, cb func(k string) bool) {
|
||||||
i := 0
|
|
||||||
for {
|
for {
|
||||||
if s.skip++; s.skip < len(s.rest) {
|
if s.skip++; s.skip < len(s.rest) {
|
||||||
arg = append(arg, s.rest[s.skip])
|
if cb(s.rest[s.skip]) {
|
||||||
if cb(i, s.rest[s.skip]) {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
i++
|
|
||||||
} else if text, ok := s.read(m); ok {
|
} else if text, ok := s.read(m); ok {
|
||||||
s.rest, s.skip = kit.Split(text, "\t ", OPS), -1
|
s.rest, s.skip = kit.Split(text, SPACE, BLOCK, QUOTE, TRANS, ice.TRUE), -1
|
||||||
} else {
|
} else {
|
||||||
|
cb(SPLIT)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
func (s *Stack) call(m *ice.Message) {
|
func (s *Stack) run(m *ice.Message) {
|
||||||
s.reads(m, func(i int, k string) bool {
|
s.reads(m, func(k string) bool {
|
||||||
|
if s.n++; s.n > 100 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
if k == SPLIT {
|
if k == SPLIT {
|
||||||
|
|
||||||
} else if k == END {
|
} else if k == END {
|
||||||
kit.If(s.peekf(m).pop != nil, func() { s.peekf(m).pop() })
|
|
||||||
s.last = s.popf(m)
|
s.last = s.popf(m)
|
||||||
} else if _, ok := m.Target().Commands[k]; ok {
|
} else if _, ok := m.Target().Commands[k]; ok {
|
||||||
m.Cmdy(k)
|
m.Cmdy(k, kit.Slice(s.rest, s.skip+1))
|
||||||
} else {
|
} else {
|
||||||
s.skip--
|
s.skip--
|
||||||
m.Cmdy(EXPR)
|
m.Cmd(EXPR, kit.Slice(s.rest, s.skip))
|
||||||
|
}
|
||||||
|
if len(s.frame) == 0 {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
func (s *Stack) parse(m *ice.Message, r io.Reader) *ice.Message {
|
func (s *Stack) call(m *ice.Message, v Any, cb func(*Frame, Function), arg ...Any) Any {
|
||||||
s.input = make(chan string, 100)
|
switch v := v.(type) {
|
||||||
m.Options(STACK, s)
|
case Function:
|
||||||
kit.For(r, func(text string) { s.input <- text })
|
f := s.pushf(m, CALL)
|
||||||
close(s.input)
|
kit.For(v.res, func(k string) { f.value[k] = "" })
|
||||||
|
kit.For(v.arg, func(i int, k string) {
|
||||||
// s.input = make(chan string)
|
if i < len(arg) {
|
||||||
// m.Options(STACK, s).Go(func() {
|
f.value[k] = arg[i]
|
||||||
// defer func() { kit.If(s.input != nil, func() { close(s.input) }) }()
|
} else {
|
||||||
// kit.For(r, func(text string) { s.input <- text })
|
f.value[k] = ""
|
||||||
// })
|
}
|
||||||
s.peekf(m)
|
})
|
||||||
s.call(m)
|
f.value["_return"], f.value["_res"] = "", v.res
|
||||||
return m
|
value, pos := Value{list: kit.List()}, s.Position
|
||||||
}
|
f.pop, s.Position = func() {
|
||||||
func (s *Stack) token(m *ice.Message) string {
|
if len(v.res) == 0 {
|
||||||
if s.skip < len(s.rest) {
|
value.list = append(value.list, f.value["_return"])
|
||||||
return s.rest[s.skip]
|
} else {
|
||||||
|
kit.For(v.res, func(k string) { value.list = append(value.list, f.value[k]) })
|
||||||
|
}
|
||||||
|
s.Position = pos
|
||||||
|
}, v.Position
|
||||||
|
cb(f, v)
|
||||||
|
s.run(m.Options(STACK, s))
|
||||||
|
return value
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
func (s *Stack) expr(m *ice.Message, pos Position) string {
|
func (s *Stack) cals(m *ice.Message) Any { return NewExpr(m, s).cals(m) }
|
||||||
s.Position = pos
|
func (s *Stack) expr(m *ice.Message, pos ...Position) string {
|
||||||
return m.Cmdx(EXPR)
|
kit.If(len(pos) > 0, func() { s.Position = pos[0] })
|
||||||
|
return m.Cmdx(EXPR, kit.Slice(s.rest, s.skip))
|
||||||
}
|
}
|
||||||
func NewStack() *Stack { return &Stack{} }
|
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) 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)
|
||||||
|
kit.If(cb != nil, func() { cb(s.peekf()) })
|
||||||
|
s.run(m)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
func NewStack() *Stack { return &Stack{} }
|
||||||
|
|
||||||
func _parse_stack(m *ice.Message) *Stack { return m.Optionv(STACK).(*Stack) }
|
func _parse_stack(m *ice.Message) *Stack { return m.Optionv(STACK).(*Stack) }
|
||||||
func _parse_frame(m *ice.Message) (*Stack, *Frame) {
|
func _parse_frame(m *ice.Message) (*Stack, *Frame) {
|
||||||
return _parse_stack(m), _parse_stack(m).pushf(m, "")
|
return _parse_stack(m), _parse_stack(m).pushf(m, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
PWD = "pwd"
|
|
||||||
CMD = "cmd"
|
|
||||||
LET = "let"
|
|
||||||
IF = "if"
|
|
||||||
FOR = "for"
|
|
||||||
FUNC = "func"
|
|
||||||
CALL = "call"
|
|
||||||
RETURN = "return"
|
|
||||||
EXPR = "expr"
|
|
||||||
)
|
|
||||||
const STACK = "stack"
|
const STACK = "stack"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Index.MergeCommands(ice.Commands{
|
Index.MergeCommands(ice.Commands{
|
||||||
PWD: {Name: "pwd", Hand: func(m *ice.Message, arg ...string) {
|
STACK: {Name: "stack path auto parse", Actions: ice.Actions{
|
||||||
s := _parse_stack(m)
|
ice.CMD: {Hand: func(m *ice.Message, arg ...string) {
|
||||||
res := []string{kit.Format("%d:%d", s.line, s.skip)}
|
nfs.Open(m, existsFile(m, arg[0]), func(r io.Reader, p string) {
|
||||||
s.stack(func(f *Frame, i int) {
|
meta := kit.Dict()
|
||||||
kit.If(i > 0, func() {
|
kit.For(NewStack().parse(m.Spawn(), p, r, nil).peekf().value, func(k string, v Any) {
|
||||||
res = append(res, kit.Format("%d:%d %s %v", f.line, f.skip, f.key, kit.Select(ice.FALSE, ice.TRUE, f.status > DISABLE)))
|
switch v := v.(type) {
|
||||||
|
case Function:
|
||||||
|
list := kit.List()
|
||||||
|
kit.For(v.arg, func(k string) {
|
||||||
|
switch k {
|
||||||
|
case "m", ice.ARG:
|
||||||
|
default:
|
||||||
|
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))
|
||||||
})
|
})
|
||||||
})
|
}},
|
||||||
m.Echo(strings.Join(res, " / ")).Echo(ice.NL)
|
ice.RUN: {Hand: func(m *ice.Message, arg ...string) {
|
||||||
}},
|
nfs.Open(m, existsFile(m, arg[0]), func(r io.Reader, p string) {
|
||||||
CMD: {Name: "cmd", Hand: func(m *ice.Message, arg ...string) {
|
s := NewStack().parse(m.Spawn(), p, r, nil)
|
||||||
s := _parse_stack(m)
|
action := mdb.LIST
|
||||||
kit.If(s.runable(m), func() {
|
if len(arg) > 2 && arg[1] == ice.ACTION && s.value(m, arg[2]) != nil {
|
||||||
m.Cmdy(s.rest[s.skip+1:])
|
action, arg = arg[2], arg[3:]
|
||||||
m.EchoLine("")
|
} else {
|
||||||
})
|
arg = arg[1:]
|
||||||
s.skip = len(s.rest)
|
}
|
||||||
}},
|
i := 0
|
||||||
LET: {Name: "let a, b = 1, 2", Hand: func(m *ice.Message, arg ...string) { m.Cmd(EXPR) }},
|
s.call(m, s.value(m, action), func(f *Frame, v Function) {
|
||||||
IF: {Name: "if a = 1; a > 1 {", Hand: func(m *ice.Message, arg ...string) {
|
kit.For(v.arg, func(k string) {
|
||||||
s, f := _parse_frame(m)
|
switch k {
|
||||||
res := m.Cmdx(EXPR)
|
case "m":
|
||||||
kit.If(s.token(m) == SPLIT, func() { res = m.Cmdx(EXPR) })
|
f.value[k] = Message{m}
|
||||||
kit.If(res == ice.FALSE, func() { f.status = DISABLE })
|
case ice.ARG:
|
||||||
}},
|
list := kit.List()
|
||||||
FOR: {Name: "for a = 1; a < 10; a++ {", Hand: func(m *ice.Message, arg ...string) {
|
kit.For(arg, func(v string) { list = append(list, String{v}) })
|
||||||
s, f := _parse_frame(m)
|
f.value[k] = Value{list}
|
||||||
list, status := []Position{s.Position}, f.status
|
default:
|
||||||
for f.status = DISABLE; s.token(m) != BEGIN; {
|
f.value[k] = String{m.Option(k, kit.Select(m.Option(k), arg, i))}
|
||||||
m.Cmd(EXPR)
|
i++
|
||||||
list = append(list, s.Position)
|
}
|
||||||
}
|
})
|
||||||
f.status = status
|
})
|
||||||
res := ice.TRUE
|
})
|
||||||
if len(list) < 3 {
|
}},
|
||||||
res = s.expr(m, list[0])
|
}, Hand: func(m *ice.Message, arg ...string) {
|
||||||
} else {
|
|
||||||
if s.last == nil || s.last.line != s.line {
|
|
||||||
res = s.expr(m, list[0])
|
|
||||||
} else {
|
|
||||||
kit.For(s.last.value, func(k string, v ice.Any) { f.value[k] = v })
|
|
||||||
}
|
|
||||||
res = s.expr(m, list[1])
|
|
||||||
}
|
|
||||||
kit.If(res == ice.FALSE, func() { f.status = DISABLE })
|
|
||||||
s.Position, f.pop = list[len(list)-1], func() {
|
|
||||||
if s.runable(m) {
|
|
||||||
kit.If(len(list) > 3, func() { s.expr(m, list[2]) })
|
|
||||||
s.Position = list[0]
|
|
||||||
s.Position.skip--
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}},
|
|
||||||
FUNC: {Name: "func show(a, b) (c, d)", Hand: func(m *ice.Message, arg ...string) {
|
|
||||||
s := _parse_stack(m)
|
|
||||||
list, key, kind := [][]string{[]string{}}, "", ""
|
|
||||||
push := func() { kit.If(key, func() { list[len(list)-1], key, kind = append(list[len(list)-1], key), "", "" }) }
|
|
||||||
s.reads(m, func(i int, k string) bool {
|
|
||||||
switch k {
|
|
||||||
case OPEN:
|
|
||||||
defer kit.If(i > 0, func() { list = append(list, []string{}) })
|
|
||||||
case FIELD, CLOSE:
|
|
||||||
case BEGIN:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
kit.If(key, func() { kind = k }, func() { key = k })
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
push()
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
kit.If(len(list) < 2, func() { list = append(list, []string{}) })
|
|
||||||
kit.If(len(list) < 3, func() { list = append(list, []string{}) })
|
|
||||||
s.value(m, kit.Select("", list[0], -1), &Func{obj: list[0], arg: list[1], res: list[2], Position: s.Position})
|
|
||||||
s.pushf(m, "").status = DISABLE
|
|
||||||
}},
|
|
||||||
CALL: {Name: "call show", Hand: func(m *ice.Message, arg ...string) {
|
|
||||||
m.Echo("%v", NewExpr(m, _parse_stack(m)).call(m, arg[0]))
|
|
||||||
}},
|
|
||||||
RETURN: {Name: "return show", Hand: func(m *ice.Message, arg ...string) {
|
|
||||||
s := _parse_stack(m)
|
|
||||||
if len(s.frame) == 1 {
|
|
||||||
close(s.input)
|
|
||||||
s.input = nil
|
|
||||||
}
|
|
||||||
f := s.peekf(m)
|
|
||||||
f.status = DISABLE
|
|
||||||
}},
|
|
||||||
STACK: {Name: "stack path auto parse", Hand: func(m *ice.Message, arg ...string) {
|
|
||||||
if m.Options(nfs.DIR_ROOT, nfs.SRC).Cmdy(nfs.CAT, arg); len(m.Result()) == 0 {
|
if m.Options(nfs.DIR_ROOT, nfs.SRC).Cmdy(nfs.CAT, arg); len(m.Result()) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
nfs.Open(m, path.Join(nfs.SRC, path.Join(arg...)), func(r io.Reader) {
|
nfs.Open(m, path.Join(nfs.SRC, path.Join(arg...)), func(r io.Reader, p string) {
|
||||||
msg := NewStack().parse(m.Spawn(), r)
|
s := NewStack().parse(m, p, r, nil)
|
||||||
if m.SetResult(); m.Option(log.DEBUG) != ice.TRUE {
|
if m.Option(ice.DEBUG) != ice.TRUE {
|
||||||
m.Copy(msg)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s := _parse_stack(msg)
|
m.EchoLine("").EchoLine("script: %s", arg[0])
|
||||||
m.EchoLine("script: %s", arg[0])
|
|
||||||
span := func(s, k, t string) string {
|
span := func(s, k, t string) string {
|
||||||
return strings.ReplaceAll(s, k, kit.Format("<span class='%s'>%s</span>", t, k))
|
return strings.ReplaceAll(s, k, kit.Format("<span class='%s'>%s</span>", t, k))
|
||||||
}
|
}
|
||||||
kit.For(s.list, func(i int, s string) {
|
kit.For(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{LET, IF, FOR, FUNC}, func(k string) { s = span(s, k, KEYWORD) })
|
||||||
kit.For([]string{"pwd", "cmd"}, func(k string) { s = span(s, k, "function") })
|
kit.For([]string{PWD, INFO, SOURCE}, func(k string) { s = span(s, k, FUNCTION) })
|
||||||
m.EchoLine("%2d: %s", i, s)
|
m.EchoLine("%2d: %s", i, s)
|
||||||
})
|
})
|
||||||
m.EchoLine("").EchoLine("output: %s", arg[0]).Copy(msg)
|
m.EchoLine("").EchoLine("stack: %s", arg[0]).Cmdy(INFO)
|
||||||
|
|
||||||
})
|
})
|
||||||
}},
|
}},
|
||||||
EXPR: {Name: "expr a = 1", Hand: func(m *ice.Message, arg ...string) {
|
|
||||||
s := _parse_stack(m)
|
|
||||||
arg = s.rest
|
|
||||||
if v := NewExpr(m, s).cals(m); !s.runable(m) {
|
|
||||||
m.Resultv(v)
|
|
||||||
} else if v != nil {
|
|
||||||
m.Echo(kit.Format(v))
|
|
||||||
} else if s.token(m) == BEGIN {
|
|
||||||
m.Echo(ice.TRUE)
|
|
||||||
}
|
|
||||||
m.Debug("expr value %v %v", m.Result(), arg)
|
|
||||||
}},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
func existsFile(m *ice.Message, p string) string {
|
||||||
const (
|
return nfs.SRC + strings.Replace(p, ice.PT, ice.PS, -1) + ice.PT + nfs.SHY
|
||||||
OPS = "(,){;}*/+-!=<>&|"
|
|
||||||
OPEN = "("
|
|
||||||
FIELD = ","
|
|
||||||
CLOSE = ")"
|
|
||||||
BEGIN = "{"
|
|
||||||
SPLIT = ";"
|
|
||||||
END = "}"
|
|
||||||
DISABLE = -1
|
|
||||||
)
|
|
||||||
|
|
||||||
var level = map[string]int{
|
|
||||||
"++": 100, "--": 100, "!": 90,
|
|
||||||
"*": 40, "/": 40, "+": 30, "-": 30,
|
|
||||||
"==": 20, "!=": 20, "<=": 20, ">=": 20, "<": 20, ">": 20, "&&": 10, "||": 10,
|
|
||||||
"=": 2, ",": 2, "(": 1, ")": 1,
|
|
||||||
}
|
}
|
||||||
|
func ExistsFile(m *ice.Message, p string) bool { return nfs.Exists(m, existsFile(m, p)) }
|
||||||
type Expr struct {
|
|
||||||
list ice.List
|
|
||||||
s *Stack
|
|
||||||
m *ice.Message
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Expr) push(v ice.Any) *Expr {
|
|
||||||
s.list = append(s.list, v)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
func (s *Expr) pop(n int) *Expr {
|
|
||||||
s.list = s.list[:len(s.list)-n]
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
func (s *Expr) get(p int) (v ice.Any) {
|
|
||||||
kit.If(0 <= p+len(s.list) && p+len(s.list) < len(s.list), func() { v = s.list[p+len(s.list)] })
|
|
||||||
kit.If(0 <= p && p < len(s.list), func() { v = s.list[p] })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
func (s *Expr) gets(p int) string { return kit.Format(s.get(p)) }
|
|
||||||
func (s *Expr) getl(p int) int { return level[s.gets(p)] }
|
|
||||||
func (s *Expr) getv(m *ice.Message, p int) (v ice.Any) {
|
|
||||||
if !s.s.runable(m) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
k := s.get(p)
|
|
||||||
if v = s.s.value(m, kit.Format(k)); v != nil {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
return k
|
|
||||||
}
|
|
||||||
func (s *Expr) setv(m *ice.Message, k string, v ice.Any) *Expr {
|
|
||||||
kit.If(s.s.runable(m), func() {
|
|
||||||
switch v := v.(type) {
|
|
||||||
case *Value:
|
|
||||||
s.s.value(m, k, v.list[0])
|
|
||||||
default:
|
|
||||||
s.s.value(m, k, v)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
func (s *Expr) ops(m *ice.Message) {
|
|
||||||
m.Debug("expr ops %v", s.list)
|
|
||||||
bin := func(v ice.Any) { s.pop(3).push(v) }
|
|
||||||
switch a, b := kit.Int(s.getv(m, -3)), kit.Int(s.getv(m, -1)); s.gets(-2) {
|
|
||||||
case "*":
|
|
||||||
bin(a * b)
|
|
||||||
case "/":
|
|
||||||
bin(a / b)
|
|
||||||
case "+":
|
|
||||||
bin(a + b)
|
|
||||||
case "-":
|
|
||||||
bin(a - b)
|
|
||||||
case ">":
|
|
||||||
bin(a > b)
|
|
||||||
case "<":
|
|
||||||
bin(a < b)
|
|
||||||
case "<=":
|
|
||||||
bin(a <= b)
|
|
||||||
case ">=":
|
|
||||||
bin(a >= b)
|
|
||||||
case "!=":
|
|
||||||
bin(a != b)
|
|
||||||
case "==":
|
|
||||||
bin(a == b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (s *Expr) end(m *ice.Message, arg ...string) ice.Any {
|
|
||||||
if s.gets(-1) == CLOSE {
|
|
||||||
s.pop(1)
|
|
||||||
}
|
|
||||||
for len(s.list) > 1 {
|
|
||||||
switch s.ops(m); s.gets(-2) {
|
|
||||||
case ",":
|
|
||||||
list := kit.List()
|
|
||||||
for i := len(s.list) - 2; i > 0; i -= 2 {
|
|
||||||
if s.list[i] == "=" {
|
|
||||||
for j := 0; j < i; j += 2 {
|
|
||||||
s.setv(m, s.gets(j), s.getv(m, j+i+1))
|
|
||||||
list = append(list, s.getv(m, j))
|
|
||||||
}
|
|
||||||
s.list = kit.List(&Value{list: list})
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(s.list) == 1 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
for i := 0; i < len(s.list); i += 2 {
|
|
||||||
list = append(list, s.getv(m, i))
|
|
||||||
}
|
|
||||||
s.list = kit.List(&Value{list: list})
|
|
||||||
case "=":
|
|
||||||
if len(s.list) == 3 {
|
|
||||||
s.setv(m, s.gets(-3), s.getv(m, -1)).pop(2)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
list := kit.List()
|
|
||||||
switch v := s.getv(m, -1).(type) {
|
|
||||||
case *Value:
|
|
||||||
for i := 0; i < len(s.list)-1; i += 2 {
|
|
||||||
if i/2 < len(v.list) {
|
|
||||||
s.setv(m, s.gets(i), v.list[i/2])
|
|
||||||
list = append(list, s.getv(m, i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.list = kit.List(&Value{list})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !s.s.runable(m) {
|
|
||||||
return arg
|
|
||||||
}
|
|
||||||
if len(s.list) > 0 {
|
|
||||||
return s.list[0]
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Expr) cals(m *ice.Message) ice.Any {
|
|
||||||
m.Debug("expr calcs %d %v", s.s.line, s.s.rest[s.s.skip:])
|
|
||||||
arg := s.s.reads(m, func(i int, k string) bool {
|
|
||||||
switch k {
|
|
||||||
case SPLIT, BEGIN:
|
|
||||||
return true
|
|
||||||
case END:
|
|
||||||
s.s.skip--
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if level[k] == 0 && len(s.list) > 0 && s.getl(-1) == 0 {
|
|
||||||
s.s.skip--
|
|
||||||
return true
|
|
||||||
} else if k == OPEN && len(s.list) > 0 && s.getl(-1) == 0 {
|
|
||||||
value := s.call(m, s.get(-1))
|
|
||||||
s.pop(1).push(value)
|
|
||||||
} else if op := s.gets(-1) + k; level[op] > 0 && s.getl(-1) > 0 {
|
|
||||||
if op == "++" {
|
|
||||||
s.setv(m, s.gets(-2), kit.Int(s.s.value(m, s.gets(-2)))+1).pop(1)
|
|
||||||
} else {
|
|
||||||
s.pop(1).push(op)
|
|
||||||
}
|
|
||||||
} else if level[k] > 0 {
|
|
||||||
for level[k] >= 9 && level[k] <= s.getl(-2) {
|
|
||||||
s.ops(m)
|
|
||||||
}
|
|
||||||
if k == CLOSE {
|
|
||||||
if s.gets(-2) == OPEN {
|
|
||||||
v := s.get(-1)
|
|
||||||
s.pop(2).push(v)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
s.push(k)
|
|
||||||
} else {
|
|
||||||
s.push(k)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
return s.end(m, arg...)
|
|
||||||
}
|
|
||||||
func (s *Expr) call(m *ice.Message, name ice.Any) (v ice.Any) {
|
|
||||||
m.Debug("call %v", name)
|
|
||||||
list := kit.List(name)
|
|
||||||
switch v = NewExpr(m, s.s).cals(m); v := v.(type) {
|
|
||||||
case *Value:
|
|
||||||
list = append(list, v.list...)
|
|
||||||
default:
|
|
||||||
list = append(list, v)
|
|
||||||
}
|
|
||||||
m.Debug("call %v", list)
|
|
||||||
switch v := s.s.value(m, kit.Format(name)).(type) {
|
|
||||||
case *Func:
|
|
||||||
f := s.s.pushf(m, "")
|
|
||||||
kit.For(v.res, func(k string) { f.value[k] = "" })
|
|
||||||
kit.For(v.arg, func(k string) { f.value[k] = "" })
|
|
||||||
kit.For(v.arg, func(i int, k string) { kit.If(i+1 < len(list), func() { f.value[k] = list[i+1] }) })
|
|
||||||
value, pos := &Value{list: kit.List()}, s.s.Position
|
|
||||||
f.pop, s.s.Position = func() {
|
|
||||||
kit.For(v.res, func(k string) { value.list = append(value.list, f.value[k]) })
|
|
||||||
s.s.Position = pos
|
|
||||||
}, v.Position
|
|
||||||
m.Debug("call %#v", f)
|
|
||||||
s.s.call(m)
|
|
||||||
m.Debug("call %#v", value)
|
|
||||||
return value
|
|
||||||
default:
|
|
||||||
if s.s.runable(m) {
|
|
||||||
return m.Cmdx(list...)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func NewExpr(m *ice.Message, s *Stack) *Expr { return &Expr{kit.List(), s, m} }
|
|
||||||
|
229
base/yac/stmt.go
Normal file
229
base/yac/stmt.go
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
package yac
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
ice "shylinux.com/x/icebergs"
|
||||||
|
"shylinux.com/x/icebergs/base/nfs"
|
||||||
|
kit "shylinux.com/x/toolkits"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LET = "let"
|
||||||
|
IF = "if"
|
||||||
|
ELSE = "else"
|
||||||
|
FOR = "for"
|
||||||
|
BREAK = "break"
|
||||||
|
CONTINUE = "continue"
|
||||||
|
SWITCH = "switch"
|
||||||
|
CASE = "case"
|
||||||
|
DEFAULT = "default"
|
||||||
|
FUNC = "func"
|
||||||
|
CALL = "call"
|
||||||
|
RETURN = "return"
|
||||||
|
SOURCE = "source"
|
||||||
|
INFO = "info"
|
||||||
|
PWD = "pwd"
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
KEYWORD = "keyword"
|
||||||
|
FUNCTION = "function"
|
||||||
|
)
|
||||||
|
|
||||||
|
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 })
|
||||||
|
}},
|
||||||
|
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 {
|
||||||
|
f.status = 0
|
||||||
|
} else {
|
||||||
|
f.status, f.pop = 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 })
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}},
|
||||||
|
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) {
|
||||||
|
s.expr(m)
|
||||||
|
}
|
||||||
|
f.status = status
|
||||||
|
res := ice.TRUE
|
||||||
|
if len(list) == 1 {
|
||||||
|
|
||||||
|
} else if len(list) == 2 {
|
||||||
|
res = s.expr(m, list[0])
|
||||||
|
} else {
|
||||||
|
if s.last == nil || s.last.line != s.line {
|
||||||
|
res = s.expr(m, list[0])
|
||||||
|
} else {
|
||||||
|
kit.For(s.last.value, func(k string, v Any) { f.value[k] = v })
|
||||||
|
}
|
||||||
|
res = s.expr(m, list[1])
|
||||||
|
}
|
||||||
|
kit.If(res == ice.FALSE, func() { f.status = DISABLE })
|
||||||
|
s.Position, f.pop = list[len(list)-1], func() {
|
||||||
|
if s.runable() {
|
||||||
|
kit.If(len(list) > 3, func() { s.expr(m, list[2]) })
|
||||||
|
s.Position = list[0]
|
||||||
|
s.Position.skip--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
BREAK: {Name: "break", Hand: func(m *ice.Message, arg ...string) {
|
||||||
|
s := _parse_stack(m)
|
||||||
|
if !s.runable() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.stack(func(f *Frame, i int) bool {
|
||||||
|
f.status = DISABLE
|
||||||
|
defer s.popf(m)
|
||||||
|
switch f.key {
|
||||||
|
case FOR:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}},
|
||||||
|
CONTINUE: {Name: "continue", Hand: func(m *ice.Message, arg ...string) {
|
||||||
|
s := _parse_stack(m)
|
||||||
|
if !s.runable() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.stack(func(f *Frame, i int) bool {
|
||||||
|
defer s.popf(m)
|
||||||
|
switch f.key {
|
||||||
|
case FOR:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}},
|
||||||
|
SWITCH: {Name: "switch a = 1; a {", Hand: func(m *ice.Message, arg ...string) {
|
||||||
|
s, f := _parse_frame(m)
|
||||||
|
res := s.cals(m)
|
||||||
|
kit.If(s.token() == SPLIT, func() { res = s.cals(m) })
|
||||||
|
f.value["_switch"], f.value["_case"] = res, ""
|
||||||
|
}},
|
||||||
|
CASE: {Name: "case b:", Hand: func(m *ice.Message, arg ...string) {
|
||||||
|
s := _parse_stack(m)
|
||||||
|
f := s.peekf()
|
||||||
|
f.status = 0
|
||||||
|
v := s.cals(m)
|
||||||
|
f.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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
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" {
|
||||||
|
f.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), "", "" }) }
|
||||||
|
s.reads(m, func(k string) bool {
|
||||||
|
switch k {
|
||||||
|
case OPEN:
|
||||||
|
defer kit.If(key != "" || len(list) > 1, func() { list = append(list, []string{}) })
|
||||||
|
case FIELD, CLOSE:
|
||||||
|
case BEGIN:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
kit.If(key, func() { kind = k }, func() { key = k })
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
push()
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
kit.If(len(list) < 2, func() { list = append(list, []string{}) })
|
||||||
|
kit.If(len(list) < 3, func() { list = append(list, []string{}) })
|
||||||
|
s.value(m, kit.Select("", list[0], -1), Function{obj: list[0], arg: list[1], res: list[2], Position: s.Position})
|
||||||
|
s.pushf(m, "").status = DISABLE
|
||||||
|
}},
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.stack(func(f *Frame, i int) bool {
|
||||||
|
f.status = DISABLE
|
||||||
|
switch f.key {
|
||||||
|
case FUNC:
|
||||||
|
|
||||||
|
case CALL:
|
||||||
|
|
||||||
|
case STACK:
|
||||||
|
s.input = nil
|
||||||
|
case SOURCE:
|
||||||
|
s.input = nil
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}},
|
||||||
|
SOURCE: {Name: "source", Hand: func(m *ice.Message, arg ...string) {
|
||||||
|
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.skip = len(s.rest)
|
||||||
|
})
|
||||||
|
}},
|
||||||
|
INFO: {Name: "info", Hand: func(m *ice.Message, arg ...string) {
|
||||||
|
_parse_stack(m).stack(func(f *Frame, i int) bool {
|
||||||
|
m.EchoLine("frame: %s %v:%v:%v", f.key, f.Position.name, f.Position.line, f.Position.skip)
|
||||||
|
kit.For(f.value, func(k string, v Any) {
|
||||||
|
m.EchoLine(" %s: %#v", k, v)
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
}},
|
||||||
|
PWD: {Name: "pwd", Hand: func(m *ice.Message, arg ...string) {
|
||||||
|
s := _parse_stack(m)
|
||||||
|
res := []string{kit.Format("%d:%d", s.line, s.skip)}
|
||||||
|
s.stack(func(f *Frame, i int) 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)))
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
m.Echo(strings.Join(res, " / ")).Echo(ice.NL)
|
||||||
|
}},
|
||||||
|
})
|
||||||
|
}
|
175
base/yac/value.go
Normal file
175
base/yac/value.go
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
package yac
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
ice "shylinux.com/x/icebergs"
|
||||||
|
kit "shylinux.com/x/toolkits"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Any = ice.Any
|
||||||
|
type Dict struct{ value map[string]Any }
|
||||||
|
type List struct{ value []Any }
|
||||||
|
type Value struct{ list []Any }
|
||||||
|
type String struct{ value string }
|
||||||
|
type Number struct{ value string }
|
||||||
|
type Boolean struct{ value bool }
|
||||||
|
type Caller interface{ Call(string, ...Any) Any }
|
||||||
|
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) }
|
||||||
|
|
||||||
|
func wrap(v Any) Any {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case string:
|
||||||
|
return String{v}
|
||||||
|
default:
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func trans(v Any) Any {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case Dict:
|
||||||
|
return v.value
|
||||||
|
case List:
|
||||||
|
return v.value
|
||||||
|
case Value:
|
||||||
|
if len(v.list) > 0 {
|
||||||
|
return v.list[0]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
case String:
|
||||||
|
return v.value
|
||||||
|
case Number:
|
||||||
|
return v.value
|
||||||
|
case Boolean:
|
||||||
|
return v.value
|
||||||
|
default:
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (s Dict) Operate(op string, v Any) Any {
|
||||||
|
switch op {
|
||||||
|
case SUBS:
|
||||||
|
return wrap(kit.Value(s.value, kit.Format(v)))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (s List) Operate(op string, v Any) Any {
|
||||||
|
switch op {
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (s String) Operate(op string, v Any) Any {
|
||||||
|
switch a, b := s.value, kit.Format(v); op {
|
||||||
|
case "+":
|
||||||
|
return String{a + b}
|
||||||
|
case "-":
|
||||||
|
return String{strings.Replace(a, b, "", -1)}
|
||||||
|
case "<":
|
||||||
|
return Boolean{a < b}
|
||||||
|
case ">":
|
||||||
|
return Boolean{a > b}
|
||||||
|
case ">=":
|
||||||
|
return Boolean{a >= b}
|
||||||
|
case "<=":
|
||||||
|
return Boolean{a <= b}
|
||||||
|
case "!=":
|
||||||
|
return Boolean{a != b}
|
||||||
|
case "==":
|
||||||
|
return Boolean{a == b}
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 * b)}
|
||||||
|
case "/":
|
||||||
|
return Number{kit.Format(a / b)}
|
||||||
|
case "+":
|
||||||
|
return Number{kit.Format(a + b)}
|
||||||
|
case "-":
|
||||||
|
return Number{kit.Format(a - b)}
|
||||||
|
case "<":
|
||||||
|
return Boolean{a < b}
|
||||||
|
case ">":
|
||||||
|
return Boolean{a > b}
|
||||||
|
case ">=":
|
||||||
|
return Boolean{a >= b}
|
||||||
|
case "<=":
|
||||||
|
return Boolean{a <= b}
|
||||||
|
case "!=":
|
||||||
|
return Boolean{a != b}
|
||||||
|
case "==":
|
||||||
|
return Boolean{a == b}
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (s Boolean) Operate(op string, v Any) Any {
|
||||||
|
switch a, b := s.value, !kit.IsIn(kit.Format(v), "", "0", ice.FALSE); op {
|
||||||
|
case "&&":
|
||||||
|
return Boolean{a && b}
|
||||||
|
case "||":
|
||||||
|
return Boolean{a || b}
|
||||||
|
case "!":
|
||||||
|
return Boolean{!a}
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Message struct{ *ice.Message }
|
||||||
|
|
||||||
|
func (m Message) Call(cmd string, arg ...Any) Any {
|
||||||
|
str := func(v Any) string { return kit.Format(trans(v)) }
|
||||||
|
args := []Any{}
|
||||||
|
for _, v := range arg {
|
||||||
|
args = append(args, trans(v))
|
||||||
|
}
|
||||||
|
switch cmd {
|
||||||
|
case "Option":
|
||||||
|
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":
|
||||||
|
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 "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)}) })
|
||||||
|
return value
|
||||||
|
default:
|
||||||
|
m.ErrorNotImplement(cmd)
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
@ -20,7 +20,8 @@ func init() {
|
|||||||
SHY: {Name: "shy path auto", Help: "笔记", Actions: ice.MergeActions(ice.Actions{
|
SHY: {Name: "shy path auto", Help: "笔记", Actions: ice.MergeActions(ice.Actions{
|
||||||
mdb.RENDER: {Hand: func(m *ice.Message, arg ...string) {
|
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, web.WIKI_WORD, kit.Simple(path.Join(arg[2], arg[1])))
|
||||||
ctx.ProcessCommand(m, yac.STACK, kit.Simple(arg[1]))
|
// ctx.ProcessCommand(m, yac.STACK, kit.Simple(arg[1]))
|
||||||
|
ctx.ProcessCommand(m, kit.TrimExt(arg[1], SHY), kit.Simple())
|
||||||
}},
|
}},
|
||||||
mdb.ENGINE: {Hand: func(m *ice.Message, arg ...string) {
|
mdb.ENGINE: {Hand: func(m *ice.Message, arg ...string) {
|
||||||
ctx.ProcessCommand(m, yac.STACK, kit.Simple(arg[1]))
|
ctx.ProcessCommand(m, yac.STACK, kit.Simple(arg[1]))
|
||||||
|
2
go.mod
2
go.mod
@ -5,6 +5,8 @@ go 1.11
|
|||||||
require (
|
require (
|
||||||
shylinux.com/x/creackpty v0.0.2
|
shylinux.com/x/creackpty v0.0.2
|
||||||
shylinux.com/x/go-qrcode v0.0.2
|
shylinux.com/x/go-qrcode v0.0.2
|
||||||
|
shylinux.com/x/gogit v0.0.7
|
||||||
|
shylinux.com/x/ice v1.3.0
|
||||||
shylinux.com/x/toolkits v0.7.4
|
shylinux.com/x/toolkits v0.7.4
|
||||||
shylinux.com/x/websocket v0.0.2
|
shylinux.com/x/websocket v0.0.2
|
||||||
)
|
)
|
||||||
|
5
go.sum
5
go.sum
@ -2,6 +2,11 @@ shylinux.com/x/creackpty v0.0.2 h1:1ekWD5zeKZiQZCYvKSkHnm819wryZxzoq3kmvheC7bA=
|
|||||||
shylinux.com/x/creackpty v0.0.2/go.mod h1:SOsAaW5FdicXUprrxgENk2JP1f8LdHBXZjqOFot488o=
|
shylinux.com/x/creackpty v0.0.2/go.mod h1:SOsAaW5FdicXUprrxgENk2JP1f8LdHBXZjqOFot488o=
|
||||||
shylinux.com/x/go-qrcode v0.0.2 h1:/c0PLj+1RT+kUPfnZVXwgbgH5m1SxBUjM2MIKXbDk+E=
|
shylinux.com/x/go-qrcode v0.0.2 h1:/c0PLj+1RT+kUPfnZVXwgbgH5m1SxBUjM2MIKXbDk+E=
|
||||||
shylinux.com/x/go-qrcode v0.0.2/go.mod h1:TlzGBENHXy19xC3AsC6h4Vs5fx2ZuDA4TZ0U3C2OeK4=
|
shylinux.com/x/go-qrcode v0.0.2/go.mod h1:TlzGBENHXy19xC3AsC6h4Vs5fx2ZuDA4TZ0U3C2OeK4=
|
||||||
|
shylinux.com/x/gogit v0.0.7 h1:2ep5QpXWLs0UBCywJuUHda/aagskYvFmn0nj3vpEdY4=
|
||||||
|
shylinux.com/x/gogit v0.0.7/go.mod h1:wYfHxpQT1C8yNV+yC1jStIy0I12bfUCyJARhn0sNn1M=
|
||||||
|
shylinux.com/x/ice v1.3.0 h1:Ro0DpT/qeFPer8R3it9+dptCFprx3/416cJWT3bceWE=
|
||||||
|
shylinux.com/x/ice v1.3.0/go.mod h1:sgSlRKoEKnZbmHZ8QuQ3VrFOlW/imi12GX2Z9drkngY=
|
||||||
|
shylinux.com/x/icebergs v1.5.4/go.mod h1:njja7CnbJD39p4OGDvIxmh7p8206nAlDiAiTh34CNiw=
|
||||||
shylinux.com/x/toolkits v0.7.4 h1:PACWkhi/Iv8I+DWUq5y5Uq/Yty58EpyAUeBtDfe6a5g=
|
shylinux.com/x/toolkits v0.7.4 h1:PACWkhi/Iv8I+DWUq5y5Uq/Yty58EpyAUeBtDfe6a5g=
|
||||||
shylinux.com/x/toolkits v0.7.4/go.mod h1:8LbYHe7oxBIqb6s4MSOD+4d28QvPdvkyCVtwB/JW7AA=
|
shylinux.com/x/toolkits v0.7.4/go.mod h1:8LbYHe7oxBIqb6s4MSOD+4d28QvPdvkyCVtwB/JW7AA=
|
||||||
shylinux.com/x/websocket v0.0.2 h1:aeeZyAsh6QN7+l5oMXlO9/rlQgx6CHvDtpZyAqMCSlU=
|
shylinux.com/x/websocket v0.0.2 h1:aeeZyAsh6QN7+l5oMXlO9/rlQgx6CHvDtpZyAqMCSlU=
|
||||||
|
15
meta.go
15
meta.go
@ -156,10 +156,25 @@ func (m *Message) Push(key string, value Any, arg ...Any) *Message {
|
|||||||
func (m *Message) EchoLine(str string, arg ...Any) *Message {
|
func (m *Message) EchoLine(str string, arg ...Any) *Message {
|
||||||
return m.Echo(str, arg...).Echo(NL)
|
return m.Echo(str, arg...).Echo(NL)
|
||||||
}
|
}
|
||||||
|
func PushNotice(m *Message, arg ...Any) bool {
|
||||||
|
if m.Option(MSG_DAEMON) == "" {
|
||||||
|
return false
|
||||||
|
} else if m.Option(MSG_USERPOD) == "" {
|
||||||
|
m.Cmd("web.space", m.Option(MSG_DAEMON), arg, Maps{MSG_OPTION: "", MSG_OPTS: ""})
|
||||||
|
} else {
|
||||||
|
// m.Cmd("web.spide", OPS, MergeURL2(m, "/share/toast/"+m.Option(MSG_DAEMON)), ARG, kit.Format(arg))
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
func (m *Message) Echo(str string, arg ...Any) *Message {
|
func (m *Message) Echo(str string, arg ...Any) *Message {
|
||||||
if str == "" {
|
if str == "" {
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
// if m.Option("output.stream") == "grow" {
|
||||||
|
// if PushNotice(m, "grow", kit.Format(str, arg...)) {
|
||||||
|
// return m
|
||||||
|
// }
|
||||||
|
// }
|
||||||
return m.Add(MSG_RESULT, kit.Format(str, arg...))
|
return m.Add(MSG_RESULT, kit.Format(str, arg...))
|
||||||
}
|
}
|
||||||
func (m *Message) Copy(msg *Message, arg ...string) *Message {
|
func (m *Message) Copy(msg *Message, arg ...string) *Message {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user