From caccaf3613ab3881b80fcd03f632ebeab9538e42 Mon Sep 17 00:00:00 2001
From: Dominic Kempf <dominic.kempf@iwr.uni-heidelberg.de>
Date: Tue, 29 Nov 2016 10:49:23 +0100
Subject: [PATCH] Use ImmutableRecord instead of Record throughout loopy

---
 loopy/codegen/__init__.py           | 16 ++++++----------
 loopy/codegen/control.py            |  4 ++--
 loopy/codegen/result.py             |  6 +++---
 loopy/kernel/__init__.py            |  8 ++++----
 loopy/kernel/array.py               | 10 +++++-----
 loopy/kernel/data.py                | 16 ++++++++--------
 loopy/kernel/instruction.py         | 11 ++++-------
 loopy/library/random123.py          |  4 ++--
 loopy/options.py                    |  6 +++---
 loopy/schedule/__init__.py          | 10 +++++-----
 loopy/symbolic.py                   |  4 ++--
 loopy/target/pyopencl_execution.py  |  4 ++--
 loopy/transform/array_buffer_map.py |  4 ++--
 loopy/transform/subst.py            |  4 ++--
 setup.py                            |  2 +-
 15 files changed, 51 insertions(+), 58 deletions(-)

diff --git a/loopy/codegen/__init__.py b/loopy/codegen/__init__.py
index ffd291d53..6f312ec79 100644
--- a/loopy/codegen/__init__.py
+++ b/loopy/codegen/__init__.py
@@ -25,7 +25,7 @@ THE SOFTWARE.
 import six
 
 from loopy.diagnostic import LoopyError, warn
-from pytools import Record
+from pytools import ImmutableRecord
 import islpy as isl
 
 from pytools.persistent_dict import PersistentDict
@@ -38,7 +38,7 @@ logger = logging.getLogger(__name__)
 
 # {{{ implemented data info
 
-class ImplementedDataInfo(Record):
+class ImplementedDataInfo(ImmutableRecord):
     """
     .. attribute:: name
 
@@ -91,7 +91,7 @@ class ImplementedDataInfo(Record):
         from loopy.types import LoopyType
         assert isinstance(dtype, LoopyType)
 
-        Record.__init__(self,
+        ImmutableRecord.__init__(self,
                 name=name,
                 dtype=dtype,
                 arg_class=arg_class,
@@ -127,7 +127,7 @@ class VectorizationInfo(object):
         self.space = space
 
 
-class SeenFunction(Record):
+class SeenFunction(ImmutableRecord):
     """
     .. attribute:: name
     .. attribute:: c_name
@@ -137,15 +137,11 @@ class SeenFunction(Record):
     """
 
     def __init__(self, name, c_name, arg_dtypes):
-        Record.__init__(self,
+        ImmutableRecord.__init__(self,
                 name=name,
                 c_name=c_name,
                 arg_dtypes=arg_dtypes)
 
-    def __hash__(self):
-        return hash((type(self),)
-                + tuple((f, getattr(self, f)) for f in type(self).fields))
-
 
 class CodeGenerationState(object):
     """
@@ -365,7 +361,7 @@ code_gen_cache = PersistentDict("loopy-code-gen-cache-v3-"+DATA_MODEL_VERSION,
         key_builder=LoopyKeyBuilder())
 
 
-class PreambleInfo(Record):
+class PreambleInfo(ImmutableRecord):
     """
     .. attribute:: kernel
     .. attribute:: seen_dtypes
diff --git a/loopy/codegen/control.py b/loopy/codegen/control.py
index 55d4560be..d206faad5 100644
--- a/loopy/codegen/control.py
+++ b/loopy/codegen/control.py
@@ -255,9 +255,9 @@ def build_loop_nest(codegen_state, schedule_index):
 
     # {{{ pass 2: find admissible conditional inames for each sibling schedule item
 
-    from pytools import Record
+    from pytools import ImmutableRecord
 
-    class ScheduleIndexInfo(Record):
+    class ScheduleIndexInfo(ImmutableRecord):
         """
         .. attribute:: schedule_index
         .. attribute:: admissible_cond_inames
diff --git a/loopy/codegen/result.py b/loopy/codegen/result.py
index c683d120d..4318ad71c 100644
--- a/loopy/codegen/result.py
+++ b/loopy/codegen/result.py
@@ -23,7 +23,7 @@ THE SOFTWARE.
 """
 
 import six
-from pytools import Record
+from pytools import ImmutableRecord
 
 
 def process_preambles(preambles):
@@ -45,7 +45,7 @@ def process_preambles(preambles):
 
 # {{{ code generation result
 
-class GeneratedProgram(Record):
+class GeneratedProgram(ImmutableRecord):
     """
     .. attribute:: name
 
@@ -64,7 +64,7 @@ class GeneratedProgram(Record):
     """
 
 
-class CodeGenerationResult(Record):
+class CodeGenerationResult(ImmutableRecord):
     """
     .. attribute:: host_program
     .. attribute:: device_programs
diff --git a/loopy/kernel/__init__.py b/loopy/kernel/__init__.py
index e71a88886..5b192934c 100644
--- a/loopy/kernel/__init__.py
+++ b/loopy/kernel/__init__.py
@@ -28,7 +28,7 @@ import six
 from six.moves import range, zip, intern
 
 import numpy as np
-from pytools import RecordWithoutPickling, Record, memoize_method
+from pytools import ImmutableRecordWithoutPickling, ImmutableRecord, memoize_method
 import islpy as isl
 from islpy import dim_type
 import re
@@ -83,7 +83,7 @@ class kernel_state:  # noqa
     SCHEDULED = 2
 
 
-class LoopKernel(RecordWithoutPickling):
+class LoopKernel(ImmutableRecordWithoutPickling):
     """These correspond more or less directly to arguments of
     :func:`loopy.make_kernel`.
 
@@ -279,7 +279,7 @@ class LoopKernel(RecordWithoutPickling):
         assert all(dom.get_ctx() == isl.DEFAULT_CONTEXT for dom in domains)
         assert assumptions.get_ctx() == isl.DEFAULT_CONTEXT
 
-        RecordWithoutPickling.__init__(self,
+        ImmutableRecordWithoutPickling.__init__(self,
                 domains=domains,
                 instructions=instructions,
                 args=args,
@@ -889,7 +889,7 @@ class LoopKernel(RecordWithoutPickling):
                     dom_intersect_assumptions, iname_idx)
                 .coalesce())
 
-        class BoundsRecord(Record):
+        class BoundsRecord(ImmutableRecord):
             pass
 
         size = (upper_bound_pw_aff - lower_bound_pw_aff + 1)
diff --git a/loopy/kernel/array.py b/loopy/kernel/array.py
index 11392f255..a02fc58d9 100644
--- a/loopy/kernel/array.py
+++ b/loopy/kernel/array.py
@@ -30,7 +30,7 @@ import six
 from six.moves import range, zip
 from six import iteritems
 
-from pytools import Record, memoize_method
+from pytools import ImmutableRecord, memoize_method
 
 import numpy as np  # noqa
 
@@ -40,7 +40,7 @@ from loopy.tools import is_integer
 
 # {{{ array dimension tags
 
-class ArrayDimImplementationTag(Record):
+class ArrayDimImplementationTag(ImmutableRecord):
     def update_persistent_hash(self, key_hash, key_builder):
         """Custom hash computation function for use with
         :class:`pytools.persistent_dict.PersistentDict`.
@@ -544,7 +544,7 @@ def _parse_shape_or_strides(x):
     return tuple(_pymbolic_parse_if_necessary(xi) for xi in x)
 
 
-class ArrayBase(Record):
+class ArrayBase(ImmutableRecord):
     """
     .. attribute :: name
 
@@ -787,7 +787,7 @@ class ArrayBase(Record):
             warn("dim_names is not a tuple when calling ArrayBase constructor",
                     DeprecationWarning, stacklevel=2)
 
-        Record.__init__(self,
+        ImmutableRecord.__init__(self,
                 name=name,
                 dtype=dtype,
                 shape=shape,
@@ -1163,7 +1163,7 @@ class ArrayBase(Record):
 
 # {{{ access code generation
 
-class AccessInfo(Record):
+class AccessInfo(ImmutableRecord):
     """
     .. attribute:: array_name
     .. attribute:: vector_index
diff --git a/loopy/kernel/data.py b/loopy/kernel/data.py
index b1430448d..61be55ca8 100644
--- a/loopy/kernel/data.py
+++ b/loopy/kernel/data.py
@@ -27,7 +27,7 @@ THE SOFTWARE.
 
 from six.moves import intern
 import numpy as np  # noqa
-from pytools import Record
+from pytools import ImmutableRecord
 from loopy.kernel.array import ArrayBase
 from loopy.diagnostic import LoopyError
 from loopy.kernel.instruction import (  # noqa
@@ -54,7 +54,7 @@ class auto(object):  # noqa
 
 # {{{ iname tags
 
-class IndexTag(Record):
+class IndexTag(ImmutableRecord):
     __slots__ = []
 
     def __hash__(self):
@@ -93,7 +93,7 @@ class AxisTag(UniqueTag):
     __slots__ = ["axis"]
 
     def __init__(self, axis):
-        Record.__init__(self,
+        ImmutableRecord.__init__(self,
                 axis=axis)
 
     @property
@@ -197,7 +197,7 @@ def parse_tag(tag):
 
 # {{{ arguments
 
-class KernelArgument(Record):
+class KernelArgument(ImmutableRecord):
     """Base class for all argument types"""
 
     def __init__(self, **kwargs):
@@ -210,7 +210,7 @@ class KernelArgument(Record):
         kwargs["dtype"] = to_loopy_type(
                 dtype, allow_auto=True, allow_none=True, target=target)
 
-        Record.__init__(self, **kwargs)
+        ImmutableRecord.__init__(self, **kwargs)
 
 
 class GlobalArg(ArrayBase, KernelArgument):
@@ -514,7 +514,7 @@ class TemporaryVariable(ArrayBase):
 
 # {{{ subsitution rule
 
-class SubstitutionRule(Record):
+class SubstitutionRule(ImmutableRecord):
     """
     .. attribute:: name
     .. attribute:: arguments
@@ -527,7 +527,7 @@ class SubstitutionRule(Record):
     def __init__(self, name, arguments, expression):
         assert isinstance(arguments, tuple)
 
-        Record.__init__(self,
+        ImmutableRecord.__init__(self,
                 name=name, arguments=arguments, expression=expression)
 
     def __str__(self):
@@ -548,7 +548,7 @@ class SubstitutionRule(Record):
 
 # {{{ function call mangling
 
-class CallMangleInfo(Record):
+class CallMangleInfo(ImmutableRecord):
     """
     .. attribute:: target_name
 
diff --git a/loopy/kernel/instruction.py b/loopy/kernel/instruction.py
index c31d9d242..9e1ef233c 100644
--- a/loopy/kernel/instruction.py
+++ b/loopy/kernel/instruction.py
@@ -23,14 +23,14 @@ THE SOFTWARE.
 """
 
 from six.moves import intern
-from pytools import Record, memoize_method
+from pytools import ImmutableRecord, memoize_method
 from loopy.diagnostic import LoopyError
 from warnings import warn
 
 
 # {{{ instructions: base class
 
-class InstructionBase(Record):
+class InstructionBase(ImmutableRecord):
     """A base class for all types of instruction that can occur in
     a kernel.
 
@@ -199,7 +199,7 @@ class InstructionBase(Record):
 
             new_predicates.add(pred)
 
-        predicates = frozenset(tuple(p for p in new_predicates))
+        predicates = frozenset(new_predicates)
         del new_predicates
 
         # }}}
@@ -255,7 +255,7 @@ class InstructionBase(Record):
         assert isinstance(groups, frozenset)
         assert isinstance(conflicts_with_groups, frozenset)
 
-        Record.__init__(self,
+        ImmutableRecord.__init__(self,
                 id=id,
                 depends_on=depends_on,
                 depends_on_is_final=depends_on_is_final,
@@ -431,9 +431,6 @@ class InstructionBase(Record):
         for field_name in sorted(self.fields):
             key_builder.rec(key_hash, getattr(self, field_name))
 
-    def __hash__(self):
-        return hash((type(self),) + tuple(getattr(self, field) for field in self.fields))
-
     # }}}
 
     def copy(self, **kwargs):
diff --git a/loopy/library/random123.py b/loopy/library/random123.py
index 7d04b8c73..b8633114d 100644
--- a/loopy/library/random123.py
+++ b/loopy/library/random123.py
@@ -25,14 +25,14 @@ THE SOFTWARE.
 """
 
 
-from pytools import Record
+from pytools import ImmutableRecord
 from mako.template import Template
 import numpy as np
 
 
 # {{{ rng metadata
 
-class RNGInfo(Record):
+class RNGInfo(ImmutableRecord):
     @property
     def full_name(self):
         return "%s%dx%d" % (self.name, self.width, self.bits)
diff --git a/loopy/options.py b/loopy/options.py
index c88c512cb..33b216e1e 100644
--- a/loopy/options.py
+++ b/loopy/options.py
@@ -24,7 +24,7 @@ THE SOFTWARE.
 
 
 import six
-from pytools import Record
+from pytools import ImmutableRecord
 import re
 
 
@@ -65,7 +65,7 @@ def _apply_legacy_map(lmap, kwargs):
     return result
 
 
-class Options(Record):
+class Options(ImmutableRecord):
     """
     Unless otherwise specified, these options are Boolean-valued
     (i.e. on/off).
@@ -181,7 +181,7 @@ class Options(Record):
         allow_terminal_colors_def = (
                 ALLOW_TERMINAL_COLORS and allow_terminal_colors_def)
 
-        Record.__init__(
+        ImmutableRecord.__init__(
                 self,
 
                 annotate_inames=kwargs.get("annotate_inames", False),
diff --git a/loopy/schedule/__init__.py b/loopy/schedule/__init__.py
index 1031488be..c8174d94c 100644
--- a/loopy/schedule/__init__.py
+++ b/loopy/schedule/__init__.py
@@ -24,7 +24,7 @@ THE SOFTWARE.
 
 
 import six
-from pytools import Record
+from pytools import ImmutableRecord
 import sys
 import islpy as isl
 from loopy.diagnostic import warn_with_kernel, LoopyError  # noqa
@@ -39,7 +39,7 @@ logger = logging.getLogger(__name__)
 
 # {{{ schedule items
 
-class ScheduleItem(Record):
+class ScheduleItem(ImmutableRecord):
     __slots__ = []
 
     def update_persistent_hash(self, key_hash, key_builder):
@@ -552,7 +552,7 @@ class ScheduleDebugInput(Exception):
 
 # {{{ scheduling algorithm
 
-class SchedulerState(Record):
+class SchedulerState(ImmutableRecord):
     """
     .. attribute:: kernel
 
@@ -1351,7 +1351,7 @@ def convert_barrier_instructions_to_barriers(kernel, schedule):
 
 # {{{ barrier insertion/verification
 
-class DependencyRecord(Record):
+class DependencyRecord(ImmutableRecord):
     """
     .. attribute:: source
 
@@ -1376,7 +1376,7 @@ class DependencyRecord(Record):
     """
 
     def __init__(self, source, target, dep_descr, variable, var_kind):
-        Record.__init__(self,
+        ImmutableRecord.__init__(self,
                 source=source,
                 target=target,
                 dep_descr=dep_descr,
diff --git a/loopy/symbolic.py b/loopy/symbolic.py
index b1743cb1a..430c65158 100644
--- a/loopy/symbolic.py
+++ b/loopy/symbolic.py
@@ -28,7 +28,7 @@ THE SOFTWARE.
 import six
 from six.moves import range, zip, reduce, intern
 
-from pytools import memoize, memoize_method, Record
+from pytools import memoize, memoize_method, ImmutableRecord
 import pytools.lex
 
 import pymbolic.primitives as p
@@ -559,7 +559,7 @@ def parse_tagged_name(expr):
         raise RuntimeError("subst rule name not understood: %s" % expr)
 
 
-class ExpansionState(Record):
+class ExpansionState(ImmutableRecord):
     """
     .. attribute:: kernel
     .. attribute:: instruction
diff --git a/loopy/target/pyopencl_execution.py b/loopy/target/pyopencl_execution.py
index 540cad000..61e8e4f39 100644
--- a/loopy/target/pyopencl_execution.py
+++ b/loopy/target/pyopencl_execution.py
@@ -25,7 +25,7 @@ THE SOFTWARE.
 import six
 from six.moves import range, zip
 
-from pytools import Record, memoize_method
+from pytools import ImmutableRecord, memoize_method
 from loopy.diagnostic import ParameterFinderWarning
 from pytools.py_codegen import (
         Indentation, PythonFunctionGenerator)
@@ -610,7 +610,7 @@ def generate_invoker(kernel, codegen_result):
 
 # {{{ kernel executor
 
-class _CLKernelInfo(Record):
+class _CLKernelInfo(ImmutableRecord):
     pass
 
 
diff --git a/loopy/transform/array_buffer_map.py b/loopy/transform/array_buffer_map.py
index 3c7bfed43..f4e6526a7 100644
--- a/loopy/transform/array_buffer_map.py
+++ b/loopy/transform/array_buffer_map.py
@@ -28,11 +28,11 @@ from islpy import dim_type
 from loopy.symbolic import (get_dependencies, SubstitutionMapper)
 from pymbolic.mapper.substitutor import make_subst_func
 
-from pytools import Record, memoize_method
+from pytools import ImmutableRecord, memoize_method
 from pymbolic import var
 
 
-class AccessDescriptor(Record):
+class AccessDescriptor(ImmutableRecord):
     """
     .. attribute:: identifier
 
diff --git a/loopy/transform/subst.py b/loopy/transform/subst.py
index b2b76ae9f..79ceff9fd 100644
--- a/loopy/transform/subst.py
+++ b/loopy/transform/subst.py
@@ -31,7 +31,7 @@ from loopy.symbolic import (
 from loopy.diagnostic import LoopyError
 from pymbolic.mapper.substitutor import make_subst_func
 
-from pytools import Record
+from pytools import ImmutableRecord
 from pymbolic import var
 
 
@@ -39,7 +39,7 @@ import logging
 logger = logging.getLogger(__name__)
 
 
-class ExprDescriptor(Record):
+class ExprDescriptor(ImmutableRecord):
     __slots__ = ["insn", "expr", "unif_var_dict"]
 
 
diff --git a/setup.py b/setup.py
index 5c8f377a6..742abee02 100644
--- a/setup.py
+++ b/setup.py
@@ -37,7 +37,7 @@ setup(name="loo.py",
           ],
 
       install_requires=[
-          "pytools>=2016.1",
+          "pytools>=2016.2.5",
           "pymbolic>=2016.2",
           "genpy>=2016.1.2",
           "cgen>=2016.1",
-- 
GitLab