github.com/gotranspile/cxgo@v0.3.7/types/types.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "fmt" 6 "sync" 7 ) 8 9 type Node interface { 10 Uses() []Usage 11 } 12 13 type Type interface { 14 Sizeof() int 15 Kind() Kind 16 GoType() GoType 17 } 18 19 func UnkT(size int) Type { 20 if size <= 0 { 21 panic("size must be specified; set to ptr size, for example") 22 } 23 return &unkType{size: size} 24 } 25 26 type unkType struct { 27 isStruct bool 28 size int 29 } 30 31 func (t *unkType) Kind() Kind { 32 return Unknown 33 } 34 35 func (t *unkType) Sizeof() int { 36 return t.size 37 } 38 39 var ( 40 uint8Type = IntType{size: 1, signed: false} 41 uint16Type = IntType{size: 2, signed: false} 42 uint32Type = IntType{size: 4, signed: false} 43 uint64Type = IntType{size: 8, signed: false} 44 int8Type = IntType{size: 1, signed: true} 45 int16Type = IntType{size: 2, signed: true} 46 int32Type = IntType{size: 4, signed: true} 47 int64Type = IntType{size: 8, signed: true} 48 ) 49 50 func UntypedIntT(minSize int) IntType { 51 if minSize <= 0 { 52 panic("size must be specified") 53 } 54 return IntType{size: minSize, untyped: true} 55 } 56 57 func AsUntypedIntT(t IntType) IntType { 58 t.untyped = true 59 return t 60 } 61 62 func AsTypedIntT(t IntType) IntType { 63 t.untyped = false 64 return t 65 } 66 67 func ToPtrType(exp Type) PtrType { 68 if t, ok := Unwrap(exp).(PtrType); ok { 69 return t 70 } 71 return nil 72 } 73 74 func IntT(size int) IntType { 75 if size <= 0 { 76 panic("size must be specified") 77 } 78 switch size { 79 case 1: 80 return int8Type 81 case 2: 82 return int16Type 83 case 4: 84 return int32Type 85 case 8: 86 return int64Type 87 } 88 return IntType{size: size, signed: true} 89 } 90 91 func UintT(size int) IntType { 92 if size <= 0 { 93 panic("size must be specified") 94 } 95 switch size { 96 case 1: 97 return uint8Type 98 case 2: 99 return uint16Type 100 case 4: 101 return uint32Type 102 case 8: 103 return uint64Type 104 } 105 return IntType{size: size, signed: false} 106 } 107 108 var ( 109 float32Type = FloatType{size: 4} 110 float64Type = FloatType{size: 8} 111 ) 112 113 func FloatT(size int) Type { 114 switch size { 115 case 4: 116 return float32Type 117 case 8: 118 return float64Type 119 } 120 return FloatType{size: size} 121 } 122 123 func NilT(size int) PtrType { 124 return &ptrType{size: size} 125 } 126 127 type PtrType interface { 128 Type 129 Elem() Type 130 SetElem(e Type) 131 ElemKind() Kind 132 ElemSizeof() int 133 } 134 135 func PtrT(size int, elem Type) PtrType { 136 if size <= 0 { 137 panic("size must be set") 138 } else if size < 4 { 139 panic("unlikely") 140 } 141 return &ptrType{elem: elem, size: size} 142 } 143 144 var _ PtrType = &ptrType{} 145 146 type ptrType struct { 147 size int 148 zero bool 149 elem Type 150 } 151 152 func (t *ptrType) Sizeof() int { 153 return t.size 154 } 155 156 func (t *ptrType) Kind() Kind { 157 if t.zero { 158 return Nil 159 } else if t.elem == nil { 160 return UnsafePtr 161 } 162 return Ptr 163 } 164 165 func (t *ptrType) Elem() Type { 166 return t.elem 167 } 168 169 func (t *ptrType) SetElem(e Type) { 170 t.elem = e 171 } 172 173 func (t *ptrType) ElemKind() Kind { 174 e := t.elem 175 for e != nil { 176 p, ok := e.(*ptrType) 177 if !ok { 178 break 179 } 180 e = p.elem 181 } 182 if e == nil { 183 return UnsafePtr 184 } 185 return e.Kind() 186 } 187 188 func (t *ptrType) ElemSizeof() int { 189 if t.elem == nil { 190 return 1 191 } 192 return t.elem.Sizeof() 193 } 194 195 var ( 196 _ PtrType = namedPtr{} 197 _ Named = namedPtr{} 198 ) 199 200 type namedPtr struct { 201 name *Ident 202 *ptrType 203 } 204 205 func (t namedPtr) Name() *Ident { 206 return t.name 207 } 208 209 func (t namedPtr) Underlying() Type { 210 return t.ptrType 211 } 212 213 func (t namedPtr) SetUnderlying(typ Type) Named { 214 panic("trying to change the named type") 215 } 216 217 func (t namedPtr) Incomplete() bool { 218 return false 219 } 220 221 type Field struct { 222 Name *Ident 223 } 224 225 func (f *Field) Type() Type { 226 return f.Name.CType(nil) 227 } 228 229 func FuncT(ptrSize int, ret Type, args ...*Field) *FuncType { 230 return funcT(ptrSize, ret, args, false) 231 } 232 233 func FuncTT(ptrSize int, ret Type, args ...Type) *FuncType { 234 fields := make([]*Field, 0, len(args)) 235 for _, t := range args { 236 fields = append(fields, &Field{Name: NewUnnamed(t)}) 237 } 238 return FuncT(ptrSize, ret, fields...) 239 } 240 241 func VarFuncT(ptrSize int, ret Type, args ...*Field) *FuncType { 242 return funcT(ptrSize, ret, args, true) 243 } 244 245 func VarFuncTT(ptrSize int, ret Type, args ...Type) *FuncType { 246 fields := make([]*Field, 0, len(args)) 247 for _, t := range args { 248 fields = append(fields, &Field{Name: NewUnnamed(t)}) 249 } 250 return VarFuncT(ptrSize, ret, fields...) 251 } 252 253 func checkFields(fields []*Field) { 254 for _, f := range fields { 255 if f.Name == nil { 256 panic("nil argument name") 257 } 258 } 259 } 260 261 func funcT(ptrSize int, ret Type, args []*Field, vari bool) *FuncType { 262 if ptrSize <= 0 { 263 panic("size must be set") 264 } else if ptrSize < 4 { 265 panic("unlikely") 266 } 267 checkFields(args) 268 return &FuncType{ 269 size: ptrSize, 270 args: append([]*Field{}, args...), 271 ret: ret, 272 vari: vari, 273 } 274 } 275 276 type FuncType struct { 277 ptr bool 278 size int 279 280 args []*Field 281 ret Type 282 vari bool 283 } 284 285 func (t *FuncType) Kind() Kind { 286 return Func 287 } 288 289 func (t *FuncType) Sizeof() int { 290 return t.size 291 } 292 293 func (t *FuncType) Return() Type { 294 return t.ret 295 } 296 297 func (t *FuncType) Variadic() bool { 298 return t.vari 299 } 300 301 func (t *FuncType) ArgN() int { 302 return len(t.args) 303 } 304 305 func (t *FuncType) Args() []*Field { 306 return append([]*Field{}, t.args...) 307 } 308 309 type IntType struct { 310 size int 311 signed bool 312 untyped bool 313 } 314 315 func (t IntType) Kind() Kind { 316 s := Unsigned 317 if t.signed { 318 s = Signed 319 } 320 if t.untyped { 321 return UntypedInt | s 322 } 323 return Int | s 324 } 325 326 func (t IntType) Sizeof() int { 327 return t.size 328 } 329 330 func (t IntType) Signed() bool { 331 return t.signed 332 } 333 334 type FloatType struct { 335 size int 336 } 337 338 func (t FloatType) Kind() Kind { 339 return Float 340 } 341 342 func (t FloatType) Sizeof() int { 343 return t.size 344 } 345 346 func BoolT() Type { 347 return BoolType{} 348 } 349 350 type BoolType struct{} 351 352 func (t BoolType) Kind() Kind { 353 return Bool 354 } 355 356 func (t BoolType) Sizeof() int { 357 return 1 358 } 359 360 func ArrayT(elem Type, size int) Type { 361 if size < 0 { 362 panic("negative size") 363 } 364 return ArrayType{ 365 elem: elem, 366 size: size, 367 slice: false, 368 } 369 } 370 371 func SliceT(elem Type) Type { 372 return ArrayType{ 373 elem: elem, 374 size: 0, 375 slice: true, 376 } 377 } 378 379 type ArrayType struct { 380 elem Type 381 size int 382 slice bool 383 } 384 385 func (t ArrayType) Kind() Kind { 386 return Array 387 } 388 389 func (t ArrayType) Elem() Type { 390 return t.elem 391 } 392 393 func (t ArrayType) Len() int { 394 if t.slice { 395 return 0 396 } 397 return t.size 398 } 399 400 func (t ArrayType) IsSlice() bool { 401 return t.slice 402 } 403 404 func (t ArrayType) Sizeof() int { 405 sz := t.size 406 if sz == 0 { 407 sz = 1 408 } 409 return sz * t.elem.Sizeof() 410 } 411 412 func NamedT(name string, typ Type) Named { 413 return NamedTGo(name, "", typ) 414 } 415 416 func NamedTGo(cname, goname string, typ Type) Named { 417 if cname == "" { 418 panic("name is not set") 419 } 420 if typ == nil { 421 panic("type is not set") 422 } 423 switch typ := typ.(type) { 424 case *ptrType: 425 named := &namedPtr{ptrType: typ} 426 named.name = NewIdentGo(cname, goname, named) 427 return named 428 } 429 named := &namedType{typ: typ} 430 named.name = NewIdentGo(cname, goname, named) 431 return named 432 } 433 434 type Named interface { 435 Type 436 Name() *Ident 437 Underlying() Type 438 } 439 440 type namedType struct { 441 name *Ident 442 typ Type 443 } 444 445 func (t *namedType) String() string { 446 return t.name.String() 447 } 448 449 func (t *namedType) Kind() Kind { 450 return t.typ.Kind() 451 } 452 453 func (t *namedType) Name() *Ident { 454 return t.name 455 } 456 457 func (t *namedType) Underlying() Type { 458 return t.typ 459 } 460 461 func (t *namedType) Sizeof() int { 462 return t.typ.Sizeof() 463 } 464 465 var ( 466 structMu sync.RWMutex 467 structTypes = make(map[string]*StructType) 468 unionTypes = make(map[string]*StructType) 469 ) 470 471 func StructT(fields []*Field) *StructType { 472 checkFields(fields) 473 s := &StructType{ 474 fields: append([]*Field{}, fields...), 475 union: false, 476 } 477 h := s.hash() 478 479 structMu.RLock() 480 t, ok := structTypes[h] 481 structMu.RUnlock() 482 if ok { 483 return t 484 } 485 486 structMu.Lock() 487 defer structMu.Unlock() 488 if t, ok := structTypes[h]; ok { 489 return t 490 } 491 structTypes[h] = s 492 return s 493 } 494 495 func UnionT(fields []*Field) *StructType { 496 checkFields(fields) 497 s := &StructType{ 498 fields: append([]*Field{}, fields...), 499 union: true, 500 } 501 h := s.hash() 502 503 structMu.RLock() 504 t, ok := unionTypes[h] 505 structMu.RUnlock() 506 if ok { 507 return t 508 } 509 510 structMu.Lock() 511 defer structMu.Unlock() 512 if t, ok := unionTypes[h]; ok { 513 return t 514 } 515 unionTypes[h] = s 516 return s 517 } 518 519 type StructType struct { 520 Where string 521 fields []*Field 522 union bool 523 } 524 525 func (t *StructType) hash() string { 526 buf := bytes.NewBuffer(nil) 527 for _, f := range t.fields { 528 buf.WriteString(f.Name.Name) 529 buf.WriteByte(0) 530 fmt.Fprintf(buf, "%p", f.Type()) 531 buf.WriteByte(0) 532 } 533 return buf.String() 534 } 535 536 func (t *StructType) Fields() []*Field { 537 return append([]*Field{}, t.fields...) 538 } 539 540 func (t *StructType) Kind() Kind { 541 return Struct 542 } 543 544 func (t *StructType) Sizeof() int { 545 if t.union { 546 max := 0 547 for _, f := range t.fields { 548 if sz := f.Type().Sizeof(); sz > max { 549 max = sz 550 } 551 } 552 return max 553 } 554 n := 0 555 for _, f := range t.fields { 556 n += f.Type().Sizeof() 557 } 558 if n == 0 { 559 n = 1 560 } 561 return n 562 }