semantic_configuration.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. from enum import *
  2. from dataclasses import *
  3. from typing import *
  4. import itertools
  5. class SemanticAspect:
  6. def __str__(self):
  7. # Override default: only print field, not the type (e.g. "TAKE_ONE" instead of "BigStepMaximality.TAKE_ONE")
  8. return self.name
  9. __repr__ = __str__
  10. class Maximality(SemanticAspect, Enum):
  11. TAKE_ONE = auto()
  12. SYNTACTIC = auto()
  13. TAKE_MANY = auto()
  14. # We define an ordering TAKE_ONE < SYNTACTIC < TAKE_MANY
  15. def __lt__(self, other):
  16. if self == other:
  17. return False
  18. if other == Maximality.TAKE_MANY:
  19. return True
  20. if other == Maximality.SYNTACTIC:
  21. return self == Maximality.TAKE_ONE
  22. return False
  23. def __le__(self, other):
  24. return self == other or self < other
  25. def __gt__(self, other):
  26. return not (self <= other)
  27. def __ge__(self, other):
  28. return not (self < other)
  29. class InternalEventLifeline(SemanticAspect, Enum):
  30. QUEUE = auto()
  31. NEXT_COMBO_STEP = auto()
  32. NEXT_SMALL_STEP = auto()
  33. REMAINDER = auto()
  34. SAME = auto()
  35. class InputEventLifeline(SemanticAspect, Enum):
  36. WHOLE = auto()
  37. FIRST_COMBO_STEP = auto()
  38. FIRST_SMALL_STEP = auto()
  39. class MemoryProtocol(SemanticAspect, Enum):
  40. BIG_STEP = auto()
  41. COMBO_STEP = auto()
  42. SMALL_STEP = auto()
  43. # NONE = auto()
  44. class HierarchicalPriority(SemanticAspect, Enum):
  45. NONE = auto()
  46. SOURCE_PARENT = auto()
  47. SOURCE_CHILD = auto()
  48. ARENA_PARENT = auto()
  49. ARENA_CHILD = auto()
  50. class OrthogonalPriority(SemanticAspect, Enum):
  51. NONE = auto()
  52. EXPLICIT = auto()
  53. class SameSourcePriority(SemanticAspect, Enum):
  54. NONE = auto()
  55. EXPLICIT = auto()
  56. class Concurrency(SemanticAspect, Enum):
  57. SINGLE = auto()
  58. MANY = auto()
  59. _T = TypeVar('_T', bound=SemanticAspect)
  60. SemanticChoice = Union[_T, List[_T]]
  61. @dataclass
  62. class SemanticConfiguration:
  63. # All semantic aspects and their default values.
  64. # Every field can be set to a list of multiple options, or just a value.
  65. # The names of the fields of this class are used when parsing semantic options in the XML input format.
  66. # The following is the default configuration. Changing these values changes SCCD's default semantics:
  67. big_step_maximality: SemanticChoice[Maximality] = Maximality.TAKE_MANY
  68. combo_step_maximality: SemanticChoice[Maximality] = Maximality.TAKE_ONE
  69. internal_event_lifeline: SemanticChoice[InternalEventLifeline] = InternalEventLifeline.NEXT_COMBO_STEP
  70. input_event_lifeline: SemanticChoice[InputEventLifeline] = InputEventLifeline.FIRST_COMBO_STEP
  71. enabledness_memory_protocol: SemanticChoice[MemoryProtocol] = MemoryProtocol.SMALL_STEP
  72. assignment_memory_protocol: SemanticChoice[MemoryProtocol] = MemoryProtocol.SMALL_STEP
  73. hierarchical_priority: SemanticChoice[HierarchicalPriority] = HierarchicalPriority.SOURCE_PARENT
  74. orthogonal_priority: SemanticChoice[OrthogonalPriority] = OrthogonalPriority.EXPLICIT
  75. same_source_priority: SemanticChoice[SameSourcePriority] = SameSourcePriority.EXPLICIT
  76. concurrency: SemanticChoice[Concurrency] = Concurrency.SINGLE
  77. def __str__(self):
  78. s = ""
  79. for f in fields(self):
  80. s += "\n %s: %s" % (f.name, getattr(self, f.name))
  81. return s
  82. @classmethod
  83. # def get_fields(cls) -> Iterator[Tuple[str, SemanticAspect]]:
  84. def get_fields(cls) -> Dict[str, SemanticAspect]:
  85. return {f.name: type(f.default) for f in fields(cls)}
  86. # Whether multiple options are set for any aspect.
  87. def has_multiple_variants(self) -> bool:
  88. for f in fields(self):
  89. if isinstance(getattr(self, f.name), list):
  90. return True
  91. return False
  92. # Get all possible combinations for aspects with multiple options (as a list) set.
  93. # Calling has_multiple_variants on resulting objects will return False.
  94. def generate_variants(self) -> List['SemanticConfiguration']:
  95. my_fields = fields(self)
  96. chosen_options = ([item] if not isinstance(item,list) else item for item in (getattr(self, f.name) for f in my_fields))
  97. variants = itertools.product(*chosen_options)
  98. return [SemanticConfiguration(**{f.name: o for f,o in zip(my_fields, variant)}) for variant in variants]