1 """Flexible enumeration of C types."""
2 from __future__
import division
, print_function
4 from Enumeration
import *
8 # - struct improvements (flexible arrays, packed &
10 # - objective-c qualified id
11 # - anonymous / transparent unions
15 # - pass arguments of different types (test extension, transparent union)
26 def isPaddingBitField(self
):
29 def getTypeName(self
, printer
):
30 name
= "T%d" % len(printer
.types
)
31 typedef
= self
.getTypedefDef(name
, printer
)
32 printer
.addDeclaration(typedef
)
36 class BuiltinType(Type
):
37 def __init__(self
, name
, size
, bitFieldSize
=None):
40 self
.bitFieldSize
= bitFieldSize
43 return self
.bitFieldSize
is not None
45 def isPaddingBitField(self
):
46 return self
.bitFieldSize
is 0
48 def getBitFieldSize(self
):
49 assert self
.isBitField()
50 return self
.bitFieldSize
52 def getTypeName(self
, printer
):
65 def __init__(self
, index
, enumerators
):
67 self
.enumerators
= enumerators
68 self
.unique_id
= self
.__class
__.unique_id
69 self
.__class
__.unique_id
+= 1
71 def getEnumerators(self
):
73 for i
, init
in enumerate(self
.enumerators
):
75 result
= result
+ ", "
76 result
= result
+ "enum%dval%d_%d" % (self
.index
, i
, self
.unique_id
)
78 result
= result
+ " = %s" % (init
)
83 return "enum { %s }" % (self
.getEnumerators())
85 def getTypedefDef(self
, name
, printer
):
86 return "typedef enum %s { %s } %s;" % (name
, self
.getEnumerators(), name
)
89 class RecordType(Type
):
90 def __init__(self
, index
, isUnion
, fields
):
92 self
.isUnion
= isUnion
99 return "%s : %d;" % (t
, t
.getBitFieldSize())
103 return "%s { %s }" % (
104 ("struct", "union")[self
.isUnion
],
105 " ".join(map(getField
, self
.fields
)),
108 def getTypedefDef(self
, name
, printer
):
112 if t
.isPaddingBitField():
113 return "%s : 0;" % (printer
.getTypeName(t
),)
115 return "%s field%d : %d;" % (
116 printer
.getTypeName(t
),
121 return "%s field%d;" % (printer
.getTypeName(t
), i
)
123 fields
= [getField(f
) for f
in enumerate(self
.fields
)]
124 # Name the struct for more readable LLVM IR.
125 return "typedef %s %s { %s } %s;" % (
126 ("struct", "union")[self
.isUnion
],
133 class ArrayType(Type
):
134 def __init__(self
, index
, isVector
, elementType
, size
):
136 # Note that for vectors, this is the size in bytes.
139 assert size
is None or size
>= 0
141 self
.isVector
= isVector
142 self
.elementType
= elementType
145 eltSize
= self
.elementType
.sizeof()
146 assert not (self
.size
% eltSize
)
147 self
.numElements
= self
.size
// eltSize
149 self
.numElements
= self
.size
153 return "vector (%s)[%d]" % (self
.elementType
, self
.size
)
154 elif self
.size
is not None:
155 return "(%s)[%d]" % (self
.elementType
, self
.size
)
157 return "(%s)[]" % (self
.elementType
,)
159 def getTypedefDef(self
, name
, printer
):
160 elementName
= printer
.getTypeName(self
.elementType
)
162 return "typedef %s %s __attribute__ ((vector_size (%d)));" % (
168 if self
.size
is None:
171 sizeStr
= str(self
.size
)
172 return "typedef %s %s[%s];" % (elementName
, name
, sizeStr
)
175 class ComplexType(Type
):
176 def __init__(self
, index
, elementType
):
178 self
.elementType
= elementType
181 return "_Complex (%s)" % (self
.elementType
)
183 def getTypedefDef(self
, name
, printer
):
184 return "typedef _Complex %s %s;" % (printer
.getTypeName(self
.elementType
), name
)
187 class FunctionType(Type
):
188 def __init__(self
, index
, returnType
, argTypes
):
190 self
.returnType
= returnType
191 self
.argTypes
= argTypes
194 if self
.returnType
is None:
197 rt
= str(self
.returnType
)
198 if not self
.argTypes
:
201 at
= ", ".join(map(str, self
.argTypes
))
202 return "%s (*)(%s)" % (rt
, at
)
204 def getTypedefDef(self
, name
, printer
):
205 if self
.returnType
is None:
208 rt
= str(self
.returnType
)
209 if not self
.argTypes
:
212 at
= ", ".join(map(str, self
.argTypes
))
213 return "typedef %s (*%s)(%s);" % (rt
, name
, at
)
220 class TypeGenerator(object):
224 def setCardinality(self
):
228 T
= self
.cache
.get(N
)
230 assert 0 <= N
< self
.cardinality
231 T
= self
.cache
[N
] = self
.generateType(N
)
234 def generateType(self
, N
):
238 class FixedTypeGenerator(TypeGenerator
):
239 def __init__(self
, types
):
240 TypeGenerator
.__init
__(self
)
242 self
.setCardinality()
244 def setCardinality(self
):
245 self
.cardinality
= len(self
.types
)
247 def generateType(self
, N
):
260 # Compute the number of combinations (n choose k)
261 def num_combinations(n
, k
):
262 return fact(n
) // (fact(k
) * fact(n
- k
))
265 # Enumerate the combinations choosing k elements from the list of values
266 def combinations(values
, k
):
267 # From ActiveState Recipe 190465: Generator for permutations,
268 # combinations, selections of a sequence
272 for i
in range(len(values
) - k
+ 1):
273 for cc
in combinations(values
[i
+ 1 :], k
- 1):
274 yield [values
[i
]] + cc
277 class EnumTypeGenerator(TypeGenerator
):
278 def __init__(self
, values
, minEnumerators
, maxEnumerators
):
279 TypeGenerator
.__init
__(self
)
281 self
.minEnumerators
= minEnumerators
282 self
.maxEnumerators
= maxEnumerators
283 self
.setCardinality()
285 def setCardinality(self
):
287 for num
in range(self
.minEnumerators
, self
.maxEnumerators
+ 1):
288 self
.cardinality
+= num_combinations(len(self
.values
), num
)
290 def generateType(self
, n
):
291 # Figure out the number of enumerators in this type
292 numEnumerators
= self
.minEnumerators
294 while numEnumerators
< self
.maxEnumerators
:
295 comb
= num_combinations(len(self
.values
), numEnumerators
)
296 if valuesCovered
+ comb
> n
:
298 numEnumerators
= numEnumerators
+ 1
299 valuesCovered
+= comb
301 # Find the requested combination of enumerators and build a
304 for enumerators
in combinations(self
.values
, numEnumerators
):
305 if i
== n
- valuesCovered
:
306 return EnumType(n
, enumerators
)
313 class ComplexTypeGenerator(TypeGenerator
):
314 def __init__(self
, typeGen
):
315 TypeGenerator
.__init
__(self
)
316 self
.typeGen
= typeGen
317 self
.setCardinality()
319 def setCardinality(self
):
320 self
.cardinality
= self
.typeGen
.cardinality
322 def generateType(self
, N
):
323 return ComplexType(N
, self
.typeGen
.get(N
))
326 class VectorTypeGenerator(TypeGenerator
):
327 def __init__(self
, typeGen
, sizes
):
328 TypeGenerator
.__init
__(self
)
329 self
.typeGen
= typeGen
330 self
.sizes
= tuple(map(int, sizes
))
331 self
.setCardinality()
333 def setCardinality(self
):
334 self
.cardinality
= len(self
.sizes
) * self
.typeGen
.cardinality
336 def generateType(self
, N
):
337 S
, T
= getNthPairBounded(N
, len(self
.sizes
), self
.typeGen
.cardinality
)
338 return ArrayType(N
, True, self
.typeGen
.get(T
), self
.sizes
[S
])
341 class FixedArrayTypeGenerator(TypeGenerator
):
342 def __init__(self
, typeGen
, sizes
):
343 TypeGenerator
.__init
__(self
)
344 self
.typeGen
= typeGen
345 self
.sizes
= tuple(size
)
346 self
.setCardinality()
348 def setCardinality(self
):
349 self
.cardinality
= len(self
.sizes
) * self
.typeGen
.cardinality
351 def generateType(self
, N
):
352 S
, T
= getNthPairBounded(N
, len(self
.sizes
), self
.typeGen
.cardinality
)
353 return ArrayType(N
, false
, self
.typeGen
.get(T
), self
.sizes
[S
])
356 class ArrayTypeGenerator(TypeGenerator
):
357 def __init__(self
, typeGen
, maxSize
, useIncomplete
=False, useZero
=False):
358 TypeGenerator
.__init
__(self
)
359 self
.typeGen
= typeGen
360 self
.useIncomplete
= useIncomplete
361 self
.useZero
= useZero
362 self
.maxSize
= int(maxSize
)
363 self
.W
= useIncomplete
+ useZero
+ self
.maxSize
364 self
.setCardinality()
366 def setCardinality(self
):
367 self
.cardinality
= self
.W
* self
.typeGen
.cardinality
369 def generateType(self
, N
):
370 S
, T
= getNthPairBounded(N
, self
.W
, self
.typeGen
.cardinality
)
371 if self
.useIncomplete
:
382 return ArrayType(N
, False, self
.typeGen
.get(T
), size
)
385 class RecordTypeGenerator(TypeGenerator
):
386 def __init__(self
, typeGen
, useUnion
, maxSize
):
387 TypeGenerator
.__init
__(self
)
388 self
.typeGen
= typeGen
389 self
.useUnion
= bool(useUnion
)
390 self
.maxSize
= int(maxSize
)
391 self
.setCardinality()
393 def setCardinality(self
):
394 M
= 1 + self
.useUnion
395 if self
.maxSize
is aleph0
:
396 S
= aleph0
* self
.typeGen
.cardinality
399 for i
in range(self
.maxSize
+ 1):
400 S
+= M
* (self
.typeGen
.cardinality
**i
)
403 def generateType(self
, N
):
404 isUnion
, I
= False, N
406 isUnion
, I
= (I
& 1), I
>> 1
409 for f
in getNthTuple(I
, self
.maxSize
, self
.typeGen
.cardinality
)
411 return RecordType(N
, isUnion
, fields
)
414 class FunctionTypeGenerator(TypeGenerator
):
415 def __init__(self
, typeGen
, useReturn
, maxSize
):
416 TypeGenerator
.__init
__(self
)
417 self
.typeGen
= typeGen
418 self
.useReturn
= useReturn
419 self
.maxSize
= maxSize
420 self
.setCardinality()
422 def setCardinality(self
):
423 if self
.maxSize
is aleph0
:
424 S
= aleph0
* self
.typeGen
.cardinality()
427 for i
in range(1, self
.maxSize
+ 1 + 1):
428 S
+= self
.typeGen
.cardinality
**i
431 for i
in range(self
.maxSize
+ 1):
432 S
+= self
.typeGen
.cardinality
**i
435 def generateType(self
, N
):
437 # Skip the empty tuple
438 argIndices
= getNthTuple(N
+ 1, self
.maxSize
+ 1, self
.typeGen
.cardinality
)
439 retIndex
, argIndices
= argIndices
[0], argIndices
[1:]
440 retTy
= self
.typeGen
.get(retIndex
)
443 argIndices
= getNthTuple(N
, self
.maxSize
, self
.typeGen
.cardinality
)
444 args
= [self
.typeGen
.get(i
) for i
in argIndices
]
445 return FunctionType(N
, retTy
, args
)
448 class AnyTypeGenerator(TypeGenerator
):
450 TypeGenerator
.__init
__(self
)
453 self
.setCardinality()
454 self
._cardinality
= None
456 def getCardinality(self
):
457 if self
._cardinality
is None:
460 return self
._cardinality
462 def setCardinality(self
):
463 self
.bounds
= [g
.cardinality
for g
in self
.generators
]
464 self
._cardinality
= sum(self
.bounds
)
466 cardinality
= property(getCardinality
, None)
468 def addGenerator(self
, g
):
469 self
.generators
.append(g
)
471 prev
= self
._cardinality
472 self
._cardinality
= None
473 for g
in self
.generators
:
475 self
.setCardinality()
476 if (self
._cardinality
is aleph0
) or prev
== self
._cardinality
:
479 raise RuntimeError("Infinite loop in setting cardinality")
481 def generateType(self
, N
):
482 index
, M
= getNthPairVariableBounds(N
, self
.bounds
)
483 return self
.generators
[index
].get(M
)
487 fbtg
= FixedTypeGenerator(
488 [BuiltinType("char", 4), BuiltinType("char", 4, 0), BuiltinType("int", 4, 5)]
491 fields1
= AnyTypeGenerator()
492 fields1
.addGenerator(fbtg
)
494 fields0
= AnyTypeGenerator()
495 fields0
.addGenerator(fbtg
)
496 # fields0.addGenerator( RecordTypeGenerator(fields1, False, 4) )
498 btg
= FixedTypeGenerator([BuiltinType("char", 4), BuiltinType("int", 4)])
499 etg
= EnumTypeGenerator([None, "-1", "1", "1u"], 0, 3)
501 atg
= AnyTypeGenerator()
502 atg
.addGenerator(btg
)
503 atg
.addGenerator(RecordTypeGenerator(fields0
, False, 4))
504 atg
.addGenerator(etg
)
505 print("Cardinality:", atg
.cardinality
)
507 if i
== atg
.cardinality
:
510 raise RuntimeError("Cardinality was wrong")
511 except AssertionError:
513 print("%4d: %s" % (i
, atg
.get(i
)))
516 if __name__
== "__main__":