1/* 2 * gomacro - A Go interpreter with Lisp-like macros 3 * 4 * Copyright (C) 2017-2019 Massimiliano Ghilardi 5 * 6 * This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * 11 * channel.go 12 * 13 * Created on May 01, 2017 14 * Author Massimiliano Ghilardi 15 */ 16 17package fast 18 19:import ( 20 "go/ast" 21 r "reflect" 22) 23 24import ( 25 "go/ast" 26 r "reflect" 27 28 . "github.com/cosmos72/gomacro/base" 29 "github.com/cosmos72/gomacro/base/reflect" 30 xr "github.com/cosmos72/gomacro/xreflect" 31) 32 33 34:func upcasefirstbyte(str string) string { 35 if len(str) > 0 && str[0] >= 'a' && str[0] <= 'z' { 36 bytes := []byte(str) 37 bytes[0] -= 'a' - 'A' 38 return string(bytes) 39 } 40 return str 41} 42 43:func makekind(typ ast.Node) ast.Node { 44 t := EvalType(typ) 45 if t == nil { 46 return nil 47 } 48 // go/ast.SelectorExpr requires the foo in r.foo to be an *ast.Ident, cannot unquote there 49 kind := ~"{r . foo} 50 kind.Sel = &ast.Ident{Name: upcasefirstbyte(t.Name())} 51 return kind 52} 53 54:func maketypevar(typ ast.Node) ast.Node { 55 t := EvalType(typ) 56 sel := &ast.SelectorExpr{ 57 X: &ast.Ident{Name: "c"}, 58 Sel: &ast.Ident{Name: "TypeOf" + upcasefirstbyte(t.Name())}, 59 } 60 return ~"{~,sel ()} 61} 62 63 64:func convertvalue(typ, val ast.Node) (ast.Node, ast.Node) { 65 var t r.Type = EvalType(typ) 66 if t == nil { 67 // keep the result wrapped in a reflect.Value 68 typ = ~'{r.Value} 69 } else { 70 // unwrap the result 71 tname := t.Name() 72 // remove final digits from t.Name() 73 // needed to convert Uint64 -> Uint etc. to calls reflect.Value.{tname} 74 for len(tname) != 0 { 75 ch := tname[len(tname)-1] 76 if ch < '0' || ch > '9' { 77 break 78 } 79 tname = tname[0:len(tname)-1] 80 } 81 if tname == "uintptr" { 82 tname = "uint" // use reflect.Value.Uint() 83 } 84 sel := ~"{~,val . foo} // we modify it destructively 85 sel.Sel = &ast.Ident{Name: upcasefirstbyte(tname)} 86 87 switch t.Kind() { 88 case r.Bool, r.Int64, r.Uint64, r.Float64, r.Complex128, r.String: 89 // result of reflect.Value.{tname} is already the correct type 90 val = ~"{~,sel ()} 91 default: 92 // convert int64, uint64... to the correct type 93 val = ~"{~,typ ( ~,sel () )} 94 } 95 } 96 return typ, val 97} 98 99// Recv compiles <-channel (returns two values: the received value and an 'ok' flag) 100func (c *Comp) Recv(node *ast.UnaryExpr, xe *Expr) *Expr { 101 t := xe.Type 102 if t.Kind() != r.Chan { 103 return c.badUnaryExpr("expecting channel, found", node, xe) 104 } 105 if t.ChanDir()&r.RecvDir == 0 { 106 return c.badUnaryExpr("cannot receive from send-only channel", node, xe) 107 } 108 var fun func(env *Env) (r.Value, []r.Value) 109 switch x := xe.Fun.(type) { 110 case func(env *Env) (r.Value, []r.Value): 111 channelfun := x 112 fun = func(env *Env) (r.Value, []r.Value) { 113 channel, _ := channelfun(env) 114 retv, ok := channel.Recv() 115 var okv r.Value 116 if ok { 117 okv = True 118 } else { 119 okv = False 120 } 121 return retv, []r.Value{retv, okv} 122 } 123 default: 124 channelfun := xe.AsX1() 125 fun = func(env *Env) (r.Value, []r.Value) { 126 retv, ok := channelfun(env).Recv() 127 var okv r.Value 128 if ok { 129 okv = True 130 } else { 131 okv = False 132 } 133 return retv, []r.Value{retv, okv} 134 } 135 } 136 types := []xr.Type{t.Elem(), c.TypeOfBool()} 137 return exprXV(types, fun) 138} 139 140:macro recv1_xv(typ ast.Node) ast.Node { 141 if EvalType(typ) == nil { 142 return ~"{ 143 default: 144 fun = func(env *Env) r.Value { 145 channel, _ := channelfun(env) 146 retv, _ := channel.Recv() 147 return retv 148 } 149 } 150 } 151 kind := makekind(typ) 152 typ2, ret := convertvalue(typ, ~'retv) 153 return ~"{ 154 case ~,kind: 155 fun = func(env *Env) ~,typ2 { 156 channel, _ := channelfun(env) 157 retv, _ := channel.Recv() 158 return ~,ret 159 } 160 } 161} 162 163:macro recv1(typ ast.Node) ast.Node { 164 if EvalType(typ) == nil { 165 return ~"{ 166 default: 167 fun = func(env *Env) r.Value { 168 retv, _ := channelfun(env).Recv() 169 return retv 170 } 171 } 172 } 173 kind := makekind(typ) 174 typ2, ret := convertvalue(typ, ~'retv) 175 return ~"{ 176 case ~,kind: 177 if telem.ReflectType() != reflect.KindToType(~,kind) { 178 fun = func(env *Env) ~,typ { 179 retv, _ := channelfun(env).Recv() 180 return ~,ret 181 } 182 } else if recvonly { 183 fun = func(env *Env) ~,typ { 184 channel := channelfun(env).Interface().(<-chan ~,typ) 185 return <-channel 186 } 187 } else { 188 fun = func(env *Env) ~,typ { 189 channel := channelfun(env).Interface().(chan ~,typ) 190 return <-channel 191 } 192 } 193 } 194} 195 196// Recv1 compiles <-channel (returns a single value: the received value) 197// mandatory optimization: fast_interpreter ASSUMES that expressions 198// returning bool, int, uint, float, complex, string do NOT wrap them in reflect.Value 199func (c *Comp) Recv1(node *ast.UnaryExpr, xe *Expr) *Expr { 200 t := xe.Type 201 if t.Kind() != r.Chan { 202 return c.badUnaryExpr("expecting channel, found", node, xe) 203 } 204 if t.ChanDir()&r.RecvDir == 0 { 205 return c.badUnaryExpr("cannot receive from send-only channel", node, xe) 206 } 207 telem := t.Elem() 208 var fun I 209 switch x := xe.Fun.(type) { 210 case func(env *Env) (r.Value, []r.Value): 211 channelfun := x 212 switch telem.Kind() { 213 {recv1_xv; bool} 214 {recv1_xv; int} 215 {recv1_xv; int8} 216 {recv1_xv; int16} 217 {recv1_xv; int32} 218 {recv1_xv; int64} 219 {recv1_xv; uint} 220 {recv1_xv; uint8} 221 {recv1_xv; uint16} 222 {recv1_xv; uint32} 223 {recv1_xv; uint64} 224 {recv1_xv; uintptr} 225 {recv1_xv; float32} 226 {recv1_xv; float64} 227 {recv1_xv; complex64} 228 {recv1_xv; complex128} 229 {recv1_xv; string} 230 {recv1_xv; nil} 231 } 232 default: 233 recvonly := t.ChanDir() == r.RecvDir 234 channelfun := xe.AsX1() 235 switch telem.Kind() { 236 {recv1; bool} 237 {recv1; int} 238 {recv1; int8} 239 {recv1; int16} 240 {recv1; int32} 241 {recv1; int64} 242 {recv1; uint} 243 {recv1; uint8} 244 {recv1; uint16} 245 {recv1; uint32} 246 {recv1; uint64} 247 {recv1; uintptr} 248 {recv1; float32} 249 {recv1; float64} 250 {recv1; complex64} 251 {recv1; complex128} 252 {recv1; string} 253 {recv1; nil} 254 } 255 } 256 return exprFun(telem, fun) 257} 258 259:macro send_c(typ ast.Node) ast.Node { 260 kind := makekind(typ) 261 typ2, conv := convertvalue(typ, ~'v) 262 return ~"{ 263 case ~,kind: 264 value := ~,conv 265 if sendonly { 266 stmt = func(env *Env) (Stmt, *Env) { 267 channel := channelfun(env).Interface().(chan<- ~,typ) 268 channel <- value 269 env.IP++ 270 return env.Code[env.IP], env 271 } 272 } else { 273 stmt = func(env *Env) (Stmt, *Env) { 274 channel := channelfun(env).Interface().(chan ~,typ) 275 channel <- value 276 env.IP++ 277 return env.Code[env.IP], env 278 } 279 } 280 } 281} 282 283:macro send_e(typ ast.Node) ast.Node { 284 kind := makekind(typ) 285 return ~"{ 286 case ~,kind: 287 if exprfun, ok := expr.Fun.(func (*Env) ~,typ); !ok { 288 break 289 } else if sendonly { 290 stmt = func(env *Env) (Stmt, *Env) { 291 channel := channelfun(env).Interface().(chan<- ~,typ) 292 channel <- exprfun(env) 293 env.IP++ 294 return env.Code[env.IP], env 295 } 296 } else { 297 stmt = func(env *Env) (Stmt, *Env) { 298 channel := channelfun(env).Interface().(chan ~,typ) 299 channel <- exprfun(env) 300 env.IP++ 301 return env.Code[env.IP], env 302 } 303 } 304 } 305} 306 307func (c *Comp) Send(node *ast.SendStmt) { 308 channel := c.Expr1(node.Chan, nil) 309 t := channel.Type 310 if t.Kind() != r.Chan { 311 c.Errorf("cannot send to non-channel type %v: %v", t, node) 312 return 313 } 314 if t.ChanDir()&r.SendDir == 0 { 315 c.Errorf("cannot send to receive-only channel type %v: %v", t, node) 316 return 317 } 318 telem := t.Elem() 319 rtelem := telem.ReflectType() 320 kelem := rtelem.Kind() 321 expr := c.Expr1(node.Value, nil) 322 if expr.Const() { 323 expr.ConstTo(telem) 324 } else if expr.Type == nil || !expr.Type.AssignableTo(telem) { 325 c.Errorf("cannot use %v <%v> as type %v in send", node.Value, expr.Type, telem) 326 return 327 } else { 328 expr.To(c, telem) 329 } 330 channelfun := channel.AsX1() 331 sendonly := t.ChanDir() == r.SendDir 332 var stmt Stmt 333 if expr.Const() { 334 v := r.ValueOf(expr.Value) 335 if reflect.KindToType(kelem) == rtelem { 336 switch kelem { 337 {send_c; bool} 338 {send_c; int} 339 {send_c; int8} 340 {send_c; int16} 341 {send_c; int32} 342 {send_c; int64} 343 {send_c; uint} 344 {send_c; uint8} 345 {send_c; uint16} 346 {send_c; uint32} 347 {send_c; uint64} 348 {send_c; uintptr} 349 {send_c; float32} 350 {send_c; float64} 351 {send_c; complex64} 352 {send_c; complex128} 353 {send_c; string} 354 } 355 } 356 if stmt == nil { 357 stmt = func(env *Env) (Stmt, *Env) { 358 channel := channelfun(env) 359 channel.Send(v) 360 env.IP++ 361 return env.Code[env.IP], env 362 } 363 } 364 } else { 365 if reflect.KindToType(kelem) == rtelem { 366 switch kelem { 367 {send_e; bool} 368 {send_e; int} 369 {send_e; int8} 370 {send_e; int16} 371 {send_e; int32} 372 {send_e; int64} 373 {send_e; uint} 374 {send_e; uint8} 375 {send_e; uint16} 376 {send_e; uint32} 377 {send_e; uint64} 378 {send_e; uintptr} 379 {send_e; float32} 380 {send_e; float64} 381 {send_e; complex64} 382 {send_e; complex128} 383 {send_e; string} 384 } 385 } 386 if stmt == nil { 387 exprfun := expr.AsX1() 388 stmt = func(env *Env) (Stmt, *Env) { 389 channel := channelfun(env) 390 value := exprfun(env) 391 channel.Send(value) 392 env.IP++ 393 return env.Code[env.IP], env 394 } 395 } 396 } 397 c.append(stmt) 398} 399