data_types.py 17.9 KB
Newer Older
1
import ctypes
2
import sympy as sp
3
import numpy as np
4
5
6
7
8
try:
    import llvmlite.ir as ir
except ImportError as e:
    ir = None
    _ir_importerror = e
9
from sympy.core.cache import cacheit
10

11
from pystencils.cache import memorycache
12
13
from pystencils.utils import allEqual

14
15
16
17
18
19
20
21
22

# to work in conditions of sp.Piecewise castFunc has to be of type Relational as well
class castFunc(sp.Function, sp.Rel):
    @property
    def canonical(self):
        if hasattr(self.args[0], 'canonical'):
            return self.args[0].canonical
        else:
            raise NotImplementedError()
23

24
25
26
27
    @property
    def is_commutative(self):
        return self.args[0].is_commutative

28

29
30
31
32
33
34
35
36
37
38
class pointerArithmeticFunc(sp.Function, sp.Rel):

    @property
    def canonical(self):
        if hasattr(self.args[0], 'canonical'):
            return self.args[0].canonical
        else:
            raise NotImplementedError()


39
class TypedSymbol(sp.Symbol):
Martin Bauer's avatar
Martin Bauer committed
40
41
    def __new__(cls, *args, **kwds):
        obj = TypedSymbol.__xnew_cached_(cls, *args, **kwds)
42
43
        return obj

44
    def __new_stage2__(cls, name, dtype):
45
        obj = super(TypedSymbol, cls).__xnew__(cls, name)
46
        try:
Martin Bauer's avatar
Martin Bauer committed
47
            obj._dtype = create_type(dtype)
48
49
50
        except TypeError:
            # on error keep the string
            obj._dtype = dtype
51
52
53
54
55
56
57
58
59
60
        return obj

    __xnew__ = staticmethod(__new_stage2__)
    __xnew_cached_ = staticmethod(cacheit(__new_stage2__))

    @property
    def dtype(self):
        return self._dtype

    def _hashable_content(self):
Martin Bauer's avatar
Martin Bauer committed
61
62
        super_class_contents = list(super(TypedSymbol, self)._hashable_content())
        return tuple(super_class_contents + [hash(self._dtype)])
63
64

    def __getnewargs__(self):
65
66
67
        return self.name, self.dtype


Martin Bauer's avatar
Martin Bauer committed
68
def create_type(specification):
Jan Hoenig's avatar
Jan Hoenig committed
69
70
71
72
73
    """
    Create a subclass of Type according to a string or an object of subclass Type
    :param specification: Type object, or a string
    :return: Type object, or a new Type object parsed from the string
    """
74
75
76
    if isinstance(specification, Type):
        return specification
    else:
Martin Bauer's avatar
Martin Bauer committed
77
78
79
        numpy_dtype = np.dtype(specification)
        if numpy_dtype.fields is None:
            return BasicType(numpy_dtype, const=False)
80
        else:
Martin Bauer's avatar
Martin Bauer committed
81
            return StructType(numpy_dtype, const=False)
82
83


84
@memorycache(maxsize=64)
Martin Bauer's avatar
Martin Bauer committed
85
def create_composite_type_from_string(specification):
Jan Hoenig's avatar
Jan Hoenig committed
86
87
88
89
90
    """
    Creates a new Type object from a c-like string specification
    :param specification: Specification string
    :return: Type object
    """
91
92
93
94
95
96
97
    specification = specification.lower().split()
    parts = []
    current = []
    for s in specification:
        if s == '*':
            parts.append(current)
            current = [s]
98
        else:
99
100
101
            current.append(s)
    if len(current) > 0:
        parts.append(current)
Jan Hoenig's avatar
Jan Hoenig committed
102
        # Parse native part
Martin Bauer's avatar
Martin Bauer committed
103
    base_part = parts.pop(0)
104
    const = False
Martin Bauer's avatar
Martin Bauer committed
105
    if 'const' in base_part:
106
        const = True
Martin Bauer's avatar
Martin Bauer committed
107
108
109
110
        base_part.remove('const')
    assert len(base_part) == 1
    if base_part[0][-1] == "*":
        base_part[0] = base_part[0][:-1]
Jan Hoenig's avatar
Jan Hoenig committed
111
        parts.append('*')
Martin Bauer's avatar
Martin Bauer committed
112
    current_type = BasicType(np.dtype(base_part[0]), const)
113
114
115
116
117
118
119
120
121
122
123
    # Parse pointer parts
    for part in parts:
        restrict = False
        const = False
        if 'restrict' in part:
            restrict = True
            part.remove('restrict')
        if 'const' in part:
            const = True
            part.remove("const")
        assert len(part) == 1 and part[0] == '*'
Martin Bauer's avatar
Martin Bauer committed
124
125
        current_type = PointerType(current_type, const, restrict)
    return current_type
126
127


Martin Bauer's avatar
Martin Bauer committed
128
129
130
131
def get_base_type(data_type):
    while data_type.base_type is not None:
        data_type = data_type.base_type
    return data_type
132
133


Martin Bauer's avatar
Martin Bauer committed
134
def to_ctypes(data_type):
Jan Hoenig's avatar
Jan Hoenig committed
135
136
    """
    Transforms a given Type into ctypes
Martin Bauer's avatar
Martin Bauer committed
137
    :param data_type: Subclass of Type
Jan Hoenig's avatar
Jan Hoenig committed
138
139
    :return: ctypes type object
    """
Martin Bauer's avatar
Martin Bauer committed
140
141
142
    if isinstance(data_type, PointerType):
        return ctypes.POINTER(to_ctypes(data_type.base_type))
    elif isinstance(data_type, StructType):
143
        return ctypes.POINTER(ctypes.c_uint8)
144
    else:
Martin Bauer's avatar
Martin Bauer committed
145
        return to_ctypes.map[data_type.numpy_dtype]
146

Martin Bauer's avatar
Martin Bauer committed
147
148

to_ctypes.map = {
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
    np.dtype(np.int8): ctypes.c_int8,
    np.dtype(np.int16): ctypes.c_int16,
    np.dtype(np.int32): ctypes.c_int32,
    np.dtype(np.int64): ctypes.c_int64,

    np.dtype(np.uint8): ctypes.c_uint8,
    np.dtype(np.uint16): ctypes.c_uint16,
    np.dtype(np.uint32): ctypes.c_uint32,
    np.dtype(np.uint64): ctypes.c_uint64,

    np.dtype(np.float32): ctypes.c_float,
    np.dtype(np.float64): ctypes.c_double,
}


164
def ctypes_from_llvm(data_type):
165
166
    if not ir:
        raise _ir_importerror
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
    if isinstance(data_type, ir.PointerType):
        ctype = ctypes_from_llvm(data_type.pointee)
        if ctype is None:
            return ctypes.c_void_p
        else:
            return ctypes.POINTER(ctype)
    elif isinstance(data_type, ir.IntType):
        if data_type.width == 8:
            return ctypes.c_int8
        elif data_type.width == 16:
            return ctypes.c_int16
        elif data_type.width == 32:
            return ctypes.c_int32
        elif data_type.width == 64:
            return ctypes.c_int64
        else:
            raise ValueError("Int width %d is not supported" % data_type.width)
    elif isinstance(data_type, ir.FloatType):
        return ctypes.c_float
    elif isinstance(data_type, ir.DoubleType):
        return ctypes.c_double
    elif isinstance(data_type, ir.VoidType):
        return None  # Void type is not supported by ctypes
    else:
        raise NotImplementedError('Data type %s of %s is not supported yet' % (type(data_type), data_type))


def to_llvm_type(data_type):
    """
    Transforms a given type into ctypes
    :param data_type: Subclass of Type
    :return: llvmlite type object
    """
200
201
    if not ir:
        raise _ir_importerror
202
    if isinstance(data_type, PointerType):
Martin Bauer's avatar
Martin Bauer committed
203
        return to_llvm_type(data_type.base_type).as_pointer()
204
    else:
Martin Bauer's avatar
Martin Bauer committed
205
206
        return to_llvm_type.map[data_type.numpy_dtype]

207

208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
if ir:
    to_llvm_type.map = {
        np.dtype(np.int8): ir.IntType(8),
        np.dtype(np.int16): ir.IntType(16),
        np.dtype(np.int32): ir.IntType(32),
        np.dtype(np.int64): ir.IntType(64),

        np.dtype(np.uint8): ir.IntType(8),
        np.dtype(np.uint16): ir.IntType(16),
        np.dtype(np.uint32): ir.IntType(32),
        np.dtype(np.uint64): ir.IntType(64),

        np.dtype(np.float32): ir.FloatType(),
        np.dtype(np.float64): ir.DoubleType(),
    }
223

224

Martin Bauer's avatar
Martin Bauer committed
225
226
227
def peel_off_type(dtype, type_to_peel_off):
    while type(dtype) is type_to_peel_off:
        dtype = dtype.base_type
228
229
230
    return dtype


Martin Bauer's avatar
Martin Bauer committed
231
def collate_types(types):
232
233
234
235
236
237
238
    """
    Takes a sequence of types and returns their "common type" e.g. (float, double, float) -> double
    Uses the collation rules from numpy.
    """

    # Pointer arithmetic case i.e. pointer + integer is allowed
    if any(type(t) is PointerType for t in types):
Martin Bauer's avatar
Martin Bauer committed
239
        pointer_type = None
240
241
        for t in types:
            if type(t) is PointerType:
Martin Bauer's avatar
Martin Bauer committed
242
                if pointer_type is not None:
243
                    raise ValueError("Cannot collate the combination of two pointer types")
Martin Bauer's avatar
Martin Bauer committed
244
                pointer_type = t
245
246
247
248
249
            elif type(t) is BasicType:
                if not (t.is_int() or t.is_uint()):
                    raise ValueError("Invalid pointer arithmetic")
            else:
                raise ValueError("Invalid pointer arithmetic")
Martin Bauer's avatar
Martin Bauer committed
250
        return pointer_type
251
252

    # peel of vector types, if at least one vector type occurred the result will also be the vector type
Martin Bauer's avatar
Martin Bauer committed
253
254
    vector_type = [t for t in types if type(t) is VectorType]
    if not allEqual(t.width for t in vector_type):
255
        raise ValueError("Collation failed because of vector types with different width")
Martin Bauer's avatar
Martin Bauer committed
256
    types = [peel_off_type(t, VectorType) for t in types]
257
258
259
260
261

    # now we should have a list of basic types - struct types are not yet supported
    assert all(type(t) is BasicType for t in types)

    # use numpy collation -> create type from numpy type -> and, put vector type around if necessary
Martin Bauer's avatar
Martin Bauer committed
262
263
264
265
    result_numpy_type = np.result_type(*(t.numpy_dtype for t in types))
    result = BasicType(result_numpy_type)
    if vector_type:
        result = VectorType(result, vector_type[0].width)
266
267
268
269
    return result


@memorycache(maxsize=2048)
Martin Bauer's avatar
Martin Bauer committed
270
def get_type_of_expression(expr):
271
272
273
    from pystencils.astnodes import ResolvedFieldAccess
    expr = sp.sympify(expr)
    if isinstance(expr, sp.Integer):
Martin Bauer's avatar
Martin Bauer committed
274
        return create_type("int")
275
    elif isinstance(expr, sp.Rational) or isinstance(expr, sp.Float):
Martin Bauer's avatar
Martin Bauer committed
276
        return create_type("double")
277
278
279
    elif isinstance(expr, ResolvedFieldAccess):
        return expr.field.dtype
    elif isinstance(expr, TypedSymbol):
280
        return expr.dtype
281
282
283
284
285
    elif isinstance(expr, sp.Symbol):
        raise ValueError("All symbols inside this expression have to be typed!")
    elif hasattr(expr, 'func') and expr.func == castFunc:
        return expr.args[1]
    elif hasattr(expr, 'func') and expr.func == sp.Piecewise:
Martin Bauer's avatar
Martin Bauer committed
286
287
288
289
290
        collated_result_type = collate_types(tuple(get_type_of_expression(a[0]) for a in expr.args))
        collated_condition_type = collate_types(tuple(get_type_of_expression(a[1]) for a in expr.args))
        if type(collated_condition_type) is VectorType and type(collated_result_type) is not VectorType:
            collated_result_type = VectorType(collated_result_type, width=collated_condition_type.width)
        return collated_result_type
291
    elif isinstance(expr, sp.Indexed):
Martin Bauer's avatar
Martin Bauer committed
292
293
        typed_symbol = expr.base.label
        return typed_symbol.dtype.base_type
294
    elif isinstance(expr, sp.boolalg.Boolean) or isinstance(expr, sp.boolalg.BooleanFunction):
295
        # if any arg is of vector type return a vector boolean, else return a normal scalar boolean
Martin Bauer's avatar
Martin Bauer committed
296
297
298
299
        result = create_type("bool")
        vec_args = [get_type_of_expression(a) for a in expr.args if isinstance(get_type_of_expression(a), VectorType)]
        if vec_args:
            result = VectorType(result, width=vec_args[0].width)
300
        return result
301
    elif isinstance(expr, sp.Expr):
Martin Bauer's avatar
Martin Bauer committed
302
303
        types = tuple(get_type_of_expression(a) for a in expr.args)
        return collate_types(types)
304

305
    raise NotImplementedError("Could not determine type for", expr, type(expr))
306
307


308
309
310
class Type(sp.Basic):
    def __new__(cls, *args, **kwargs):
        return sp.Basic.__new__(cls)
311

312
    def __lt__(self, other):  # deprecated
Jan Hoenig's avatar
Jan Hoenig committed
313
314
315
        # Needed for sorting the types inside an expression
        if isinstance(self, BasicType):
            if isinstance(other, BasicType):
Martin Bauer's avatar
Martin Bauer committed
316
                return self.numpy_dtype > other.numpy_dtype  # TODO const
317
            elif isinstance(other, PointerType):
318
                return False
319
            else:  # isinstance(other, StructType):
Jan Hoenig's avatar
Jan Hoenig committed
320
                raise NotImplementedError("Struct type comparison is not yet implemented")
321
        elif isinstance(self, PointerType):
Jan Hoenig's avatar
Jan Hoenig committed
322
            if isinstance(other, BasicType):
323
                return True
324
            elif isinstance(other, PointerType):
Martin Bauer's avatar
Martin Bauer committed
325
                return self.base_type > other.base_type  # TODO const, restrict
326
            else:  # isinstance(other, StructType):
Jan Hoenig's avatar
Jan Hoenig committed
327
                raise NotImplementedError("Struct type comparison is not yet implemented")
328
        elif isinstance(self, StructType):
Jan Hoenig's avatar
Jan Hoenig committed
329
            raise NotImplementedError("Struct type comparison is not yet implemented")
330
331
332
333
334
        else:
            raise NotImplementedError

    def _sympystr(self, *args, **kwargs):
        return str(self)
335
336
337
338


class BasicType(Type):
    @staticmethod
Martin Bauer's avatar
Martin Bauer committed
339
    def numpy_name_to_c(name):
Jan Hoenig's avatar
Jan Hoenig committed
340
341
342
343
        if name == 'float64':
            return 'double'
        elif name == 'float32':
            return 'float'
344
345
346
347
        elif name.startswith('int'):
            width = int(name[len("int"):])
            return "int%d_t" % (width,)
        elif name.startswith('uint'):
348
            width = int(name[len("uint"):])
349
350
351
352
353
354
355
356
            return "uint%d_t" % (width,)
        elif name == 'bool':
            return 'bool'
        else:
            raise NotImplemented("Can map numpy to C name for %s" % (name,))

    def __init__(self, dtype, const=False):
        self.const = const
357
        if isinstance(dtype, Type):
Martin Bauer's avatar
Martin Bauer committed
358
            self._dtype = dtype.numpy_dtype
359
360
        else:
            self._dtype = np.dtype(dtype)
361
362
363
364
        assert self._dtype.fields is None, "Tried to initialize NativeType with a structured type"
        assert self._dtype.hasobject is False
        assert self._dtype.subdtype is None

365
    def __getnewargs__(self):
Martin Bauer's avatar
Martin Bauer committed
366
        return self.numpy_dtype, self.const
367

368
    @property
Martin Bauer's avatar
Martin Bauer committed
369
    def base_type(self):
370
        return None
371

372
    @property
Martin Bauer's avatar
Martin Bauer committed
373
    def numpy_dtype(self):
374
375
        return self._dtype

376
    @property
Martin Bauer's avatar
Martin Bauer committed
377
    def item_size(self):
378
379
        return 1

380
    def is_int(self):
Martin Bauer's avatar
Martin Bauer committed
381
        return self.numpy_dtype in np.sctypes['int']
382
383

    def is_float(self):
Martin Bauer's avatar
Martin Bauer committed
384
        return self.numpy_dtype in np.sctypes['float']
385
386

    def is_uint(self):
Martin Bauer's avatar
Martin Bauer committed
387
        return self.numpy_dtype in np.sctypes['uint']
388

Martin Bauer's avatar
Martin Bauer committed
389
390
    def is_complex(self):
        return self.numpy_dtype in np.sctypes['complex']
391
392

    def is_other(self):
Martin Bauer's avatar
Martin Bauer committed
393
        return self.numpy_dtype in np.sctypes['others']
394

395
    @property
Martin Bauer's avatar
Martin Bauer committed
396
397
    def base_name(self):
        return BasicType.numpy_name_to_c(str(self._dtype))
398

Jan Hoenig's avatar
Jan Hoenig committed
399
    def __str__(self):
Martin Bauer's avatar
Martin Bauer committed
400
        result = BasicType.numpy_name_to_c(str(self._dtype))
401
402
403
        if self.const:
            result += " const"
        return result
Jan Hoenig's avatar
Jan Hoenig committed
404

405
406
407
    def __repr__(self):
        return str(self)

Jan Hoenig's avatar
Jan Hoenig committed
408
    def __eq__(self, other):
409
410
        if not isinstance(other, BasicType):
            return False
Jan Hoenig's avatar
Jan Hoenig committed
411
        else:
Martin Bauer's avatar
Martin Bauer committed
412
            return (self.numpy_dtype, self.const) == (other.numpy_dtype, other.const)
413
414
415
416
417

    def __hash__(self):
        return hash(str(self))


418
419
420
class VectorType(Type):
    instructionSet = None

Martin Bauer's avatar
Martin Bauer committed
421
422
    def __init__(self, base_type, width=4):
        self._base_type = base_type
423
424
425
        self.width = width

    @property
Martin Bauer's avatar
Martin Bauer committed
426
427
    def base_type(self):
        return self._base_type
428
429

    @property
Martin Bauer's avatar
Martin Bauer committed
430
431
    def item_size(self):
        return self.width * self.base_type.item_size
432
433
434
435
436

    def __eq__(self, other):
        if not isinstance(other, VectorType):
            return False
        else:
Martin Bauer's avatar
Martin Bauer committed
437
            return (self.base_type, self.width) == (other.base_type, other.width)
438
439
440

    def __str__(self):
        if self.instructionSet is None:
Martin Bauer's avatar
Martin Bauer committed
441
            return "%s[%d]" % (self.base_type, self.width)
442
        else:
Martin Bauer's avatar
Martin Bauer committed
443
            if self.base_type == create_type("int64"):
444
                return self.instructionSet['int']
Martin Bauer's avatar
Martin Bauer committed
445
            elif self.base_type == create_type("float64"):
446
                return self.instructionSet['double']
Martin Bauer's avatar
Martin Bauer committed
447
            elif self.base_type == create_type("float32"):
448
                return self.instructionSet['float']
Martin Bauer's avatar
Martin Bauer committed
449
            elif self.base_type == create_type("bool"):
450
                return self.instructionSet['bool']
451
452
453
454
            else:
                raise NotImplementedError()

    def __hash__(self):
Martin Bauer's avatar
Martin Bauer committed
455
        return hash((self.base_type, self.width))
456
457


458
class PointerType(Type):
Martin Bauer's avatar
Martin Bauer committed
459
460
    def __init__(self, base_type, const=False, restrict=True):
        self._base_type = base_type
461
462
463
        self.const = const
        self.restrict = restrict

464
    def __getnewargs__(self):
Martin Bauer's avatar
Martin Bauer committed
465
        return self.base_type, self.const, self.restrict
466

467
468
469
470
471
    @property
    def alias(self):
        return not self.restrict

    @property
Martin Bauer's avatar
Martin Bauer committed
472
473
    def base_type(self):
        return self._base_type
474

475
    @property
Martin Bauer's avatar
Martin Bauer committed
476
477
    def item_size(self):
        return self.base_type.item_size
478

479
480
    def __eq__(self, other):
        if not isinstance(other, PointerType):
Jan Hoenig's avatar
Jan Hoenig committed
481
            return False
482
        else:
Martin Bauer's avatar
Martin Bauer committed
483
            return (self.base_type, self.const, self.restrict) == (other.base_type, other.const, other.restrict)
484

Jan Hoenig's avatar
Jan Hoenig committed
485
    def __str__(self):
Martin Bauer's avatar
Martin Bauer committed
486
        return "%s *%s%s" % (self.base_type, " RESTRICT " if self.restrict else "", " const " if self.const else "")
487

488
489
490
    def __repr__(self):
        return str(self)

491
    def __hash__(self):
Martin Bauer's avatar
Martin Bauer committed
492
        return hash((self._base_type, self.const, self.restrict))
493

Jan Hoenig's avatar
Jan Hoenig committed
494

495
class StructType(object):
Martin Bauer's avatar
Martin Bauer committed
496
    def __init__(self, numpy_type, const=False):
497
        self.const = const
Martin Bauer's avatar
Martin Bauer committed
498
        self._dtype = np.dtype(numpy_type)
Martin Bauer's avatar
Martin Bauer committed
499

500
    def __getnewargs__(self):
Martin Bauer's avatar
Martin Bauer committed
501
        return self.numpy_dtype, self.const
502

503
    @property
Martin Bauer's avatar
Martin Bauer committed
504
    def base_type(self):
505
506
507
        return None

    @property
Martin Bauer's avatar
Martin Bauer committed
508
    def numpy_dtype(self):
509
510
511
        return self._dtype

    @property
Martin Bauer's avatar
Martin Bauer committed
512
513
    def item_size(self):
        return self.numpy_dtype.itemsize
514

Martin Bauer's avatar
Martin Bauer committed
515
516
    def get_element_offset(self, element_name):
        return self.numpy_dtype.fields[element_name][1]
517

Martin Bauer's avatar
Martin Bauer committed
518
519
520
    def get_element_type(self, element_name):
        np_element_type = self.numpy_dtype.fields[element_name][0]
        return BasicType(np_element_type, self.const)
521

Martin Bauer's avatar
Martin Bauer committed
522
523
    def has_element(self, element_name):
        return element_name in self.numpy_dtype.fields
524

525
526
527
528
    def __eq__(self, other):
        if not isinstance(other, StructType):
            return False
        else:
Martin Bauer's avatar
Martin Bauer committed
529
            return (self.numpy_dtype, self.const) == (other.numpy_dtype, other.const)
530
531
532
533
534
535
536
537

    def __str__(self):
        # structs are handled byte-wise
        result = "uint8_t"
        if self.const:
            result += " const"
        return result

538
539
540
    def __repr__(self):
        return str(self)

541
    def __hash__(self):
Martin Bauer's avatar
Martin Bauer committed
542
        return hash((self.numpy_dtype, self.const))
543

Jan Hoenig's avatar
Jan Hoenig committed
544
    # TODO this should not work at all!!!
Jan Hoenig's avatar
Jan Hoenig committed
545
546
547
548
549
550
551
    def __gt__(self, other):
        if self.ptr and not other.ptr:
            return True
        if self.dtype > other.dtype:
            return True


Jan Hoenig's avatar
Jan Hoenig committed
552
def get_type_from_sympy(node):
Jan Hoenig's avatar
Jan Hoenig committed
553
554
555
556
557
    """
    Creates a Type object from a Sympy object
    :param node: Sympy object
    :return: Type object
    """
Jan Hoenig's avatar
Jan Hoenig committed
558
559
560
561
562
563
564
565
566
567
    # Rational, NumberSymbol?
    # Zero, One, NegativeOne )= Integer
    # Half )= Rational
    # NAN, Infinity, Negative Inifinity,
    # Exp1, Imaginary Unit, Pi, EulerGamma, Catalan, Golden Ratio
    # Pow, Mul, Add, Mod, Relational
    if not isinstance(node, sp.Number):
        raise TypeError(node, 'is not a sp.Number')

    if isinstance(node, sp.Float) or isinstance(node, sp.RealNumber):
Martin Bauer's avatar
Martin Bauer committed
568
        return create_type('double'), float(node)
Jan Hoenig's avatar
Jan Hoenig committed
569
    elif isinstance(node, sp.Integer):
Martin Bauer's avatar
Martin Bauer committed
570
        return create_type('int'), int(node)
Jan Hoenig's avatar
Jan Hoenig committed
571
    elif isinstance(node, sp.Rational):
572
        # TODO is it always float?
Martin Bauer's avatar
Martin Bauer committed
573
        return create_type('double'), float(node.p / node.q)
Jan Hoenig's avatar
Jan Hoenig committed
574
    else:
Jan Hoenig's avatar
Jan Hoenig committed
575
        raise TypeError(node, ' is not a supported type (yet)!')