-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathchannel.go
149 lines (137 loc) · 3.81 KB
/
channel.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package gisp
import (
"reflect"
px "github.com/Dwarfartisan/goparsec/parsex"
)
// Chan 封装 golang 的 channel 功能
type Chan struct {
Type reflect.Type
Dir reflect.ChanDir
value reflect.Value
}
// MakeChan 实现 chan 的构造
func MakeChan(typ reflect.Type, dir reflect.ChanDir, buf Int) *Chan {
return &Chan{typ, dir, reflect.MakeChan(typ, int(buf))}
}
// MakeRecvChan 实现一个单向的 recv chan
func MakeRecvChan(typ reflect.Type, buf Int) *Chan {
return MakeChan(typ, reflect.RecvDir, buf)
}
// MakeSendChan 实现一个单向的 Send chan
func MakeSendChan(typ reflect.Type, buf Int) *Chan {
return MakeChan(typ, reflect.SendDir, buf)
}
// MakeBothChan 构造一个双向 chan
func MakeBothChan(typ reflect.Type, buf Int) *Chan {
return MakeChan(typ, reflect.BothDir, buf)
}
// Send 方法实现 chan x <- v
func (ch *Chan) Send(x interface{}) {
ch.value.Send(reflect.ValueOf(x))
}
// Recv 方法实现 v <- chan x
func (ch *Chan) Recv() (x interface{}, ok bool) {
val, ok := ch.value.Recv()
if val.IsValid() {
return val.Interface(), ok
}
return nil, ok
}
// TrySend 实现试写入(带状态返回)
func (ch *Chan) TrySend(x interface{}) {
ch.value.TrySend(reflect.ValueOf(x))
}
// TryRecv 实现试接收(带状态返回)
func (ch *Chan) TryRecv() (x interface{}, ok bool) {
val, ok := ch.value.TryRecv()
if val.IsValid() {
return val.Interface(), ok
}
return nil, ok
}
var channel = Toolkit{
Meta: map[string]interface{}{
"category": "toolkit",
"name": "channel",
},
Content: map[string]interface{}{
"chan": SimpleBox{
ParsexSignChecker(px.Binds_(
TypeAs(reflect.TypeOf((*reflect.Type)(nil)).Elem()),
TypeAs(INT),
px.Eof)),
func(args ...interface{}) Tasker {
return func(env Env) (interface{}, error) {
return MakeBothChan(args[0].(reflect.Type), args[1].(Int)), nil
}
}},
"chan->": SimpleBox{
ParsexSignChecker(px.Binds_(
TypeAs(reflect.TypeOf((*reflect.Type)(nil)).Elem()),
TypeAs(INT),
px.Eof)),
func(args ...interface{}) Tasker {
return func(env Env) (interface{}, error) {
return MakeRecvChan(args[0].(reflect.Type), args[1].(Int)), nil
}
}},
"chan<-": SimpleBox{
ParsexSignChecker(px.Binds_(
TypeAs(reflect.TypeOf((*reflect.Type)(nil)).Elem()),
TypeAs(INT),
px.Eof)),
func(args ...interface{}) Tasker {
return func(env Env) (interface{}, error) {
return MakeSendChan(args[0].(reflect.Type), args[1].(Int)), nil
}
}},
"send": SimpleBox{
ParsexSignChecker(px.Binds_(
TypeAs(reflect.TypeOf((*Chan)(nil))),
px.Either(px.Try(TypeAs(ANYOPTION)), TypeAs(ANYMUST)),
px.Eof)),
func(args ...interface{}) Tasker {
return func(env Env) (interface{}, error) {
ch := args[0].(*Chan)
ch.Send(args[1])
return nil, nil
}
}},
"send?": SimpleBox{
ParsexSignChecker(px.Binds_(
TypeAs(reflect.TypeOf((*Chan)(nil))),
px.Either(px.Try(TypeAs(ANYOPTION)), TypeAs(ANYMUST)),
px.Eof)),
func(args ...interface{}) Tasker {
return func(env Env) (interface{}, error) {
ch := args[0].(*Chan)
ch.TrySend(args[1])
return nil, nil
}
}},
"recv": SimpleBox{
ParsexSignChecker(px.Binds_(
TypeAs(reflect.TypeOf((*Chan)(nil))),
px.Either(px.Try(TypeAs(ANYOPTION)), TypeAs(ANYMUST)),
px.Eof)),
func(args ...interface{}) Tasker {
return func(env Env) (interface{}, error) {
ch := args[0].(*Chan)
data, ok := ch.Recv()
return List{data, ok}, nil
}
}},
"recv?": SimpleBox{
ParsexSignChecker(px.Binds_(
TypeAs(reflect.TypeOf((*Chan)(nil))),
px.Either(px.Try(TypeAs(ANYOPTION)), TypeAs(ANYMUST)),
px.Eof)),
func(args ...interface{}) Tasker {
return func(env Env) (interface{}, error) {
ch := args[0].(*Chan)
data, ok := ch.TryRecv()
return List{data, ok}, nil
}
}},
},
}