1a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar"""Flexible enumeration of C types."""
2a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
3a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbarfrom Enumeration import *
4a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
5a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar# TODO:
6a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
798cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar#  - struct improvements (flexible arrays, packed &
8a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar#    unpacked, alignment)
9880c40345f903b087b52eb559cbd435f2ccac484Daniel Dunbar#  - objective-c qualified id
10880c40345f903b087b52eb559cbd435f2ccac484Daniel Dunbar#  - anonymous / transparent unions
11880c40345f903b087b52eb559cbd435f2ccac484Daniel Dunbar#  - VLAs
12880c40345f903b087b52eb559cbd435f2ccac484Daniel Dunbar#  - block types
13dda09c8704f47a17ca34e0aa7f3a0d3f8bc6f399Daniel Dunbar#  - K&R functions
14dda09c8704f47a17ca34e0aa7f3a0d3f8bc6f399Daniel Dunbar#  - pass arguments of different types (test extension, transparent union)
15dda09c8704f47a17ca34e0aa7f3a0d3f8bc6f399Daniel Dunbar#  - varargs
16a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
17a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar###
18a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar# Actual type types
19a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
2098cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbarclass Type:
2198cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar    def isBitField(self):
2298cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar        return False
2398cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar
2498cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar    def isPaddingBitField(self):
2598cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar        return False
2698cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar
276ffef197e9388a54f983bfd86931119e0885ce51Daniel Dunbar    def getTypeName(self, printer):
286ffef197e9388a54f983bfd86931119e0885ce51Daniel Dunbar        name = 'T%d' % len(printer.types)
296ffef197e9388a54f983bfd86931119e0885ce51Daniel Dunbar        typedef = self.getTypedefDef(name, printer)
306ffef197e9388a54f983bfd86931119e0885ce51Daniel Dunbar        printer.addDeclaration(typedef)
316ffef197e9388a54f983bfd86931119e0885ce51Daniel Dunbar        return name
326ffef197e9388a54f983bfd86931119e0885ce51Daniel Dunbar
3398cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbarclass BuiltinType(Type):
3498cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar    def __init__(self, name, size, bitFieldSize=None):
35a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.name = name
36789e4babc9cf78df9565f215a119acad291aea63Daniel Dunbar        self.size = size
3798cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar        self.bitFieldSize = bitFieldSize
3898cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar
3998cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar    def isBitField(self):
4098cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar        return self.bitFieldSize is not None
4198cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar
4298cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar    def isPaddingBitField(self):
4398cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar        return self.bitFieldSize is 0
4498cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar
4598cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar    def getBitFieldSize(self):
4698cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar        assert self.isBitField()
4798cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar        return self.bitFieldSize
48789e4babc9cf78df9565f215a119acad291aea63Daniel Dunbar
496ffef197e9388a54f983bfd86931119e0885ce51Daniel Dunbar    def getTypeName(self, printer):
506ffef197e9388a54f983bfd86931119e0885ce51Daniel Dunbar        return self.name
516ffef197e9388a54f983bfd86931119e0885ce51Daniel Dunbar
52789e4babc9cf78df9565f215a119acad291aea63Daniel Dunbar    def sizeof(self):
53789e4babc9cf78df9565f215a119acad291aea63Daniel Dunbar        return self.size
54a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
55a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __str__(self):
56a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        return self.name
57a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
5843ec96da71b94f064ed6a3031025208d23acd592Douglas Gregorclass EnumType(Type):
5943ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    def __init__(self, index, enumerators):
6043ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        self.index = index
6143ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        self.enumerators = enumerators
6243ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor
6343ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    def getEnumerators(self):
6443ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        result = ''
6543ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        for i, init in enumerate(self.enumerators):
6643ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor            if i > 0:
6743ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor                result = result + ', '
6843ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor            result = result + 'enum%dval%d' % (self.index, i)
6943ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor            if init:
7043ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor                result = result + ' = %s' % (init)
7143ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor
7243ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        return result
7343ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor
7443ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    def __str__(self):
7543ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        return 'enum { %s }' % (self.getEnumerators())
7643ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor
7743ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    def getTypedefDef(self, name, printer):
7843ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        return 'typedef enum %s { %s } %s;'%(name, self.getEnumerators(), name)
7943ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor
8098cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbarclass RecordType(Type):
81a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __init__(self, index, isUnion, fields):
82a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.index = index
83a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.isUnion = isUnion
84a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.fields = fields
85a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.name = None
86a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
8798cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar    def __str__(self):
8898cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar        def getField(t):
8998cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar            if t.isBitField():
9098cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar                return "%s : %d;" % (t, t.getBitFieldSize())
9198cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar            else:
9298cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar                return "%s;" % t
9398cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar
94a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        return '%s { %s }'%(('struct','union')[self.isUnion],
9598cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar                            ' '.join(map(getField, self.fields)))
96a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
97a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def getTypedefDef(self, name, printer):
9898cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar        def getField((i, t)):
9998cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar            if t.isBitField():
10098cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar                if t.isPaddingBitField():
10198cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar                    return '%s : 0;'%(printer.getTypeName(t),)
10298cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar                else:
10398cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar                    return '%s field%d : %d;'%(printer.getTypeName(t),i,
10498cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar                                               t.getBitFieldSize())
10598cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar            else:
10698cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar                return '%s field%d;'%(printer.getTypeName(t),i)
10798cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar        fields = map(getField, enumerate(self.fields))
108a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        # Name the struct for more readable LLVM IR.
109a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        return 'typedef %s %s { %s } %s;'%(('struct','union')[self.isUnion],
110a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar                                           name, ' '.join(fields), name)
111a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
11298cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbarclass ArrayType(Type):
113a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __init__(self, index, isVector, elementType, size):
114a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        if isVector:
115a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            # Note that for vectors, this is the size in bytes.
116a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            assert size > 0
117a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        else:
118a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            assert size is None or size >= 0
119a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.index = index
120a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.isVector = isVector
121a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.elementType = elementType
122a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.size = size
123789e4babc9cf78df9565f215a119acad291aea63Daniel Dunbar        if isVector:
124789e4babc9cf78df9565f215a119acad291aea63Daniel Dunbar            eltSize = self.elementType.sizeof()
125789e4babc9cf78df9565f215a119acad291aea63Daniel Dunbar            assert not (self.size % eltSize)
126789e4babc9cf78df9565f215a119acad291aea63Daniel Dunbar            self.numElements = self.size // eltSize
127789e4babc9cf78df9565f215a119acad291aea63Daniel Dunbar        else:
128789e4babc9cf78df9565f215a119acad291aea63Daniel Dunbar            self.numElements = self.size
129a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
130a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __str__(self):
131a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        if self.isVector:
132a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            return 'vector (%s)[%d]'%(self.elementType,self.size)
133a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        elif self.size is not None:
134a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            return '(%s)[%d]'%(self.elementType,self.size)
135a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        else:
136a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            return '(%s)[]'%(self.elementType,)
137a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
138a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def getTypedefDef(self, name, printer):
139a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        elementName = printer.getTypeName(self.elementType)
140a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        if self.isVector:
141a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            return 'typedef %s %s __attribute__ ((vector_size (%d)));'%(elementName,
142a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar                                                                        name,
143a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar                                                                        self.size)
144a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        else:
145a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            if self.size is None:
146a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar                sizeStr = ''
147a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            else:
148a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar                sizeStr = str(self.size)
149a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            return 'typedef %s %s[%s];'%(elementName, name, sizeStr)
150a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
15198cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbarclass ComplexType(Type):
152a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __init__(self, index, elementType):
153a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.index = index
154a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.elementType = elementType
155a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
156a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __str__(self):
157a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        return '_Complex (%s)'%(self.elementType)
158a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
159a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def getTypedefDef(self, name, printer):
160a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        return 'typedef _Complex %s %s;'%(printer.getTypeName(self.elementType), name)
161a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
16298cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbarclass FunctionType(Type):
163a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __init__(self, index, returnType, argTypes):
164a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.index = index
165a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.returnType = returnType
166a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.argTypes = argTypes
167a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
168a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __str__(self):
169a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        if self.returnType is None:
170a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            rt = 'void'
171a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        else:
172a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            rt = str(self.returnType)
173a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        if not self.argTypes:
174a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            at = 'void'
175a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        else:
176a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            at = ', '.join(map(str, self.argTypes))
177a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        return '%s (*)(%s)'%(rt, at)
178a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
179a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def getTypedefDef(self, name, printer):
180a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        if self.returnType is None:
181a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            rt = 'void'
182a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        else:
183a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            rt = str(self.returnType)
184a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        if not self.argTypes:
185a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            at = 'void'
186a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        else:
187a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            at = ', '.join(map(str, self.argTypes))
188a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        return 'typedef %s (*%s)(%s);'%(rt, name, at)
189a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
190a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar###
191a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar# Type enumerators
192a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
193a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbarclass TypeGenerator(object):
194a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __init__(self):
195a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.cache = {}
196a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
197a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def setCardinality(self):
198a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        abstract
199a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
200a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def get(self, N):
201a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        T = self.cache.get(N)
202a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        if T is None:
203a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            assert 0 <= N < self.cardinality
204a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            T = self.cache[N] = self.generateType(N)
205a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        return T
206a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
207a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def generateType(self, N):
208a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        abstract
209a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
210a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbarclass FixedTypeGenerator(TypeGenerator):
211a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __init__(self, types):
212a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        TypeGenerator.__init__(self)
213a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.types = types
214a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.setCardinality()
215a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
216a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def setCardinality(self):
217a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.cardinality = len(self.types)
218a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
219a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def generateType(self, N):
220a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        return self.types[N]
221a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
22243ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor# Factorial
22343ec96da71b94f064ed6a3031025208d23acd592Douglas Gregordef fact(n):
22443ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    result = 1
22543ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    while n > 0:
22643ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        result = result * n
22743ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        n = n - 1
22843ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    return result
22943ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor
23043ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor# Compute the number of combinations (n choose k)
23143ec96da71b94f064ed6a3031025208d23acd592Douglas Gregordef num_combinations(n, k):
23243ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    return fact(n) / (fact(k) * fact(n - k))
23343ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor
23443ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor# Enumerate the combinations choosing k elements from the list of values
23543ec96da71b94f064ed6a3031025208d23acd592Douglas Gregordef combinations(values, k):
23643ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    # From ActiveState Recipe 190465: Generator for permutations,
23743ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    # combinations, selections of a sequence
23843ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    if k==0: yield []
23943ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    else:
24043ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        for i in xrange(len(values)-k+1):
24143ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor            for cc in combinations(values[i+1:],k-1):
24243ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor                yield [values[i]]+cc
24343ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor
24443ec96da71b94f064ed6a3031025208d23acd592Douglas Gregorclass EnumTypeGenerator(TypeGenerator):
24543ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    def __init__(self, values, minEnumerators, maxEnumerators):
24643ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        TypeGenerator.__init__(self)
24743ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        self.values = values
24843ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        self.minEnumerators = minEnumerators
24943ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        self.maxEnumerators = maxEnumerators
25043ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        self.setCardinality()
25143ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor
25243ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    def setCardinality(self):
25343ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        self.cardinality = 0
25443ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        for num in range(self.minEnumerators, self.maxEnumerators + 1):
25543ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor            self.cardinality += num_combinations(len(self.values), num)
25643ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor
25743ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    def generateType(self, n):
25843ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        # Figure out the number of enumerators in this type
25943ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        numEnumerators = self.minEnumerators
26043ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        valuesCovered = 0
26143ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        while numEnumerators < self.maxEnumerators:
26243ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor            comb = num_combinations(len(self.values), numEnumerators)
26343ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor            if valuesCovered + comb > n:
26443ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor                break
26543ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor            numEnumerators = numEnumerators + 1
26643ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor            valuesCovered += comb
26743ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor
26843ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        # Find the requested combination of enumerators and build a
26943ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        # type from it.
27043ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        i = 0
27143ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        for enumerators in combinations(self.values, numEnumerators):
27243ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor            if i == n - valuesCovered:
27343ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor                return EnumType(n, enumerators)
27443ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor
27543ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor            i = i + 1
27643ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor
27743ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor        assert False
27843ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor
279a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbarclass ComplexTypeGenerator(TypeGenerator):
280a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __init__(self, typeGen):
281a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        TypeGenerator.__init__(self)
282a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.typeGen = typeGen
283a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.setCardinality()
284a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
285a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def setCardinality(self):
286a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.cardinality = self.typeGen.cardinality
287a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
288a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def generateType(self, N):
289a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        return ComplexType(N, self.typeGen.get(N))
290a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
291a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbarclass VectorTypeGenerator(TypeGenerator):
292a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __init__(self, typeGen, sizes):
293a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        TypeGenerator.__init__(self)
294a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.typeGen = typeGen
295a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.sizes = tuple(map(int,sizes))
296a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.setCardinality()
297a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
298a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def setCardinality(self):
299a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.cardinality = len(self.sizes)*self.typeGen.cardinality
300a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
301a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def generateType(self, N):
302a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        S,T = getNthPairBounded(N, len(self.sizes), self.typeGen.cardinality)
303a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        return ArrayType(N, True, self.typeGen.get(T), self.sizes[S])
304a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
305a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbarclass FixedArrayTypeGenerator(TypeGenerator):
306a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __init__(self, typeGen, sizes):
307a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        TypeGenerator.__init__(self)
308a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.typeGen = typeGen
309a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.sizes = tuple(size)
310a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.setCardinality()
311a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
312a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def setCardinality(self):
313a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.cardinality = len(self.sizes)*self.typeGen.cardinality
314a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
315a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def generateType(self, N):
316a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        S,T = getNthPairBounded(N, len(self.sizes), self.typeGen.cardinality)
317a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        return ArrayType(N, false, self.typeGen.get(T), self.sizes[S])
318a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
319a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbarclass ArrayTypeGenerator(TypeGenerator):
320a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __init__(self, typeGen, maxSize, useIncomplete=False, useZero=False):
321a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        TypeGenerator.__init__(self)
322a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.typeGen = typeGen
323a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.useIncomplete = useIncomplete
324a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.useZero = useZero
325a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.maxSize = int(maxSize)
326a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.W = useIncomplete + useZero + self.maxSize
327a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.setCardinality()
328a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
329a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def setCardinality(self):
330a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.cardinality = self.W * self.typeGen.cardinality
331a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
332a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def generateType(self, N):
333a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        S,T = getNthPairBounded(N, self.W, self.typeGen.cardinality)
334a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        if self.useIncomplete:
335a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            if S==0:
336a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar                size = None
337a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar                S = None
338a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            else:
339a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar                S = S - 1
340a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        if S is not None:
341a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            if self.useZero:
342a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar                size = S
343a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            else:
344a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar                size = S + 1
345a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        return ArrayType(N, False, self.typeGen.get(T), size)
346a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
347a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbarclass RecordTypeGenerator(TypeGenerator):
348a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __init__(self, typeGen, useUnion, maxSize):
349a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        TypeGenerator.__init__(self)
350a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.typeGen = typeGen
351a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.useUnion = bool(useUnion)
352a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.maxSize = int(maxSize)
353a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.setCardinality()
354a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
355a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def setCardinality(self):
356a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        M = 1 + self.useUnion
357a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        if self.maxSize is aleph0:
358a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            S =  aleph0 * self.typeGen.cardinality
359a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        else:
360a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            S = 0
361a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            for i in range(self.maxSize+1):
362a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar                S += M * (self.typeGen.cardinality ** i)
363a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.cardinality = S
364a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
365a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def generateType(self, N):
366a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        isUnion,I = False,N
367a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        if self.useUnion:
368a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            isUnion,I = (I&1),I>>1
369a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        fields = map(self.typeGen.get,getNthTuple(I,self.maxSize,self.typeGen.cardinality))
370a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        return RecordType(N, isUnion, fields)
371a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
372a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbarclass FunctionTypeGenerator(TypeGenerator):
373a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __init__(self, typeGen, useReturn, maxSize):
374a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        TypeGenerator.__init__(self)
375a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.typeGen = typeGen
376a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.useReturn = useReturn
377a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.maxSize = maxSize
378a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.setCardinality()
379a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
380a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def setCardinality(self):
381a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        if self.maxSize is aleph0:
382a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            S = aleph0 * self.typeGen.cardinality()
383a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        elif self.useReturn:
384a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            S = 0
385a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            for i in range(1,self.maxSize+1+1):
386a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar                S += self.typeGen.cardinality ** i
387a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        else:
388a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            S = 0
389a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            for i in range(self.maxSize+1):
390a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar                S += self.typeGen.cardinality ** i
391a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.cardinality = S
392a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
393a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def generateType(self, N):
394a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        if self.useReturn:
395a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            # Skip the empty tuple
396a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            argIndices = getNthTuple(N+1, self.maxSize+1, self.typeGen.cardinality)
397a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            retIndex,argIndices = argIndices[0],argIndices[1:]
398a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            retTy = self.typeGen.get(retIndex)
399a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        else:
400a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            retTy = None
401a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            argIndices = getNthTuple(N, self.maxSize, self.typeGen.cardinality)
402a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        args = map(self.typeGen.get, argIndices)
403a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        return FunctionType(N, retTy, args)
404a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
405a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbarclass AnyTypeGenerator(TypeGenerator):
406a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def __init__(self):
407a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        TypeGenerator.__init__(self)
408a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.generators = []
409a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.bounds = []
410a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.setCardinality()
411a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self._cardinality = None
412a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
413a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def getCardinality(self):
414a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        if self._cardinality is None:
415a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            return aleph0
416a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        else:
417a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            return self._cardinality
418a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def setCardinality(self):
419a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.bounds = [g.cardinality for g in self.generators]
420a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self._cardinality = sum(self.bounds)
421a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    cardinality = property(getCardinality, None)
422a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
423a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def addGenerator(self, g):
424a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        self.generators.append(g)
425a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        for i in range(100):
426a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            prev = self._cardinality
427a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            self._cardinality = None
428a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            for g in self.generators:
429a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar                g.setCardinality()
430a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            self.setCardinality()
431a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            if (self._cardinality is aleph0) or prev==self._cardinality:
432a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar                break
433a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        else:
434a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar            raise RuntimeError,"Infinite loop in setting cardinality"
435a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
436a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    def generateType(self, N):
437a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        index,M = getNthPairVariableBounds(N, self.bounds)
438a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        return self.generators[index].get(M)
439a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
440a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbardef test():
44198cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar    fbtg = FixedTypeGenerator([BuiltinType('char', 4),
44298cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar                               BuiltinType('char', 4, 0),
44398cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar                               BuiltinType('int',  4, 5)])
44498cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar
44598cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar    fields1 = AnyTypeGenerator()
44698cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar    fields1.addGenerator( fbtg )
44798cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar
44898cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar    fields0 = AnyTypeGenerator()
44998cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar    fields0.addGenerator( fbtg )
45098cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar#    fields0.addGenerator( RecordTypeGenerator(fields1, False, 4) )
45198cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar
45298cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar    btg = FixedTypeGenerator([BuiltinType('char', 4),
45398cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar                              BuiltinType('int',  4)])
45443ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    etg = EnumTypeGenerator([None, '-1', '1', '1u'], 0, 3)
45543ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor
456a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    atg = AnyTypeGenerator()
457a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    atg.addGenerator( btg )
45898cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar    atg.addGenerator( RecordTypeGenerator(fields0, False, 4) )
45943ec96da71b94f064ed6a3031025208d23acd592Douglas Gregor    atg.addGenerator( etg )
460a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    print 'Cardinality:',atg.cardinality
461a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    for i in range(100):
46298cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar        if i == atg.cardinality:
46398cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar            try:
46498cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar                atg.get(i)
46598cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar                raise RuntimeError,"Cardinality was wrong"
46698cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar            except AssertionError:
46798cca78ecd75704998eea81031bb82f06a9ed5deDaniel Dunbar                break
468a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar        print '%4d: %s'%(i, atg.get(i))
469a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar
470a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbarif __name__ == '__main__':
471a1bfe638c03c517b110f55962adb882f47131667Daniel Dunbar    test()
472