github.com/goplus/gogen@v1.16.0/codebuild.go (about) 1 /* 2 Copyright 2021 The GoPlus Authors (goplus.org) 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 http://www.apache.org/licenses/LICENSE-2.0 7 Unless required by applicable law or agreed to in writing, software 8 distributed under the License is distributed on an "AS IS" BASIS, 9 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 See the License for the specific language governing permissions and 11 limitations under the License. 12 */ 13 14 package gogen 15 16 import ( 17 "errors" 18 "fmt" 19 "go/ast" 20 "go/constant" 21 "go/token" 22 "go/types" 23 "log" 24 "math/big" 25 "reflect" 26 "strconv" 27 "strings" 28 "syscall" 29 30 "github.com/goplus/gogen/internal" 31 xtoken "github.com/goplus/gogen/token" 32 "golang.org/x/tools/go/types/typeutil" 33 ) 34 35 func getSrc(node []ast.Node) ast.Node { 36 if node != nil { 37 return node[0] 38 } 39 return nil 40 } 41 42 func getSrcPos(node ast.Node) token.Pos { 43 if node != nil { 44 return node.Pos() 45 } 46 return token.NoPos 47 } 48 49 func getPos(src []ast.Node) token.Pos { 50 if src == nil { 51 return token.NoPos 52 } 53 return getSrcPos(src[0]) 54 } 55 56 // ---------------------------------------------------------------------------- 57 58 type posNode struct { 59 pos, end token.Pos 60 } 61 62 func NewPosNode(pos token.Pos, end ...token.Pos) ast.Node { 63 ret := &posNode{pos: pos, end: pos} 64 if end != nil { 65 ret.end = end[0] 66 } 67 return ret 68 } 69 70 func (p *posNode) Pos() token.Pos { return p.pos } 71 func (p *posNode) End() token.Pos { return p.end } 72 73 // ---------------------------------------------------------------------------- 74 75 type codeBlock interface { 76 End(cb *CodeBuilder, src ast.Node) 77 } 78 79 type vblockCtx struct { 80 codeBlock 81 scope *types.Scope 82 } 83 84 type codeBlockCtx struct { 85 codeBlock 86 scope *types.Scope 87 base int 88 stmts []ast.Stmt 89 label *ast.LabeledStmt 90 flows int // flow flags 91 } 92 93 const ( 94 flowFlagBreak = 1 << iota 95 flowFlagContinue 96 flowFlagReturn 97 flowFlagGoto 98 flowFlagWithLabel 99 ) 100 101 type Label struct { 102 types.Label 103 used bool 104 } 105 106 type funcBodyCtx struct { 107 codeBlockCtx 108 fn *Func 109 labels map[string]*Label 110 } 111 112 func (p *funcBodyCtx) checkLabels(cb *CodeBuilder) { 113 for name, l := range p.labels { 114 if !l.used { 115 cb.handleCodeErrorf(l.Pos(), "label %s defined and not used", name) 116 } 117 } 118 } 119 120 type CodeError struct { 121 Fset dbgPositioner 122 Pos token.Pos 123 Msg string 124 } 125 126 func (p *CodeError) Error() string { 127 pos := p.Fset.Position(p.Pos) 128 return fmt.Sprintf("%v: %s", pos, p.Msg) 129 } 130 131 // CodeBuilder type 132 type CodeBuilder struct { 133 stk internal.Stack 134 current funcBodyCtx 135 fset dbgPositioner 136 comments *ast.CommentGroup 137 pkg *Package 138 btiMap *typeutil.Map 139 valDecl *ValueDecl 140 ctxt *typesContext 141 interp NodeInterpreter 142 rec Recorder 143 loadNamed LoadNamedFunc 144 handleErr func(err error) 145 closureParamInsts 146 iotav int 147 commentOnce bool 148 noSkipConst bool 149 } 150 151 func (p *CodeBuilder) init(pkg *Package) { 152 conf := pkg.conf 153 p.pkg = pkg 154 p.fset = conf.DbgPositioner 155 if p.fset == nil { 156 p.fset = conf.Fset 157 } 158 p.noSkipConst = conf.NoSkipConstant 159 p.handleErr = conf.HandleErr 160 if p.handleErr == nil { 161 p.handleErr = defaultHandleErr 162 } 163 p.rec = conf.Recorder 164 p.interp = conf.NodeInterpreter 165 if p.interp == nil { 166 p.interp = nodeInterp{} 167 } 168 p.ctxt = newTypesContext() 169 p.loadNamed = conf.LoadNamed 170 if p.loadNamed == nil { 171 p.loadNamed = defaultLoadNamed 172 } 173 p.current.scope = pkg.Types.Scope() 174 p.stk.Init() 175 p.closureParamInsts.init() 176 } 177 178 func defaultLoadNamed(at *Package, t *types.Named) { 179 // no delay-loaded named types 180 } 181 182 func defaultHandleErr(err error) { 183 panic(err) 184 } 185 186 type nodeInterp struct{} 187 188 func (p nodeInterp) LoadExpr(expr ast.Node) string { 189 return "" 190 } 191 192 func getFunExpr(fn *internal.Elem) (caller string, pos token.Pos) { 193 if fn == nil { 194 return "the closure call", token.NoPos 195 } 196 caller = types.ExprString(fn.Val) 197 pos = getSrcPos(fn.Src) 198 return 199 } 200 201 func getCaller(expr *internal.Elem) string { 202 if ce, ok := expr.Val.(*ast.CallExpr); ok { 203 return types.ExprString(ce.Fun) 204 } 205 return "the function call" 206 } 207 208 func (p *CodeBuilder) loadExpr(expr ast.Node) (string, token.Pos) { 209 if expr == nil { 210 return "", token.NoPos 211 } 212 return p.interp.LoadExpr(expr), expr.Pos() 213 } 214 215 func (p *CodeBuilder) newCodeError(pos token.Pos, msg string) *CodeError { 216 return &CodeError{Msg: msg, Pos: pos, Fset: p.fset} 217 } 218 219 func (p *CodeBuilder) newCodeErrorf(pos token.Pos, format string, args ...interface{}) *CodeError { 220 return p.newCodeError(pos, fmt.Sprintf(format, args...)) 221 } 222 223 func (p *CodeBuilder) handleCodeError(pos token.Pos, msg string) { 224 p.handleErr(p.newCodeError(pos, msg)) 225 } 226 227 func (p *CodeBuilder) handleCodeErrorf(pos token.Pos, format string, args ...interface{}) { 228 p.handleErr(p.newCodeError(pos, fmt.Sprintf(format, args...))) 229 } 230 231 func (p *CodeBuilder) panicCodeError(pos token.Pos, msg string) { 232 panic(p.newCodeError(pos, msg)) 233 } 234 235 func (p *CodeBuilder) panicCodeErrorf(pos token.Pos, format string, args ...interface{}) { 236 panic(p.newCodeError(pos, fmt.Sprintf(format, args...))) 237 } 238 239 // Scope returns current scope. 240 func (p *CodeBuilder) Scope() *types.Scope { 241 return p.current.scope 242 } 243 244 // Func returns current func (nil means in global scope). 245 func (p *CodeBuilder) Func() *Func { 246 return p.current.fn 247 } 248 249 // Pkg returns the package instance. 250 func (p *CodeBuilder) Pkg() *Package { 251 return p.pkg 252 } 253 254 func (p *CodeBuilder) startFuncBody(fn *Func, src []ast.Node, old *funcBodyCtx) *CodeBuilder { 255 p.current.fn, old.fn = fn, p.current.fn 256 p.current.labels, old.labels = nil, p.current.labels 257 p.startBlockStmt(fn, src, "func "+fn.Name(), &old.codeBlockCtx) 258 scope := p.current.scope 259 sig := fn.Type().(*types.Signature) 260 insertParams(scope, sig.Params()) 261 insertParams(scope, sig.Results()) 262 if recv := sig.Recv(); recv != nil { 263 scope.Insert(recv) 264 } 265 return p 266 } 267 268 func insertParams(scope *types.Scope, params *types.Tuple) { 269 for i, n := 0, params.Len(); i < n; i++ { 270 v := params.At(i) 271 if name := v.Name(); name != "" && name != "_" { 272 scope.Insert(v) 273 } 274 } 275 } 276 277 func (p *CodeBuilder) endFuncBody(old funcBodyCtx) []ast.Stmt { 278 p.current.checkLabels(p) 279 p.current.fn = old.fn 280 p.current.labels = old.labels 281 stmts, _ := p.endBlockStmt(&old.codeBlockCtx) 282 return stmts 283 } 284 285 func (p *CodeBuilder) startBlockStmt(current codeBlock, src []ast.Node, comment string, old *codeBlockCtx) *CodeBuilder { 286 var start, end token.Pos 287 if src != nil { 288 start, end = src[0].Pos(), src[0].End() 289 } 290 scope := types.NewScope(p.current.scope, start, end, comment) 291 p.current.codeBlockCtx, *old = codeBlockCtx{current, scope, p.stk.Len(), nil, nil, 0}, p.current.codeBlockCtx 292 return p 293 } 294 295 func (p *CodeBuilder) endBlockStmt(old *codeBlockCtx) ([]ast.Stmt, int) { 296 flows := p.current.flows 297 if p.current.label != nil { 298 p.emitStmt(&ast.EmptyStmt{}) 299 } 300 stmts := p.current.stmts 301 p.stk.SetLen(p.current.base) 302 p.current.codeBlockCtx = *old 303 return stmts, flows 304 } 305 306 func (p *CodeBuilder) clearBlockStmt() []ast.Stmt { 307 stmts := p.current.stmts 308 p.current.stmts = nil 309 return stmts 310 } 311 312 func (p *CodeBuilder) startVBlockStmt(current codeBlock, comment string, old *vblockCtx) *CodeBuilder { 313 *old = vblockCtx{codeBlock: p.current.codeBlock, scope: p.current.scope} 314 scope := types.NewScope(p.current.scope, token.NoPos, token.NoPos, comment) 315 p.current.codeBlock, p.current.scope = current, scope 316 return p 317 } 318 319 func (p *CodeBuilder) endVBlockStmt(old *vblockCtx) { 320 p.current.codeBlock, p.current.scope = old.codeBlock, old.scope 321 } 322 323 func (p *CodeBuilder) popStmt() ast.Stmt { 324 stmts := p.current.stmts 325 n := len(stmts) - 1 326 stmt := stmts[n] 327 p.current.stmts = stmts[:n] 328 return stmt 329 } 330 331 func (p *CodeBuilder) startStmtAt(stmt ast.Stmt) int { 332 idx := len(p.current.stmts) 333 p.emitStmt(stmt) 334 return idx 335 } 336 337 // Usage: 338 // 339 // idx := cb.startStmtAt(stmt) 340 // ... 341 // cb.commitStmt(idx) 342 func (p *CodeBuilder) commitStmt(idx int) { 343 stmts := p.current.stmts 344 n := len(stmts) - 1 345 if n > idx { 346 stmt := stmts[idx] 347 copy(stmts[idx:], stmts[idx+1:]) 348 stmts[n] = stmt 349 } 350 } 351 352 func (p *CodeBuilder) emitStmt(stmt ast.Stmt) { 353 if p.comments != nil { 354 p.pkg.setStmtComments(stmt, p.comments) 355 if p.commentOnce { 356 p.comments = nil 357 } 358 } 359 if p.current.label != nil { 360 p.current.label.Stmt = stmt 361 stmt, p.current.label = p.current.label, nil 362 } 363 p.current.stmts = append(p.current.stmts, stmt) 364 } 365 366 func (p *CodeBuilder) startInitExpr(current codeBlock) (old codeBlock) { 367 p.current.codeBlock, old = current, p.current.codeBlock 368 return 369 } 370 371 func (p *CodeBuilder) endInitExpr(old codeBlock) { 372 p.current.codeBlock = old 373 } 374 375 // Comments returns the comments of next statement. 376 func (p *CodeBuilder) Comments() *ast.CommentGroup { 377 return p.comments 378 } 379 380 func (p *CodeBuilder) BackupComments() (*ast.CommentGroup, bool) { 381 return p.comments, p.commentOnce 382 } 383 384 // SetComments sets comments to next statement. 385 func (p *CodeBuilder) SetComments(comments *ast.CommentGroup, once bool) *CodeBuilder { 386 if debugComments && comments != nil { 387 for i, c := range comments.List { 388 log.Println("SetComments", i, c.Text) 389 } 390 } 391 p.comments, p.commentOnce = comments, once 392 return p 393 } 394 395 // ReturnErr func 396 func (p *CodeBuilder) ReturnErr(outer bool) *CodeBuilder { 397 if debugInstr { 398 log.Println("ReturnErr", outer) 399 } 400 fn := p.current.fn 401 if outer { 402 if !fn.isInline() { 403 panic("only support ReturnOuterErr in an inline call") 404 } 405 fn = fn.old.fn 406 } 407 results := fn.Type().(*types.Signature).Results() 408 n := results.Len() 409 if n > 0 { 410 last := results.At(n - 1) 411 if last.Type() == TyError { // last result is error 412 err := p.stk.Pop() 413 for i := 0; i < n-1; i++ { 414 p.doZeroLit(results.At(i).Type(), false) 415 } 416 p.stk.Push(err) 417 p.returnResults(n) 418 p.current.flows |= flowFlagReturn 419 return p 420 } 421 } 422 panic("TODO: last result type isn't an error") 423 } 424 425 func (p *CodeBuilder) returnResults(n int) { 426 var rets []ast.Expr 427 if n > 0 { 428 args := p.stk.GetArgs(n) 429 rets = make([]ast.Expr, n) 430 for i := 0; i < n; i++ { 431 rets[i] = args[i].Val 432 } 433 p.stk.PopN(n) 434 } 435 p.emitStmt(&ast.ReturnStmt{Results: rets}) 436 } 437 438 // Return func 439 func (p *CodeBuilder) Return(n int, src ...ast.Node) *CodeBuilder { 440 if debugInstr { 441 log.Println("Return", n) 442 } 443 fn := p.current.fn 444 results := fn.Type().(*types.Signature).Results() 445 checkFuncResults(p.pkg, p.stk.GetArgs(n), results, getSrc(src)) 446 if fn.isInline() { 447 for i := n - 1; i >= 0; i-- { 448 key := closureParamInst{fn, results.At(i)} 449 elem := p.stk.Pop() 450 p.doVarRef(p.paramInsts[key], nil, false) 451 p.stk.Push(elem) 452 p.doAssignWith(1, 1, nil) 453 } 454 p.Goto(p.getEndingLabel(fn)) 455 } else { 456 p.current.flows |= flowFlagReturn 457 p.returnResults(n) 458 } 459 return p 460 } 461 462 // Call func 463 func (p *CodeBuilder) Call(n int, ellipsis ...bool) *CodeBuilder { 464 var flags InstrFlags 465 if ellipsis != nil && ellipsis[0] { 466 flags = InstrFlagEllipsis 467 } 468 return p.CallWith(n, flags) 469 } 470 471 // CallWith always panics on error, while CallWithEx returns err if match function call failed. 472 func (p *CodeBuilder) CallWith(n int, flags InstrFlags, src ...ast.Node) *CodeBuilder { 473 if err := p.CallWithEx(n, flags, src...); err != nil { 474 panic(err) 475 } 476 return p 477 } 478 479 // CallWith always panics on error, while CallWithEx returns err if match function call failed. 480 // If an error ocurs, CallWithEx pops all function arguments from the CodeBuilder stack. 481 // In most case, you should call CallWith instead of CallWithEx. 482 func (p *CodeBuilder) CallWithEx(n int, flags InstrFlags, src ...ast.Node) error { 483 fn := p.stk.Get(-(n + 1)) 484 if t, ok := fn.Type.(*btiMethodType); ok { 485 n++ 486 fn.Type = t.Type 487 fn = p.stk.Get(-(n + 1)) 488 if t.eargs != nil { 489 for _, arg := range t.eargs { 490 p.Val(arg) 491 } 492 n += len(t.eargs) 493 } 494 } 495 args := p.stk.GetArgs(n) 496 if debugInstr { 497 log.Println("Call", n, int(flags), "//", fn.Type) 498 } 499 s := getSrc(src) 500 fn.Src = s 501 ret, err := matchFuncCall(p.pkg, fn, args, flags) 502 if err != nil { 503 p.stk.PopN(n) 504 return err 505 } 506 ret.Src = s 507 p.stk.Ret(n+1, ret) 508 return nil 509 } 510 511 type closureParamInst struct { 512 inst *Func 513 param *types.Var 514 } 515 516 type closureParamInsts struct { 517 paramInsts map[closureParamInst]*types.Var 518 } 519 520 func (p *closureParamInsts) init() { 521 p.paramInsts = make(map[closureParamInst]*types.Var) 522 } 523 524 func (p *CodeBuilder) getEndingLabel(fn *Func) *Label { 525 key := closureParamInst{fn, nil} 526 if v, ok := p.paramInsts[key]; ok { 527 return p.current.labels[v.Name()] 528 } 529 ending := p.pkg.autoName() 530 p.paramInsts[key] = types.NewParam(token.NoPos, nil, ending, nil) 531 return p.NewLabel(token.NoPos, ending) 532 } 533 534 func (p *CodeBuilder) needEndingLabel(fn *Func) (*Label, bool) { 535 key := closureParamInst{fn, nil} 536 if v, ok := p.paramInsts[key]; ok { 537 return p.current.labels[v.Name()], true 538 } 539 return nil, false 540 } 541 542 func (p *Func) inlineClosureEnd(cb *CodeBuilder) { 543 if ending, ok := cb.needEndingLabel(p); ok { 544 cb.Label(ending) 545 } 546 sig := p.Type().(*types.Signature) 547 cb.emitStmt(&ast.BlockStmt{List: cb.endFuncBody(p.old)}) 548 cb.stk.PopN(p.getInlineCallArity()) 549 results := sig.Results() 550 for i, n := 0, results.Len(); i < n; i++ { // return results & clean env 551 key := closureParamInst{p, results.At(i)} 552 cb.pushVal(cb.paramInsts[key], nil) 553 delete(cb.paramInsts, key) 554 } 555 for i, n := 0, getParamLen(sig); i < n; i++ { // clean env 556 key := closureParamInst{p, getParam(sig, i)} 557 delete(cb.paramInsts, key) 558 } 559 } 560 561 // CallInlineClosureStart func 562 func (p *CodeBuilder) CallInlineClosureStart(sig *types.Signature, arity int, ellipsis bool) *CodeBuilder { 563 if debugInstr { 564 log.Println("CallInlineClosureStart", arity, ellipsis) 565 } 566 pkg := p.pkg 567 closure := pkg.newInlineClosure(sig, arity) 568 results := sig.Results() 569 for i, n := 0, results.Len(); i < n; i++ { 570 p.emitVar(pkg, closure, results.At(i), false) 571 } 572 p.startFuncBody(closure, nil, &closure.old) 573 args := p.stk.GetArgs(arity) 574 var flags InstrFlags 575 if ellipsis { 576 flags = InstrFlagEllipsis 577 } 578 if err := matchFuncType(pkg, args, flags, sig, nil); err != nil { 579 panic(err) 580 } 581 n1 := getParamLen(sig) - 1 582 if sig.Variadic() && !ellipsis { 583 p.SliceLit(getParam(sig, n1).Type().(*types.Slice), arity-n1) 584 } 585 for i := n1; i >= 0; i-- { 586 p.emitVar(pkg, closure, getParam(sig, i), true) 587 } 588 return p 589 } 590 591 func (p *CodeBuilder) emitVar(pkg *Package, closure *Func, param *types.Var, withInit bool) { 592 name := pkg.autoName() 593 if withInit { 594 p.NewVarStart(param.Type(), name).EndInit(1) 595 } else { 596 p.NewVar(param.Type(), name) 597 } 598 key := closureParamInst{closure, param} 599 p.paramInsts[key] = p.current.scope.Lookup(name).(*types.Var) 600 } 601 602 // NewClosure func 603 func (p *CodeBuilder) NewClosure(params, results *Tuple, variadic bool) *Func { 604 sig := types.NewSignatureType(nil, nil, nil, params, results, variadic) 605 return p.NewClosureWith(sig) 606 } 607 608 // NewClosureWith func 609 func (p *CodeBuilder) NewClosureWith(sig *types.Signature) *Func { 610 if debugInstr { 611 t := sig.Params() 612 for i, n := 0, t.Len(); i < n; i++ { 613 v := t.At(i) 614 if _, ok := v.Type().(*unboundType); ok { 615 panic("can't use unbound type in func parameters") 616 } 617 } 618 } 619 return p.pkg.newClosure(sig) 620 } 621 622 // NewType func 623 func (p *CodeBuilder) NewType(name string, src ...ast.Node) *TypeDecl { 624 return p.NewTypeDefs().NewType(name, src...) 625 } 626 627 // AliasType func 628 func (p *CodeBuilder) AliasType(name string, typ types.Type, src ...ast.Node) *types.Named { 629 decl := p.NewTypeDefs().AliasType(name, typ, src...) 630 return decl.typ 631 } 632 633 // NewConstStart func 634 func (p *CodeBuilder) NewConstStart(typ types.Type, names ...string) *CodeBuilder { 635 if debugInstr { 636 log.Println("NewConstStart", names) 637 } 638 defs := p.valueDefs(token.CONST) 639 return p.pkg.newValueDecl(defs.NewPos(), defs.scope, token.NoPos, token.CONST, typ, names...).InitStart(p.pkg) 640 } 641 642 // NewVar func 643 func (p *CodeBuilder) NewVar(typ types.Type, names ...string) *CodeBuilder { 644 if debugInstr { 645 log.Println("NewVar", names) 646 } 647 defs := p.valueDefs(token.VAR) 648 p.pkg.newValueDecl(defs.NewPos(), defs.scope, token.NoPos, token.VAR, typ, names...) 649 return p 650 } 651 652 // NewVarStart func 653 func (p *CodeBuilder) NewVarStart(typ types.Type, names ...string) *CodeBuilder { 654 if debugInstr { 655 log.Println("NewVarStart", names) 656 } 657 defs := p.valueDefs(token.VAR) 658 return p.pkg.newValueDecl(defs.NewPos(), defs.scope, token.NoPos, token.VAR, typ, names...).InitStart(p.pkg) 659 } 660 661 // DefineVarStart func 662 func (p *CodeBuilder) DefineVarStart(pos token.Pos, names ...string) *CodeBuilder { 663 if debugInstr { 664 log.Println("DefineVarStart", names) 665 } 666 return p.pkg.newValueDecl( 667 ValueAt{}, p.current.scope, pos, token.DEFINE, nil, names...).InitStart(p.pkg) 668 } 669 670 // NewAutoVar func 671 func (p *CodeBuilder) NewAutoVar(pos token.Pos, name string, pv **types.Var) *CodeBuilder { 672 spec := &ast.ValueSpec{Names: []*ast.Ident{ident(name)}} 673 decl := &ast.GenDecl{Tok: token.VAR, Specs: []ast.Spec{spec}} 674 stmt := &ast.DeclStmt{ 675 Decl: decl, 676 } 677 if debugInstr { 678 log.Println("NewAutoVar", name) 679 } 680 p.emitStmt(stmt) 681 typ := &unboundType{ptypes: []*ast.Expr{&spec.Type}} 682 *pv = types.NewVar(pos, p.pkg.Types, name, typ) 683 if old := p.current.scope.Insert(*pv); old != nil { 684 oldPos := p.fset.Position(old.Pos()) 685 p.panicCodeErrorf( 686 pos, "%s redeclared in this block\n\tprevious declaration at %v", name, oldPos) 687 } 688 return p 689 } 690 691 // VarRef func: p.VarRef(nil) means underscore (_) 692 func (p *CodeBuilder) VarRef(ref interface{}, src ...ast.Node) *CodeBuilder { 693 return p.doVarRef(ref, getSrc(src), true) 694 } 695 696 func (p *CodeBuilder) doVarRef(ref interface{}, src ast.Node, allowDebug bool) *CodeBuilder { 697 if ref == nil { 698 if allowDebug && debugInstr { 699 log.Println("VarRef _") 700 } 701 p.stk.Push(&internal.Elem{ 702 Val: underscore, // _ 703 }) 704 } else { 705 if v, ok := ref.(string); ok { 706 _, ref = p.Scope().LookupParent(v, token.NoPos) 707 } 708 if v, ok := ref.(*types.Var); ok { 709 if allowDebug && debugInstr { 710 log.Println("VarRef", v.Name(), v.Type()) 711 } 712 fn := p.current.fn 713 if fn != nil && fn.isInline() { // is in an inline call 714 key := closureParamInst{fn, v} 715 if arg, ok := p.paramInsts[key]; ok { // replace param with arg 716 v = arg 717 } 718 } 719 p.stk.Push(&internal.Elem{ 720 Val: toObjectExpr(p.pkg, v), Type: &refType{typ: v.Type()}, Src: src, 721 }) 722 } else { 723 code, pos := p.loadExpr(src) 724 p.panicCodeErrorf(pos, "%s is not a variable", code) 725 } 726 } 727 return p 728 } 729 730 var ( 731 elemNone = &internal.Elem{} 732 ) 733 734 // None func 735 func (p *CodeBuilder) None() *CodeBuilder { 736 if debugInstr { 737 log.Println("None") 738 } 739 p.stk.Push(elemNone) 740 return p 741 } 742 743 // ZeroLit func 744 func (p *CodeBuilder) ZeroLit(typ types.Type) *CodeBuilder { 745 return p.doZeroLit(typ, true) 746 } 747 748 func (p *CodeBuilder) doZeroLit(typ types.Type, allowDebug bool) *CodeBuilder { 749 typ0 := typ 750 if allowDebug && debugInstr { 751 log.Println("ZeroLit //", typ) 752 } 753 retry: 754 switch t := typ.(type) { 755 case *types.Basic: 756 switch kind := t.Kind(); kind { 757 case types.Bool: 758 return p.Val(false) 759 case types.String: 760 return p.Val("") 761 case types.UnsafePointer: 762 return p.Val(nil) 763 default: 764 return p.Val(0) 765 } 766 case *types.Interface, *types.Map, *types.Slice, *types.Pointer, *types.Signature, *types.Chan: 767 return p.Val(nil) 768 case *types.Named: 769 typ = p.getUnderlying(t) 770 goto retry 771 } 772 ret := &ast.CompositeLit{} 773 switch t := typ.(type) { 774 case *unboundType: 775 if t.tBound == nil { 776 t.ptypes = append(t.ptypes, &ret.Type) 777 } else { 778 typ = t.tBound 779 typ0 = typ 780 ret.Type = toType(p.pkg, typ) 781 } 782 default: 783 ret.Type = toType(p.pkg, typ) 784 } 785 p.stk.Push(&internal.Elem{Type: typ0, Val: ret}) 786 return p 787 } 788 789 // MapLit func 790 func (p *CodeBuilder) MapLit(typ types.Type, arity int, src ...ast.Node) *CodeBuilder { 791 if err := p.MapLitEx(typ, arity, src...); err != nil { 792 panic(err) 793 } 794 return p 795 } 796 797 // MapLit func 798 func (p *CodeBuilder) MapLitEx(typ types.Type, arity int, src ...ast.Node) error { 799 if debugInstr { 800 log.Println("MapLit", typ, arity) 801 } 802 var t *types.Map 803 var typExpr ast.Expr 804 var pkg = p.pkg 805 if typ != nil { 806 var ok bool 807 switch tt := typ.(type) { 808 case *types.Named: 809 typExpr = toNamedType(pkg, tt) 810 t, ok = p.getUnderlying(tt).(*types.Map) 811 case *types.Map: 812 typExpr = toMapType(pkg, tt) 813 t, ok = tt, true 814 } 815 if !ok { 816 return p.newCodeErrorf(getPos(src), "type %v isn't a map", typ) 817 } 818 } 819 if arity == 0 { 820 if t == nil { 821 t = types.NewMap(types.Typ[types.String], TyEmptyInterface) 822 typ = t 823 typExpr = toMapType(pkg, t) 824 } 825 ret := &ast.CompositeLit{Type: typExpr} 826 p.stk.Push(&internal.Elem{Type: typ, Val: ret, Src: getSrc(src)}) 827 return nil 828 } 829 if (arity & 1) != 0 { 830 return p.newCodeErrorf(getPos(src), "MapLit: invalid arity, can't be odd - %d", arity) 831 } 832 var key, val types.Type 833 var args = p.stk.GetArgs(arity) 834 var check = (t != nil) 835 if check { 836 key, val = t.Key(), t.Elem() 837 } else { 838 key = boundElementType(pkg, args, 0, arity, 2) 839 val = boundElementType(pkg, args, 1, arity, 2) 840 t = types.NewMap(Default(pkg, key), Default(pkg, val)) 841 typ = t 842 typExpr = toMapType(pkg, t) 843 } 844 elts := make([]ast.Expr, arity>>1) 845 for i := 0; i < arity; i += 2 { 846 elts[i>>1] = &ast.KeyValueExpr{Key: args[i].Val, Value: args[i+1].Val} 847 if check { 848 if !AssignableTo(pkg, args[i].Type, key) { 849 src, pos := p.loadExpr(args[i].Src) 850 return p.newCodeErrorf( 851 pos, "cannot use %s (type %v) as type %v in map key", src, args[i].Type, key) 852 } else if !AssignableTo(pkg, args[i+1].Type, val) { 853 src, pos := p.loadExpr(args[i+1].Src) 854 return p.newCodeErrorf( 855 pos, "cannot use %s (type %v) as type %v in map value", src, args[i+1].Type, val) 856 } 857 } 858 } 859 p.stk.Ret(arity, &internal.Elem{ 860 Type: typ, Val: &ast.CompositeLit{Type: typExpr, Elts: elts}, Src: getSrc(src), 861 }) 862 return nil 863 } 864 865 func (p *CodeBuilder) toBoundArrayLen(elts []*internal.Elem, arity, limit int) int { 866 n := -1 867 max := -1 868 for i := 0; i < arity; i += 2 { 869 if elts[i].Val != nil { 870 n = p.toIntVal(elts[i], "index which must be non-negative integer constant") 871 } else { 872 n++ 873 } 874 if limit >= 0 && n >= limit { // error message 875 if elts[i].Src == nil { 876 pos := getSrcPos(elts[i+1].Src) 877 p.panicCodeErrorf(pos, "array index %d out of bounds [0:%d]", n, limit) 878 } 879 src, pos := p.loadExpr(elts[i].Src) 880 p.panicCodeErrorf(pos, "array index %s (value %d) out of bounds [0:%d]", src, n, limit) 881 } 882 if max < n { 883 max = n 884 } 885 } 886 return max + 1 887 } 888 889 func (p *CodeBuilder) toIntVal(v *internal.Elem, msg string) int { 890 if cval := v.CVal; cval != nil && cval.Kind() == constant.Int { 891 if v, ok := constant.Int64Val(cval); ok { 892 return int(v) 893 } 894 } 895 code, pos := p.loadExpr(v.Src) 896 p.panicCodeErrorf(pos, "cannot use %s as %s", code, msg) 897 return 0 898 } 899 900 func (p *CodeBuilder) indexElemExpr(args []*internal.Elem, i int) ast.Expr { 901 key := args[i].Val 902 if key == nil { // none 903 return args[i+1].Val 904 } 905 p.toIntVal(args[i], "index which must be non-negative integer constant") 906 return &ast.KeyValueExpr{Key: key, Value: args[i+1].Val} 907 } 908 909 // SliceLit func 910 func (p *CodeBuilder) SliceLit(typ types.Type, arity int, keyVal ...bool) *CodeBuilder { 911 var keyValMode = (keyVal != nil && keyVal[0]) 912 return p.SliceLitEx(typ, arity, keyValMode) 913 } 914 915 // SliceLitEx func 916 func (p *CodeBuilder) SliceLitEx(typ types.Type, arity int, keyVal bool, src ...ast.Node) *CodeBuilder { 917 var elts []ast.Expr 918 if debugInstr { 919 log.Println("SliceLit", typ, arity, keyVal) 920 } 921 var t *types.Slice 922 var typExpr ast.Expr 923 var pkg = p.pkg 924 if typ != nil { 925 switch tt := typ.(type) { 926 case *types.Named: 927 typExpr = toNamedType(pkg, tt) 928 t = p.getUnderlying(tt).(*types.Slice) 929 case *types.Slice: 930 typExpr = toSliceType(pkg, tt) 931 t = tt 932 default: 933 log.Panicln("SliceLit: typ isn't a slice type -", reflect.TypeOf(typ)) 934 } 935 } 936 if keyVal { // in keyVal mode 937 if (arity & 1) != 0 { 938 log.Panicln("SliceLit: invalid arity, can't be odd in keyVal mode -", arity) 939 } 940 args := p.stk.GetArgs(arity) 941 val := t.Elem() 942 n := arity >> 1 943 elts = make([]ast.Expr, n) 944 for i := 0; i < arity; i += 2 { 945 arg := args[i+1] 946 if !AssignableConv(pkg, arg.Type, val, arg) { 947 src, pos := p.loadExpr(args[i+1].Src) 948 p.panicCodeErrorf( 949 pos, "cannot use %s (type %v) as type %v in slice literal", src, args[i+1].Type, val) 950 } 951 elts[i>>1] = p.indexElemExpr(args, i) 952 } 953 } else { 954 if arity == 0 { 955 if t == nil { 956 t = types.NewSlice(TyEmptyInterface) 957 typ = t 958 typExpr = toSliceType(pkg, t) 959 } 960 p.stk.Push(&internal.Elem{ 961 Type: typ, Val: &ast.CompositeLit{Type: typExpr}, Src: getSrc(src), 962 }) 963 return p 964 } 965 var val types.Type 966 var args = p.stk.GetArgs(arity) 967 var check = (t != nil) 968 if check { 969 val = t.Elem() 970 } else { 971 val = boundElementType(pkg, args, 0, arity, 1) 972 t = types.NewSlice(Default(pkg, val)) 973 typ = t 974 typExpr = toSliceType(pkg, t) 975 } 976 elts = make([]ast.Expr, arity) 977 for i, arg := range args { 978 elts[i] = arg.Val 979 if check { 980 if !AssignableConv(pkg, arg.Type, val, arg) { 981 src, pos := p.loadExpr(arg.Src) 982 p.panicCodeErrorf( 983 pos, "cannot use %s (type %v) as type %v in slice literal", src, arg.Type, val) 984 } 985 } 986 } 987 } 988 p.stk.Ret(arity, &internal.Elem{ 989 Type: typ, Val: &ast.CompositeLit{Type: typExpr, Elts: elts}, Src: getSrc(src), 990 }) 991 return p 992 } 993 994 // ArrayLit func 995 func (p *CodeBuilder) ArrayLit(typ types.Type, arity int, keyVal ...bool) *CodeBuilder { 996 var keyValMode = (keyVal != nil && keyVal[0]) 997 return p.ArrayLitEx(typ, arity, keyValMode) 998 } 999 1000 // ArrayLitEx func 1001 func (p *CodeBuilder) ArrayLitEx(typ types.Type, arity int, keyVal bool, src ...ast.Node) *CodeBuilder { 1002 var elts []ast.Expr 1003 if debugInstr { 1004 log.Println("ArrayLit", typ, arity, keyVal) 1005 } 1006 var t *types.Array 1007 var typExpr ast.Expr 1008 var pkg = p.pkg 1009 switch tt := typ.(type) { 1010 case *types.Named: 1011 typExpr = toNamedType(pkg, tt) 1012 t = p.getUnderlying(tt).(*types.Array) 1013 case *types.Array: 1014 typExpr = toArrayType(pkg, tt) 1015 t = tt 1016 default: 1017 log.Panicln("ArrayLit: typ isn't a array type -", reflect.TypeOf(typ)) 1018 } 1019 if keyVal { // in keyVal mode 1020 if (arity & 1) != 0 { 1021 log.Panicln("ArrayLit: invalid arity, can't be odd in keyVal mode -", arity) 1022 } 1023 n := int(t.Len()) 1024 args := p.stk.GetArgs(arity) 1025 max := p.toBoundArrayLen(args, arity, n) 1026 val := t.Elem() 1027 if n < 0 { 1028 t = types.NewArray(val, int64(max)) 1029 typ = t 1030 } 1031 elts = make([]ast.Expr, arity>>1) 1032 for i := 0; i < arity; i += 2 { 1033 if !AssignableTo(pkg, args[i+1].Type, val) { 1034 src, pos := p.loadExpr(args[i+1].Src) 1035 p.panicCodeErrorf( 1036 pos, "cannot use %s (type %v) as type %v in array literal", src, args[i+1].Type, val) 1037 } 1038 elts[i>>1] = p.indexElemExpr(args, i) 1039 } 1040 } else { 1041 args := p.stk.GetArgs(arity) 1042 val := t.Elem() 1043 if n := t.Len(); n < 0 { 1044 t = types.NewArray(val, int64(arity)) 1045 typ = t 1046 } else if int(n) < arity { 1047 pos := getSrcPos(args[n].Src) 1048 p.panicCodeErrorf(pos, "array index %d out of bounds [0:%d]", n, n) 1049 } 1050 elts = make([]ast.Expr, arity) 1051 for i, arg := range args { 1052 elts[i] = arg.Val 1053 if !AssignableConv(pkg, arg.Type, val, arg) { 1054 src, pos := p.loadExpr(arg.Src) 1055 p.panicCodeErrorf( 1056 pos, "cannot use %s (type %v) as type %v in array literal", src, arg.Type, val) 1057 } 1058 } 1059 } 1060 p.stk.Ret(arity, &internal.Elem{ 1061 Type: typ, Val: &ast.CompositeLit{Type: typExpr, Elts: elts}, Src: getSrc(src), 1062 }) 1063 return p 1064 } 1065 1066 // StructLit func 1067 func (p *CodeBuilder) StructLit(typ types.Type, arity int, keyVal bool, src ...ast.Node) *CodeBuilder { 1068 if debugInstr { 1069 log.Println("StructLit", typ, arity, keyVal) 1070 } 1071 var t *types.Struct 1072 var typExpr ast.Expr 1073 var pkg = p.pkg 1074 switch tt := typ.(type) { 1075 case *types.Named: 1076 typExpr = toNamedType(pkg, tt) 1077 t = p.getUnderlying(tt).(*types.Struct) 1078 case *types.Struct: 1079 typExpr = toStructType(pkg, tt) 1080 t = tt 1081 default: 1082 log.Panicln("StructLit: typ isn't a struct type -", reflect.TypeOf(typ)) 1083 } 1084 var elts []ast.Expr 1085 var n = t.NumFields() 1086 var args = p.stk.GetArgs(arity) 1087 if keyVal { 1088 if (arity & 1) != 0 { 1089 log.Panicln("StructLit: invalid arity, can't be odd in keyVal mode -", arity) 1090 } 1091 elts = make([]ast.Expr, arity>>1) 1092 for i := 0; i < arity; i += 2 { 1093 idx := p.toIntVal(args[i], "field which must be non-negative integer constant") 1094 if idx >= n { 1095 panic("invalid struct field index") 1096 } 1097 elt := t.Field(idx) 1098 eltTy, eltName := elt.Type(), elt.Name() 1099 if !AssignableTo(pkg, args[i+1].Type, eltTy) { 1100 src, pos := p.loadExpr(args[i+1].Src) 1101 p.panicCodeErrorf( 1102 pos, "cannot use %s (type %v) as type %v in value of field %s", 1103 src, args[i+1].Type, eltTy, eltName) 1104 } 1105 elts[i>>1] = &ast.KeyValueExpr{Key: ident(eltName), Value: args[i+1].Val} 1106 } 1107 } else if arity != n { 1108 if arity != 0 { 1109 fewOrMany := "few" 1110 if arity > n { 1111 fewOrMany = "many" 1112 } 1113 pos := getSrcPos(args[arity-1].Src) 1114 p.panicCodeErrorf(pos, "too %s values in %v{...}", fewOrMany, typ) 1115 } 1116 } else { 1117 elts = make([]ast.Expr, arity) 1118 for i, arg := range args { 1119 elts[i] = arg.Val 1120 eltTy := t.Field(i).Type() 1121 if !AssignableTo(pkg, arg.Type, eltTy) { 1122 src, pos := p.loadExpr(arg.Src) 1123 p.panicCodeErrorf( 1124 pos, "cannot use %s (type %v) as type %v in value of field %s", 1125 src, arg.Type, eltTy, t.Field(i).Name()) 1126 } 1127 } 1128 } 1129 p.stk.Ret(arity, &internal.Elem{ 1130 Type: typ, Val: &ast.CompositeLit{Type: typExpr, Elts: elts}, Src: getSrc(src), 1131 }) 1132 return p 1133 } 1134 1135 // Slice func 1136 func (p *CodeBuilder) Slice(slice3 bool, src ...ast.Node) *CodeBuilder { // a[i:j:k] 1137 if debugInstr { 1138 log.Println("Slice", slice3) 1139 } 1140 n := 3 1141 if slice3 { 1142 n++ 1143 } 1144 srcExpr := getSrc(src) 1145 args := p.stk.GetArgs(n) 1146 x := args[0] 1147 typ := x.Type 1148 switch t := typ.(type) { 1149 case *types.Slice: 1150 // nothing to do 1151 case *types.Basic: 1152 if t.Kind() == types.String || t.Kind() == types.UntypedString { 1153 if slice3 { 1154 code, pos := p.loadExpr(srcExpr) 1155 p.panicCodeErrorf(pos, "invalid operation %s (3-index slice of string)", code) 1156 } 1157 } else { 1158 code, pos := p.loadExpr(x.Src) 1159 p.panicCodeErrorf(pos, "cannot slice %s (type %v)", code, typ) 1160 } 1161 case *types.Array: 1162 typ = types.NewSlice(t.Elem()) 1163 case *types.Pointer: 1164 if tt, ok := t.Elem().(*types.Array); ok { 1165 typ = types.NewSlice(tt.Elem()) 1166 } else { 1167 code, pos := p.loadExpr(x.Src) 1168 p.panicCodeErrorf(pos, "cannot slice %s (type %v)", code, typ) 1169 } 1170 } 1171 var exprMax ast.Expr 1172 if slice3 { 1173 exprMax = args[3].Val 1174 } 1175 // TODO: check type 1176 elem := &internal.Elem{ 1177 Val: &ast.SliceExpr{ 1178 X: x.Val, Low: args[1].Val, High: args[2].Val, Max: exprMax, Slice3: slice3, 1179 }, 1180 Type: typ, Src: srcExpr, 1181 } 1182 p.stk.Ret(n, elem) 1183 return p 1184 } 1185 1186 // Index func: 1187 // - a[i] 1188 // - fn[T1, T2, ..., Tn] 1189 // - G[T1, T2, ..., Tn] 1190 func (p *CodeBuilder) Index(nidx int, twoValue bool, src ...ast.Node) *CodeBuilder { 1191 if debugInstr { 1192 log.Println("Index", nidx, twoValue) 1193 } 1194 args := p.stk.GetArgs(nidx + 1) 1195 if nidx > 0 { 1196 if _, ok := args[1].Type.(*TypeType); ok { 1197 return p.instantiate(nidx, args, src...) 1198 } 1199 } 1200 if nidx != 1 { 1201 panic("Index doesn't support a[i, j...] yet") 1202 } 1203 srcExpr := getSrc(src) 1204 typs, allowTwoValue := p.getIdxValTypes(args[0].Type, false, srcExpr) 1205 var tyRet types.Type 1206 if twoValue { // elem, ok = a[key] 1207 if !allowTwoValue { 1208 pos := getSrcPos(srcExpr) 1209 p.panicCodeError(pos, "assignment mismatch: 2 variables but 1 values") 1210 } 1211 pkg := p.pkg 1212 tyRet = types.NewTuple( 1213 pkg.NewParam(token.NoPos, "", typs[1]), 1214 pkg.NewParam(token.NoPos, "", types.Typ[types.Bool])) 1215 } else { // elem = a[key] 1216 tyRet = typs[1] 1217 } 1218 elem := &internal.Elem{ 1219 Val: &ast.IndexExpr{X: args[0].Val, Index: args[1].Val}, Type: tyRet, Src: srcExpr, 1220 } 1221 // TODO: check index type 1222 p.stk.Ret(2, elem) 1223 return p 1224 } 1225 1226 // IndexRef func 1227 func (p *CodeBuilder) IndexRef(nidx int, src ...ast.Node) *CodeBuilder { 1228 if debugInstr { 1229 log.Println("IndexRef", nidx) 1230 } 1231 if nidx != 1 { 1232 panic("IndexRef doesn't support a[i, j...] = val yet") 1233 } 1234 args := p.stk.GetArgs(2) 1235 typ := args[0].Type 1236 elemRef := &internal.Elem{ 1237 Val: &ast.IndexExpr{X: args[0].Val, Index: args[1].Val}, 1238 Src: getSrc(src), 1239 } 1240 if t, ok := typ.(*unboundType); ok { 1241 tyMapElem := &unboundMapElemType{key: args[1].Type, typ: t} 1242 elemRef.Type = &refType{typ: tyMapElem} 1243 } else { 1244 typs, _ := p.getIdxValTypes(typ, true, elemRef.Src) 1245 elemRef.Type = &refType{typ: typs[1]} 1246 // TODO: check index type 1247 } 1248 p.stk.Ret(2, elemRef) 1249 return p 1250 } 1251 1252 func (p *CodeBuilder) getIdxValTypes(typ types.Type, ref bool, idxSrc ast.Node) ([]types.Type, bool) { 1253 retry: 1254 switch t := typ.(type) { 1255 case *types.Slice: 1256 return []types.Type{tyInt, t.Elem()}, false 1257 case *types.Map: 1258 return []types.Type{t.Key(), t.Elem()}, true 1259 case *types.Array: 1260 return []types.Type{tyInt, t.Elem()}, false 1261 case *types.Pointer: 1262 elem := t.Elem() 1263 if named, ok := elem.(*types.Named); ok { 1264 elem = p.getUnderlying(named) 1265 } 1266 if e, ok := elem.(*types.Array); ok { 1267 return []types.Type{tyInt, e.Elem()}, false 1268 } 1269 case *types.Basic: 1270 if (t.Info() & types.IsString) != 0 { 1271 if ref { 1272 src, pos := p.loadExpr(idxSrc) 1273 p.panicCodeErrorf(pos, "cannot assign to %s (strings are immutable)", src) 1274 } 1275 return []types.Type{tyInt, TyByte}, false 1276 } 1277 case *types.Named: 1278 typ = p.getUnderlying(t) 1279 goto retry 1280 } 1281 src, pos := p.loadExpr(idxSrc) 1282 p.panicCodeErrorf(pos, "invalid operation: %s (type %v does not support indexing)", src, typ) 1283 return nil, false 1284 } 1285 1286 var ( 1287 tyInt = types.Typ[types.Int] 1288 ) 1289 1290 // Typ func 1291 func (p *CodeBuilder) Typ(typ types.Type, src ...ast.Node) *CodeBuilder { 1292 if debugInstr { 1293 log.Println("Typ", typ) 1294 } 1295 p.stk.Push(&internal.Elem{ 1296 Val: toType(p.pkg, typ), 1297 Type: NewTypeType(typ), 1298 Src: getSrc(src), 1299 }) 1300 return p 1301 } 1302 1303 // UntypedBigInt func 1304 func (p *CodeBuilder) UntypedBigInt(v *big.Int, src ...ast.Node) *CodeBuilder { 1305 pkg := p.pkg 1306 bigPkg := pkg.big() 1307 if v.IsInt64() { 1308 val := &ast.BasicLit{Kind: token.INT, Value: strconv.FormatInt(v.Int64(), 10)} 1309 p.Val(bigPkg.Ref("NewInt")).Val(val).Call(1) 1310 } else { 1311 /* 1312 func() *typ { 1313 v, _ := new(typ).SetString(strVal, 10) 1314 return v 1315 }() 1316 */ 1317 typ := bigPkg.Ref("Int").Type() 1318 retTyp := types.NewPointer(typ) 1319 ret := pkg.NewParam(token.NoPos, "", retTyp) 1320 p.NewClosure(nil, types.NewTuple(ret), false).BodyStart(pkg). 1321 DefineVarStart(token.NoPos, "v", "_"). 1322 Val(pkg.builtin.Ref("new")).Typ(typ).Call(1). 1323 MemberVal("SetString").Val(v.String()).Val(10).Call(2).EndInit(1). 1324 Val(p.Scope().Lookup("v")).Return(1). 1325 End().Call(0) 1326 } 1327 ret := p.stk.Get(-1) 1328 ret.Type, ret.CVal, ret.Src = pkg.utBigInt, constant.Make(v), getSrc(src) 1329 return p 1330 } 1331 1332 // UntypedBigRat func 1333 func (p *CodeBuilder) UntypedBigRat(v *big.Rat, src ...ast.Node) *CodeBuilder { 1334 pkg := p.pkg 1335 bigPkg := pkg.big() 1336 a, b := v.Num(), v.Denom() 1337 if a.IsInt64() && b.IsInt64() { 1338 va := &ast.BasicLit{Kind: token.INT, Value: strconv.FormatInt(a.Int64(), 10)} 1339 vb := &ast.BasicLit{Kind: token.INT, Value: strconv.FormatInt(b.Int64(), 10)} 1340 p.Val(bigPkg.Ref("NewRat")).Val(va).Val(vb).Call(2) 1341 } else { 1342 // new(big.Rat).SetFrac(a, b) 1343 p.Val(p.pkg.builtin.Ref("new")).Typ(bigPkg.Ref("Rat").Type()).Call(1). 1344 MemberVal("SetFrac").UntypedBigInt(a).UntypedBigInt(b).Call(2) 1345 } 1346 ret := p.stk.Get(-1) 1347 ret.Type, ret.CVal, ret.Src = pkg.utBigRat, constant.Make(v), getSrc(src) 1348 return p 1349 } 1350 1351 func (p *CodeBuilder) VarVal(name string, src ...ast.Node) *CodeBuilder { 1352 _, o := p.Scope().LookupParent(name, token.NoPos) 1353 if o == nil { 1354 log.Panicf("VarVal: variable `%v` not found\n", name) 1355 } 1356 return p.Val(o, src...) 1357 } 1358 1359 // Val func 1360 func (p *CodeBuilder) Val(v interface{}, src ...ast.Node) *CodeBuilder { 1361 if debugInstr { 1362 if o, ok := v.(types.Object); ok { 1363 log.Println("Val", o.Name(), o.Type()) 1364 } else { 1365 log.Println("Val", v, reflect.TypeOf(v)) 1366 } 1367 } 1368 fn := p.current.fn 1369 if fn != nil && fn.isInline() { // is in an inline call 1370 if param, ok := v.(*types.Var); ok { 1371 key := closureParamInst{fn, param} 1372 if arg, ok := p.paramInsts[key]; ok { // replace param with arg 1373 v = arg 1374 } 1375 } 1376 } 1377 return p.pushVal(v, getSrc(src)) 1378 } 1379 1380 func (p *CodeBuilder) pushVal(v interface{}, src ast.Node) *CodeBuilder { 1381 p.stk.Push(toExpr(p.pkg, v, src)) 1382 return p 1383 } 1384 1385 // Star func 1386 func (p *CodeBuilder) Star(src ...ast.Node) *CodeBuilder { 1387 if debugInstr { 1388 log.Println("Star") 1389 } 1390 arg := p.stk.Get(-1) 1391 ret := &internal.Elem{Val: &ast.StarExpr{X: arg.Val}, Src: getSrc(src)} 1392 argType := arg.Type 1393 retry: 1394 switch t := argType.(type) { 1395 case *TypeType: 1396 ret.Type = t.Pointer() 1397 case *types.Pointer: 1398 ret.Type = t.Elem() 1399 case *types.Named: 1400 argType = p.getUnderlying(t) 1401 goto retry 1402 default: 1403 code, pos := p.loadExpr(arg.Src) 1404 p.panicCodeErrorf(pos, "invalid indirect of %s (type %v)", code, t) 1405 } 1406 p.stk.Ret(1, ret) 1407 return p 1408 } 1409 1410 // Elem func 1411 func (p *CodeBuilder) Elem(src ...ast.Node) *CodeBuilder { 1412 if debugInstr { 1413 log.Println("Elem") 1414 } 1415 arg := p.stk.Get(-1) 1416 t, ok := arg.Type.(*types.Pointer) 1417 if !ok { 1418 code, pos := p.loadExpr(arg.Src) 1419 p.panicCodeErrorf(pos, "invalid indirect of %s (type %v)", code, arg.Type) 1420 } 1421 p.stk.Ret(1, &internal.Elem{Val: &ast.StarExpr{X: arg.Val}, Type: t.Elem(), Src: getSrc(src)}) 1422 return p 1423 } 1424 1425 // ElemRef func 1426 func (p *CodeBuilder) ElemRef(src ...ast.Node) *CodeBuilder { 1427 if debugInstr { 1428 log.Println("ElemRef") 1429 } 1430 arg := p.stk.Get(-1) 1431 t, ok := arg.Type.(*types.Pointer) 1432 if !ok { 1433 code, pos := p.loadExpr(arg.Src) 1434 p.panicCodeErrorf(pos, "invalid indirect of %s (type %v)", code, arg.Type) 1435 } 1436 p.stk.Ret(1, &internal.Elem{ 1437 Val: &ast.StarExpr{X: arg.Val}, Type: &refType{typ: t.Elem()}, Src: getSrc(src), 1438 }) 1439 return p 1440 } 1441 1442 // MemberVal func 1443 func (p *CodeBuilder) MemberVal(name string, src ...ast.Node) *CodeBuilder { 1444 _, err := p.Member(name, MemberFlagVal, src...) 1445 if err != nil { 1446 panic(err) 1447 } 1448 return p 1449 } 1450 1451 // MemberRef func 1452 func (p *CodeBuilder) MemberRef(name string, src ...ast.Node) *CodeBuilder { 1453 _, err := p.Member(name, MemberFlagRef, src...) 1454 if err != nil { 1455 panic(err) 1456 } 1457 return p 1458 } 1459 1460 func (p *CodeBuilder) refMember(typ types.Type, name string, argVal ast.Expr, src ast.Node) MemberKind { 1461 switch o := indirect(typ).(type) { 1462 case *types.Named: 1463 if struc, ok := p.getUnderlying(o).(*types.Struct); ok { 1464 if p.fieldRef(argVal, struc, name, src) { 1465 return MemberField 1466 } 1467 } 1468 case *types.Struct: 1469 if p.fieldRef(argVal, o, name, src) { 1470 return MemberField 1471 } 1472 } 1473 return MemberInvalid 1474 } 1475 1476 func (p *CodeBuilder) fieldRef(x ast.Expr, o *types.Struct, name string, src ast.Node) bool { 1477 for i, n := 0, o.NumFields(); i < n; i++ { 1478 fld := o.Field(i) 1479 if fld.Name() == name { 1480 if p.rec != nil { 1481 p.rec.Member(src, fld) 1482 } 1483 p.stk.Ret(1, &internal.Elem{ 1484 Val: &ast.SelectorExpr{X: x, Sel: ident(name)}, 1485 Type: &refType{typ: fld.Type()}, 1486 }) 1487 return true 1488 } else if fld.Embedded() { 1489 fldt := fld.Type() 1490 if o, ok := fldt.(*types.Pointer); ok { 1491 fldt = o.Elem() 1492 } 1493 if t, ok := fldt.(*types.Named); ok { 1494 u := p.getUnderlying(t) 1495 if struc, ok := u.(*types.Struct); ok { 1496 if p.fieldRef(x, struc, name, src) { 1497 return true 1498 } 1499 } 1500 } 1501 } 1502 } 1503 return false 1504 } 1505 1506 type ( 1507 MemberKind int 1508 MemberFlag int 1509 ) 1510 1511 const ( 1512 MemberInvalid MemberKind = iota 1513 MemberMethod 1514 MemberAutoProperty 1515 MemberField 1516 memberBad MemberKind = -1 1517 ) 1518 1519 const ( 1520 MemberFlagVal MemberFlag = iota 1521 MemberFlagMethodAlias 1522 MemberFlagAutoProperty 1523 MemberFlagRef MemberFlag = -1 1524 1525 // private state 1526 memberFlagMethodToFunc MemberFlag = 0x80 1527 ) 1528 1529 func aliasNameOf(name string, flag MemberFlag) (string, MemberFlag) { 1530 // flag > 0 means: 1531 // flag == MemberFlagMethodAlias || 1532 // flag == MemberFlagAutoProperty || 1533 // flag == memberFlagMethodToFunc 1534 if flag > 0 && name != "" { 1535 if c := name[0]; c >= 'a' && c <= 'z' { 1536 return string(rune(c)+('A'-'a')) + name[1:], flag 1537 } 1538 if flag != memberFlagMethodToFunc { 1539 flag = MemberFlagVal 1540 } 1541 } 1542 return "", flag 1543 } 1544 1545 // Member access member by its name. 1546 // src should point to the full source node `x.sel` 1547 func (p *CodeBuilder) Member(name string, flag MemberFlag, src ...ast.Node) (kind MemberKind, err error) { 1548 srcExpr := getSrc(src) 1549 arg := p.stk.Get(-1) 1550 if debugInstr { 1551 log.Println("Member", name, flag, "//", arg.Type) 1552 } 1553 switch arg.Type { 1554 case p.pkg.utBigInt, p.pkg.utBigRat, p.pkg.utBigFlt: 1555 arg.Type = DefaultConv(p.pkg, arg.Type, arg) 1556 } 1557 at := arg.Type 1558 if flag == MemberFlagRef { 1559 kind = p.refMember(at, name, arg.Val, srcExpr) 1560 } else { 1561 var aliasName string 1562 var t, isType = at.(*TypeType) 1563 if isType { // (T).method or (*T).method 1564 at = t.Type() 1565 flag = memberFlagMethodToFunc 1566 } 1567 aliasName, flag = aliasNameOf(name, flag) 1568 kind = p.findMember(at, name, aliasName, flag, arg, srcExpr) 1569 if isType && kind != MemberMethod { 1570 code, pos := p.loadExpr(srcExpr) 1571 return MemberInvalid, p.newCodeError( 1572 pos, fmt.Sprintf("%s undefined (type %v has no method %s)", code, at, name)) 1573 } 1574 } 1575 if kind > 0 { 1576 return 1577 } 1578 code, pos := p.loadExpr(srcExpr) 1579 return MemberInvalid, p.newCodeError( 1580 pos, fmt.Sprintf("%s undefined (type %v has no field or method %s)", code, arg.Type, name)) 1581 } 1582 1583 func (p *CodeBuilder) getUnderlying(t *types.Named) types.Type { 1584 u := t.Underlying() 1585 if u == nil { 1586 p.loadNamed(p.pkg, t) 1587 u = t.Underlying() 1588 } 1589 return u 1590 } 1591 1592 func (p *CodeBuilder) ensureLoaded(typ types.Type) { 1593 if t, ok := typ.(*types.Pointer); ok { 1594 typ = t.Elem() 1595 } 1596 if t, ok := typ.(*types.Named); ok && (t.NumMethods() == 0 || t.Underlying() == nil) { 1597 if debugMatch { 1598 log.Println("==> EnsureLoaded", typ) 1599 } 1600 p.loadNamed(p.pkg, t) 1601 } 1602 } 1603 1604 func getUnderlying(pkg *Package, typ types.Type) types.Type { 1605 u := typ.Underlying() 1606 if u == nil { 1607 if t, ok := typ.(*types.Named); ok { 1608 pkg.cb.loadNamed(pkg, t) 1609 u = t.Underlying() 1610 } 1611 } 1612 return u 1613 } 1614 1615 func (p *CodeBuilder) findMember( 1616 typ types.Type, name, aliasName string, flag MemberFlag, arg *Element, srcExpr ast.Node) MemberKind { 1617 var named *types.Named 1618 retry: 1619 switch o := typ.(type) { 1620 case *types.Pointer: 1621 switch t := o.Elem().(type) { 1622 case *types.Named: 1623 u := p.getUnderlying(t) // may cause to loadNamed (delay-loaded) 1624 struc, fstruc := u.(*types.Struct) 1625 if fstruc { 1626 if kind := p.normalField(struc, name, arg, srcExpr); kind != MemberInvalid { 1627 return kind 1628 } 1629 } 1630 if kind := p.method(t, name, aliasName, flag, arg, srcExpr); kind != MemberInvalid { 1631 return kind 1632 } 1633 if fstruc { 1634 return p.embeddedField(struc, name, aliasName, flag, arg, srcExpr) 1635 } 1636 case *types.Struct: 1637 if kind := p.field(t, name, aliasName, flag, arg, srcExpr); kind != MemberInvalid { 1638 return kind 1639 } 1640 } 1641 case *types.Named: 1642 named, typ = o, p.getUnderlying(o) // may cause to loadNamed (delay-loaded) 1643 if kind := p.method(o, name, aliasName, flag, arg, srcExpr); kind != MemberInvalid { 1644 return kind 1645 } 1646 goto retry 1647 case *types.Struct: 1648 if kind := p.field(o, name, aliasName, flag, arg, srcExpr); kind != MemberInvalid { 1649 return kind 1650 } 1651 if named != nil { 1652 return MemberInvalid 1653 } 1654 case *types.Interface: 1655 o.Complete() 1656 if kind := p.method(o, name, aliasName, flag, arg, srcExpr); kind != MemberInvalid { 1657 return kind 1658 } 1659 case *types.Basic, *types.Slice, *types.Map, *types.Chan: 1660 return p.btiMethod(p.getBuiltinTI(o), name, aliasName, flag, srcExpr) 1661 } 1662 return MemberInvalid 1663 } 1664 1665 type methodList interface { 1666 NumMethods() int 1667 Method(i int) *types.Func 1668 } 1669 1670 func selector(arg *Element, name string) *ast.SelectorExpr { 1671 denoted := &ast.Object{Data: arg} 1672 return &ast.SelectorExpr{X: arg.Val, Sel: &ast.Ident{Name: name, Obj: denoted}} 1673 } 1674 1675 func denoteRecv(v *ast.SelectorExpr) *Element { 1676 if o := v.Sel.Obj; o != nil { 1677 if e, ok := o.Data.(*Element); ok { 1678 return e 1679 } 1680 } 1681 return nil 1682 } 1683 1684 func getDenoted(expr ast.Expr) *ast.Object { 1685 switch v := expr.(type) { 1686 case *ast.SelectorExpr: 1687 return v.Sel.Obj 1688 case *ast.Ident: 1689 return v.Obj 1690 default: 1691 return nil 1692 } 1693 } 1694 1695 func setDenoted(expr ast.Expr, denoted *ast.Object) { 1696 switch v := expr.(type) { 1697 case *ast.SelectorExpr: 1698 v.Sel.Obj = denoted 1699 case *ast.Ident: 1700 v.Obj = denoted 1701 } 1702 } 1703 1704 func (p *CodeBuilder) allowAccess(pkg *types.Package, name string) bool { 1705 if !ast.IsExported(name) && pkg != nil && pkg.Path() != p.pkg.Path() { 1706 return false 1707 } 1708 return true 1709 } 1710 1711 func (p *CodeBuilder) method( 1712 o methodList, name, aliasName string, flag MemberFlag, arg *Element, src ast.Node) (kind MemberKind) { 1713 var found *types.Func 1714 var exact bool 1715 for i, n := 0, o.NumMethods(); i < n; i++ { 1716 method := o.Method(i) 1717 v := method.Name() 1718 if !p.allowAccess(method.Pkg(), v) { 1719 continue 1720 } 1721 if v == name { 1722 found, exact = method, true 1723 break 1724 } else if flag > 0 && v == aliasName { 1725 found = method 1726 if method.Pkg() != p.pkg.Types { 1727 break 1728 } 1729 } 1730 } 1731 if found != nil { 1732 autoprop := !exact && flag == MemberFlagAutoProperty 1733 typ := found.Type() 1734 if autoprop && !methodHasAutoProperty(typ, 0) { 1735 return memberBad 1736 } 1737 1738 sel := selector(arg, found.Name()) 1739 ret := &internal.Elem{Val: sel, Src: src} 1740 if t, set := p.methodSigOf(typ, flag, arg, ret); set { 1741 ret.Type = t 1742 } 1743 p.stk.Ret(1, ret) 1744 1745 if p.rec != nil { 1746 p.rec.Member(src, found) 1747 } 1748 if autoprop { 1749 p.CallWith(0, 0, src) 1750 return MemberAutoProperty 1751 } 1752 return MemberMethod 1753 } 1754 if t, ok := o.(*types.Named); ok { 1755 kind = p.btiMethod(p.getBuiltinTI(t), name, aliasName, flag, src) 1756 } 1757 return 1758 } 1759 1760 func isTypeConvert(otyp, typ types.Type) (string, bool) { 1761 if otyp != typ { 1762 if t, ok := typ.Underlying().(*types.Basic); ok && 1763 (t.Info()&types.IsUntyped) == 0 { 1764 return t.Name(), true 1765 } 1766 } 1767 return "", false 1768 } 1769 1770 func (p *CodeBuilder) btiMethod( 1771 o *builtinTI, name, aliasName string, flag MemberFlag, src ast.Node) MemberKind { 1772 if o != nil { 1773 for i, n := 0, o.NumMethods(); i < n; i++ { 1774 method := o.Method(i) 1775 v := method.name 1776 if v == name || (flag > 0 && v == aliasName) { 1777 autoprop := flag == MemberFlagAutoProperty && v == aliasName 1778 this := p.stk.Pop() 1779 if fn, ok := isTypeConvert(o.typ, this.Type); ok { 1780 this.Val = &ast.CallExpr{ 1781 Fun: ast.NewIdent(fn), 1782 Args: []ast.Expr{this.Val}, 1783 } 1784 this.Type = &btiMethodType{Type: o.typ, eargs: method.eargs} 1785 } else { 1786 this.Type = &btiMethodType{Type: this.Type, eargs: method.eargs} 1787 } 1788 p.Val(method.fn, src) 1789 p.stk.Push(this) 1790 if p.rec != nil { 1791 p.rec.Member(src, method.fn) 1792 } 1793 if autoprop { 1794 p.CallWith(0, 0, src) 1795 return MemberAutoProperty 1796 } 1797 return MemberMethod 1798 } 1799 } 1800 } 1801 return MemberInvalid 1802 } 1803 1804 func (p *CodeBuilder) normalField( 1805 o *types.Struct, name string, arg *Element, src ast.Node) MemberKind { 1806 for i, n := 0, o.NumFields(); i < n; i++ { 1807 fld := o.Field(i) 1808 v := fld.Name() 1809 if !p.allowAccess(fld.Pkg(), v) { 1810 continue 1811 } 1812 if v == name { 1813 p.stk.Ret(1, &internal.Elem{ 1814 Val: selector(arg, name), 1815 Type: fld.Type(), 1816 Src: src, 1817 }) 1818 if p.rec != nil { 1819 p.rec.Member(src, fld) 1820 } 1821 return MemberField 1822 } 1823 } 1824 return MemberInvalid 1825 } 1826 1827 func (p *CodeBuilder) embeddedField( 1828 o *types.Struct, name, aliasName string, flag MemberFlag, arg *Element, src ast.Node) MemberKind { 1829 for i, n := 0, o.NumFields(); i < n; i++ { 1830 if fld := o.Field(i); fld.Embedded() { 1831 if kind := p.findMember(fld.Type(), name, aliasName, flag, arg, src); kind != MemberInvalid { 1832 return kind 1833 } 1834 } 1835 } 1836 return MemberInvalid 1837 } 1838 1839 func (p *CodeBuilder) field( 1840 o *types.Struct, name, aliasName string, flag MemberFlag, arg *Element, src ast.Node) MemberKind { 1841 if kind := p.normalField(o, name, arg, src); kind != MemberInvalid { 1842 return kind 1843 } 1844 return p.embeddedField(o, name, aliasName, flag, arg, src) 1845 } 1846 1847 func toFuncSig(sig *types.Signature, recv *types.Var) *types.Signature { 1848 sp := sig.Params() 1849 spLen := sp.Len() 1850 vars := make([]*types.Var, spLen+1) 1851 vars[0] = recv 1852 for i := 0; i < spLen; i++ { 1853 vars[i+1] = sp.At(i) 1854 } 1855 return types.NewSignatureType(nil, nil, nil, types.NewTuple(vars...), sig.Results(), sig.Variadic()) 1856 } 1857 1858 func methodToFuncSig(pkg *Package, o types.Object, fn *Element) *types.Signature { 1859 sig := o.Type().(*types.Signature) 1860 recv := sig.Recv() 1861 if recv == nil { // special signature 1862 fn.Val = toObjectExpr(pkg, o) 1863 return sig 1864 } 1865 1866 sel := fn.Val.(*ast.SelectorExpr) 1867 sel.Sel = ident(o.Name()) 1868 sel.X = &ast.ParenExpr{X: sel.X} 1869 return toFuncSig(sig, recv) 1870 } 1871 1872 func (p *CodeBuilder) methodSigOf(typ types.Type, flag MemberFlag, arg, ret *Element) (types.Type, bool) { 1873 if flag != memberFlagMethodToFunc { 1874 return methodCallSig(typ), true 1875 } 1876 1877 sig := typ.(*types.Signature) 1878 if t, ok := CheckFuncEx(sig); ok { 1879 switch ext := t.(type) { 1880 case *TyStaticMethod: 1881 return p.funcExSigOf(ext.Func, ret) 1882 case *TyTemplateRecvMethod: 1883 return p.funcExSigOf(ext.Func, ret) 1884 } 1885 // TODO: We should take `methodSigOf` more seriously 1886 return typ, true 1887 } 1888 1889 sel := ret.Val.(*ast.SelectorExpr) 1890 at := arg.Type.(*TypeType).typ 1891 recv := sig.Recv().Type() 1892 _, isPtr := recv.(*types.Pointer) // recv is a pointer 1893 if t, ok := at.(*types.Pointer); ok { 1894 if !isPtr { 1895 if _, ok := recv.Underlying().(*types.Interface); !ok { // and recv isn't a interface 1896 log.Panicf("recv of method %v.%s isn't a pointer\n", t.Elem(), sel.Sel.Name) 1897 } 1898 } 1899 } else if isPtr { // use *T 1900 at = types.NewPointer(at) 1901 sel.X = &ast.StarExpr{X: sel.X} 1902 } 1903 sel.X = &ast.ParenExpr{X: sel.X} 1904 1905 return toFuncSig(sig, types.NewVar(token.NoPos, nil, "", at)), true 1906 } 1907 1908 func (p *CodeBuilder) funcExSigOf(o types.Object, ret *Element) (types.Type, bool) { 1909 ret.Val = toObjectExpr(p.pkg, o) 1910 ret.Type = o.Type() 1911 return nil, false 1912 } 1913 1914 func methodCallSig(typ types.Type) types.Type { 1915 sig := typ.(*types.Signature) 1916 if _, ok := CheckFuncEx(sig); ok { 1917 // TODO: We should take `methodSigOf` more seriously 1918 return typ 1919 } 1920 return types.NewSignatureType(nil, nil, nil, sig.Params(), sig.Results(), sig.Variadic()) 1921 } 1922 1923 func indirect(typ types.Type) types.Type { 1924 if t, ok := typ.(*types.Pointer); ok { 1925 typ = t.Elem() 1926 } 1927 return typ 1928 } 1929 1930 // IncDec func 1931 func (p *CodeBuilder) IncDec(op token.Token, src ...ast.Node) *CodeBuilder { 1932 name := goxPrefix + incdecOps[op] 1933 if debugInstr { 1934 log.Println("IncDec", op) 1935 } 1936 pkg := p.pkg 1937 arg := p.stk.Pop() 1938 if t, ok := arg.Type.(*refType).typ.(*types.Named); ok { 1939 op := lookupMethod(t, name) 1940 if op != nil { 1941 fn := &internal.Elem{ 1942 Val: &ast.SelectorExpr{X: arg.Val, Sel: ident(name)}, 1943 Type: realType(op.Type()), 1944 } 1945 ret := toFuncCall(pkg, fn, []*Element{arg}, 0) 1946 if ret.Type != nil { 1947 p.shouldNoResults(name, src) 1948 } 1949 p.emitStmt(&ast.ExprStmt{X: ret.Val}) 1950 return p 1951 } 1952 } 1953 fn := pkg.builtin.Ref(name) 1954 t := fn.Type().(*TyInstruction) 1955 if _, err := t.instr.Call(pkg, []*Element{arg}, 0, nil); err != nil { 1956 panic(err) 1957 } 1958 return p 1959 } 1960 1961 var ( 1962 incdecOps = [...]string{ 1963 token.INC: "Inc", 1964 token.DEC: "Dec", 1965 } 1966 ) 1967 1968 // AssignOp func 1969 func (p *CodeBuilder) AssignOp(op token.Token, src ...ast.Node) *CodeBuilder { 1970 args := p.stk.GetArgs(2) 1971 stmt := callAssignOp(p.pkg, op, args, src) 1972 p.emitStmt(stmt) 1973 p.stk.PopN(2) 1974 return p 1975 } 1976 1977 func checkDivisionByZero(cb *CodeBuilder, a, b *internal.Elem) { 1978 if a.CVal == nil { 1979 if isNormalInt(cb, a) { 1980 if c := b.CVal; c != nil { 1981 switch c.Kind() { 1982 case constant.Int, constant.Float, constant.Complex: 1983 if constant.Sign(c) == 0 { 1984 pos := getSrcPos(b.Src) 1985 cb.panicCodeError(pos, "invalid operation: division by zero") 1986 } 1987 } 1988 } 1989 } 1990 } else if c := b.CVal; c != nil { 1991 switch c.Kind() { 1992 case constant.Int, constant.Float, constant.Complex: 1993 if constant.Sign(c) == 0 { 1994 pos := getSrcPos(b.Src) 1995 cb.panicCodeError(pos, "invalid operation: division by zero") 1996 } 1997 } 1998 } 1999 } 2000 2001 func callAssignOp(pkg *Package, tok token.Token, args []*internal.Elem, src []ast.Node) ast.Stmt { 2002 name := goxPrefix + assignOps[tok] 2003 if debugInstr { 2004 log.Println("AssignOp", tok, name) 2005 } 2006 if t, ok := args[0].Type.(*refType).typ.(*types.Named); ok { 2007 op := lookupMethod(t, name) 2008 if op != nil { 2009 fn := &internal.Elem{ 2010 Val: &ast.SelectorExpr{X: args[0].Val, Sel: ident(name)}, 2011 Type: realType(op.Type()), 2012 } 2013 ret := toFuncCall(pkg, fn, args, 0) 2014 if ret.Type != nil { 2015 pkg.cb.shouldNoResults(name, src) 2016 } 2017 return &ast.ExprStmt{X: ret.Val} 2018 } 2019 } 2020 op := pkg.builtin.Ref(name) 2021 if tok == token.QUO_ASSIGN { 2022 checkDivisionByZero(&pkg.cb, &internal.Elem{Val: args[0].Val, Type: args[0].Type.(*refType).typ}, args[1]) 2023 } 2024 fn := &internal.Elem{ 2025 Val: ident(op.Name()), Type: op.Type(), 2026 } 2027 toFuncCall(pkg, fn, args, 0) 2028 return &ast.AssignStmt{ 2029 Tok: tok, 2030 Lhs: []ast.Expr{args[0].Val}, 2031 Rhs: []ast.Expr{args[1].Val}, 2032 } 2033 } 2034 2035 func (p *CodeBuilder) shouldNoResults(name string, src []ast.Node) { 2036 pos := token.NoPos 2037 if src != nil { 2038 pos = src[0].Pos() 2039 } 2040 p.panicCodeErrorf(pos, "operator %s should return no results\n", name) 2041 } 2042 2043 var ( 2044 assignOps = [...]string{ 2045 token.ADD_ASSIGN: "AddAssign", // += 2046 token.SUB_ASSIGN: "SubAssign", // -= 2047 token.MUL_ASSIGN: "MulAssign", // *= 2048 token.QUO_ASSIGN: "QuoAssign", // /= 2049 token.REM_ASSIGN: "RemAssign", // %= 2050 2051 token.AND_ASSIGN: "AndAssign", // &= 2052 token.OR_ASSIGN: "OrAssign", // |= 2053 token.XOR_ASSIGN: "XorAssign", // ^= 2054 token.AND_NOT_ASSIGN: "AndNotAssign", // &^= 2055 token.SHL_ASSIGN: "LshAssign", // <<= 2056 token.SHR_ASSIGN: "RshAssign", // >>= 2057 } 2058 ) 2059 2060 // Assign func 2061 func (p *CodeBuilder) Assign(lhs int, rhs ...int) *CodeBuilder { 2062 var v int 2063 if rhs != nil { 2064 v = rhs[0] 2065 } else { 2066 v = lhs 2067 } 2068 if debugInstr { 2069 log.Println("Assign", lhs, v) 2070 } 2071 return p.doAssignWith(lhs, v, nil) 2072 } 2073 2074 // AssignWith func 2075 func (p *CodeBuilder) AssignWith(lhs, rhs int, src ...ast.Node) *CodeBuilder { 2076 if debugInstr { 2077 log.Println("Assign", lhs, rhs) 2078 } 2079 return p.doAssignWith(lhs, rhs, getSrc(src)) 2080 } 2081 2082 func (p *CodeBuilder) doAssignWith(lhs, rhs int, src ast.Node) *CodeBuilder { 2083 mkBlockStmt := false 2084 args := p.stk.GetArgs(lhs + rhs) 2085 stmt := &ast.AssignStmt{ 2086 Tok: token.ASSIGN, 2087 Lhs: make([]ast.Expr, lhs), 2088 Rhs: make([]ast.Expr, rhs), 2089 } 2090 if rhs == 1 { 2091 if rhsVals, ok := args[lhs].Type.(*types.Tuple); ok { 2092 if lhs != rhsVals.Len() { 2093 pos := getSrcPos(src) 2094 caller := getCaller(args[lhs]) 2095 p.panicCodeErrorf( 2096 pos, "assignment mismatch: %d variables but %v returns %d values", 2097 lhs, caller, rhsVals.Len()) 2098 } 2099 for i := 0; i < lhs; i++ { 2100 val := &internal.Elem{Type: rhsVals.At(i).Type()} 2101 checkAssignType(p.pkg, args[i].Type, val) 2102 stmt.Lhs[i] = args[i].Val 2103 } 2104 stmt.Rhs[0] = args[lhs].Val 2105 goto done 2106 } 2107 } 2108 if lhs == rhs { 2109 for i := 0; i < lhs; i++ { 2110 lhsType := args[i].Type 2111 checkAssignType(p.pkg, lhsType, args[lhs+i]) 2112 stmt.Lhs[i] = args[i].Val 2113 stmt.Rhs[i] = args[lhs+i].Val 2114 } 2115 } else { 2116 pos := getSrcPos(src) 2117 p.panicCodeErrorf( 2118 pos, "assignment mismatch: %d variables but %d values", lhs, rhs) 2119 } 2120 done: 2121 p.emitStmt(stmt) 2122 if mkBlockStmt { // } 2123 p.End() 2124 } else { 2125 p.stk.PopN(lhs + rhs) 2126 } 2127 return p 2128 } 2129 2130 func lookupMethod(t *types.Named, name string) types.Object { 2131 for i, n := 0, t.NumMethods(); i < n; i++ { 2132 m := t.Method(i) 2133 if m.Name() == name { 2134 return m 2135 } 2136 } 2137 return nil 2138 } 2139 2140 func doUnaryOp(cb *CodeBuilder, op token.Token, args []*internal.Elem, flags InstrFlags) (ret *internal.Elem, err error) { 2141 name := goxPrefix + unaryOps[op] 2142 pkg := cb.pkg 2143 typ := args[0].Type 2144 retry: 2145 switch t := typ.(type) { 2146 case *types.Named: 2147 lm := lookupMethod(t, name) 2148 if lm != nil { 2149 fn := &internal.Elem{ 2150 Val: &ast.SelectorExpr{X: args[0].Val, Sel: ident(name)}, 2151 Type: realType(lm.Type()), 2152 } 2153 return matchFuncCall(pkg, fn, args, flags|instrFlagOpFunc) 2154 } 2155 case *types.Pointer: 2156 typ = t.Elem() 2157 goto retry 2158 } 2159 lm := pkg.builtin.Ref(name) 2160 return matchFuncCall(pkg, toObject(pkg, lm, nil), args, flags) 2161 } 2162 2163 // UnaryOp: 2164 // - cb.UnaryOp(op token.Token) 2165 // - cb.UnaryOp(op token.Token, twoValue bool) 2166 // - cb.UnaryOp(op token.Token, twoValue bool, src ast.Node) 2167 func (p *CodeBuilder) UnaryOp(op token.Token, params ...interface{}) *CodeBuilder { 2168 var src ast.Node 2169 var flags InstrFlags 2170 switch len(params) { 2171 case 2: 2172 src, _ = params[1].(ast.Node) 2173 fallthrough 2174 case 1: 2175 if params[0].(bool) { 2176 flags = InstrFlagTwoValue 2177 } 2178 } 2179 if debugInstr { 2180 log.Println("UnaryOp", op, "flags:", flags) 2181 } 2182 ret, err := doUnaryOp(p, op, p.stk.GetArgs(1), flags) 2183 if err != nil { 2184 panic(err) 2185 } 2186 ret.Src = src 2187 p.stk.Ret(1, ret) 2188 return p 2189 } 2190 2191 // BinaryOp func 2192 func (p *CodeBuilder) BinaryOp(op token.Token, src ...ast.Node) *CodeBuilder { 2193 const ( 2194 errNotFound = syscall.ENOENT 2195 ) 2196 if debugInstr { 2197 log.Println("BinaryOp", xtoken.String(op)) 2198 } 2199 pkg := p.pkg 2200 name := goxPrefix + binaryOps[op] 2201 args := p.stk.GetArgs(2) 2202 2203 var ret *internal.Elem 2204 var err error = errNotFound 2205 isUserDef := false 2206 arg0 := args[0].Type 2207 named0, ok0 := checkNamed(arg0) 2208 if ok0 { 2209 if fn, e := pkg.MethodToFunc(arg0, name, src...); e == nil { 2210 ret, err = matchFuncCall(pkg, fn, args, instrFlagBinaryOp) 2211 isUserDef = true 2212 } 2213 } 2214 if err != nil { 2215 arg1 := args[1].Type 2216 if named1, ok1 := checkNamed(arg1); ok1 && named0 != named1 { 2217 if fn, e := pkg.MethodToFunc(arg1, name, src...); e == nil { 2218 ret, err = matchFuncCall(pkg, fn, args, instrFlagBinaryOp) 2219 isUserDef = true 2220 } 2221 } 2222 } 2223 if err != nil && !isUserDef { 2224 if op == token.QUO { 2225 checkDivisionByZero(p, args[0], args[1]) 2226 } 2227 if op == token.EQL || op == token.NEQ { 2228 if !ComparableTo(pkg, args[0], args[1]) { 2229 err = errors.New("mismatched types") 2230 } else { 2231 ret, err = &internal.Elem{ 2232 Val: &ast.BinaryExpr{ 2233 X: checkParenExpr(args[0].Val), Op: op, 2234 Y: checkParenExpr(args[1].Val), 2235 }, 2236 Type: types.Typ[types.UntypedBool], 2237 CVal: binaryOp(p, op, args), 2238 }, nil 2239 } 2240 } else if lm := pkg.builtin.TryRef(name); lm != nil { 2241 ret, err = matchFuncCall(pkg, toObject(pkg, lm, nil), args, 0) 2242 } else { 2243 err = errNotFound 2244 } 2245 } 2246 2247 expr := getSrc(src) 2248 if err != nil { 2249 opstr := xtoken.String(op) 2250 src, pos := p.loadExpr(expr) 2251 if src == "" { 2252 src = opstr 2253 } 2254 if err != errNotFound { 2255 p.panicCodeErrorf( 2256 pos, "invalid operation: %s (mismatched types %v and %v)", src, arg0, args[1].Type) 2257 } else { 2258 arg0Src, _ := p.loadExpr(args[0].Src) 2259 p.panicCodeErrorf( 2260 pos, "invalid operation: operator %s not defined on %s (%v)", opstr, arg0Src, arg0) 2261 } 2262 } 2263 ret.Src = expr 2264 p.stk.Ret(2, ret) 2265 return p 2266 } 2267 2268 func checkNamed(typ types.Type) (ret *types.Named, ok bool) { 2269 if t, ok := typ.(*types.Pointer); ok { 2270 typ = t.Elem() 2271 } 2272 ret, ok = typ.(*types.Named) 2273 return 2274 } 2275 2276 var ( 2277 unaryOps = [...]string{ 2278 token.SUB: "Neg", 2279 token.ADD: "Dup", 2280 token.XOR: "Not", 2281 token.NOT: "LNot", 2282 token.ARROW: "Recv", 2283 token.AND: "Addr", 2284 } 2285 binaryOps = [...]string{ 2286 token.ADD: "Add", // + 2287 token.SUB: "Sub", // - 2288 token.MUL: "Mul", // * 2289 token.QUO: "Quo", // / 2290 token.REM: "Rem", // % 2291 2292 token.AND: "And", // & 2293 token.OR: "Or", // | 2294 token.XOR: "Xor", // ^ 2295 token.AND_NOT: "AndNot", // &^ 2296 token.SHL: "Lsh", // << 2297 token.SHR: "Rsh", // >> 2298 2299 token.LAND: "LAnd", // && 2300 token.LOR: "LOr", // || 2301 2302 token.LSS: "LT", 2303 token.LEQ: "LE", 2304 token.GTR: "GT", 2305 token.GEQ: "GE", 2306 token.EQL: "EQ", 2307 token.NEQ: "NE", 2308 2309 xtoken.SRARROW: "PointTo", // -> 2310 xtoken.BIDIARROW: "PointBi", // <> 2311 } 2312 ) 2313 2314 // CompareNil func 2315 func (p *CodeBuilder) CompareNil(op token.Token, src ...ast.Node) *CodeBuilder { 2316 return p.Val(nil).BinaryOp(op) 2317 } 2318 2319 // Send func 2320 func (p *CodeBuilder) Send() *CodeBuilder { 2321 if debugInstr { 2322 log.Println("Send") 2323 } 2324 val := p.stk.Pop() 2325 ch := p.stk.Pop() 2326 // TODO: check types 2327 p.emitStmt(&ast.SendStmt{Chan: ch.Val, Value: val.Val}) 2328 return p 2329 } 2330 2331 // Defer func 2332 func (p *CodeBuilder) Defer() *CodeBuilder { 2333 if debugInstr { 2334 log.Println("Defer") 2335 } 2336 arg := p.stk.Pop() 2337 call, ok := arg.Val.(*ast.CallExpr) 2338 if !ok { 2339 panic("TODO: please use defer callExpr()") 2340 } 2341 p.emitStmt(&ast.DeferStmt{Call: call}) 2342 return p 2343 } 2344 2345 // Go func 2346 func (p *CodeBuilder) Go() *CodeBuilder { 2347 if debugInstr { 2348 log.Println("Go") 2349 } 2350 arg := p.stk.Pop() 2351 call, ok := arg.Val.(*ast.CallExpr) 2352 if !ok { 2353 panic("TODO: please use go callExpr()") 2354 } 2355 p.emitStmt(&ast.GoStmt{Call: call}) 2356 return p 2357 } 2358 2359 // Block starts a block statement. 2360 func (p *CodeBuilder) Block(src ...ast.Node) *CodeBuilder { 2361 if debugInstr { 2362 log.Println("Block") 2363 } 2364 stmt := &blockStmt{} 2365 p.startBlockStmt(stmt, src, "block statement", &stmt.old) 2366 return p 2367 } 2368 2369 // VBlock starts a vblock statement. 2370 func (p *CodeBuilder) VBlock() *CodeBuilder { 2371 if debugInstr { 2372 log.Println("VBlock") 2373 } 2374 stmt := &vblockStmt{} 2375 p.startVBlockStmt(stmt, "vblock statement", &stmt.old) 2376 return p 2377 } 2378 2379 // InVBlock checks if current statement is in vblock or not. 2380 func (p *CodeBuilder) InVBlock() bool { 2381 _, ok := p.current.codeBlock.(*vblockStmt) 2382 return ok 2383 } 2384 2385 // Block starts a if statement. 2386 func (p *CodeBuilder) If(src ...ast.Node) *CodeBuilder { 2387 if debugInstr { 2388 log.Println("If") 2389 } 2390 stmt := &ifStmt{} 2391 p.startBlockStmt(stmt, src, "if statement", &stmt.old) 2392 return p 2393 } 2394 2395 // Then starts body of a if/switch/for/case statement. 2396 func (p *CodeBuilder) Then(src ...ast.Node) *CodeBuilder { 2397 if debugInstr { 2398 log.Println("Then") 2399 } 2400 if flow, ok := p.current.codeBlock.(controlFlow); ok { 2401 flow.Then(p, src...) 2402 return p 2403 } 2404 panic("use if..then or switch..then or for..then please") 2405 } 2406 2407 // Else starts else body of a if..else statement. 2408 func (p *CodeBuilder) Else(src ...ast.Node) *CodeBuilder { 2409 if debugInstr { 2410 log.Println("Else") 2411 } 2412 if flow, ok := p.current.codeBlock.(*ifStmt); ok { 2413 flow.Else(p, src...) 2414 return p 2415 } 2416 panic("use if..else please") 2417 } 2418 2419 // TypeSwitch starts a type switch statement. 2420 // 2421 // <pre> 2422 // typeSwitch(name) init; expr typeAssertThen 2423 // type1, type2, ... typeN typeCase(N) 2424 // 2425 // ... 2426 // end 2427 // 2428 // type1, type2, ... typeM typeCase(M) 2429 // 2430 // ... 2431 // end 2432 // 2433 // end 2434 // </pre> 2435 func (p *CodeBuilder) TypeSwitch(name string, src ...ast.Node) *CodeBuilder { 2436 if debugInstr { 2437 log.Println("TypeSwitch") 2438 } 2439 stmt := &typeSwitchStmt{name: name} 2440 p.startBlockStmt(stmt, src, "type switch statement", &stmt.old) 2441 return p 2442 } 2443 2444 // TypeAssert func 2445 func (p *CodeBuilder) TypeAssert(typ types.Type, twoValue bool, src ...ast.Node) *CodeBuilder { 2446 if debugInstr { 2447 log.Println("TypeAssert", typ, twoValue) 2448 } 2449 arg := p.stk.Get(-1) 2450 xType, ok := p.checkInterface(arg.Type) 2451 if !ok { 2452 text, pos := p.loadExpr(getSrc(src)) 2453 p.panicCodeErrorf( 2454 pos, "invalid type assertion: %s (non-interface type %v on left)", text, arg.Type) 2455 } 2456 if missing := p.missingMethod(typ, xType); missing != "" { 2457 pos := getSrcPos(getSrc(src)) 2458 p.panicCodeErrorf( 2459 pos, "impossible type assertion:\n\t%v does not implement %v (missing %s method)", 2460 typ, arg.Type, missing) 2461 } 2462 pkg := p.pkg 2463 ret := &ast.TypeAssertExpr{X: arg.Val, Type: toType(pkg, typ)} 2464 if twoValue { 2465 tyRet := types.NewTuple( 2466 pkg.NewParam(token.NoPos, "", typ), 2467 pkg.NewParam(token.NoPos, "", types.Typ[types.Bool])) 2468 p.stk.Ret(1, &internal.Elem{Type: tyRet, Val: ret}) 2469 } else { 2470 p.stk.Ret(1, &internal.Elem{Type: typ, Val: ret}) 2471 } 2472 return p 2473 } 2474 2475 func (p *CodeBuilder) missingMethod(T types.Type, V *types.Interface) (missing string) { 2476 p.ensureLoaded(T) 2477 if m, _ := types.MissingMethod(T, V, false); m != nil { 2478 missing = m.Name() 2479 } 2480 return 2481 } 2482 2483 func (p *CodeBuilder) checkInterface(typ types.Type) (*types.Interface, bool) { 2484 retry: 2485 switch t := typ.(type) { 2486 case *types.Interface: 2487 return t, true 2488 case *types.Named: 2489 typ = p.getUnderlying(t) 2490 goto retry 2491 } 2492 return nil, false 2493 } 2494 2495 // TypeAssertThen starts body of a type switch statement. 2496 func (p *CodeBuilder) TypeAssertThen() *CodeBuilder { 2497 if debugInstr { 2498 log.Println("TypeAssertThen") 2499 } 2500 if flow, ok := p.current.codeBlock.(*typeSwitchStmt); ok { 2501 flow.TypeAssertThen(p) 2502 return p 2503 } 2504 panic("use typeSwitch..typeAssertThen please") 2505 } 2506 2507 // TypeCase starts case body of a type switch statement. 2508 func (p *CodeBuilder) TypeCase(src ...ast.Node) *CodeBuilder { 2509 if debugInstr { 2510 log.Println("TypeCase") 2511 } 2512 if flow, ok := p.current.codeBlock.(*typeSwitchStmt); ok { 2513 flow.TypeCase(p, src...) 2514 return p 2515 } 2516 panic("use switch x.(type) .. case please") 2517 } 2518 2519 // TypeDefaultThen starts default clause of a type switch statement. 2520 func (p *CodeBuilder) TypeDefaultThen(src ...ast.Node) *CodeBuilder { 2521 return p.TypeCase(src...).Then(src...) 2522 } 2523 2524 // Select starts a select statement. 2525 func (p *CodeBuilder) Select(src ...ast.Node) *CodeBuilder { 2526 if debugInstr { 2527 log.Println("Select") 2528 } 2529 stmt := &selectStmt{} 2530 p.startBlockStmt(stmt, src, "select statement", &stmt.old) 2531 return p 2532 } 2533 2534 // CommCase starts case clause of a select statement. 2535 func (p *CodeBuilder) CommCase(src ...ast.Node) *CodeBuilder { 2536 if debugInstr { 2537 log.Println("CommCase") 2538 } 2539 if flow, ok := p.current.codeBlock.(*selectStmt); ok { 2540 flow.CommCase(p, src...) 2541 return p 2542 } 2543 panic("use select..case please") 2544 } 2545 2546 // CommDefaultThen starts default clause of a select statement. 2547 func (p *CodeBuilder) CommDefaultThen(src ...ast.Node) *CodeBuilder { 2548 return p.CommCase(src...).Then(src...) 2549 } 2550 2551 // Switch starts a switch statement. 2552 func (p *CodeBuilder) Switch(src ...ast.Node) *CodeBuilder { 2553 if debugInstr { 2554 log.Println("Switch") 2555 } 2556 stmt := &switchStmt{} 2557 p.startBlockStmt(stmt, src, "switch statement", &stmt.old) 2558 return p 2559 } 2560 2561 // Case starts case clause of a switch statement. 2562 func (p *CodeBuilder) Case(src ...ast.Node) *CodeBuilder { 2563 if debugInstr { 2564 log.Println("Case") 2565 } 2566 if flow, ok := p.current.codeBlock.(*switchStmt); ok { 2567 flow.Case(p, src...) 2568 return p 2569 } 2570 panic("use switch..case please") 2571 } 2572 2573 // DefaultThen starts default clause of a switch statement. 2574 func (p *CodeBuilder) DefaultThen(src ...ast.Node) *CodeBuilder { 2575 return p.Case(src...).Then(src...) 2576 } 2577 2578 func (p *CodeBuilder) NewLabel(pos token.Pos, name string) *Label { 2579 if p.current.fn == nil { 2580 panic(p.newCodeError(pos, "syntax error: non-declaration statement outside function body")) 2581 } 2582 if old, ok := p.current.labels[name]; ok { 2583 oldPos := p.fset.Position(old.Pos()) 2584 p.handleCodeErrorf(pos, "label %s already defined at %v", name, oldPos) 2585 return nil 2586 } 2587 if p.current.labels == nil { 2588 p.current.labels = make(map[string]*Label) 2589 } 2590 l := &Label{Label: *types.NewLabel(pos, p.pkg.Types, name)} 2591 p.current.labels[name] = l 2592 return l 2593 } 2594 2595 // LookupLabel func 2596 func (p *CodeBuilder) LookupLabel(name string) (l *Label, ok bool) { 2597 l, ok = p.current.labels[name] 2598 return 2599 } 2600 2601 // Label func 2602 func (p *CodeBuilder) Label(l *Label) *CodeBuilder { 2603 name := l.Name() 2604 if debugInstr { 2605 log.Println("Label", name) 2606 } 2607 if p.current.label != nil { 2608 p.current.label.Stmt = &ast.EmptyStmt{} 2609 p.current.stmts = append(p.current.stmts, p.current.label) 2610 } 2611 p.current.label = &ast.LabeledStmt{Label: ident(name)} 2612 return p 2613 } 2614 2615 // Goto func 2616 func (p *CodeBuilder) Goto(l *Label) *CodeBuilder { 2617 name := l.Name() 2618 if debugInstr { 2619 log.Println("Goto", name) 2620 } 2621 l.used = true 2622 p.current.flows |= flowFlagGoto 2623 p.emitStmt(&ast.BranchStmt{Tok: token.GOTO, Label: ident(name)}) 2624 return p 2625 } 2626 2627 func (p *CodeBuilder) labelFlow(flow int, l *Label) (string, *ast.Ident) { 2628 if l != nil { 2629 l.used = true 2630 p.current.flows |= (flow | flowFlagWithLabel) 2631 return l.Name(), ident(l.Name()) 2632 } 2633 p.current.flows |= flow 2634 return "", nil 2635 } 2636 2637 // Break func 2638 func (p *CodeBuilder) Break(l *Label) *CodeBuilder { 2639 name, label := p.labelFlow(flowFlagBreak, l) 2640 if debugInstr { 2641 log.Println("Break", name) 2642 } 2643 p.emitStmt(&ast.BranchStmt{Tok: token.BREAK, Label: label}) 2644 return p 2645 } 2646 2647 // Continue func 2648 func (p *CodeBuilder) Continue(l *Label) *CodeBuilder { 2649 name, label := p.labelFlow(flowFlagContinue, l) 2650 if debugInstr { 2651 log.Println("Continue", name) 2652 } 2653 p.emitStmt(&ast.BranchStmt{Tok: token.CONTINUE, Label: label}) 2654 return p 2655 } 2656 2657 // Fallthrough func 2658 func (p *CodeBuilder) Fallthrough() *CodeBuilder { 2659 if debugInstr { 2660 log.Println("Fallthrough") 2661 } 2662 if flow, ok := p.current.codeBlock.(*caseStmt); ok { 2663 flow.Fallthrough(p) 2664 return p 2665 } 2666 panic("please use fallthrough in case statement") 2667 } 2668 2669 // For func 2670 func (p *CodeBuilder) For(src ...ast.Node) *CodeBuilder { 2671 if debugInstr { 2672 log.Println("For") 2673 } 2674 stmt := &forStmt{} 2675 p.startBlockStmt(stmt, src, "for statement", &stmt.old) 2676 return p 2677 } 2678 2679 // Post func 2680 func (p *CodeBuilder) Post() *CodeBuilder { 2681 if debugInstr { 2682 log.Println("Post") 2683 } 2684 if flow, ok := p.current.codeBlock.(*forStmt); ok { 2685 flow.Post(p) 2686 return p 2687 } 2688 panic("please use Post() in for statement") 2689 } 2690 2691 // ForRange func 2692 func (p *CodeBuilder) ForRange(names ...string) *CodeBuilder { 2693 return p.ForRangeEx(names) 2694 } 2695 2696 // ForRangeEx func 2697 func (p *CodeBuilder) ForRangeEx(names []string, src ...ast.Node) *CodeBuilder { 2698 if debugInstr { 2699 log.Println("ForRange", names) 2700 } 2701 stmt := &forRangeStmt{names: names} 2702 p.startBlockStmt(stmt, src, "for range statement", &stmt.old) 2703 return p 2704 } 2705 2706 // RangeAssignThen func 2707 func (p *CodeBuilder) RangeAssignThen(pos token.Pos) *CodeBuilder { 2708 if debugInstr { 2709 log.Println("RangeAssignThen") 2710 } 2711 if flow, ok := p.current.codeBlock.(*forRangeStmt); ok { 2712 flow.RangeAssignThen(p, pos) 2713 return p 2714 } 2715 panic("please use RangeAssignThen() in for range statement") 2716 } 2717 2718 // ResetStmt resets the statement state of CodeBuilder. 2719 func (p *CodeBuilder) ResetStmt() { 2720 if debugInstr { 2721 log.Println("ResetStmt") 2722 } 2723 p.stk.SetLen(p.current.base) 2724 } 2725 2726 // EndStmt func 2727 func (p *CodeBuilder) EndStmt() *CodeBuilder { 2728 n := p.stk.Len() - p.current.base 2729 if n > 0 { 2730 if n != 1 { 2731 panic("syntax error: unexpected newline, expecting := or = or comma") 2732 } 2733 if e := p.stk.Pop(); p.noSkipConst || e.CVal == nil { // skip constant 2734 p.emitStmt(&ast.ExprStmt{X: e.Val}) 2735 } 2736 } 2737 return p 2738 } 2739 2740 // End func 2741 func (p *CodeBuilder) End(src ...ast.Node) *CodeBuilder { 2742 if debugInstr { 2743 typ := reflect.TypeOf(p.current.codeBlock) 2744 if typ.Kind() == reflect.Ptr { 2745 typ = typ.Elem() 2746 } 2747 name := strings.TrimSuffix(strings.Title(typ.Name()), "Stmt") 2748 log.Println("End //", name) 2749 if p.stk.Len() > p.current.base { 2750 panic("forget to call EndStmt()?") 2751 } 2752 } 2753 p.current.End(p, getSrc(src)) 2754 return p 2755 } 2756 2757 func (p *CodeBuilder) SetBodyHandler(handle func(body *ast.BlockStmt, kind int)) *CodeBuilder { 2758 if ini, ok := p.current.codeBlock.(interface { 2759 SetBodyHandler(func(body *ast.BlockStmt, kind int)) 2760 }); ok { 2761 ini.SetBodyHandler(handle) 2762 } 2763 return p 2764 } 2765 2766 // ResetInit resets the variable init state of CodeBuilder. 2767 func (p *CodeBuilder) ResetInit() { 2768 if debugInstr { 2769 log.Println("ResetInit") 2770 } 2771 p.valDecl = p.valDecl.resetInit(p) 2772 } 2773 2774 // EndInit func 2775 func (p *CodeBuilder) EndInit(n int) *CodeBuilder { 2776 if debugInstr { 2777 log.Println("EndInit", n) 2778 } 2779 p.valDecl = p.valDecl.endInit(p, n) 2780 return p 2781 } 2782 2783 // Debug func 2784 func (p *CodeBuilder) Debug(dbg func(cb *CodeBuilder)) *CodeBuilder { 2785 dbg(p) 2786 return p 2787 } 2788 2789 // Get func 2790 func (p *CodeBuilder) Get(idx int) *Element { 2791 return p.stk.Get(idx) 2792 } 2793 2794 // ---------------------------------------------------------------------------- 2795 2796 type InternalStack = internal.Stack 2797 2798 // InternalStack: don't call it (only for internal use) 2799 func (p *CodeBuilder) InternalStack() *InternalStack { 2800 return &p.stk 2801 } 2802 2803 // ----------------------------------------------------------------------------