github.com/gotranspile/cxgo@v0.3.7/nums_test.go (about) 1 package cxgo 2 3 import ( 4 "fmt" 5 "testing" 6 ) 7 8 var casesTranslateNumbers = []parseCase{ 9 { 10 name: "binary operators", 11 src: ` 12 void foo(int a, int b) { 13 int c; 14 c = a + b; 15 c = a - b; 16 c = a * b; 17 c = a / b; 18 c = a + 1; 19 c = a - 1; 20 c = a * 1; 21 c = a / 1; 22 c = 1 + b; 23 c = 1 - b; 24 c = 1 * b; 25 c = 1 / b; 26 } 27 `, 28 exp: ` 29 func foo(a int32, b int32) { 30 var c int32 31 _ = c 32 c = a + b 33 c = a - b 34 c = a * b 35 c = a / b 36 c = a + 1 37 c = a - 1 38 c = a * 1 39 c = a / 1 40 c = b + 1 41 c = 1 - b 42 c = b * 1 43 c = 1 / b 44 } 45 `, 46 }, 47 { 48 name: "binary conversions", 49 src: ` 50 void foo(short a, int b) { 51 int c; 52 short d; 53 c = a + b; 54 c = a - b; 55 c = a * b; 56 c = a / b; 57 c = b + a; 58 c = b - a; 59 c = b * a; 60 c = b / a; 61 d = a + b; 62 d = a - b; 63 d = a * b; 64 d = a / b; 65 d = b + a; 66 d = b - a; 67 d = b * a; 68 d = b / a; 69 } 70 `, 71 exp: ` 72 func foo(a int16, b int32) { 73 var c int32 74 _ = c 75 var d int16 76 _ = d 77 c = int32(a) + b 78 c = int32(a) - b 79 c = int32(a) * b 80 c = int32(a) / b 81 c = b + int32(a) 82 c = b - int32(a) 83 c = b * int32(a) 84 c = b / int32(a) 85 d = int16(int32(a) + b) 86 d = int16(int32(a) - b) 87 d = int16(int32(a) * b) 88 d = int16(int32(a) / b) 89 d = int16(b + int32(a)) 90 d = int16(b - int32(a)) 91 d = int16(b * int32(a)) 92 d = int16(b / int32(a)) 93 } 94 `, 95 }, 96 { 97 name: "binary conversions sign", 98 src: ` 99 void foo(int a, unsigned int b) { 100 int c; 101 unsigned int d; 102 c = a + b; 103 c = a - b; 104 c = a * b; 105 c = a / b; 106 c = b + a; 107 c = b - a; 108 c = b * a; 109 c = b / a; 110 d = a + b; 111 d = a - b; 112 d = a * b; 113 d = a / b; 114 d = b + a; 115 d = b - a; 116 d = b * a; 117 d = b / a; 118 } 119 `, 120 exp: ` 121 func foo(a int32, b uint32) { 122 var c int32 123 _ = c 124 var d uint32 125 _ = d 126 c = int32(uint32(a) + b) 127 c = int32(uint32(a) - b) 128 c = int32(uint32(a) * b) 129 c = int32(uint32(a) / b) 130 c = int32(b + uint32(a)) 131 c = int32(b - uint32(a)) 132 c = int32(b * uint32(a)) 133 c = int32(b / uint32(a)) 134 d = uint32(a) + b 135 d = uint32(a) - b 136 d = uint32(a) * b 137 d = uint32(a) / b 138 d = b + uint32(a) 139 d = b - uint32(a) 140 d = b * uint32(a) 141 d = b / uint32(a) 142 } 143 `, 144 }, 145 { 146 name: "int -> named int", 147 inc: `typedef int NINT;`, 148 src: ` 149 void foo() { 150 int a; 151 NINT b; 152 b = a; 153 } 154 `, 155 exp: ` 156 func foo() { 157 var ( 158 a int32 159 b NINT 160 ) 161 _ = b 162 b = NINT(a) 163 } 164 `, 165 }, 166 { 167 name: "int -> go int", 168 builtins: true, 169 src: ` 170 void foo() { 171 int a; 172 _cxgo_go_int b; 173 b = a; 174 } 175 `, 176 exp: ` 177 func foo() { 178 var ( 179 a int32 180 b int 181 ) 182 _ = b 183 b = int(a) 184 } 185 `, 186 }, 187 { 188 name: "int16 - uint16", 189 src: ` 190 void foo() { 191 short a; 192 unsigned short b; 193 b = a; 194 a = b; 195 if (a < b) { 196 return; 197 } 198 } 199 `, 200 exp: ` 201 func foo() { 202 var ( 203 a int16 204 b uint16 205 ) 206 b = uint16(a) 207 a = int16(b) 208 if int32(a) < int32(b) { 209 return 210 } 211 } 212 `, 213 }, 214 { 215 skip: true, // TODO: verify 216 name: "int16 and uint16", 217 src: ` 218 void foo() { 219 short a; 220 unsigned short b; 221 b = 8 - a; 222 if (b < 8 - a) { 223 return; 224 } 225 } 226 `, 227 exp: ` 228 func foo() { 229 var ( 230 a int16 231 b uint16 232 ) 233 b = uint16(8 - a) 234 if int16(b) < 8 - a { 235 return 236 } 237 } 238 `, 239 }, 240 { 241 skip: true, // TODO: verify 242 name: "types", 243 src: ` 244 void foo() { 245 __int8 i8; 246 __int16 i16; 247 __int32 i32; 248 __int64 i64; 249 unsigned __int8 u8; 250 unsigned __int16 u16; 251 unsigned __int32 u32; 252 unsigned __int64 u64; 253 254 i16 = i8 * i8; 255 i32 = i8 * i8; 256 i32 = i16 * i16; 257 i64 = i8 * i8; 258 i64 = i16 * i16; 259 i64 = i32 * i32; 260 261 i16 = i8 * u8; 262 i32 = i8 * u8; 263 i32 = i16 * u16; 264 i64 = i8 * u8; 265 i64 = i16 * u16; 266 i64 = i32 * u32; 267 268 u16 = u8 * u8; 269 u32 = u8 * u8; 270 u32 = u16 * u16; 271 u64 = u8 * u8; 272 u64 = u16 * u16; 273 u64 = u32 * u32; 274 275 u16 = i8 * u8; 276 u32 = i8 * u8; 277 u32 = i16 * u16; 278 u64 = i8 * u8; 279 u64 = i16 * u16; 280 u64 = i32 * u32; 281 } 282 `, 283 exp: ` 284 func foo() { 285 var ( 286 i8 int8 287 i16 int16 288 i32 int32 289 i64 int64 290 u8 uint8 291 u16 uint16 292 u32 uint32 293 u64 uint64 294 ) 295 i16 = int16(int32(i8) * int32(i8)) 296 i32 = int32(i8) * int32(i8) 297 i32 = int32(i16) * int32(i16) 298 i64 = int64(int32(i8) * int32(i8)) 299 i64 = int64(int32(i16) * int32(i16)) 300 i64 = int64(i32) * int64(i32) 301 i16 = int16(i8) * int16(u8) 302 i32 = int32(i8) * int32(u8) 303 i32 = int32(i16) * int32(u16) 304 i64 = int64(i8) * int64(u8) 305 i64 = int64(i16) * int64(u16) 306 i64 = int64(i32) * int64(u32) 307 u16 = uint16(u8) * uint16(u8) 308 u32 = uint32(u8) * uint32(u8) 309 u32 = uint32(u16) * uint32(u16) 310 u64 = uint64(u8) * uint64(u8) 311 u64 = uint64(u16) * uint64(u16) 312 u64 = uint64(u32) * uint64(u32) 313 u16 = uint16(i8) * uint16(u8) 314 u32 = uint32(i8) * uint32(u8) 315 u32 = uint32(i16) * uint32(u16) 316 u64 = uint64(i8) * uint64(u8) 317 u64 = uint64(i16) * uint64(u16) 318 u64 = uint64(i32) * uint64(u32) 319 } 320 `, 321 }, 322 { 323 name: "named int -> int", 324 inc: `typedef int NINT;`, 325 src: ` 326 void foo() { 327 NINT a; 328 int b; 329 b = a; 330 } 331 `, 332 exp: ` 333 func foo() { 334 var ( 335 a NINT 336 b int32 337 ) 338 _ = b 339 b = int32(a) 340 } 341 `, 342 }, 343 { 344 name: "named int eq int", 345 inc: `typedef int NINT;`, 346 src: ` 347 void foo() { 348 NINT a; 349 int b; 350 if (b == a) return; 351 } 352 `, 353 exp: ` 354 func foo() { 355 var ( 356 a NINT 357 b int32 358 ) 359 if b == int32(a) { 360 return 361 } 362 } 363 `, 364 }, 365 { 366 name: "diff ints", 367 src: ` 368 void foo() { 369 unsigned short a; 370 int b; 371 b = a; 372 } 373 `, 374 exp: ` 375 func foo() { 376 var ( 377 a uint16 378 b int32 379 ) 380 _ = b 381 b = int32(a) 382 } 383 `, 384 }, 385 { 386 name: "sub unsigned const", 387 src: ` 388 void foo(unsigned int a) { 389 unsigned int b; 390 b = a - 0x1; 391 } 392 `, 393 exp: ` 394 func foo(a uint32) { 395 var b uint32 396 _ = b 397 b = a - 1 398 } 399 `, 400 }, 401 { 402 name: "named int arithm", 403 inc: `typedef int my_size_t;`, 404 src: ` 405 void foo() { 406 my_size_t a; 407 my_size_t b; 408 a = 1 + b; 409 a = b + 1; 410 } 411 `, 412 exp: ` 413 func foo() { 414 var a my_size_t 415 _ = a 416 var b my_size_t 417 a = b + 1 418 a = b + 1 419 } 420 `, 421 }, 422 { 423 name: "overflow mult char", 424 src: ` 425 void foo() { 426 char a; 427 int b; 428 b = 300 * a; 429 } 430 `, 431 exp: ` 432 func foo() { 433 var ( 434 a int8 435 b int32 436 ) 437 _ = b 438 b = int32(a) * 300 439 } 440 `, 441 }, 442 { 443 name: "overflow mult schar", 444 src: ` 445 void foo() { 446 signed char a; 447 int b; 448 b = 300 * a; 449 } 450 `, 451 exp: ` 452 func foo() { 453 var ( 454 a int8 455 b int32 456 ) 457 _ = b 458 b = int32(a) * 300 459 } 460 `, 461 }, 462 { 463 name: "overflow mult uchar", 464 src: ` 465 void foo() { 466 unsigned char a; 467 int b; 468 b = 300 * a; 469 } 470 `, 471 exp: ` 472 func foo() { 473 var ( 474 a uint8 475 b int32 476 ) 477 _ = b 478 b = int32(a) * 300 479 } 480 `, 481 }, 482 { 483 name: "diff int equality", 484 src: ` 485 void foo() { 486 short a; 487 unsigned int b; 488 if (b != (a & 0x17F0)) { 489 return; 490 } 491 } 492 `, 493 exp: ` 494 func foo() { 495 var ( 496 a int16 497 b uint32 498 ) 499 if b != uint32(int32(a)&6128) { 500 return 501 } 502 } 503 `, 504 }, 505 { 506 name: "const overflow", 507 src: ` 508 void foo(int a) { 509 if (a != 0xdeadface) { 510 return; 511 } 512 } 513 `, 514 exp: ` 515 func foo(a int32) { 516 if uint32(a) != 0xDEADFACE { 517 return 518 } 519 } 520 `, 521 }, 522 { 523 name: "const overflow 2", 524 src: ` 525 void foo(unsigned int a) { 526 a = -1; 527 a += -1; 528 a = ~0; 529 a ^= 0; 530 a ^= ~0; 531 } 532 `, 533 exp: ` 534 func foo(a uint32) { 535 a = math.MaxUint32 536 a += math.MaxUint32 537 a = uint32(^int32(0)) 538 a ^= 0 539 a ^= uint32(^int32(0)) 540 } 541 `, 542 }, 543 { 544 name: "const and named int", 545 inc: `typedef unsigned int mDWORD;`, 546 src: ` 547 void foo(int a, mDWORD b) { 548 a = 1 - b; 549 } 550 `, 551 exp: ` 552 func foo(a int32, b mDWORD) { 553 a = int32(1 - b) 554 } 555 `, 556 }, 557 { 558 name: "ternary", 559 src: ` 560 void foo(int a) { 561 foo(a != 0 ? 0 : 99999); 562 } 563 `, 564 exp: ` 565 func foo(a int32) { 566 foo(int32(func() uint32 { 567 if a != 0 { 568 return 0 569 } 570 return 99999 571 }())) 572 } 573 `, 574 }, 575 { 576 name: "seq", 577 src: ` 578 void foo(int a) { 579 a = (a = 1, 1); 580 } 581 `, 582 exp: ` 583 func foo(a int32) { 584 a = func() int32 { 585 a = 1 586 return 1 587 }() 588 } 589 `, 590 }, 591 { 592 name: "float and int", 593 src: ` 594 void foo(int a, int b, float c) { 595 c = (a - b * c) / 2; 596 } 597 `, 598 exp: ` 599 func foo(a int32, b int32, c float32) { 600 c = (float32(a) - float32(b)*c) / 2 601 } 602 `, 603 }, 604 { 605 name: "sizeof and shift", 606 src: ` 607 #include <stdlib.h> 608 609 typedef unsigned int word; 610 611 void foo() { 612 word a = (((word)1)<<((8*((int)sizeof(word)))-1)); 613 } 614 `, 615 exp: ` 616 type word uint32 617 618 func foo() { 619 var a word = word(1 << ((8 * (int32(unsafe.Sizeof(word(0))))) - 1)) 620 _ = a 621 } 622 `, 623 }, 624 } 625 626 func TestNumbers(t *testing.T) { 627 t.Run("int types", testNumbersInts) 628 t.Run("fixed types", testNumbersFixed) 629 t.Run("cxgo types", testNumberscxgo) 630 t.Run("stdlib types", testNumbersStdlib) 631 t.Run("go types", testNumbersGo) 632 runTestTranslate(t, casesTranslateNumbers) 633 } 634 635 func testNumbersInts(t *testing.T) { 636 const ( 637 kindVal = iota 638 kindPtr 639 kindArr 640 ) 641 const ( 642 signUndefined = iota 643 signSigned 644 signUnsigned 645 ) 646 type intType struct { 647 cname string 648 size int 649 } 650 for _, kind := range []int{ 651 kindVal, kindPtr, kindArr, 652 } { 653 for _, sign := range []int{ 654 signUndefined, signSigned, signUnsigned, 655 } { 656 for _, size := range []intType{ 657 {"char", 1}, 658 {"short", 2}, 659 {"int", 4}, 660 {"long", 4}, 661 {"long long", 8}, 662 } { 663 ctype := size.cname 664 switch sign { 665 case signSigned: 666 ctype = "signed " + ctype 667 case signUnsigned: 668 ctype = "unsigned " + ctype 669 } 670 csuff := "" 671 switch kind { 672 case kindPtr: 673 ctype += "*" 674 case kindArr: 675 csuff = "[2]" 676 } 677 t.Run(ctype+csuff, func(t *testing.T) { 678 gotype := fmt.Sprintf("int%d", size.size*8) 679 switch sign { 680 case signUnsigned: 681 gotype = "u" + gotype 682 } 683 // special case for char pointers/arrays -> turn to byte 684 if size.cname == "char" && sign == signUndefined && kind != kindVal { 685 gotype = "byte" 686 } 687 switch kind { 688 case kindPtr: 689 gotype = "*" + gotype 690 case kindArr: 691 gotype = "[2]" + gotype 692 } 693 runTestTranslateCase(t, parseCase{ 694 src: ctype + " v" + csuff + ";", 695 exp: "var v " + gotype, 696 }) 697 }) 698 } 699 } 700 } 701 } 702 703 func testNumbersFixed(t *testing.T) { 704 const ( 705 kindVal = iota 706 kindPtr 707 kindArr 708 ) 709 const ( 710 signUndefined = iota 711 signSigned 712 signUnsigned 713 ) 714 for _, kind := range []int{ 715 kindVal, kindPtr, kindArr, 716 } { 717 for _, sign := range []int{ 718 signUndefined, signSigned, signUnsigned, 719 } { 720 for _, size := range []int{ 721 1, 2, 4, 8, 722 } { 723 ctype := fmt.Sprintf("__int%d", size*8) 724 switch sign { 725 case signSigned: 726 ctype = "signed " + ctype 727 case signUnsigned: 728 ctype = "unsigned " + ctype 729 } 730 csuff := "" 731 switch kind { 732 case kindPtr: 733 ctype += "*" 734 case kindArr: 735 csuff = "[2]" 736 } 737 t.Run(ctype+csuff, func(t *testing.T) { 738 gotype := fmt.Sprintf("int%d", size*8) 739 switch sign { 740 case signUnsigned: 741 gotype = "u" + gotype 742 } 743 switch kind { 744 case kindPtr: 745 gotype = "*" + gotype 746 case kindArr: 747 gotype = "[2]" + gotype 748 } 749 runTestTranslateCase(t, parseCase{ 750 src: ctype + " v" + csuff + ";", 751 exp: "var v " + gotype, 752 }) 753 }) 754 } 755 } 756 } 757 } 758 759 func testNumberscxgo(t *testing.T) { 760 const ( 761 kindVal = iota 762 kindPtr 763 kindArr 764 ) 765 const ( 766 signUndefined = iota 767 signSigned 768 signUnsigned 769 ) 770 for _, kind := range []int{ 771 kindVal, kindPtr, kindArr, 772 } { 773 for _, sign := range []int{ 774 signUndefined, signSigned, signUnsigned, 775 } { 776 for _, size := range []int{ 777 1, 2, 4, 8, 778 } { 779 csign := "" 780 switch sign { 781 case signSigned: 782 csign = "s" 783 case signUnsigned: 784 csign = "u" 785 } 786 ctype := fmt.Sprintf("_cxgo_%sint%d", csign, size*8) 787 csuff := "" 788 switch kind { 789 case kindPtr: 790 ctype += "*" 791 case kindArr: 792 csuff = "[2]" 793 } 794 t.Run(ctype+csuff, func(t *testing.T) { 795 gotype := fmt.Sprintf("int%d", size*8) 796 switch sign { 797 case signUnsigned: 798 gotype = "u" + gotype 799 } 800 switch kind { 801 case kindPtr: 802 gotype = "*" + gotype 803 case kindArr: 804 gotype = "[2]" + gotype 805 } 806 runTestTranslateCase(t, parseCase{ 807 builtins: true, 808 src: ctype + " v" + csuff + ";", 809 exp: "var v " + gotype, 810 }) 811 }) 812 } 813 } 814 } 815 } 816 817 func testNumbersStdlib(t *testing.T) { 818 const ( 819 kindVal = iota 820 kindPtr 821 kindArr 822 ) 823 const ( 824 signSigned = iota 825 signUnsigned 826 ) 827 for _, kind := range []int{ 828 kindVal, kindPtr, kindArr, 829 } { 830 for _, sign := range []int{ 831 signSigned, signUnsigned, 832 } { 833 for _, size := range []int{ 834 1, 2, 4, 8, 835 } { 836 ctype := fmt.Sprintf("int%d_t", size*8) 837 if sign == signUnsigned { 838 ctype = "u" + ctype 839 } 840 csuff := "" 841 switch kind { 842 case kindPtr: 843 ctype += "*" 844 case kindArr: 845 csuff = "[2]" 846 } 847 t.Run(ctype+csuff, func(t *testing.T) { 848 gotype := fmt.Sprintf("int%d", size*8) 849 switch sign { 850 case signUnsigned: 851 gotype = "u" + gotype 852 } 853 switch kind { 854 case kindPtr: 855 gotype = "*" + gotype 856 case kindArr: 857 gotype = "[2]" + gotype 858 } 859 runTestTranslateCase(t, parseCase{ 860 src: "#include <stdint.h>\n" + ctype + " v" + csuff + ";", 861 exp: "var v " + gotype, 862 }) 863 }) 864 } 865 } 866 } 867 } 868 869 func testNumbersGo(t *testing.T) { 870 for _, gotype := range []string{ 871 "int", "uint", "uintptr", "byte", "rune", 872 } { 873 t.Run(gotype, func(t *testing.T) { 874 runTestTranslateCase(t, parseCase{ 875 builtins: true, 876 src: "_cxgo_go_" + gotype + " v;", 877 exp: "var v " + gotype, 878 }) 879 }) 880 } 881 }