# Path: sanskrit_parser/base/sanskrit_base.py
# class SanskritImmutableString(SanskritString):
#     """ Immutable version of SanskritString
#     """
#     def __init__(self, thing=None, encoding=None, unicode_encoding='utf-8'):
#         super().__init__(thing, encoding, unicode_encoding)
# 
#     def __hash__(self):
#         return hash(str(self))
# 
#     def __eq__(self, other):
#         return str(self) == str(other)
# 
#     def __ne__(self, other):
#         return str(self) != str(other)
# 
# SLP1 = sanscript.SLP1
# 
# Path: sanskrit_parser/generator/paninian_object.py
# class PaninianObject(SanskritObject):
#     """ Paninian Object Class: Derived From SanskritObject
# 
#     Attributes:
#     """
#     def __init__(self, thing=None, encoding=None, unicode_encoding='utf-8',
#                  strict_io=True, replace_ending_visarga='s'):
#         super().__init__(thing, encoding, unicode_encoding, strict_io,
#                          replace_ending_visarga)
#         self.inPrakriya = True
#         # FIXME: I don't like this being here
#         self.disabled_sutras = []
#         # Prakriya Related Tags are ephemeral
# 
#     def hasTag(self, t):
#         return t in self.tags
# 
#     def deleteTag(self, t):
#         return self.tags.remove(t)
# 
#     def setTag(self, t):
#         if t not in self.tags:
#             self.tags.append(t)
#         return t
# 
#     def fix(self):
#         self.inPrakriya = False
# 
#     def isPada(self):
#         return self.hasTag("pada")
# 
#     @classmethod
#     def join_objects(cls, objects):
#         logger.debug(f"Joining Objects {objects} {type(objects)}")
#         for o in objects[0]:
#             logger.debug(f"{o} type {type(o)}")
#             assert isinstance(o, SanskritObject), f"{o} type {type(o)}"
#         s = "".join([o.canonical() for o in objects[0]])
#         so = PaninianObject(s, encoding=SLP1)
#         # Tag rules
#         # 1.4.14 suptiNantaM padam
#         if objects[0][-1].hasTag("sup") or objects[0][-1].hasTag("tiN"):
#             so.setTag("pada")
#         # 1.4.13 yasmAtpratyayaviDistadAdipratyayeNgam
#         elif objects[0][0].hasTag("aNga"):
#             so.setTag("aNga")
#         # 3.1.32 sannAdyantA dhAtavaH
#         if objects[0][-1].hasTag("sannAdi"):
#             so.setTag("DAtu")
#         # 1.2.46 krttaDitasamAsAsca
#         if objects[0][-1].hasTag("krt") or objects[0][-1].hasTag("tadDita"):
#             so.setTag("prAtipadika")
# 
#         # Custom tag propagation for rule implementation
#         for t in ["eti", "eDati", "UW", "sTA", "sTamB"]:
#             if objects[0][0].hasTag(t) and objects[0][0].hasTag("DAtu"):
#                 so.setTag(t)
#         for t in ["AN"]:
#             if objects[0][0].hasTag(t) and objects[0][0].hasTag("upasarga"):
#                 so.setTag(t)
#         for t in ["trc", "trn"]:
#             if objects[0][-1].hasTag(t) and objects[0][0].hasTag("aNga"):
#                 so.setTag(t)
#         for t in ["NI", "Ap", 'strI_abs']:
#             if objects[0][-1].hasTag(t):
#                 so.setTag("strI")
#                 so.setTag(t)
#                 for tt in objects[0][0].tags:
#                     so.setTag(tt)
#                 if so.hasTag("pum"):
#                     so.deleteTag("pum")
#                 if so.hasTag("napum"):
#                     so.deleteTag("napum")
#         return so


from sanskrit_parser.base.sanskrit_base import SanskritImmutableString, SLP1
from decimal import Decimal
from copy import deepcopy
from sanskrit_parser.generator.paninian_object import PaninianObject
import logging
        rs2 = deepcopy(s2)
        if self.xform is not None:
            env = _env(s1, s2)
            ret = self.xform(env)
            rs1.update(ret[0], SLP1)
            rs2.update(ret[1], SLP1)
        return rs1, rs2

    def insert(self, s1, s2):
        if self.insertx is not None:
            env = _env(s1, s2)
            itx = self.insertx(env)
            r = [s1, s2]
            for i in itx:
                if not isinstance(itx[i], PaninianObject):
                    assert isinstance(itx[i], str)
                    itx[i] = PaninianObject(itx[i])
                r.insert(i, itx[i])
            logger.debug(f"After insertion {r}")
            return r
        else:
            return(s1, s2)


def _env(s1, s2):
    # Helper function to define execution environment
    env = {}
    env["lp"] = s1
    env["rp"] = s2
    if s1.canonical() == "":

# Path: sanskrit_parser/base/sanskrit_base.py
# class SanskritImmutableString(SanskritString):
#     """ Immutable version of SanskritString
#     """
#     def __init__(self, thing=None, encoding=None, unicode_encoding='utf-8'):
#         super().__init__(thing, encoding, unicode_encoding)
# 
#     def __hash__(self):
#         return hash(str(self))
# 
#     def __eq__(self, other):
#         return str(self) == str(other)
# 
#     def __ne__(self, other):
#         return str(self) != str(other)
# 
# SLP1 = sanscript.SLP1
# 
# Path: sanskrit_parser/generator/paninian_object.py
# class PaninianObject(SanskritObject):
#     """ Paninian Object Class: Derived From SanskritObject
# 
#     Attributes:
#     """
#     def __init__(self, thing=None, encoding=None, unicode_encoding='utf-8',
#                  strict_io=True, replace_ending_visarga='s'):
#         super().__init__(thing, encoding, unicode_encoding, strict_io,
#                          replace_ending_visarga)
#         self.inPrakriya = True
#         # FIXME: I don't like this being here
#         self.disabled_sutras = []
#         # Prakriya Related Tags are ephemeral
# 
#     def hasTag(self, t):
#         return t in self.tags
# 
#     def deleteTag(self, t):
#         return self.tags.remove(t)
# 
#     def setTag(self, t):
#         if t not in self.tags:
#             self.tags.append(t)
#         return t
# 
#     def fix(self):
#         self.inPrakriya = False
# 
#     def isPada(self):
#         return self.hasTag("pada")
# 
#     @classmethod
#     def join_objects(cls, objects):
#         logger.debug(f"Joining Objects {objects} {type(objects)}")
#         for o in objects[0]:
#             logger.debug(f"{o} type {type(o)}")
#             assert isinstance(o, SanskritObject), f"{o} type {type(o)}"
#         s = "".join([o.canonical() for o in objects[0]])
#         so = PaninianObject(s, encoding=SLP1)
#         # Tag rules
#         # 1.4.14 suptiNantaM padam
#         if objects[0][-1].hasTag("sup") or objects[0][-1].hasTag("tiN"):
#             so.setTag("pada")
#         # 1.4.13 yasmAtpratyayaviDistadAdipratyayeNgam
#         elif objects[0][0].hasTag("aNga"):
#             so.setTag("aNga")
#         # 3.1.32 sannAdyantA dhAtavaH
#         if objects[0][-1].hasTag("sannAdi"):
#             so.setTag("DAtu")
#         # 1.2.46 krttaDitasamAsAsca
#         if objects[0][-1].hasTag("krt") or objects[0][-1].hasTag("tadDita"):
#             so.setTag("prAtipadika")
# 
#         # Custom tag propagation for rule implementation
#         for t in ["eti", "eDati", "UW", "sTA", "sTamB"]:
#             if objects[0][0].hasTag(t) and objects[0][0].hasTag("DAtu"):
#                 so.setTag(t)
#         for t in ["AN"]:
#             if objects[0][0].hasTag(t) and objects[0][0].hasTag("upasarga"):
#                 so.setTag(t)
#         for t in ["trc", "trn"]:
#             if objects[0][-1].hasTag(t) and objects[0][0].hasTag("aNga"):
#                 so.setTag(t)
#         for t in ["NI", "Ap", 'strI_abs']:
#             if objects[0][-1].hasTag(t):
#                 so.setTag("strI")
#                 so.setTag(t)
#                 for tt in objects[0][0].tags:
#                     so.setTag(tt)
#                 if so.hasTag("pum"):
#                     so.deleteTag("pum")
#                 if so.hasTag("napum"):
#                     so.deleteTag("napum")
#         return so


# Path: sanskrit_parser/generator/sutra.py
from sanskrit_parser.base.sanskrit_base import SanskritImmutableString, SLP1
from decimal import Decimal
from copy import deepcopy
from sanskrit_parser.generator.paninian_object import PaninianObject
import logging

        rs2 = deepcopy(s2)
        if self.xform is not None:
            env = _env(s1, s2)
            ret = self.xform(env)
            rs1.update(ret[0], SLP1)
            rs2.update(ret[1], SLP1)
        return rs1, rs2

    def insert(self, s1, s2):
        if self.insertx is not None:
            env = _env(s1, s2)
            itx = self.insertx(env)
            r = [s1, s2]
            for i in itx:
                if not isinstance(itx[i], PaninianObject):
                    assert isinstance(itx[i], str)
                    itx[i] = PaninianObject(itx[i])
                r.insert(i, itx[i])
            logger.debug(f"After insertion {r}")
            return r
        else:
            return(s1, s2)


def _env(s1, s2):
    # Helper function to define execution environment
    env = {}
    env["lp"] = s1
    env["rp"] = s2
    if s1.canonical() == "":

        env["l"] = SanskritImmutableString("")