github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/transpiler/operators.go (about) 1 // This file contains functions transpiling some general operator expressions. 2 // See binary.go and unary.go. 3 4 package transpiler 5 6 import ( 7 "fmt" 8 goast "go/ast" 9 "go/token" 10 11 "github.com/Konstantin8105/c4go/ast" 12 "github.com/Konstantin8105/c4go/program" 13 "github.com/Konstantin8105/c4go/types" 14 "github.com/Konstantin8105/c4go/util" 15 ) 16 17 // ternary without middle operation 18 // 19 // Example: 20 // 21 // BinaryConditionalOperator 'int' 22 // |-BinaryOperator 'int' '>' 23 // | |-IntegerLiteral 'int' 19 24 // | `-UnaryOperator 'int' prefix '-' 25 // | `-IntegerLiteral 'int' 9 26 // |-OpaqueValueExpr 'int' 27 // | `-BinaryOperator 'int' '>' 28 // | |-IntegerLiteral 'int' 19 29 // | `-UnaryOperator 'int' prefix '-' 30 // | `-IntegerLiteral 'int' 9 31 // |-OpaqueValueExpr 'int' 32 // | `-BinaryOperator 'int' '>' 33 // | |-IntegerLiteral 'int' 19 34 // | `-UnaryOperator 'int' prefix '-' 35 // | `-IntegerLiteral 'int' 9 36 // `-IntegerLiteral 0x3646f70 <col:18> 'int' 23 37 func transpileBinaryConditionalOperator(n *ast.BinaryConditionalOperator, p *program.Program) ( 38 _ *goast.CallExpr, theType string, preStmts []goast.Stmt, postStmts []goast.Stmt, err error) { 39 defer func() { 40 if err != nil { 41 err = fmt.Errorf("cannot transpile BinaryConditionalOperator : err = %v", err) 42 } 43 }() 44 45 var co ast.ConditionalOperator 46 co.Type = n.Type 47 co.AddChild(n.Children()[0]) 48 co.AddChild(&ast.IntegerLiteral{ 49 Type: co.Type, 50 Value: "1", 51 }) 52 co.AddChild(n.Children()[3]) 53 54 return transpileConditionalOperator(&co, p) 55 } 56 57 // transpileConditionalOperator transpiles a conditional (also known as a 58 // ternary) operator: 59 // 60 // a ? b : c 61 // 62 // We cannot simply convert these to an "if" statement because they by inside 63 // another expression. 64 // 65 // Since Go does not support the ternary operator or inline "if" statements we 66 // use a closure to work the same way. 67 // 68 // It is also important to note that C only evaluates the "b" or "c" condition 69 // based on the result of "a" (from the above example). 70 // 71 // Example AST: 72 // ConditionalOperator 'int' 73 // |-ImplicitCastExpr 'int (*)(int)' <LValueToRValue> 74 // | `-DeclRefExpr 'int (*)(int)' lvalue Var 'v' 'int (*)(int)' 75 // |-IntegerLiteral 'int' 1 76 // `-CallExpr 'int' 77 // 78 // |-... 79 // 80 // ConditionalOperator 'int' 81 // |-BinaryOperator 'int' '!=' 82 // | |-... 83 // |-BinaryOperator 'int' '-' 84 // | |-... 85 // `-BinaryOperator 'int' '-' 86 // 87 // |-... 88 func transpileConditionalOperator(n *ast.ConditionalOperator, p *program.Program) ( 89 _ *goast.CallExpr, theType string, preStmts []goast.Stmt, postStmts []goast.Stmt, err error) { 90 defer func() { 91 if err != nil { 92 err = fmt.Errorf("cannot transpile ConditionalOperator : err = %v", err) 93 } 94 }() 95 96 // a - condition 97 a, aType, newPre, newPost, err := atomicOperation(n.Children()[0], p) 98 if err != nil { 99 return 100 } 101 preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost) 102 103 // null in C is zero 104 if aType == types.NullPointer { 105 a = &goast.BasicLit{ 106 Kind: token.INT, 107 Value: "0", 108 } 109 aType = "int" 110 } 111 112 a, err = types.CastExpr(p, a, aType, "bool") 113 if err != nil { 114 err = fmt.Errorf("parameter `a` : %v", err) 115 return 116 } 117 118 // b - body 119 b, bType, newPre, newPost, err := atomicOperation(n.Children()[1], p) 120 if err != nil { 121 err = fmt.Errorf("parameter `b` : %v", err) 122 return 123 } 124 // Theorephly, length is must be zero 125 if len(newPre) > 0 || len(newPost) > 0 { 126 p.AddMessage(p.GenerateWarningMessage( 127 fmt.Errorf("length of pre or post in body must be zero. {%d,%d}", len(newPre), len(newPost)), n)) 128 } 129 preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost) 130 131 if n.Type != "void" { 132 b, err = types.CastExpr(p, b, bType, n.Type) 133 if err != nil { 134 return 135 } 136 bType = n.Type 137 } 138 139 // c - else body 140 c, cType, newPre, newPost, err := atomicOperation(n.Children()[2], p) 141 if err != nil { 142 err = fmt.Errorf("parameter `c` : %v", err) 143 return nil, "", nil, nil, err 144 } 145 preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost) 146 147 if n.Type != "void" { 148 c, err = types.CastExpr(p, c, cType, n.Type) 149 if err != nil { 150 err = fmt.Errorf("parameter `c` : %v", err) 151 return 152 } 153 cType = n.Type 154 } 155 156 // rightType - generate return type 157 var returnType string 158 if n.Type != "void" { 159 returnType, err = types.ResolveType(p, n.Type) 160 if err != nil { 161 return 162 } 163 } 164 165 var bod, els goast.BlockStmt 166 167 bod.Lbrace = 1 168 if bType != types.ToVoid { 169 if n.Type != "void" { 170 bod.List = []goast.Stmt{ 171 &goast.ReturnStmt{ 172 Results: []goast.Expr{b}, 173 }, 174 } 175 } else { 176 bod.List = []goast.Stmt{ 177 &goast.ExprStmt{ 178 X: b, 179 }, 180 } 181 } 182 } 183 184 els.Lbrace = 1 185 if cType != types.ToVoid { 186 if n.Type != "void" { 187 els.List = []goast.Stmt{ 188 &goast.ReturnStmt{ 189 Results: []goast.Expr{c}, 190 }, 191 } 192 } else { 193 els.List = []goast.Stmt{ 194 &goast.ExprStmt{ 195 X: c, 196 }, 197 } 198 } 199 } 200 201 stmts := append([]goast.Stmt{}, &goast.IfStmt{ 202 Cond: a, 203 Body: &bod, 204 Else: &els, 205 }) 206 if len(bod.List) > 0 { 207 if _, ok := bod.List[len(bod.List)-1].(*goast.ReturnStmt); ok { 208 stmts = append([]goast.Stmt{}, &goast.IfStmt{ 209 Cond: a, 210 Body: &bod, 211 }) 212 stmts = append(stmts, els.List...) 213 } 214 } 215 216 return util.NewFuncClosure( 217 returnType, 218 stmts...), n.Type, preStmts, postStmts, nil 219 } 220 221 // transpileParenExpr transpiles an expression that is wrapped in parentheses. 222 // There is a special case where "(0)" is treated as a NULL (since that's what 223 // the macro expands to). We have to return the type as "null" since we don't 224 // know at this point what the NULL expression will be used in conjunction with. 225 func transpileParenExpr(n *ast.ParenExpr, p *program.Program) ( 226 r *goast.ParenExpr, exprType string, preStmts []goast.Stmt, postStmts []goast.Stmt, err error) { 227 defer func() { 228 if err != nil { 229 err = fmt.Errorf("cannot transpile ParenExpr. err = %v", err) 230 p.AddMessage(p.GenerateWarningMessage(err, n)) 231 } 232 }() 233 234 n.Type = util.GenerateCorrectType(n.Type) 235 n.Type2 = util.GenerateCorrectType(n.Type2) 236 237 expr, exprType, preStmts, postStmts, err := atomicOperation(n.Children()[0], p) 238 if err != nil { 239 return 240 } 241 if expr == nil { 242 err = fmt.Errorf("expr is nil") 243 return 244 } 245 246 if exprType == types.NullPointer { 247 r = &goast.ParenExpr{X: expr} 248 return 249 } 250 251 if !util.IsFunction(exprType) && 252 exprType != "void" && 253 exprType != "bool" && 254 exprType != types.ToVoid { 255 expr, err = types.CastExpr(p, expr, exprType, n.Type) 256 if err != nil { 257 return 258 } 259 exprType = n.Type 260 } 261 262 var ok bool 263 r, ok = expr.(*goast.ParenExpr) 264 if !ok { 265 r = &goast.ParenExpr{X: expr} 266 } 267 268 return 269 } 270 271 func transpileCompoundAssignOperator( 272 n *ast.CompoundAssignOperator, p *program.Program, exprIsStmt bool) ( 273 _ goast.Expr, _ string, preStmts []goast.Stmt, postStmts []goast.Stmt, err error) { 274 275 defer func() { 276 if err != nil { 277 err = fmt.Errorf("cannot transpileCompoundAssignOperator. err = %v", err) 278 } 279 }() 280 281 operator := n.Opcode[:len(n.Opcode)-1] 282 283 if len(n.ChildNodes) != 2 { 284 err = fmt.Errorf("not enought ChildNodes: %d", len(n.ChildNodes)) 285 return 286 } 287 288 if !types.IsCPointer(n.Type, p) && !types.IsCArray(n.Type, p) { 289 return transpileBinaryOperator(&ast.BinaryOperator{ 290 Type: n.Type, 291 Operator: n.Opcode, 292 ChildNodes: n.ChildNodes, 293 }, p, false) 294 } 295 296 return transpileBinaryOperator(&ast.BinaryOperator{ 297 Type: n.Type, 298 Operator: "=", 299 ChildNodes: []ast.Node{ 300 n.ChildNodes[0], 301 &ast.BinaryOperator{ 302 Type: n.Type, 303 Operator: operator, 304 ChildNodes: n.ChildNodes, 305 }, 306 }, 307 }, p, false) 308 } 309 310 func getTokenForOperatorNoError(operator string) token.Token { 311 t, err := getTokenForOperator(operator) 312 if err != nil { 313 return token.XOR 314 } 315 return t 316 } 317 318 // getTokenForOperator returns the Go operator token for the provided C 319 // operator. 320 func getTokenForOperator(operator string) (t token.Token, err error) { 321 switch operator { 322 // Arithmetic 323 case "--": 324 return token.DEC, nil 325 case "++": 326 return token.INC, nil 327 case "+": 328 return token.ADD, nil 329 case "-": 330 return token.SUB, nil 331 case "*": 332 return token.MUL, nil 333 case "/": 334 return token.QUO, nil 335 case "%": 336 return token.REM, nil 337 338 // Assignment 339 case "=": 340 return token.ASSIGN, nil 341 case "+=": 342 return token.ADD_ASSIGN, nil 343 case "-=": 344 return token.SUB_ASSIGN, nil 345 case "*=": 346 return token.MUL_ASSIGN, nil 347 case "/=": 348 return token.QUO_ASSIGN, nil 349 case "%=": 350 return token.REM_ASSIGN, nil 351 case "&=": 352 return token.AND_ASSIGN, nil 353 case "|=": 354 return token.OR_ASSIGN, nil 355 case "^=": 356 return token.XOR_ASSIGN, nil 357 case "<<=": 358 return token.SHL_ASSIGN, nil 359 case ">>=": 360 return token.SHR_ASSIGN, nil 361 362 // Bitwise 363 case "&": 364 return token.AND, nil 365 case "|": 366 return token.OR, nil 367 case "~": 368 return token.XOR, nil 369 case ">>": 370 return token.SHR, nil 371 case "<<": 372 return token.SHL, nil 373 case "^": 374 return token.XOR, nil 375 376 // Comparison 377 case ">=": 378 return token.GEQ, nil 379 case "<=": 380 return token.LEQ, nil 381 case "<": 382 return token.LSS, nil 383 case ">": 384 return token.GTR, nil 385 case "!=": 386 return token.NEQ, nil 387 case "==": 388 return token.EQL, nil 389 390 // Logical 391 case "!": 392 return token.NOT, nil 393 case "&&": 394 return token.LAND, nil 395 case "||": 396 return token.LOR, nil 397 398 // Other 399 case ",": 400 return token.COMMA, nil 401 } 402 403 err = fmt.Errorf("unknown operator: %s and replaced to XOR operator\n", operator) 404 return 405 } 406 407 func convertToWithoutAssign(operator token.Token) token.Token { 408 switch operator { 409 case token.ADD_ASSIGN: // "+=" 410 return token.ADD 411 case token.SUB_ASSIGN: // "-=" 412 return token.SUB 413 case token.MUL_ASSIGN: // "*=" 414 return token.MUL 415 case token.QUO_ASSIGN: // "/=" 416 return token.QUO 417 } 418 panic(fmt.Sprintf("not support operator: %v", operator)) 419 } 420 421 func findUnaryWithInteger(node ast.Node) (*ast.UnaryOperator, bool) { 422 switch n := node.(type) { 423 case *ast.UnaryOperator: 424 return n, true 425 case *ast.ParenExpr: 426 return findUnaryWithInteger(n.Children()[0]) 427 } 428 return nil, false 429 } 430 431 func atomicOperation(n ast.Node, p *program.Program) ( 432 expr goast.Expr, exprType string, preStmts, postStmts []goast.Stmt, err error) { 433 434 expr, exprType, preStmts, postStmts, err = transpileToExpr(n, p, false) 435 if err != nil { 436 return 437 } 438 439 defer func() { 440 if err != nil { 441 err = fmt.Errorf("cannot create atomicOperation |%T|. err = %v", n, err) 442 } 443 if exprType == "" { 444 p.AddMessage(p.GenerateWarningMessage(fmt.Errorf("exprType is empty"), n)) 445 } 446 }() 447 448 switch v := n.(type) { 449 case *ast.UnaryOperator: 450 switch v.Operator { 451 case "&", "*", "!", "-", "+", "~": 452 return 453 } 454 // UnaryOperator 0x252d798 <col:17, col:18> 'double' prefix '-' 455 // `-FloatingLiteral 0x252d778 <col:18> 'double' 0.000000e+00 456 if _, ok := v.Children()[0].(*ast.IntegerLiteral); ok { 457 return 458 } 459 if _, ok := v.Children()[0].(*ast.FloatingLiteral); ok { 460 return 461 } 462 463 // UnaryOperator 0x3001768 <col:204, col:206> 'int' prefix '++' 464 // `-DeclRefExpr 0x3001740 <col:206> 'int' lvalue Var 0x303e888 'current_test' 'int' 465 // OR 466 // UnaryOperator 0x3001768 <col:204, col:206> 'int' postfix '++' 467 // `-DeclRefExpr 0x3001740 <col:206> 'int' lvalue Var 0x303e888 'current_test' 'int' 468 var varName string 469 if vv, ok := v.Children()[0].(*ast.DeclRefExpr); ok { 470 varName = vv.Name 471 472 var exprResolveType string 473 exprResolveType, err = types.ResolveType(p, v.Type) 474 if err != nil { 475 return 476 } 477 478 // operators: ++, -- 479 if v.IsPrefix { 480 // Example: 481 // UnaryOperator 0x3001768 <col:204, col:206> 'int' prefix '++' 482 // `-DeclRefExpr 0x3001740 <col:206> 'int' lvalue Var 0x303e888 'current_test' 'int' 483 expr = util.NewAnonymousFunction( 484 append(preStmts, &goast.ExprStmt{X: expr}), 485 nil, 486 util.NewIdent(varName), 487 exprResolveType) 488 preStmts = nil 489 break 490 } 491 // Example: 492 // UnaryOperator 0x3001768 <col:204, col:206> 'int' postfix '++' 493 // `-DeclRefExpr 0x3001740 <col:206> 'int' lvalue Var 0x303e888 'current_test' 'int' 494 expr = util.NewAnonymousFunction(preStmts, 495 []goast.Stmt{&goast.ExprStmt{X: expr}}, 496 util.NewIdent(varName), 497 exprResolveType) 498 preStmts = nil 499 500 break 501 } 502 503 // UnaryOperator 'char *' postfix '++' 504 // `-ParenExpr 'char *' lvalue 505 // `-UnaryOperator 'char *' lvalue prefix '*' 506 // `-ImplicitCastExpr 'char **' <LValueToRValue> 507 // `-DeclRefExpr 'char **' lvalue Var 0x2699168 'bpp' 'char **' 508 // 509 // UnaryOperator 'int' postfix '++' 510 // `-MemberExpr 'int' lvalue .pos 0x358b538 511 // `-ArraySubscriptExpr 'struct struct_I_A':'struct struct_I_A' lvalue 512 // |-ImplicitCastExpr 'struct struct_I_A *' <ArrayToPointerDecay> 513 // | `-DeclRefExpr 'struct struct_I_A [2]' lvalue Var 0x358b6e8 'siia' 'struct struct_I_A [2]' 514 // `-IntegerLiteral 'int' 0 515 varName = "tempVar1" 516 517 nextNode := v.Children()[0] 518 for { 519 if par, ok := nextNode.(*ast.ParenExpr); ok { 520 nextNode = par.ChildNodes[0] 521 continue 522 } 523 break 524 } 525 expr, exprType, preStmts, postStmts, err = transpileToExpr(nextNode, p, false) 526 if err != nil { 527 return 528 } 529 530 var exprResolveType string 531 exprResolveType, err = types.ResolveType(p, v.Type) 532 if err != nil { 533 return 534 } 535 536 if v.Operator == "__extension__" { 537 // `-ImplicitCastExpr 0x27aea88 <> 'const char *' <ArrayToPointerDecay> 538 // `-UnaryOperator 0x27ae970 <> 'const char [18]' lvalue prefix '__extension__' cannot overfl 539 // 540 // `-PredefinedExpr 0x27ae958 <> 'const char [18]' lvalue __PRETTY_FUNCTION__ 541 // `-StringLiteral 0x27ae928 <> 'const char [18]' lvalue "void handler(int)" 542 preStmts = nil 543 postStmts = nil 544 return 545 } 546 547 if types.IsPointer(v.Type, p) { 548 switch e := expr.(type) { 549 case *goast.IndexExpr: 550 if v.Operator == "++" { 551 // expr = 'bpp[0]' 552 // example of snippet: 553 // func () []byte{ 554 // tempVar = bpp[0] 555 // defer func(){ 556 // bpp = bpp[1:] 557 // }() 558 // return tempVar 559 // } 560 expr = util.NewAnonymousFunction( 561 // body : 562 append(preStmts, &goast.AssignStmt{ 563 Lhs: []goast.Expr{util.NewIdent(varName)}, 564 Tok: token.DEFINE, 565 Rhs: []goast.Expr{expr}, 566 }), 567 // defer : 568 append([]goast.Stmt{ 569 &goast.AssignStmt{ 570 Lhs: []goast.Expr{ 571 e, 572 }, 573 Tok: token.ASSIGN, 574 Rhs: []goast.Expr{ 575 &goast.SliceExpr{ 576 X: e, 577 Low: goast.NewIdent("1"), 578 Slice3: false, 579 }, 580 }, 581 }, 582 }, postStmts...), 583 // return : 584 util.NewIdent(varName), 585 exprResolveType) 586 preStmts = nil 587 postStmts = nil 588 return 589 } 590 591 case *goast.Ident, *goast.SelectorExpr: 592 if v.Operator == "++" { 593 // expr = 'p' 594 // example of snippet: 595 // func () [][]byte{ 596 // tempVar = p 597 // defer func(){ 598 // p = p[1:] 599 // }() 600 // return tempVar 601 // } 602 expr = util.NewAnonymousFunction( 603 // body : 604 append(preStmts, &goast.AssignStmt{ 605 Lhs: []goast.Expr{util.NewIdent(varName)}, 606 Tok: token.DEFINE, 607 Rhs: []goast.Expr{expr}, 608 }), 609 // defer : 610 append([]goast.Stmt{ 611 &goast.AssignStmt{ 612 Lhs: []goast.Expr{ 613 e, 614 }, 615 Tok: token.ASSIGN, 616 Rhs: []goast.Expr{ 617 &goast.SliceExpr{ 618 X: e, 619 Low: goast.NewIdent("1"), 620 Slice3: false, 621 }, 622 }, 623 }, 624 }, postStmts...), 625 // return : 626 util.NewIdent(varName), 627 exprResolveType) 628 preStmts = nil 629 postStmts = nil 630 return 631 } 632 633 default: 634 // TODO add here 635 p.AddMessage(p.GenerateWarningMessage( 636 fmt.Errorf("transpilation pointer is not support: %T", e), v)) 637 } 638 } 639 640 body := append(preStmts, &goast.AssignStmt{ 641 Lhs: []goast.Expr{util.NewIdent(varName)}, 642 Tok: token.DEFINE, 643 Rhs: []goast.Expr{util.NewUnaryExpr( 644 expr, 645 token.AND, 646 )}, 647 }) 648 649 deferBody := postStmts 650 postStmts = nil 651 preStmts = nil 652 653 switch v.Operator { 654 case "++": 655 expr = &goast.BinaryExpr{ 656 X: &goast.StarExpr{X: util.NewIdent(varName)}, 657 Op: token.ADD_ASSIGN, 658 Y: &goast.BasicLit{Kind: token.INT, Value: "1"}, 659 } 660 case "--": 661 expr = &goast.BinaryExpr{ 662 X: &goast.StarExpr{X: util.NewIdent(varName)}, 663 Op: token.SUB_ASSIGN, 664 Y: &goast.BasicLit{Kind: token.INT, Value: "1"}, 665 } 666 } 667 668 body = append(body, preStmts...) 669 deferBody = append(deferBody, postStmts...) 670 671 // operators: ++, -- 672 if v.IsPrefix { 673 // Example: 674 // UnaryOperator 0x3001768 <col:204, col:206> 'int' prefix '++' 675 // `-DeclRefExpr 0x3001740 <col:206> 'int' lvalue Var 0x303e888 'current_test' 'int' 676 expr = util.NewAnonymousFunction( 677 append(body, &goast.ExprStmt{X: expr}), 678 deferBody, 679 &goast.StarExpr{ 680 X: util.NewIdent(varName), 681 }, 682 exprResolveType) 683 preStmts = nil 684 postStmts = nil 685 break 686 } 687 // Example: 688 // UnaryOperator 0x3001768 <col:204, col:206> 'int' postfix '++' 689 // `-DeclRefExpr 0x3001740 <col:206> 'int' lvalue Var 0x303e888 'current_test' 'int' 690 expr = util.NewAnonymousFunction(body, 691 append(deferBody, &goast.ExprStmt{X: expr}), 692 &goast.StarExpr{ 693 X: util.NewIdent(varName), 694 }, 695 exprResolveType) 696 preStmts = nil 697 postStmts = nil 698 699 case *ast.CompoundAssignOperator: 700 // CompoundAssignOperator 0x32911c0 <col:18, col:28> 'int' '-=' ComputeLHSTy='int' ComputeResultTy='int' 701 // |-DeclRefExpr 0x3291178 <col:18> 'int' lvalue Var 0x328df60 'iterator' 'int' 702 // `-IntegerLiteral 0x32911a0 <col:28> 'int' 2 703 if vv, ok := v.Children()[0].(*ast.DeclRefExpr); ok { 704 varName := vv.Name 705 706 var exprResolveType string 707 exprResolveType, err = types.ResolveType(p, v.Type) 708 if err != nil { 709 return 710 } 711 712 expr = util.NewAnonymousFunction( 713 append(preStmts, &goast.ExprStmt{X: expr}), 714 postStmts, 715 util.NewIdent(varName), 716 exprResolveType) 717 preStmts = nil 718 postStmts = nil 719 break 720 } 721 // CompoundAssignOperator 0x27906c8 <line:450:2, col:6> 'double' '+=' ComputeLHSTy='double' ComputeResultTy='double' 722 // |-UnaryOperator 0x2790670 <col:2, col:3> 'double' lvalue prefix '*' 723 // | `-ImplicitCastExpr 0x2790658 <col:3> 'double *' <LValueToRValue> 724 // | `-DeclRefExpr 0x2790630 <col:3> 'double *' lvalue Var 0x2790570 'p' 'double *' 725 // `-IntegerLiteral 0x32911a0 <col:28> 'int' 2 726 if vv, ok := v.Children()[0].(*ast.UnaryOperator); ok && vv.IsPrefix && vv.Operator == "*" { 727 if vvv, ok := vv.Children()[0].(*ast.ImplicitCastExpr); ok { 728 if vvvv, ok := vvv.Children()[0].(*ast.DeclRefExpr); ok { 729 if types.IsPointer(vvvv.Type, p) { 730 varName := vvvv.Name 731 732 var exprResolveType string 733 exprResolveType, err = types.ResolveType(p, v.Type) 734 if err != nil { 735 return 736 } 737 738 expr = util.NewAnonymousFunction( 739 append(preStmts, &goast.ExprStmt{X: expr}), 740 postStmts, 741 util.NewUnaryExpr( 742 util.NewIdent(varName), 743 token.AND, 744 ), 745 exprResolveType) 746 preStmts = nil 747 postStmts = nil 748 break 749 } 750 } 751 } 752 } 753 754 // CompoundAssignOperator 0x32911c0 <col:18, col:28> 'int' '-=' ComputeLHSTy='int' ComputeResultTy='int' 755 // |-DeclRefExpr 0x3291178 <col:18> 'int' lvalue Var 0x328df60 'iterator' 'int' 756 // `-IntegerLiteral 0x32911a0 <col:28> 'int' 2 757 varName := "tempVar2" 758 expr, exprType, preStmts, postStmts, err = transpileToExpr(v.Children()[0], p, false) 759 if err != nil { 760 return 761 } 762 body := append(preStmts, &goast.AssignStmt{ 763 Lhs: []goast.Expr{util.NewIdent(varName)}, 764 Tok: token.DEFINE, 765 Rhs: []goast.Expr{util.NewUnaryExpr(expr, token.AND)}, 766 }) 767 preStmts = nil 768 769 // CompoundAssignOperator 0x27906c8 <line:450:2, col:6> 'double' '+=' ComputeLHSTy='double' ComputeResultTy='double' 770 // |-UnaryOperator 0x2790670 <col:2, col:3> 'double' lvalue prefix '*' 771 // | `-ImplicitCastExpr 0x2790658 <col:3> 'double *' <LValueToRValue> 772 // | `-DeclRefExpr 0x2790630 <col:3> 'double *' lvalue Var 0x2790570 'p' 'double *' 773 // `-ImplicitCastExpr 0x27906b0 <col:6> 'double' <IntegralToFloating> 774 // `-IntegerLiteral 0x2790690 <col:6> 'int' 1 775 var newPre, newPost []goast.Stmt 776 expr, exprType, newPre, newPost, err = atomicOperation(v.Children()[1], p) 777 if err != nil { 778 return 779 } 780 preStmts, postStmts = combinePreAndPostStmts(preStmts, postStmts, newPre, newPost) 781 782 var exprResolveType string 783 exprResolveType, err = types.ResolveType(p, v.Type) 784 if err != nil { 785 return 786 } 787 788 body = append(preStmts, body...) 789 body = append(body, &goast.AssignStmt{ 790 Lhs: []goast.Expr{&goast.StarExpr{ 791 X: util.NewIdent(varName), 792 }}, 793 Tok: getTokenForOperatorNoError(v.Opcode), 794 Rhs: []goast.Expr{expr}, 795 }) 796 797 expr = util.NewAnonymousFunction(body, postStmts, 798 &goast.StarExpr{ 799 X: util.NewIdent(varName), 800 }, 801 exprResolveType) 802 preStmts = nil 803 postStmts = nil 804 805 case *ast.ParenExpr: 806 // ParenExpr 0x3c42468 <col:18, col:40> 'int' 807 if len(n.Children()) == 1 { 808 return atomicOperation(n.Children()[0], p) 809 } 810 return 811 812 case *ast.ImplicitCastExpr: 813 if _, ok := v.Children()[0].(*ast.MemberExpr); ok { 814 return 815 } 816 if _, ok := v.Children()[0].(*ast.IntegerLiteral); ok { 817 return 818 } 819 if v.Kind == "IntegralToPointer" { 820 return 821 } 822 if v.Kind == "BitCast" { 823 return 824 } 825 826 v.Type = util.GenerateCorrectType(v.Type) 827 v.Type2 = util.GenerateCorrectType(v.Type2) 828 829 // avoid problem : 830 // 831 // constant -1331 overflows uint32 832 // 833 // ImplicitCastExpr 'unsigned int' <IntegralCast> 834 // `-UnaryOperator 'int' prefix '~' 835 if t, ok := ast.GetTypeIfExist(v.Children()[0]); ok && !types.IsSigned(p, v.Type) && types.IsSigned(p, *t) { 836 if un, ok := n.Children()[0].(*ast.UnaryOperator); ok && un.Operator == "~" { 837 var goType string 838 goType, err = types.ResolveType(p, v.Type) 839 if err != nil { 840 return 841 } 842 expr = util.ConvertToUnsigned(expr, goType) 843 return 844 } 845 } 846 847 // for case : overflow char 848 // ImplicitCastExpr 0x2027358 <col:6, col:7> 'char' <IntegralCast> 849 // `-UnaryOperator 0x2027338 <col:6, col:7> 'int' prefix '-' 850 // `-IntegerLiteral 0x2027318 <col:7> 'int' 1 851 // 852 // another example : 853 // ImplicitCastExpr 0x2982630 <col:11, col:14> 'char' <IntegralCast> 854 // `-ParenExpr 0x2982610 <col:11, col:14> 'int' 855 // `-UnaryOperator 0x29825f0 <col:12, col:13> 'int' prefix '-' 856 // `-IntegerLiteral 0x29825d0 <col:13> 'int' 1 857 if v.Type == "char" { 858 if len(v.Children()) == 1 { 859 if u, ok := findUnaryWithInteger(n.Children()[0]); ok { 860 if u.IsPrefix && u.Type == "int" && u.Operator == "-" { 861 if _, ok := u.Children()[0].(*ast.IntegerLiteral); ok { 862 return transpileToExpr(&ast.BinaryOperator{ 863 Type: "int", 864 Type2: "int", 865 Operator: "+", 866 ChildNodes: []ast.Node{ 867 u, 868 &ast.IntegerLiteral{ 869 Type: "int", 870 Value: "256", 871 }, 872 }, 873 }, p, false) 874 } 875 } 876 } 877 } 878 } 879 880 var isSameBaseType bool 881 if impl, ok := v.Children()[0].(*ast.ImplicitCastExpr); ok { 882 if types.GetBaseType(v.Type) == types.GetBaseType(impl.Type) { 883 isSameBaseType = true 884 } 885 } 886 887 if v.Kind == "PointerToIntegral" { 888 if isSameBaseType { 889 expr = &goast.IndexExpr{ 890 X: expr, 891 Lbrack: 1, 892 Index: &goast.BasicLit{ 893 Kind: token.INT, 894 Value: "0", 895 }, 896 } 897 exprType = v.Type 898 return 899 } 900 expr = goast.NewIdent("0") 901 expr, _ = types.CastExpr(p, expr, "int", v.Type) 902 exprType = v.Type 903 return 904 } 905 906 expr, exprType, preStmts, postStmts, err = atomicOperation(v.Children()[0], p) 907 if err != nil { 908 return nil, "", nil, nil, err 909 } 910 if exprType == types.NullPointer { 911 return 912 } 913 914 var cast bool = true 915 if util.IsFunction(exprType) { 916 cast = false 917 } 918 if v.Kind == ast.ImplicitCastExprArrayToPointerDecay { 919 cast = false 920 } 921 922 if cast { 923 expr, err = types.CastExpr(p, expr, exprType, v.Type) 924 if err != nil { 925 return nil, "", nil, nil, err 926 } 927 exprType = v.Type 928 } 929 return 930 931 case *ast.BinaryOperator: 932 defer func() { 933 if err != nil { 934 err = fmt.Errorf("binary operator : `%v`. %v", v.Operator, err) 935 } 936 }() 937 switch v.Operator { 938 case ",": 939 // BinaryOperator 0x35b95e8 <col:29, col:51> 'int' ',' 940 // |-UnaryOperator 0x35b94b0 <col:29, col:31> 'int' postfix '++' 941 // | `-DeclRefExpr 0x35b9488 <col:29> 'int' lvalue Var 0x35b8dc8 't' 'int' 942 // `-CompoundAssignOperator 0x35b95b0 <col:36, col:51> 'int' '+=' ComputeLHSTy='int' ComputeResultTy='int' 943 // |-MemberExpr 0x35b9558 <col:36, col:44> 'int' lvalue .pos 0x35b8730 944 // | `-ArraySubscriptExpr 0x35b9530 <col:36, col:42> 'struct struct_I_A4':'struct struct_I_A4' lvalue 945 // | |-ImplicitCastExpr 0x35b9518 <col:36> 'struct struct_I_A4 *' <ArrayToPointerDecay> 946 // | | `-DeclRefExpr 0x35b94d0 <col:36> 'struct struct_I_A4 [2]' lvalue Var 0x35b88d8 'siia' 'struct struct_I_A4 [2]' 947 // | `-IntegerLiteral 0x35b94f8 <col:41> 'int' 0 948 // `-IntegerLiteral 0x35b9590 <col:51> 'int' 1 949 950 // `-BinaryOperator 0x3c42440 <col:19, col:32> 'int' ',' 951 // |-BinaryOperator 0x3c423d8 <col:19, col:30> 'int' '=' 952 // | |-DeclRefExpr 0x3c42390 <col:19> 'int' lvalue Var 0x3c3cf60 'iterator' 'int' 953 // | `-IntegerLiteral 0x3c423b8 <col:30> 'int' 0 954 // `-ImplicitCastExpr 0x3c42428 <col:32> 'int' <LValueToRValue> 955 // `-DeclRefExpr 0x3c42400 <col:32> 'int' lvalue Var 0x3c3cf60 'iterator' 'int' 956 varName := "tempVar3" 957 958 expr, exprType, preStmts, postStmts, err = transpileToExpr(v.Children()[0], p, false) 959 if err != nil { 960 return 961 } 962 963 inBody := combineStmts(preStmts, &goast.ExprStmt{X: expr}, postStmts) 964 965 expr, exprType, preStmts, postStmts, err = atomicOperation(v.Children()[1], p) 966 if err != nil { 967 return 968 } 969 970 if v, ok := expr.(*goast.CallExpr); ok { 971 if vv, ok := v.Fun.(*goast.FuncLit); ok { 972 vv.Body.List = append(inBody, vv.Body.List...) 973 break 974 } 975 } 976 977 body := append(inBody, preStmts...) 978 preStmts = nil 979 980 body = append(body, &goast.AssignStmt{ 981 Lhs: []goast.Expr{util.NewIdent(varName)}, 982 Tok: token.DEFINE, 983 Rhs: []goast.Expr{util.NewUnaryExpr(expr, token.AND)}, 984 }) 985 986 var exprResolveType string 987 exprResolveType, err = types.ResolveType(p, v.Type) 988 if err != nil { 989 err = fmt.Errorf("exprResolveType error for type `%v`: %v", v.Type, err) 990 return 991 } 992 993 expr = util.NewAnonymousFunction(body, postStmts, 994 util.NewUnaryExpr(util.NewIdent(varName), token.MUL), 995 exprResolveType) 996 preStmts = nil 997 postStmts = nil 998 exprType = v.Type 999 return 1000 1001 case "=": 1002 // Find ast.DeclRefExpr in Children[0] 1003 // Or 1004 // Find ast.ArraySubscriptExpr in Children[0] 1005 decl, ok := getDeclRefExprOrArraySub(v.Children()[0]) 1006 if !ok { 1007 return 1008 } 1009 // BinaryOperator 0x2a230c0 <col:8, col:13> 'int' '=' 1010 // |-UnaryOperator 0x2a23080 <col:8, col:9> 'int' lvalue prefix '*' 1011 // | `-ImplicitCastExpr 0x2a23068 <col:9> 'int *' <LValueToRValue> 1012 // | `-DeclRefExpr 0x2a23040 <col:9> 'int *' lvalue Var 0x2a22f20 'a' 'int *' 1013 // `-IntegerLiteral 0x2a230a0 <col:13> 'int' 42 1014 1015 // VarDecl 0x328dc50 <col:3, col:29> col:13 used d 'int' cinit 1016 // `-BinaryOperator 0x328dd98 <col:17, col:29> 'int' '=' 1017 // |-DeclRefExpr 0x328dcb0 <col:17> 'int' lvalue Var 0x328dae8 'a' 'int' 1018 // `-BinaryOperator 0x328dd70 <col:21, col:29> 'int' '=' 1019 // |-DeclRefExpr 0x328dcd8 <col:21> 'int' lvalue Var 0x328db60 'b' 'int' 1020 // `-BinaryOperator 0x328dd48 <col:25, col:29> 'int' '=' 1021 // |-DeclRefExpr 0x328dd00 <col:25> 'int' lvalue Var 0x328dbd8 'c' 'int' 1022 // `-IntegerLiteral 0x328dd28 <col:29> 'int' 42 1023 1024 // BinaryOperator 0x364a878 <line:139:7, col:23> 'int' '==' 1025 // |-ParenExpr 0x364a838 <col:7, col:18> 'int' 1026 // | `-BinaryOperator 0x364a810 <col:8, col:17> 'int' '=' 1027 // | |-ArraySubscriptExpr 0x364a740 <col:8, col:11> 'int' lvalue 1028 // | | |-ImplicitCastExpr 0x364a728 <col:8> 'int *' <ArrayToPointerDecay> 1029 // | | | `-DeclRefExpr 0x364a6e0 <col:8> 'int [5]' lvalue Var 0x3648ea0 'l' 'int [5]' 1030 // | | `-IntegerLiteral 0x364a708 <col:10> 'int' 0 1031 // | `-BinaryOperator 0x364a7e8 <col:15, col:17> 'int' '-' 1032 // | |-ImplicitCastExpr 0x364a7b8 <col:15> 'int' <LValueToRValue> 1033 // | | `-DeclRefExpr 0x364a768 <col:15> 'int' lvalue Var 0x3647c00 'y' 'int' 1034 // | `-ImplicitCastExpr 0x364a7d0 <col:17> 'int' <LValueToRValue> 1035 // | `-DeclRefExpr 0x364a790 <col:17> 'int' lvalue Var 0x364a648 's' 'int' 1036 // `-IntegerLiteral 0x364a858 <col:23> 'int' 3 1037 1038 var exprResolveType string 1039 exprResolveType, err = types.ResolveType(p, v.Type) 1040 if err != nil { 1041 return 1042 } 1043 1044 e, _, newPre, newPost, _ := transpileToExpr(v, p, false) 1045 body := combineStmts(newPre, &goast.ExprStmt{X: e}, newPost) 1046 1047 preStmts = nil 1048 postStmts = nil 1049 1050 var returnValue goast.Expr 1051 if bin, ok := e.(*goast.BinaryExpr); ok { 1052 returnValue = bin.X 1053 } else { 1054 returnValue, _, _, _, _ = transpileToExpr(decl, p, false) 1055 if d, ok := decl.(*ast.DeclRefExpr); ok && 1056 types.IsPointer(d.Type, p) && !types.IsPointer(v.Type, p) { 1057 returnValue = &goast.IndexExpr{ 1058 X: returnValue, 1059 Index: &goast.BasicLit{ 1060 Kind: token.INT, 1061 Value: "0", 1062 }, 1063 } 1064 } 1065 } 1066 1067 expr = util.NewAnonymousFunction(body, 1068 nil, 1069 returnValue, 1070 exprResolveType) 1071 expr = &goast.ParenExpr{ 1072 X: expr, 1073 Lparen: 1, 1074 } 1075 } 1076 1077 } 1078 1079 return 1080 } 1081 1082 // getDeclRefExprOrArraySub - find ast DeclRefExpr 1083 // Examples of input ast trees: 1084 // UnaryOperator 0x2a23080 <col:8, col:9> 'int' lvalue prefix '*' 1085 // `-ImplicitCastExpr 0x2a23068 <col:9> 'int *' <LValueToRValue> 1086 // 1087 // `-DeclRefExpr 0x2a23040 <col:9> 'int *' lvalue Var 0x2a22f20 'a' 'int *' 1088 // 1089 // DeclRefExpr 0x328dd00 <col:25> 'int' lvalue Var 0x328dbd8 'c' 'int' 1090 func getDeclRefExprOrArraySub(n ast.Node) (ast.Node, bool) { 1091 switch v := n.(type) { 1092 case *ast.DeclRefExpr: 1093 return v, true 1094 case *ast.ParenExpr: 1095 return getDeclRefExprOrArraySub(n.Children()[0]) 1096 case *ast.ImplicitCastExpr: 1097 return getDeclRefExprOrArraySub(n.Children()[0]) 1098 case *ast.UnaryOperator: 1099 return getDeclRefExprOrArraySub(n.Children()[0]) 1100 case *ast.ArraySubscriptExpr: 1101 return v, true 1102 case *ast.BinaryOperator: 1103 for i := range v.Children() { 1104 if v, ok := getDeclRefExprOrArraySub(v.Children()[i]); ok { 1105 return v, true 1106 } 1107 } 1108 case *ast.MemberExpr: 1109 return v, true 1110 } 1111 return nil, false 1112 }