github.com/gotranspile/cxgo@v0.3.7/go_types.go (about) 1 package cxgo 2 3 import ( 4 "go/ast" 5 "go/token" 6 "strconv" 7 "strings" 8 ) 9 10 type GoExpr = ast.Expr 11 type GoStmt = ast.Stmt 12 type GoDecl = ast.Decl 13 type GoType = ast.Expr 14 15 type GoField = ast.Field 16 17 func ident(name string) *ast.Ident { 18 return &ast.Ident{Name: name} 19 } 20 21 func boolLit(v bool) GoExpr { 22 if v { 23 return ident("true") 24 } 25 return ident("false") 26 } 27 28 func intLit(v int) GoExpr { 29 return &ast.BasicLit{ 30 Kind: token.INT, 31 Value: strconv.Itoa(v), 32 } 33 } 34 35 func intLit64(v int64) GoExpr { 36 return &ast.BasicLit{ 37 Kind: token.INT, 38 Value: strconv.FormatInt(v, 10), 39 } 40 } 41 42 func uintLit64(v uint64) GoExpr { 43 s10 := strconv.FormatUint(v, 10) 44 s := s10 45 if len(s) > 4 { 46 s16 := strconv.FormatUint(v, 16) 47 if len(strings.Trim(s10, "0")) > len(strings.Trim(s16, "0")) { 48 s = "0x" + strings.ToUpper(s16) 49 } 50 } 51 return &ast.BasicLit{ 52 Kind: token.INT, 53 Value: s, 54 } 55 } 56 57 func noFields() *ast.FieldList { 58 return &ast.FieldList{} 59 } 60 61 func fields(arr []*GoField) *ast.FieldList { 62 return &ast.FieldList{List: arr} 63 } 64 65 func fieldTypes(arr ...GoType) *ast.FieldList { 66 var out []*GoField 67 for _, t := range arr { 68 out = append(out, &ast.Field{Type: t}) 69 } 70 return fields(out) 71 } 72 73 func funcTypeRet(ret GoType) *ast.FuncType { 74 var fret *ast.FieldList 75 if ret != nil { 76 fret = fieldTypes(ret) 77 } 78 return &ast.FuncType{ 79 Params: noFields(), 80 Results: fret, 81 } 82 } 83 84 func fixLabels(stmts []GoStmt) []GoStmt { 85 for i := 0; i < len(stmts); i++ { 86 l, ok := stmts[i].(*ast.LabeledStmt) 87 if !ok { 88 continue 89 } 90 switch l.Stmt.(type) { 91 case nil, *ast.EmptyStmt: 92 if i == len(stmts)-1 { 93 l.Stmt = &ast.EmptyStmt{Implicit: true} 94 } else { 95 l.Stmt = stmts[i+1] 96 switch l.Stmt.(type) { 97 case *ast.CaseClause: 98 l.Stmt = &ast.EmptyStmt{Implicit: true} 99 continue 100 } 101 stmts = append(stmts[:i+1], stmts[i+2:]...) 102 } 103 } 104 } 105 return stmts 106 } 107 108 func mergeDecls(stmts []GoStmt) []GoStmt { 109 if len(stmts) < 2 { 110 return stmts 111 } 112 d1, ok := stmts[0].(*ast.DeclStmt) 113 if !ok { 114 return stmts 115 } 116 g1, ok := d1.Decl.(*ast.GenDecl) 117 if !ok { 118 return stmts 119 } 120 j := 0 121 for i := 0; i < len(stmts); i++ { 122 if i == 0 { 123 continue 124 } 125 d2, ok := stmts[i].(*ast.DeclStmt) 126 if !ok { 127 break 128 } 129 g2, ok := d2.Decl.(*ast.GenDecl) 130 if !ok || g2.Tok != g1.Tok { 131 break 132 } 133 g1.Specs = append(g1.Specs, g2.Specs...) 134 g2.Specs = nil 135 j = i 136 } 137 if j == 0 { 138 return stmts 139 } 140 return append([]GoStmt{d1}, stmts[j+1:]...) 141 } 142 143 func block(stmts ...GoStmt) *ast.BlockStmt { 144 if len(stmts) == 1 { 145 if b, ok := stmts[0].(*ast.BlockStmt); ok { 146 return b 147 } 148 } 149 stmts = fixLabels(stmts) 150 stmts = mergeDecls(stmts) 151 return &ast.BlockStmt{List: stmts} 152 } 153 154 func ifelse(cond GoExpr, then, els []GoStmt) *ast.IfStmt { 155 s := &ast.IfStmt{ 156 Cond: cond, 157 Body: block(then...), 158 } 159 if len(els) != 0 { 160 if len(els) == 1 { 161 if s2, ok := els[0].(*ast.IfStmt); ok { 162 s.Else = s2 163 } else { 164 s.Else = block(els...) 165 } 166 } else { 167 s.Else = block(els...) 168 } 169 } 170 return s 171 } 172 173 func returnStmt(expr ...GoExpr) *ast.ReturnStmt { 174 return &ast.ReturnStmt{Results: expr} 175 } 176 177 func call(fnc GoExpr, args ...GoExpr) *ast.CallExpr { 178 for i, a := range args { 179 if p, ok := a.(*ast.ParenExpr); ok { 180 args[i] = p.X 181 } 182 } 183 return &ast.CallExpr{ 184 Fun: fnc, 185 Args: args, 186 } 187 } 188 189 func callVari(fnc GoExpr, args ...GoExpr) *ast.CallExpr { 190 e := call(fnc, args...) 191 e.Ellipsis = 1 192 return e 193 } 194 195 func callLambda(ret GoType, stmts ...GoStmt) *ast.CallExpr { 196 return call(&ast.FuncLit{ 197 Type: funcTypeRet(ret), 198 Body: block(stmts...), 199 }) 200 } 201 202 func assignTok(x GoExpr, tok token.Token, y GoExpr) *ast.AssignStmt { 203 return &ast.AssignStmt{ 204 Tok: tok, 205 Lhs: []GoExpr{x}, 206 Rhs: []GoExpr{y}, 207 } 208 } 209 210 func assign(x, y GoExpr) *ast.AssignStmt { 211 return assignTok(x, token.ASSIGN, y) 212 } 213 214 func define(x, y GoExpr) *ast.AssignStmt { 215 return assignTok(x, token.DEFINE, y) 216 } 217 218 func addr(x GoExpr) GoExpr { 219 if e1, ok := x.(*ast.StarExpr); ok { 220 return e1.X 221 } 222 return &ast.UnaryExpr{ 223 Op: token.AND, 224 X: x, 225 } 226 } 227 228 func deref(x GoExpr) *ast.StarExpr { 229 return &ast.StarExpr{ 230 X: x, 231 } 232 } 233 234 func index(x, ind GoExpr) *ast.IndexExpr { 235 return &ast.IndexExpr{ 236 X: x, Index: ind, 237 } 238 } 239 240 func exprStmt(x GoExpr) GoStmt { 241 return &ast.ExprStmt{ 242 X: x, 243 } 244 } 245 246 func paren(x GoExpr) *ast.ParenExpr { 247 if p, ok := x.(*ast.ParenExpr); ok { 248 return p 249 } 250 return &ast.ParenExpr{ 251 X: x, 252 } 253 } 254 255 func unsafePtr() GoType { 256 return ident("unsafe.Pointer") 257 } 258 259 func typAssert(x GoExpr, t GoType) GoExpr { 260 return &ast.TypeAssertExpr{ 261 X: x, 262 Type: t, 263 } 264 }