desophos/idleon-saver

View on GitHub
idleon_saver/stencyl/common.py

Summary

Maintainability
A
0 mins
Test Coverage
from abc import ABC
from typing import Any, Dict, List

constants = {
    "n": None,
    "z": 0,
    "k": "NaN",
    "m": "-inf",
    "p": "inf",
    "t": True,
    "f": False,
}


class StencylData(ABC):
    def __init__(self, start: str, end: str, contents: Any):
        self.start = start
        self.end = end
        self.contents = contents

    def __str__(self):
        return str(self.unwrapped)

    @property
    def _contents_wrapped(self):
        return NotImplemented

    @property
    def unwrapped(self):
        return self.contents

    @property
    def wrapped(self):
        data = {
            "start": self.start,
            "contents": self._contents_wrapped,
        }
        if self.end:
            data["end"] = self.end
        return data


class StencylLiteral(StencylData):
    """All non-container Stencyl types."""

    def __init__(self, start: str, contents: Any):
        super().__init__(start, "", contents)

    @property
    def _contents_wrapped(self):
        # We need type data for literals to disambiguate floats and strings.
        # We dump floats as strings to preserve their exact representation
        # because json.dump doesn't respect float format.
        # TODO: reduce JSON clutter from constants
        return self.contents


class StencylFloat(StencylLiteral):
    def __init__(self, start: str, contents: str):
        super().__init__(start, contents)

    @property
    def unwrapped(self):
        return float(self.contents)


class StencylList(StencylData):
    """Stencyl types that can be represented by a list:
    array (a), list (l)"""

    def __init__(self, start: str, end: str, contents: List[StencylData]):
        super().__init__(start, end, contents)

    @property
    def _contents_wrapped(self) -> list:
        return [v.wrapped for v in self.contents]

    @property
    def unwrapped(self) -> list:
        return [v.unwrapped for v in self.contents]


class StencylDict(StencylData):
    """Stencyl types that can be represented by a dict:
    object (o), StringMap (b), IntMap (q), ObjectMap (M)"""

    def __init__(
        self, start: str, end: str, contents: Dict[StencylLiteral, StencylData]
    ):
        super().__init__(start, end, contents)

    @property
    def _contents_wrapped(self) -> dict:
        # dict keys are always literals so they can be unwrapped
        return {k.unwrapped: v.wrapped for k, v in self.contents.items()}

    @property
    def unwrapped(self) -> dict:
        return {k.unwrapped: v.unwrapped for k, v in self.contents.items()}