# pylint:disable=missing-class-docstring
"""
All type constants used in type inference. They can be mapped, translated, or rewritten to C-style types.
"""
from typing import Optional
[docs]class TypeConstant:
SIZE = None
[docs] def pp_str(self, mapping) -> str: # pylint:disable=unused-argument
return repr(self)
def __eq__(self, other):
return type(self) == type(other)
def __hash__(self):
return hash(type(self))
@property
def size(self) -> int:
if self.SIZE is None:
raise NotImplementedError()
return self.SIZE
[docs]class TopType(TypeConstant):
def __repr__(self):
return "TOP"
[docs]class BottomType(TypeConstant):
def __repr__(self):
return "BOT"
[docs]class Int(TypeConstant):
def __repr__(self):
return "intbase"
[docs]class Int1(Int):
SIZE = 1
[docs]class Int8(Int):
SIZE = 1
def __repr__(self):
return "int8"
[docs]class Int16(Int):
SIZE = 2
def __repr__(self):
return "int16"
[docs]class Int32(Int):
SIZE = 4
def __repr__(self):
return "int32"
[docs]class Int64(Int):
SIZE = 8
def __repr__(self):
return "int64"
[docs]class Int128(Int):
SIZE = 16
def __repr__(self):
return "int128"
[docs]class FloatBase(TypeConstant):
def __repr__(self):
return "floatbase"
[docs]class Float(FloatBase):
SIZE = 4
def __repr__(self):
return "float"
[docs]class Double(FloatBase):
SIZE = 8
def __repr__(self):
return "double"
[docs]class Pointer(TypeConstant):
def __init__(self, basetype):
self.basetype = basetype
def __eq__(self, other):
return type(self) is type(other) and self.basetype == other.basetype
def __hash__(self):
return hash((type(self), hash(self.basetype)))
[docs] def new(self, basetype):
return self.__class__(basetype)
[docs]class Pointer32(Pointer, Int32):
"""
32-bit pointers.
"""
def __init__(self, basetype):
Pointer.__init__(self, basetype)
def __repr__(self):
return "ptr32(%r)" % self.basetype
[docs]class Pointer64(Pointer, Int64):
"""
64-bit pointers.
"""
def __init__(self, basetype):
Pointer.__init__(self, basetype)
def __repr__(self):
return "ptr64(%r)" % self.basetype
[docs]class Array(TypeConstant):
def __init__(self, element, count=None):
self.element: TypeConstant = element
self.count: Optional[int] = count
def __repr__(self):
if self.count is None:
return "%r[?]" % self.element
else:
return "%r[%d]" % (self.element, self.count)
def __eq__(self, other):
return type(other) is type(self) and self.element == other.element and self.count == other.count
def __hash__(self):
return hash((type(self), self.element, self.count))
[docs]class Struct(TypeConstant):
def __init__(self, fields=None):
self.fields = {} if fields is None else fields # offset to type
def _hash_fields(self):
keys = sorted(self.fields.keys())
tpl = tuple((k, self.fields[k]) for k in keys)
return hash(tpl)
def __repr__(self):
return "struct%r" % self.fields
def __eq__(self, other):
return type(other) is type(self) and self.fields == other.fields
def __hash__(self):
return hash((type(self), self._hash_fields()))
[docs]class TypeVariableReference(TypeConstant):
def __init__(self, typevar):
self.typevar = typevar
def __repr__(self):
return "ref(%s)" % self.typevar
def __eq__(self, other):
return type(other) is type(self) and self.typevar == other.typevar
def __hash__(self):
return hash((type(self), self.typevar))
#
# Methods
#
[docs]def int_type(bits: int) -> Optional[Int]:
mapping = {
1: Int1,
8: Int8,
16: Int16,
32: Int32,
64: Int64,
128: Int128,
}
if bits in mapping:
return mapping[bits]()
return None
[docs]def float_type(bits: int) -> Optional[FloatBase]:
if bits == 32:
return Float()
elif bits == 64:
return Double()
return None