1package gogrep 2 3import ( 4 "fmt" 5 "go/ast" 6 "go/token" 7) 8 9type compileError string 10 11func (e compileError) Error() string { return string(e) } 12 13type compiler struct { 14 prog *program 15 stringIndexes map[string]uint8 16 ifaceIndexes map[interface{}]uint8 17 strict bool 18 fset *token.FileSet 19} 20 21func (c *compiler) Compile(fset *token.FileSet, root ast.Node, strict bool) (p *program, err error) { 22 defer func() { 23 if err != nil { 24 return 25 } 26 rv := recover() 27 if rv == nil { 28 return 29 } 30 if parseErr, ok := rv.(compileError); ok { 31 err = parseErr 32 return 33 } 34 panic(rv) // Not our panic 35 }() 36 37 c.fset = fset 38 c.strict = strict 39 c.prog = &program{ 40 insts: make([]instruction, 0, 8), 41 } 42 c.stringIndexes = make(map[string]uint8) 43 c.ifaceIndexes = make(map[interface{}]uint8) 44 45 c.compileNode(root) 46 47 if len(c.prog.insts) == 0 { 48 return nil, c.errorf(root, "0 instructions generated") 49 } 50 51 return c.prog, nil 52} 53 54func (c *compiler) errorf(n ast.Node, format string, args ...interface{}) compileError { 55 loc := c.fset.Position(n.Pos()) 56 message := fmt.Sprintf("%s:%d: %s", loc.Filename, loc.Line, fmt.Sprintf(format, args...)) 57 return compileError(message) 58} 59 60func (c *compiler) toUint8(n ast.Node, v int) uint8 { 61 if !fitsUint8(v) { 62 panic(c.errorf(n, "implementation error: %v can't be converted to uint8", v)) 63 } 64 return uint8(v) 65} 66 67func (c *compiler) internString(n ast.Node, s string) uint8 { 68 if index, ok := c.stringIndexes[s]; ok { 69 return index 70 } 71 index := len(c.prog.strings) 72 if !fitsUint8(index) { 73 panic(c.errorf(n, "implementation limitation: too many string values")) 74 } 75 c.stringIndexes[s] = uint8(index) 76 c.prog.strings = append(c.prog.strings, s) 77 return uint8(index) 78} 79 80func (c *compiler) internIface(n ast.Node, v interface{}) uint8 { 81 if index, ok := c.ifaceIndexes[v]; ok { 82 return index 83 } 84 index := len(c.prog.ifaces) 85 if !fitsUint8(index) { 86 panic(c.errorf(n, "implementation limitation: too many values")) 87 } 88 c.ifaceIndexes[v] = uint8(index) 89 c.prog.ifaces = append(c.prog.ifaces, v) 90 return uint8(index) 91} 92 93func (c *compiler) emitInst(inst instruction) { 94 c.prog.insts = append(c.prog.insts, inst) 95} 96 97func (c *compiler) emitInstOp(op operation) { 98 c.emitInst(instruction{op: op}) 99} 100 101func (c *compiler) compileNode(n ast.Node) { 102 switch n := n.(type) { 103 case *ast.File: 104 c.compileFile(n) 105 case ast.Decl: 106 c.compileDecl(n) 107 case ast.Expr: 108 c.compileExpr(n) 109 case ast.Stmt: 110 c.compileStmt(n) 111 case *ast.ValueSpec: 112 c.compileValueSpec(n) 113 case stmtSlice: 114 c.compileStmtSlice(n) 115 case exprSlice: 116 c.compileExprSlice(n) 117 default: 118 panic(c.errorf(n, "compileNode: unexpected %T", n)) 119 } 120} 121 122func (c *compiler) compileOptStmt(n ast.Stmt) { 123 if exprStmt, ok := n.(*ast.ExprStmt); ok { 124 if ident, ok := exprStmt.X.(*ast.Ident); ok && isWildName(ident.Name) { 125 c.compileWildIdent(ident, true) 126 return 127 } 128 } 129 c.compileStmt(n) 130} 131 132func (c *compiler) compileOptExpr(n ast.Expr) { 133 if ident, ok := n.(*ast.Ident); ok && isWildName(ident.Name) { 134 c.compileWildIdent(ident, true) 135 return 136 } 137 c.compileExpr(n) 138} 139 140func (c *compiler) compileFieldList(n *ast.FieldList) { 141 c.emitInstOp(opFieldList) 142 for _, x := range n.List { 143 c.compileField(x) 144 } 145 c.emitInstOp(opEnd) 146} 147 148func (c *compiler) compileField(n *ast.Field) { 149 switch { 150 case len(n.Names) == 0: 151 c.emitInstOp(opUnnamedField) 152 case len(n.Names) == 1: 153 name := n.Names[0] 154 if isWildName(name.Name) { 155 c.emitInstOp(opField) 156 c.compileWildIdent(name, false) 157 } else { 158 c.emitInst(instruction{ 159 op: opSimpleField, 160 valueIndex: c.internString(name, name.Name), 161 }) 162 } 163 default: 164 c.emitInstOp(opMultiField) 165 for _, name := range n.Names { 166 c.compileIdent(name) 167 } 168 c.emitInstOp(opEnd) 169 } 170 c.compileExpr(n.Type) 171} 172 173func (c *compiler) compileValueSpec(spec *ast.ValueSpec) { 174 switch { 175 case spec.Type == nil: 176 c.emitInstOp(opValueInitSpec) 177 case len(spec.Values) == 0: 178 c.emitInstOp(opTypedValueSpec) 179 default: 180 c.emitInstOp(opTypedValueInitSpec) 181 } 182 for _, name := range spec.Names { 183 c.compileIdent(name) 184 } 185 c.emitInstOp(opEnd) 186 if spec.Type != nil { 187 c.compileExpr(spec.Type) 188 } 189 if len(spec.Values) != 0 { 190 for _, v := range spec.Values { 191 c.compileExpr(v) 192 } 193 c.emitInstOp(opEnd) 194 } 195} 196 197func (c *compiler) compileTypeSpec(spec *ast.TypeSpec) { 198 c.emitInstOp(pickOp(spec.Assign.IsValid(), opTypeAliasSpec, opTypeSpec)) 199 c.compileIdent(spec.Name) 200 c.compileExpr(spec.Type) 201} 202 203func (c *compiler) compileFile(n *ast.File) { 204 if len(n.Imports) == 0 && len(n.Decls) == 0 { 205 c.emitInstOp(opEmptyPackage) 206 c.compileIdent(n.Name) 207 return 208 } 209 210 panic(c.errorf(n, "compileFile: unsupported file pattern")) 211} 212 213func (c *compiler) compileDecl(n ast.Decl) { 214 switch n := n.(type) { 215 case *ast.FuncDecl: 216 c.compileFuncDecl(n) 217 case *ast.GenDecl: 218 c.compileGenDecl(n) 219 220 default: 221 panic(c.errorf(n, "compileDecl: unexpected %T", n)) 222 } 223} 224 225func (c *compiler) compileFuncDecl(n *ast.FuncDecl) { 226 if n.Recv == nil { 227 c.emitInstOp(pickOp(n.Body == nil, opFuncProtoDecl, opFuncDecl)) 228 } else { 229 c.emitInstOp(pickOp(n.Body == nil, opMethodProtoDecl, opMethodDecl)) 230 } 231 232 if n.Recv != nil { 233 c.compileFieldList(n.Recv) 234 } 235 c.compileIdent(n.Name) 236 c.compileFuncType(n.Type) 237 if n.Body != nil { 238 c.compileBlockStmt(n.Body) 239 } 240} 241 242func (c *compiler) compileGenDecl(n *ast.GenDecl) { 243 switch n.Tok { 244 case token.CONST, token.VAR: 245 c.emitInstOp(pickOp(n.Tok == token.CONST, opConstDecl, opVarDecl)) 246 for _, spec := range n.Specs { 247 c.compileValueSpec(spec.(*ast.ValueSpec)) 248 } 249 c.emitInstOp(opEnd) 250 case token.TYPE: 251 c.emitInstOp(opTypeDecl) 252 for _, spec := range n.Specs { 253 c.compileTypeSpec(spec.(*ast.TypeSpec)) 254 } 255 c.emitInstOp(opEnd) 256 257 default: 258 panic(c.errorf(n, "unexpected gen decl")) 259 } 260} 261 262func (c *compiler) compileExpr(n ast.Expr) { 263 switch n := n.(type) { 264 case *ast.BasicLit: 265 c.compileBasicLit(n) 266 case *ast.BinaryExpr: 267 c.compileBinaryExpr(n) 268 case *ast.IndexExpr: 269 c.compileIndexExpr(n) 270 case *ast.Ident: 271 c.compileIdent(n) 272 case *ast.CallExpr: 273 c.compileCallExpr(n) 274 case *ast.UnaryExpr: 275 c.compileUnaryExpr(n) 276 case *ast.StarExpr: 277 c.compileStarExpr(n) 278 case *ast.ParenExpr: 279 c.compileParenExpr(n) 280 case *ast.SliceExpr: 281 c.compileSliceExpr(n) 282 case *ast.FuncType: 283 c.compileFuncType(n) 284 case *ast.ArrayType: 285 c.compileArrayType(n) 286 case *ast.MapType: 287 c.compileMapType(n) 288 case *ast.ChanType: 289 c.compileChanType(n) 290 case *ast.CompositeLit: 291 c.compileCompositeLit(n) 292 case *ast.FuncLit: 293 c.compileFuncLit(n) 294 case *ast.Ellipsis: 295 c.compileEllipsis(n) 296 case *ast.KeyValueExpr: 297 c.compileKeyValueExpr(n) 298 case *ast.SelectorExpr: 299 c.compileSelectorExpr(n) 300 case *ast.TypeAssertExpr: 301 c.compileTypeAssertExpr(n) 302 303 default: 304 panic(c.errorf(n, "compileExpr: unexpected %T", n)) 305 } 306} 307 308func (c *compiler) compileBasicLit(n *ast.BasicLit) { 309 if !c.strict { 310 v := literalValue(n) 311 if v == nil { 312 panic(c.errorf(n, "can't convert %s (%s) value", n.Value, n.Kind)) 313 } 314 c.prog.insts = append(c.prog.insts, instruction{ 315 op: opBasicLit, 316 valueIndex: c.internIface(n, v), 317 }) 318 return 319 } 320 321 var inst instruction 322 switch n.Kind { 323 case token.INT: 324 inst.op = opStrictIntLit 325 case token.FLOAT: 326 inst.op = opStrictFloatLit 327 case token.STRING: 328 inst.op = opStrictStringLit 329 case token.CHAR: 330 inst.op = opStrictCharLit 331 default: 332 inst.op = opStrictComplexLit 333 } 334 inst.valueIndex = c.internString(n, n.Value) 335 c.prog.insts = append(c.prog.insts, inst) 336} 337 338func (c *compiler) compileBinaryExpr(n *ast.BinaryExpr) { 339 c.prog.insts = append(c.prog.insts, instruction{ 340 op: opBinaryExpr, 341 value: c.toUint8(n, int(n.Op)), 342 }) 343 c.compileExpr(n.X) 344 c.compileExpr(n.Y) 345} 346 347func (c *compiler) compileIndexExpr(n *ast.IndexExpr) { 348 c.emitInstOp(opIndexExpr) 349 c.compileExpr(n.X) 350 c.compileExpr(n.Index) 351} 352 353func (c *compiler) compileWildIdent(n *ast.Ident, optional bool) { 354 info := decodeWildName(n.Name) 355 var inst instruction 356 switch { 357 case info.Name == "_" && !info.Seq: 358 inst.op = opNode 359 case info.Name == "_" && info.Seq: 360 inst.op = pickOp(optional, opOptNode, opNodeSeq) 361 case info.Name != "_" && !info.Seq: 362 inst.op = opNamedNode 363 inst.valueIndex = c.internString(n, info.Name) 364 default: 365 inst.op = pickOp(optional, opNamedOptNode, opNamedNodeSeq) 366 inst.valueIndex = c.internString(n, info.Name) 367 } 368 c.prog.insts = append(c.prog.insts, inst) 369} 370 371func (c *compiler) compileIdent(n *ast.Ident) { 372 if isWildName(n.Name) { 373 c.compileWildIdent(n, false) 374 return 375 } 376 377 c.prog.insts = append(c.prog.insts, instruction{ 378 op: opIdent, 379 valueIndex: c.internString(n, n.Name), 380 }) 381} 382 383func (c *compiler) compileCallExpr(n *ast.CallExpr) { 384 op := opCallExpr 385 if n.Ellipsis.IsValid() { 386 op = opVariadicCallExpr 387 } 388 c.emitInstOp(op) 389 c.compileExpr(n.Fun) 390 for _, arg := range n.Args { 391 c.compileExpr(arg) 392 } 393 c.emitInstOp(opEnd) 394} 395 396func (c *compiler) compileUnaryExpr(n *ast.UnaryExpr) { 397 c.prog.insts = append(c.prog.insts, instruction{ 398 op: opUnaryExpr, 399 value: c.toUint8(n, int(n.Op)), 400 }) 401 c.compileExpr(n.X) 402} 403 404func (c *compiler) compileStarExpr(n *ast.StarExpr) { 405 c.emitInstOp(opStarExpr) 406 c.compileExpr(n.X) 407} 408 409func (c *compiler) compileParenExpr(n *ast.ParenExpr) { 410 c.emitInstOp(opParenExpr) 411 c.compileExpr(n.X) 412} 413 414func (c *compiler) compileSliceExpr(n *ast.SliceExpr) { 415 switch { 416 case n.Low == nil && n.High == nil && !n.Slice3: 417 c.emitInstOp(opSliceExpr) 418 c.compileExpr(n.X) 419 case n.Low != nil && n.High == nil && !n.Slice3: 420 c.emitInstOp(opSliceFromExpr) 421 c.compileExpr(n.X) 422 c.compileExpr(n.Low) 423 case n.Low == nil && n.High != nil && !n.Slice3: 424 c.emitInstOp(opSliceToExpr) 425 c.compileExpr(n.X) 426 c.compileExpr(n.High) 427 case n.Low != nil && n.High != nil && !n.Slice3: 428 c.emitInstOp(opSliceFromToExpr) 429 c.compileExpr(n.X) 430 c.compileExpr(n.Low) 431 c.compileExpr(n.High) 432 case n.Low == nil && n.Slice3: 433 c.emitInstOp(opSliceToCapExpr) 434 c.compileExpr(n.X) 435 c.compileExpr(n.High) 436 c.compileExpr(n.Max) 437 case n.Low != nil && n.Slice3: 438 c.emitInstOp(opSliceFromToCapExpr) 439 c.compileExpr(n.X) 440 c.compileExpr(n.Low) 441 c.compileExpr(n.High) 442 c.compileExpr(n.Max) 443 default: 444 panic(c.errorf(n, "unexpected slice expr")) 445 } 446} 447 448func (c *compiler) compileFuncType(n *ast.FuncType) { 449 void := n.Results == nil || len(n.Results.List) == 0 450 if void { 451 c.emitInstOp(opVoidFuncType) 452 } else { 453 c.emitInstOp(opFuncType) 454 } 455 c.compileFieldList(n.Params) 456 if !void { 457 c.compileFieldList(n.Results) 458 } 459} 460 461func (c *compiler) compileArrayType(n *ast.ArrayType) { 462 if n.Len == nil { 463 c.emitInstOp(opSliceType) 464 c.compileExpr(n.Elt) 465 } else { 466 c.emitInstOp(opArrayType) 467 c.compileExpr(n.Len) 468 c.compileExpr(n.Elt) 469 } 470} 471 472func (c *compiler) compileMapType(n *ast.MapType) { 473 c.emitInstOp(opMapType) 474 c.compileExpr(n.Key) 475 c.compileExpr(n.Value) 476} 477 478func (c *compiler) compileChanType(n *ast.ChanType) { 479 c.emitInst(instruction{ 480 op: opChanType, 481 value: c.toUint8(n, int(n.Dir)), 482 }) 483 c.compileExpr(n.Value) 484} 485 486func (c *compiler) compileCompositeLit(n *ast.CompositeLit) { 487 if n.Type == nil { 488 c.emitInstOp(opCompositeLit) 489 } else { 490 c.emitInstOp(opTypedCompositeLit) 491 c.compileExpr(n.Type) 492 } 493 for _, elt := range n.Elts { 494 c.compileExpr(elt) 495 } 496 c.emitInstOp(opEnd) 497} 498 499func (c *compiler) compileFuncLit(n *ast.FuncLit) { 500 c.emitInstOp(opFuncLit) 501 c.compileFuncType(n.Type) 502 c.compileBlockStmt(n.Body) 503} 504 505func (c *compiler) compileEllipsis(n *ast.Ellipsis) { 506 if n.Elt == nil { 507 c.emitInstOp(opEllipsis) 508 } else { 509 c.emitInstOp(opTypedEllipsis) 510 c.compileExpr(n.Elt) 511 } 512} 513 514func (c *compiler) compileKeyValueExpr(n *ast.KeyValueExpr) { 515 c.emitInstOp(opKeyValueExpr) 516 c.compileExpr(n.Key) 517 c.compileExpr(n.Value) 518} 519 520func (c *compiler) compileSelectorExpr(n *ast.SelectorExpr) { 521 if isWildName(n.Sel.Name) { 522 c.emitInstOp(opSelectorExpr) 523 c.compileWildIdent(n.Sel, false) 524 c.compileExpr(n.X) 525 return 526 } 527 528 c.prog.insts = append(c.prog.insts, instruction{ 529 op: opSimpleSelectorExpr, 530 valueIndex: c.internString(n.Sel, n.Sel.String()), 531 }) 532 c.compileExpr(n.X) 533} 534 535func (c *compiler) compileTypeAssertExpr(n *ast.TypeAssertExpr) { 536 if n.Type != nil { 537 c.emitInstOp(opTypeAssertExpr) 538 c.compileExpr(n.X) 539 c.compileExpr(n.Type) 540 } else { 541 c.emitInstOp(opTypeSwitchAssertExpr) 542 c.compileExpr(n.X) 543 } 544} 545 546func (c *compiler) compileStmt(n ast.Stmt) { 547 switch n := n.(type) { 548 case *ast.AssignStmt: 549 c.compileAssignStmt(n) 550 case *ast.BlockStmt: 551 c.compileBlockStmt(n) 552 case *ast.ExprStmt: 553 c.compileExprStmt(n) 554 case *ast.IfStmt: 555 c.compileIfStmt(n) 556 case *ast.CaseClause: 557 c.compileCaseClause(n) 558 case *ast.SwitchStmt: 559 c.compileSwitchStmt(n) 560 case *ast.TypeSwitchStmt: 561 c.compileTypeSwitchStmt(n) 562 case *ast.SelectStmt: 563 c.compileSelectStmt(n) 564 case *ast.ForStmt: 565 c.compileForStmt(n) 566 case *ast.RangeStmt: 567 c.compileRangeStmt(n) 568 case *ast.IncDecStmt: 569 c.compileIncDecStmt(n) 570 case *ast.EmptyStmt: 571 c.compileEmptyStmt(n) 572 case *ast.ReturnStmt: 573 c.compileReturnStmt(n) 574 case *ast.BranchStmt: 575 c.compileBranchStmt(n) 576 case *ast.LabeledStmt: 577 c.compileLabeledStmt(n) 578 case *ast.GoStmt: 579 c.compileGoStmt(n) 580 case *ast.DeferStmt: 581 c.compileDeferStmt(n) 582 case *ast.SendStmt: 583 c.compileSendStmt(n) 584 case *ast.DeclStmt: 585 c.compileDecl(n.Decl) 586 587 default: 588 panic(c.errorf(n, "compileStmt: unexpected %T", n)) 589 } 590} 591 592func (c *compiler) compileAssignStmt(n *ast.AssignStmt) { 593 if len(n.Lhs) == 1 && len(n.Rhs) == 1 { 594 lhsInfo := decodeWildNode(n.Lhs[0]) 595 rhsInfo := decodeWildNode(n.Rhs[0]) 596 if !lhsInfo.Seq && !rhsInfo.Seq { 597 c.emitInst(instruction{ 598 op: opAssignStmt, 599 value: uint8(n.Tok), 600 }) 601 c.compileExpr(n.Lhs[0]) 602 c.compileExpr(n.Rhs[0]) 603 return 604 } 605 } 606 607 c.emitInst(instruction{ 608 op: opMultiAssignStmt, 609 value: uint8(n.Tok), 610 }) 611 for _, x := range n.Lhs { 612 c.compileExpr(x) 613 } 614 c.emitInstOp(opEnd) 615 for _, x := range n.Rhs { 616 c.compileExpr(x) 617 } 618 c.emitInstOp(opEnd) 619} 620 621func (c *compiler) compileBlockStmt(n *ast.BlockStmt) { 622 c.emitInstOp(opBlockStmt) 623 for _, elt := range n.List { 624 c.compileStmt(elt) 625 } 626 c.emitInstOp(opEnd) 627} 628 629func (c *compiler) compileExprStmt(n *ast.ExprStmt) { 630 if ident, ok := n.X.(*ast.Ident); ok && isWildName(ident.Name) { 631 c.compileIdent(ident) 632 } else { 633 c.emitInstOp(opExprStmt) 634 c.compileExpr(n.X) 635 } 636} 637 638func (c *compiler) compileIfStmt(n *ast.IfStmt) { 639 // Check for the special case: `if $*_ ...` should match all if statements. 640 if ident, ok := n.Cond.(*ast.Ident); ok && n.Init == nil && isWildName(ident.Name) { 641 info := decodeWildName(ident.Name) 642 if info.Seq && info.Name == "_" { 643 // Set Init to Cond, change cond from $*_ to $_. 644 n.Init = &ast.ExprStmt{X: n.Cond} 645 cond := &ast.Ident{Name: encodeWildName(info.Name, false)} 646 n.Cond = cond 647 c.compileIfStmt(n) 648 return 649 } 650 // Named $* is harder and slower. 651 c.prog.insts = append(c.prog.insts, instruction{ 652 op: pickOp(n.Else == nil, opIfNamedOptStmt, opIfNamedOptElseStmt), 653 valueIndex: c.internString(ident, info.Name), 654 }) 655 c.compileStmt(n.Body) 656 if n.Else != nil { 657 c.compileStmt(n.Else) 658 } 659 return 660 } 661 662 switch { 663 case n.Init == nil && n.Else == nil: 664 c.emitInstOp(opIfStmt) 665 c.compileExpr(n.Cond) 666 c.compileStmt(n.Body) 667 case n.Init != nil && n.Else == nil: 668 c.emitInstOp(opIfInitStmt) 669 c.compileOptStmt(n.Init) 670 c.compileExpr(n.Cond) 671 c.compileStmt(n.Body) 672 case n.Init == nil && n.Else != nil: 673 c.emitInstOp(opIfElseStmt) 674 c.compileExpr(n.Cond) 675 c.compileStmt(n.Body) 676 c.compileStmt(n.Else) 677 case n.Init != nil && n.Else != nil: 678 c.emitInstOp(opIfInitElseStmt) 679 c.compileOptStmt(n.Init) 680 c.compileExpr(n.Cond) 681 c.compileStmt(n.Body) 682 c.compileStmt(n.Else) 683 684 default: 685 panic(c.errorf(n, "unexpected if stmt")) 686 } 687} 688 689func (c *compiler) compileCommClause(n *ast.CommClause) { 690 c.emitInstOp(pickOp(n.Comm == nil, opDefaultCommClause, opCommClause)) 691 if n.Comm != nil { 692 c.compileStmt(n.Comm) 693 } 694 for _, x := range n.Body { 695 c.compileStmt(x) 696 } 697 c.emitInstOp(opEnd) 698} 699 700func (c *compiler) compileCaseClause(n *ast.CaseClause) { 701 c.emitInstOp(pickOp(n.List == nil, opDefaultCaseClause, opCaseClause)) 702 if n.List != nil { 703 for _, x := range n.List { 704 c.compileExpr(x) 705 } 706 c.emitInstOp(opEnd) 707 } 708 for _, x := range n.Body { 709 c.compileStmt(x) 710 } 711 c.emitInstOp(opEnd) 712} 713 714func (c *compiler) compileSwitchBody(n *ast.BlockStmt) { 715 wildcardCase := func(cc *ast.CaseClause) *ast.Ident { 716 if len(cc.List) != 1 || len(cc.Body) != 1 { 717 return nil 718 } 719 v, ok := cc.List[0].(*ast.Ident) 720 if !ok || !isWildName(v.Name) { 721 return nil 722 } 723 bodyStmt, ok := cc.Body[0].(*ast.ExprStmt) 724 if !ok { 725 return nil 726 } 727 bodyIdent, ok := bodyStmt.X.(*ast.Ident) 728 if !ok || bodyIdent.Name != "gogrep_body" { 729 return nil 730 } 731 return v 732 } 733 for _, cc := range n.List { 734 cc := cc.(*ast.CaseClause) 735 wildcard := wildcardCase(cc) 736 if wildcard == nil { 737 c.compileCaseClause(cc) 738 continue 739 } 740 c.compileWildIdent(wildcard, false) 741 } 742 c.emitInstOp(opEnd) 743} 744 745func (c *compiler) compileSwitchStmt(n *ast.SwitchStmt) { 746 var op operation 747 switch { 748 case n.Init == nil && n.Tag == nil: 749 op = opSwitchStmt 750 case n.Init == nil && n.Tag != nil: 751 op = opSwitchTagStmt 752 case n.Init != nil && n.Tag == nil: 753 op = opSwitchInitStmt 754 default: 755 op = opSwitchInitTagStmt 756 } 757 758 c.emitInstOp(op) 759 if n.Init != nil { 760 c.compileOptStmt(n.Init) 761 } 762 if n.Tag != nil { 763 c.compileOptExpr(n.Tag) 764 } 765 c.compileSwitchBody(n.Body) 766} 767 768func (c *compiler) compileTypeSwitchStmt(n *ast.TypeSwitchStmt) { 769 c.emitInstOp(pickOp(n.Init == nil, opTypeSwitchStmt, opTypeSwitchInitStmt)) 770 if n.Init != nil { 771 c.compileOptStmt(n.Init) 772 } 773 c.compileStmt(n.Assign) 774 c.compileSwitchBody(n.Body) 775} 776 777func (c *compiler) compileSelectStmt(n *ast.SelectStmt) { 778 c.emitInstOp(opSelectStmt) 779 780 wildcardCase := func(cc *ast.CommClause) *ast.Ident { 781 if cc.Comm == nil { 782 return nil 783 } 784 vStmt, ok := cc.Comm.(*ast.ExprStmt) 785 if !ok { 786 return nil 787 } 788 v, ok := vStmt.X.(*ast.Ident) 789 if !ok || !isWildName(v.Name) { 790 return nil 791 } 792 bodyStmt, ok := cc.Body[0].(*ast.ExprStmt) 793 if !ok { 794 return nil 795 } 796 bodyIdent, ok := bodyStmt.X.(*ast.Ident) 797 if !ok || bodyIdent.Name != "gogrep_body" { 798 return nil 799 } 800 return v 801 } 802 for _, cc := range n.Body.List { 803 cc := cc.(*ast.CommClause) 804 wildcard := wildcardCase(cc) 805 if wildcard == nil { 806 c.compileCommClause(cc) 807 continue 808 } 809 c.compileWildIdent(wildcard, false) 810 } 811 c.emitInstOp(opEnd) 812} 813 814func (c *compiler) compileForStmt(n *ast.ForStmt) { 815 var op operation 816 switch { 817 case n.Init == nil && n.Cond == nil && n.Post == nil: 818 op = opForStmt 819 case n.Init == nil && n.Cond == nil && n.Post != nil: 820 op = opForPostStmt 821 case n.Init == nil && n.Cond != nil && n.Post == nil: 822 op = opForCondStmt 823 case n.Init == nil && n.Cond != nil && n.Post != nil: 824 op = opForCondPostStmt 825 case n.Init != nil && n.Cond == nil && n.Post == nil: 826 op = opForInitStmt 827 case n.Init != nil && n.Cond == nil && n.Post != nil: 828 op = opForInitPostStmt 829 case n.Init != nil && n.Cond != nil && n.Post == nil: 830 op = opForInitCondStmt 831 default: 832 op = opForInitCondPostStmt 833 } 834 835 c.emitInstOp(op) 836 if n.Init != nil { 837 c.compileOptStmt(n.Init) 838 } 839 if n.Cond != nil { 840 c.compileOptExpr(n.Cond) 841 } 842 if n.Post != nil { 843 c.compileOptStmt(n.Post) 844 } 845 c.compileBlockStmt(n.Body) 846} 847 848func (c *compiler) compileRangeStmt(n *ast.RangeStmt) { 849 switch { 850 case n.Key == nil && n.Value == nil: 851 c.emitInstOp(opRangeStmt) 852 c.compileExpr(n.X) 853 c.compileStmt(n.Body) 854 case n.Key != nil && n.Value == nil: 855 c.emitInst(instruction{ 856 op: opRangeKeyStmt, 857 value: c.toUint8(n, int(n.Tok)), 858 }) 859 c.compileExpr(n.Key) 860 c.compileExpr(n.X) 861 c.compileStmt(n.Body) 862 case n.Key != nil && n.Value != nil: 863 c.emitInst(instruction{ 864 op: opRangeKeyValueStmt, 865 value: c.toUint8(n, int(n.Tok)), 866 }) 867 c.compileExpr(n.Key) 868 c.compileExpr(n.Value) 869 c.compileExpr(n.X) 870 c.compileStmt(n.Body) 871 default: 872 panic(c.errorf(n, "unexpected range stmt")) 873 } 874} 875 876func (c *compiler) compileIncDecStmt(n *ast.IncDecStmt) { 877 c.prog.insts = append(c.prog.insts, instruction{ 878 op: opIncDecStmt, 879 value: c.toUint8(n, int(n.Tok)), 880 }) 881 c.compileExpr(n.X) 882} 883 884func (c *compiler) compileEmptyStmt(n *ast.EmptyStmt) { 885 _ = n // unused 886 c.emitInstOp(opEmptyStmt) 887} 888 889func (c *compiler) compileReturnStmt(n *ast.ReturnStmt) { 890 c.emitInstOp(opReturnStmt) 891 for _, x := range n.Results { 892 c.compileExpr(x) 893 } 894 c.emitInstOp(opEnd) 895} 896 897func (c *compiler) compileBranchStmt(n *ast.BranchStmt) { 898 if n.Label != nil { 899 if isWildName(n.Label.Name) { 900 c.prog.insts = append(c.prog.insts, instruction{ 901 op: opLabeledBranchStmt, 902 value: c.toUint8(n, int(n.Tok)), 903 }) 904 c.compileWildIdent(n.Label, false) 905 } else { 906 c.prog.insts = append(c.prog.insts, instruction{ 907 op: opSimpleLabeledBranchStmt, 908 value: c.toUint8(n, int(n.Tok)), 909 valueIndex: c.internString(n.Label, n.Label.Name), 910 }) 911 } 912 return 913 } 914 c.prog.insts = append(c.prog.insts, instruction{ 915 op: opBranchStmt, 916 value: c.toUint8(n, int(n.Tok)), 917 }) 918} 919 920func (c *compiler) compileLabeledStmt(n *ast.LabeledStmt) { 921 if isWildName(n.Label.Name) { 922 c.emitInstOp(opLabeledStmt) 923 c.compileWildIdent(n.Label, false) 924 c.compileStmt(n.Stmt) 925 return 926 } 927 928 c.prog.insts = append(c.prog.insts, instruction{ 929 op: opSimpleLabeledStmt, 930 valueIndex: c.internString(n.Label, n.Label.Name), 931 }) 932 c.compileStmt(n.Stmt) 933} 934 935func (c *compiler) compileGoStmt(n *ast.GoStmt) { 936 c.emitInstOp(opGoStmt) 937 c.compileExpr(n.Call) 938} 939 940func (c *compiler) compileDeferStmt(n *ast.DeferStmt) { 941 c.emitInstOp(opDeferStmt) 942 c.compileExpr(n.Call) 943} 944 945func (c *compiler) compileSendStmt(n *ast.SendStmt) { 946 c.emitInstOp(opSendStmt) 947 c.compileExpr(n.Chan) 948 c.compileExpr(n.Value) 949} 950 951func (c *compiler) compileStmtSlice(stmts stmtSlice) { 952 c.emitInstOp(opMultiStmt) 953 for _, n := range stmts { 954 c.compileStmt(n) 955 } 956 c.emitInstOp(opEnd) 957} 958 959func (c *compiler) compileExprSlice(exprs exprSlice) { 960 c.emitInstOp(opMultiExpr) 961 for _, n := range exprs { 962 c.compileExpr(n) 963 } 964 c.emitInstOp(opEnd) 965} 966 967func pickOp(cond bool, ifTrue, ifFalse operation) operation { 968 if cond { 969 return ifTrue 970 } 971 return ifFalse 972} 973 974func fitsUint8(v int) bool { 975 return v >= 0 && v <= 0xff 976} 977