github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/compiler/codegen/gen_expr.go (about) 1 package codegen 2 3 import ( 4 "github.com/hirochachacha/plua/compiler/ast" 5 "github.com/hirochachacha/plua/compiler/token" 6 "github.com/hirochachacha/plua/internal/version" 7 "github.com/hirochachacha/plua/object" 8 "github.com/hirochachacha/plua/opcode" 9 "github.com/hirochachacha/plua/position" 10 ) 11 12 type genType uint 13 14 const ( 15 genR genType = 0 // normal register number 16 genK genType = 1 << iota // constant number 17 genMove // copied register number 18 genKey // if expr is *ast.Name, then return constant number of it'g name 19 ) 20 21 // load or resolve 22 func (g *generator) genExpr(expr ast.Expr, typ genType) (rk int) { 23 switch expr := expr.(type) { 24 case *ast.BadExpr: 25 panic("bad expr") 26 case *ast.Name: 27 rk = g.genName(expr, typ) 28 case *ast.Vararg: 29 rk = g.genVarargN(expr, 1) 30 case *ast.BasicLit: 31 rk = g.genBasicLit(expr, typ) 32 case *ast.FuncLit: 33 rk = g.genFuncLit(expr) 34 case *ast.TableLit: 35 rk = g.genTableLit(expr) 36 case *ast.ParenExpr: 37 rk = g.genExpr(expr.X, typ) 38 case *ast.SelectorExpr: 39 rk = g.genSelectorExpr(expr) 40 case *ast.IndexExpr: 41 rk = g.genIndexExpr(expr) 42 case *ast.CallExpr: 43 rk = g.genCallExprN(expr, 1, false) 44 case *ast.UnaryExpr: 45 // const folding 46 if val, ok := g.foldUnary(expr); ok { 47 rk = g.genConst(val, typ) 48 } else { 49 rk = g.genUnaryExpr(expr, typ) 50 } 51 case *ast.BinaryExpr: 52 // const folding 53 if val, ok := g.foldBinary(expr); ok { 54 rk = g.genConst(val, typ) 55 } else { 56 rk = g.genBinaryExpr(expr, typ) 57 } 58 case *ast.KeyValueExpr: 59 panic("unexpected") 60 default: 61 panic("unreachable") 62 } 63 return 64 } 65 66 func (g *generator) genExprN(expr ast.Expr, nrets int) (isvar bool) { 67 locktmp := g.locktmp 68 69 g.locktmp = true 70 71 switch expr := expr.(type) { 72 case *ast.BadExpr: 73 panic("bad expr") 74 case *ast.Name: 75 g.genName(expr, genMove) 76 case *ast.Vararg: 77 g.genVarargN(expr, nrets) 78 79 isvar = true 80 case *ast.BasicLit: 81 g.genBasicLit(expr, genMove) 82 case *ast.FuncLit: 83 g.genFuncLit(expr) 84 case *ast.TableLit: 85 g.genTableLit(expr) 86 case *ast.ParenExpr: 87 g.genExpr(expr.X, genMove) 88 case *ast.SelectorExpr: 89 g.genSelectorExpr(expr) 90 case *ast.IndexExpr: 91 g.genIndexExpr(expr) 92 case *ast.CallExpr: 93 g.genCallExprN(expr, nrets, false) 94 95 isvar = true 96 case *ast.UnaryExpr: 97 // const folding 98 if val, ok := g.foldUnary(expr); ok { 99 g.genConst(val, genMove) 100 } else { 101 g.genUnaryExpr(expr, genMove) 102 } 103 case *ast.BinaryExpr: 104 // const folding 105 if val, ok := g.foldBinary(expr); ok { 106 g.genConst(val, genMove) 107 } else { 108 g.genBinaryExpr(expr, genMove) 109 } 110 case *ast.KeyValueExpr: 111 panic("unexpected") 112 default: 113 panic("unreachable") 114 } 115 116 if !isvar { 117 if nrets > 1 { 118 g.pushInst(opcode.AB(opcode.LOADNIL, g.sp, nrets-2)) 119 120 g.addSP(nrets - 1) 121 } 122 123 if nrets == 0 { 124 g.addSP(-1) 125 } 126 } 127 128 g.locktmp = locktmp 129 130 return 131 } 132 133 // resolve or move 134 func (g *generator) genName(expr *ast.Name, typ genType) (rk int) { 135 g.tokLine = expr.Pos().Line 136 137 if typ&genKey != 0 { 138 return g.markRK(g.constant(object.String(expr.Name)), true) 139 } 140 141 l, ok := g.resolveName(expr) 142 if !ok { 143 return g.genGetGlobal(expr) 144 } 145 146 switch l.kind { 147 case linkUpval: 148 g.pushInst(opcode.AB(opcode.GETUPVAL, g.sp, l.index)) 149 150 rk = g.sp 151 152 g.nextSP() 153 case linkLocal: 154 if typ&genMove == 0 { 155 return l.index 156 } 157 158 rk = g.sp 159 160 g.pushInst(opcode.AB(opcode.MOVE, g.sp, l.index)) 161 162 g.nextSP() 163 default: 164 panic("unreachable") 165 } 166 167 return 168 } 169 170 func (g *generator) genVarargN(expr *ast.Vararg, nrets int) (r int) { 171 g.tokLine = expr.Pos().Line 172 173 sp := g.sp 174 175 g.pushInst(opcode.AB(opcode.VARARG, g.sp, nrets+1)) 176 177 r = g.sp 178 179 if nrets < 0 { 180 // just update maxstacksize 181 if g.sp+1 > g.MaxStackSize { 182 g.MaxStackSize = g.sp + 1 183 } 184 185 return 186 } 187 188 g.setSP(sp + nrets) 189 190 return 191 } 192 193 func (g *generator) genBasicLit(expr *ast.BasicLit, typ genType) (rk int) { 194 g.tokLine = expr.Pos().Line 195 196 var val object.Value 197 198 tok := expr.Token 199 200 switch tok.Type { 201 case token.NIL: 202 g.pushInst(opcode.AB(opcode.LOADNIL, g.sp, 0)) 203 204 rk = g.sp 205 206 g.nextSP() 207 208 return 209 case token.FALSE: 210 g.pushInst(opcode.ABC(opcode.LOADBOOL, g.sp, 0, 0)) 211 212 rk = g.sp 213 214 g.nextSP() 215 216 return 217 case token.TRUE: 218 g.pushInst(opcode.ABC(opcode.LOADBOOL, g.sp, 1, 0)) 219 220 rk = g.sp 221 222 g.nextSP() 223 224 return 225 case token.INT: 226 if i, ok := g.parseInteger(tok, false); ok { 227 val = i 228 } else { 229 val = g.parseNumber(tok, false) 230 } 231 case token.FLOAT: 232 val = g.parseNumber(tok, false) 233 case token.STRING: 234 val = object.String(g.unquoteString(tok)) 235 default: 236 panic("unreachable") 237 } 238 239 return g.genConst(val, typ) 240 } 241 242 func (g *generator) genFuncLit(expr *ast.FuncLit) (r int) { 243 g.tokLine = expr.Pos().Line 244 245 body := expr.Body 246 247 endLine := expr.End().Line 248 249 p := g.proto(body, false, endLine) 250 251 g.pushInstLine(opcode.ABx(opcode.CLOSURE, g.sp, p), endLine) 252 253 r = g.sp 254 255 g.nextSP() 256 257 return 258 } 259 260 func (g *generator) genTableLit(expr *ast.TableLit) (r int) { 261 g.tokLine = expr.Pos().Line 262 263 var a []ast.Expr 264 var m []*ast.KeyValueExpr 265 for _, e := range expr.Fields { 266 if keyval, ok := e.(*ast.KeyValueExpr); ok { 267 m = append(m, keyval) 268 } else { 269 a = append(a, e) 270 } 271 } 272 273 var skipped bool 274 for len(a) > 0 { 275 if lit, ok := a[len(a)-1].(*ast.BasicLit); ok && lit.Token.Type == token.NIL { 276 a = a[:len(a)-1] 277 278 skipped = true 279 280 continue 281 } 282 283 break 284 } 285 286 g.pushInst(opcode.ABC(opcode.NEWTABLE, g.sp, opcode.IntToLog(len(a)), opcode.IntToLog(len(m)))) 287 288 tp := g.sp 289 290 g.nextSP() 291 292 for _, e := range m { 293 sp := g.sp 294 if e.Lbrack != position.NoPos { 295 x := g.genExpr(e.Key, genR|genK) 296 y := g.genExpr(e.Value, genR|genK) 297 298 g.pushInst(opcode.ABC(opcode.SETTABLE, tp, x, y)) 299 } else { 300 x := g.genExpr(e.Key, genR|genK|genKey) 301 y := g.genExpr(e.Value, genR|genK) 302 303 g.pushInst(opcode.ABC(opcode.SETTABLE, tp, x, y)) 304 } 305 g.sp = sp 306 } 307 308 if len(a) > 0 { 309 locktmp := g.locktmp 310 311 g.locktmp = true 312 313 sp := g.sp 314 315 i := 1 316 for { 317 if len(a) < version.LUA_FPF { 318 if len(a) == 0 { 319 break 320 } 321 322 var isVar bool 323 324 if skipped { 325 for _, e := range a { 326 g.genExpr(e, genMove) 327 } 328 } else { 329 for _, e := range a[:len(a)-1] { 330 g.genExpr(e, genMove) 331 } 332 333 isVar = g.genExprN(a[len(a)-1], -1) 334 } 335 336 n := len(a) 337 if isVar { 338 n = 0 339 } 340 341 if i > opcode.MaxC { 342 g.pushInst(opcode.ABC(opcode.SETLIST, tp, n, 0)) 343 g.pushInst(opcode.Ax(opcode.EXTRAARG, i)) 344 } else { 345 g.pushInst(opcode.ABC(opcode.SETLIST, tp, n, i)) 346 } 347 348 // recover sp 349 g.sp = sp 350 351 break 352 } 353 354 for _, e := range a[:version.LUA_FPF] { 355 g.genExpr(e, genMove) 356 } 357 358 if i > opcode.MaxC { 359 g.pushInst(opcode.ABC(opcode.SETLIST, tp, version.LUA_FPF, 0)) 360 g.pushInst(opcode.Ax(opcode.EXTRAARG, i)) 361 } else { 362 g.pushInst(opcode.ABC(opcode.SETLIST, tp, version.LUA_FPF, i)) 363 } 364 365 // recover sp 366 g.sp = sp 367 368 a = a[version.LUA_FPF:] 369 i++ 370 } 371 372 g.locktmp = locktmp 373 } 374 375 r = tp 376 377 return 378 } 379 380 func (g *generator) genSelectorExpr(expr *ast.SelectorExpr) (r int) { 381 g.tokLine = expr.Pos().Line 382 383 sp := g.sp 384 385 x := g.genExpr(expr.X, genR) 386 y := g.genName(expr.Sel, genKey) 387 388 g.pushInst(opcode.ABC(opcode.GETTABLE, sp, x, y)) 389 390 r = sp 391 392 // recover sp 393 g.setSP(sp + 1) 394 395 return 396 } 397 398 func (g *generator) genIndexExpr(expr *ast.IndexExpr) (r int) { 399 g.tokLine = expr.Pos().Line 400 401 sp := g.sp 402 403 x := g.genExpr(expr.X, genR) 404 y := g.genExpr(expr.Index, genR|genK) 405 406 g.pushInst(opcode.ABC(opcode.GETTABLE, sp, x, y)) 407 408 r = sp 409 410 // recover sp 411 g.setSP(sp + 1) 412 413 return 414 } 415 416 func (g *generator) genCallExprN(expr *ast.CallExpr, nrets int, isTail bool) (r int) { 417 g.tokLine = expr.Pos().Line 418 419 sp := g.sp 420 421 var fn int 422 423 nargs := len(expr.Args) 424 425 locktmp := g.locktmp 426 427 if expr.Colon != position.NoPos { 428 self := g.genExpr(expr.X, genR) 429 430 name := g.genName(expr.Name, genKey) 431 432 g.pushInst(opcode.ABC(opcode.SELF, sp, self, name)) 433 434 nargs++ 435 436 fn = sp 437 438 g.setSP(sp + 2) 439 440 g.locktmp = true 441 } else { 442 g.locktmp = true 443 444 fn = g.genExpr(expr.X, genMove) 445 } 446 447 var isVar bool 448 if len(expr.Args) != 0 { 449 for _, e := range expr.Args[:len(expr.Args)-1] { 450 g.genExpr(e, genMove) 451 } 452 453 isVar = g.genExprN(expr.Args[len(expr.Args)-1], -1) 454 } 455 456 g.locktmp = locktmp 457 458 if isTail { 459 if isVar { 460 g.pushInst(opcode.ABC(opcode.TAILCALL, fn, 0, 0)) 461 } else { 462 g.pushInst(opcode.ABC(opcode.TAILCALL, fn, nargs+1, 0)) 463 } 464 465 r = fn 466 467 // recover sp 468 g.setSP(sp) 469 470 return 471 } 472 473 if isVar { 474 g.pushInst(opcode.ABC(opcode.CALL, fn, 0, nrets+1)) 475 } else { 476 g.pushInst(opcode.ABC(opcode.CALL, fn, nargs+1, nrets+1)) 477 } 478 479 r = fn 480 481 if nrets < 0 { 482 // just update maxstacksize 483 if g.sp+1 > g.MaxStackSize { 484 g.MaxStackSize = g.sp + 1 485 } 486 487 return 488 } 489 490 // recover sp 491 g.setSP(sp + nrets) 492 493 return 494 } 495 496 func (g *generator) genUnaryExpr(expr *ast.UnaryExpr, typ genType) (r int) { 497 g.tokLine = expr.Pos().Line 498 499 if expr.Op == token.UNM { 500 if x, ok := expr.X.(*ast.BasicLit); ok { 501 tok := x.Token 502 503 switch tok.Type { 504 case token.INT: 505 var val object.Value 506 507 if i, ok := g.parseInteger(tok, true); ok { 508 val = i 509 } else { 510 val = g.parseNumber(tok, true) 511 } 512 513 return g.genConst(val, typ) 514 case token.FLOAT: 515 val := g.parseNumber(tok, true) 516 517 return g.genConst(val, typ) 518 } 519 } 520 } 521 522 sp := g.sp 523 524 x := g.genExpr(expr.X, genR) 525 526 switch expr.Op { 527 case token.UNM: 528 g.pushInst(opcode.AB(opcode.UNM, sp, x)) 529 case token.BNOT: 530 g.pushInst(opcode.AB(opcode.BNOT, sp, x)) 531 case token.NOT: 532 g.pushInst(opcode.AB(opcode.NOT, sp, x)) 533 case token.LEN: 534 g.pushInst(opcode.AB(opcode.LEN, sp, x)) 535 default: 536 panic("unreachable") 537 } 538 539 r = sp 540 541 // recover sp 542 g.setSP(sp + 1) 543 544 return 545 } 546 547 func (g *generator) genBinaryExpr(expr *ast.BinaryExpr, typ genType) (r int) { 548 g.tokLine = expr.Pos().Line 549 550 sp := g.sp 551 552 switch expr.Op { 553 case token.EQ: 554 x := g.genExpr(expr.X, genR|genK) 555 y := g.genExpr(expr.Y, genR|genK) 556 557 g.pushInst(opcode.ABC(opcode.EQ, 1, x, y)) 558 g.pushInst(opcode.AsBx(opcode.JMP, 0, 1)) 559 g.pushInst(opcode.ABC(opcode.LOADBOOL, sp, 0, 1)) 560 g.pushInst(opcode.ABC(opcode.LOADBOOL, sp, 1, 0)) 561 562 g.lockpeep = true 563 case token.NE: 564 x := g.genExpr(expr.X, genR|genK) 565 y := g.genExpr(expr.Y, genR|genK) 566 567 g.pushInst(opcode.ABC(opcode.EQ, 0, x, y)) 568 g.pushInst(opcode.AsBx(opcode.JMP, 0, 1)) 569 g.pushInst(opcode.ABC(opcode.LOADBOOL, sp, 0, 1)) 570 g.pushInst(opcode.ABC(opcode.LOADBOOL, sp, 1, 0)) 571 572 g.lockpeep = true 573 case token.LT: 574 x := g.genExpr(expr.X, genR|genK) 575 y := g.genExpr(expr.Y, genR|genK) 576 577 g.pushInst(opcode.ABC(opcode.LT, 1, x, y)) 578 g.pushInst(opcode.AsBx(opcode.JMP, 0, 1)) 579 g.pushInst(opcode.ABC(opcode.LOADBOOL, sp, 0, 1)) 580 g.pushInst(opcode.ABC(opcode.LOADBOOL, sp, 1, 0)) 581 582 g.lockpeep = true 583 case token.LE: 584 x := g.genExpr(expr.X, genR|genK) 585 y := g.genExpr(expr.Y, genR|genK) 586 587 g.pushInst(opcode.ABC(opcode.LE, 1, x, y)) 588 g.pushInst(opcode.AsBx(opcode.JMP, 0, 1)) 589 g.pushInst(opcode.ABC(opcode.LOADBOOL, sp, 0, 1)) 590 g.pushInst(opcode.ABC(opcode.LOADBOOL, sp, 1, 0)) 591 592 g.lockpeep = true 593 case token.GT: 594 x := g.genExpr(expr.X, genR|genK) 595 y := g.genExpr(expr.Y, genR|genK) 596 597 g.pushInst(opcode.ABC(opcode.LT, 1, y, x)) 598 g.pushInst(opcode.AsBx(opcode.JMP, 0, 1)) 599 g.pushInst(opcode.ABC(opcode.LOADBOOL, sp, 0, 1)) 600 g.pushInst(opcode.ABC(opcode.LOADBOOL, sp, 1, 0)) 601 602 g.lockpeep = true 603 case token.GE: 604 x := g.genExpr(expr.X, genR|genK) 605 y := g.genExpr(expr.Y, genR|genK) 606 607 g.pushInst(opcode.ABC(opcode.LE, 1, y, x)) 608 g.pushInst(opcode.AsBx(opcode.JMP, 0, 1)) 609 g.pushInst(opcode.ABC(opcode.LOADBOOL, sp, 0, 1)) 610 g.pushInst(opcode.ABC(opcode.LOADBOOL, sp, 1, 0)) 611 612 g.lockpeep = true 613 case token.ADD: 614 x := g.genExpr(expr.X, genR|genK) 615 y := g.genExpr(expr.Y, genR|genK) 616 617 g.pushInst(opcode.ABC(opcode.ADD, sp, x, y)) 618 case token.SUB: 619 x := g.genExpr(expr.X, genR|genK) 620 y := g.genExpr(expr.Y, genR|genK) 621 622 g.pushInst(opcode.ABC(opcode.SUB, sp, x, y)) 623 case token.MUL: 624 x := g.genExpr(expr.X, genR|genK) 625 y := g.genExpr(expr.Y, genR|genK) 626 627 g.pushInst(opcode.ABC(opcode.MUL, sp, x, y)) 628 case token.MOD: 629 x := g.genExpr(expr.X, genR|genK) 630 y := g.genExpr(expr.Y, genR|genK) 631 632 g.pushInst(opcode.ABC(opcode.MOD, sp, x, y)) 633 case token.POW: 634 x := g.genExpr(expr.X, genR|genK) 635 y := g.genExpr(expr.Y, genR|genK) 636 637 g.pushInst(opcode.ABC(opcode.POW, sp, x, y)) 638 case token.DIV: 639 x := g.genExpr(expr.X, genR|genK) 640 y := g.genExpr(expr.Y, genR|genK) 641 642 g.pushInst(opcode.ABC(opcode.DIV, sp, x, y)) 643 case token.IDIV: 644 x := g.genExpr(expr.X, genR|genK) 645 y := g.genExpr(expr.Y, genR|genK) 646 647 g.pushInst(opcode.ABC(opcode.IDIV, sp, x, y)) 648 case token.BAND: 649 x := g.genExpr(expr.X, genR|genK) 650 y := g.genExpr(expr.Y, genR|genK) 651 652 g.pushInst(opcode.ABC(opcode.BAND, sp, x, y)) 653 case token.BOR: 654 x := g.genExpr(expr.X, genR|genK) 655 y := g.genExpr(expr.Y, genR|genK) 656 657 g.pushInst(opcode.ABC(opcode.BOR, sp, x, y)) 658 case token.BXOR: 659 x := g.genExpr(expr.X, genR|genK) 660 y := g.genExpr(expr.Y, genR|genK) 661 662 g.pushInst(opcode.ABC(opcode.BXOR, sp, x, y)) 663 case token.SHL: 664 x := g.genExpr(expr.X, genR|genK) 665 y := g.genExpr(expr.Y, genR|genK) 666 667 g.pushInst(opcode.ABC(opcode.SHL, sp, x, y)) 668 case token.SHR: 669 x := g.genExpr(expr.X, genR|genK) 670 y := g.genExpr(expr.Y, genR|genK) 671 672 g.pushInst(opcode.ABC(opcode.SHR, sp, x, y)) 673 case token.CONCAT: 674 locktmp := g.locktmp 675 676 g.locktmp = true 677 678 x := g.genExpr(expr.X, genMove) 679 680 Y := expr.Y 681 for { 682 ct, ok := Y.(*ast.BinaryExpr) 683 if !ok || ct.Op != token.CONCAT { 684 break 685 } 686 687 g.genExpr(ct.X, genMove) 688 689 Y = ct.Y 690 } 691 692 y := g.genExpr(Y, genMove) 693 694 g.locktmp = locktmp 695 696 g.pushInst(opcode.ABC(opcode.CONCAT, sp, x, y)) 697 case token.AND: 698 if _, ok := g.foldExpr(expr.X); ok { 699 x := g.genExpr(expr.Y, genR) 700 701 if typ&genMove == 0 { 702 return x 703 } 704 705 g.pushInst(opcode.AB(opcode.MOVE, sp, x)) 706 } else { 707 x := g.genExpr(expr.X, genR) 708 709 g.pushInst(opcode.ABC(opcode.TESTSET, sp, x, 0)) 710 711 endJump := g.genJumpPoint() 712 713 y := g.genExpr(expr.Y, genR) 714 715 g.pushInst(opcode.AB(opcode.MOVE, sp, y)) 716 717 g.genJumpFrom(endJump) 718 } 719 case token.OR: 720 if _, ok := g.foldExpr(expr.X); ok { 721 y := g.genExpr(expr.Y, genR) 722 723 if typ&genMove == 0 { 724 return y 725 } 726 727 g.pushInst(opcode.AB(opcode.MOVE, sp, y)) 728 } else { 729 x := g.genExpr(expr.X, genR) 730 731 g.pushInst(opcode.ABC(opcode.TESTSET, sp, x, 1)) 732 733 endJump := g.genJumpPoint() 734 735 y := g.genExpr(expr.Y, genR) 736 737 g.pushInst(opcode.AB(opcode.MOVE, sp, y)) 738 739 g.genJumpFrom(endJump) 740 } 741 default: 742 panic("unreachable") 743 } 744 745 r = sp 746 747 // recover sp 748 g.setSP(sp + 1) 749 750 return 751 }