Move TypeVar and TypeSet into their own Python package.

These classes are not very entangled with the rest of __init__, and
we'll be expanding them a bit.
This commit is contained in:
Jakob Stoklund Olesen
2016-09-27 10:53:53 -07:00
parent d915718526
commit b06668aa8a
4 changed files with 102 additions and 95 deletions

View File

@@ -96,7 +96,7 @@ instances that refer to a *type variable* instead of a concrete value type.
Polymorphism only works for SSA value operands. Other operands have a fixed Polymorphism only works for SSA value operands. Other operands have a fixed
operand kind. operand kind.
.. autoclass:: TypeVar .. autoclass:: cretonne.typevar.TypeVar
:members: :members:
If multiple operands refer to the same type variable they will be required to If multiple operands refer to the same type variable they will be required to

View File

@@ -8,7 +8,7 @@ from __future__ import absolute_import
import re import re
import math import math
import importlib import importlib
from collections import namedtuple, OrderedDict from collections import OrderedDict
from .predicates import And from .predicates import And
@@ -518,98 +518,6 @@ class BoolType(ScalarType):
return 'BoolType(bits={})'.format(self.bits) return 'BoolType(bits={})'.format(self.bits)
# Parametric polymorphism.
#: A `TypeSet` represents a set of types. We don't allow arbitrary subsets of
#: types, but use a parametrized approach instead.
#: This is represented as a named tuple so it can be used as a dictionary key.
TypeSet = namedtuple(
'TypeSet', [
'allow_scalars',
'allow_simd',
'base',
'all_ints',
'all_floats',
'all_bools'])
class TypeVar(object):
"""
Type variables can be used in place of concrete types when defining
instructions. This makes the instructions *polymorphic*.
A type variable is restricted to vary over a subset of the value types.
This subset is specified by a set of flags that control the permitted base
types and whether the type variable can assume scalar or vector types, or
both.
:param name: Short name of type variable used in instruction descriptions.
:param doc: Documentation string.
:param base: Single base type or list of base types. Use this to specify an
exact set of base types if the general categories below are not good
enough.
:param ints: Allow all integer base types.
:param floats: Allow all floating point base types.
:param bools: Allow all boolean base types.
:param scalars: Allow type variable to assume scalar types.
:param simd: Allow type variable to assume vector types.
"""
def __init__(
self, name, doc, base=None,
ints=False, floats=False, bools=False,
scalars=True, simd=False,
derived_func=None):
self.name = name
self.__doc__ = doc
self.base = base
self.is_derived = isinstance(base, TypeVar)
if self.is_derived:
assert derived_func
self.derived_func = derived_func
self.name = '{}({})'.format(derived_func, base.name)
else:
self.type_set = TypeSet(
allow_scalars=scalars,
allow_simd=simd,
base=base,
all_ints=ints,
all_floats=floats,
all_bools=bools)
def __str__(self):
return "`{}`".format(self.name)
def lane_of(self):
"""
Return a derived type variable that is the scalar lane type of this
type variable.
When this type variable assumes a scalar type, the derived type will be
the same scalar type.
"""
return TypeVar(None, None, base=self, derived_func='LaneOf')
def as_bool(self):
"""
Return a derived type variable that has the same vector geometry as
this type variable, but with boolean lanes. Scalar types map to `b1`.
"""
return TypeVar(None, None, base=self, derived_func='AsBool')
def operand_kind(self):
# When a `TypeVar` object is used to describe the type of an `Operand`
# in an instruction definition, the kind of that operand is an SSA
# value.
return value
def free_typevar(self):
if isinstance(self.base, TypeVar):
return self.base
else:
return self
# Defining instructions. # Defining instructions.

View File

@@ -5,7 +5,8 @@ This module defines the basic Cretonne instruction set that all targets
support. support.
""" """
from __future__ import absolute_import from __future__ import absolute_import
from . import TypeVar, Operand, Instruction, InstructionGroup, variable_args from . import Operand, Instruction, InstructionGroup, variable_args
from .typevar import TypeVar
from .types import i8, f32, f64, b1 from .types import i8, f32, f64, b1
from .immediates import imm64, uimm8, ieee32, ieee64, immvector, intcc, floatcc from .immediates import imm64, uimm8, ieee32, ieee64, immvector, intcc, floatcc
from . import entities from . import entities

98
meta/cretonne/typevar.py Normal file
View File

@@ -0,0 +1,98 @@
"""
Type variables for Parametric polymorphism.
Cretonne instructions and instruction transformations can be specified to be
polymorphic by using type variables.
"""
from __future__ import absolute_import
from collections import namedtuple
from . import value
#: A `TypeSet` represents a set of types. We don't allow arbitrary subsets of
#: types, but use a parametrized approach instead.
#: This is represented as a named tuple so it can be used as a dictionary key.
TypeSet = namedtuple(
'TypeSet', [
'allow_scalars',
'allow_simd',
'base',
'all_ints',
'all_floats',
'all_bools'])
class TypeVar(object):
"""
Type variables can be used in place of concrete types when defining
instructions. This makes the instructions *polymorphic*.
A type variable is restricted to vary over a subset of the value types.
This subset is specified by a set of flags that control the permitted base
types and whether the type variable can assume scalar or vector types, or
both.
:param name: Short name of type variable used in instruction descriptions.
:param doc: Documentation string.
:param base: Single base type or list of base types. Use this to specify an
exact set of base types if the general categories below are not good
enough.
:param ints: Allow all integer base types.
:param floats: Allow all floating point base types.
:param bools: Allow all boolean base types.
:param scalars: Allow type variable to assume scalar types.
:param simd: Allow type variable to assume vector types.
"""
def __init__(
self, name, doc, base=None,
ints=False, floats=False, bools=False,
scalars=True, simd=False,
derived_func=None):
self.name = name
self.__doc__ = doc
self.base = base
self.is_derived = isinstance(base, TypeVar)
if self.is_derived:
assert derived_func
self.derived_func = derived_func
self.name = '{}({})'.format(derived_func, base.name)
else:
self.type_set = TypeSet(
allow_scalars=scalars,
allow_simd=simd,
base=base,
all_ints=ints,
all_floats=floats,
all_bools=bools)
def __str__(self):
return "`{}`".format(self.name)
def lane_of(self):
"""
Return a derived type variable that is the scalar lane type of this
type variable.
When this type variable assumes a scalar type, the derived type will be
the same scalar type.
"""
return TypeVar(None, None, base=self, derived_func='LaneOf')
def as_bool(self):
"""
Return a derived type variable that has the same vector geometry as
this type variable, but with boolean lanes. Scalar types map to `b1`.
"""
return TypeVar(None, None, base=self, derived_func='AsBool')
def operand_kind(self):
# When a `TypeVar` object is used to describe the type of an `Operand`
# in an instruction definition, the kind of that operand is an SSA
# value.
return value
def free_typevar(self):
if isinstance(self.base, TypeVar):
return self.base
else:
return self