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  }