103 lines
2.9 KiB
Python
103 lines
2.9 KiB
Python
from emis_funky_funktions import *
|
|
|
|
from typing import Collection, Mapping, Sequence, Tuple, TypeAlias
|
|
|
|
import types_
|
|
from match_tree import LeafNode, IntNode, MatchTree, StructurePath, FAIL_NODE, EMPTY_STRUCT_PATH
|
|
|
|
Pattern: TypeAlias = 'NamePattern | IntPattern | SPattern | IgnorePattern'
|
|
|
|
@dataclass(frozen=True)
|
|
class NamePattern:
|
|
"""
|
|
A pattern which always succeeds to match, and binds a whole expression to a name
|
|
"""
|
|
name: str
|
|
|
|
def match_tree(self, location: StructurePath, success_leaf: 'MatchTree[A]') -> 'MatchTree[A]':
|
|
return success_leaf
|
|
|
|
def bindings(self) -> Collection[Tuple[str, StructurePath]]:
|
|
return ((self.name, EMPTY_STRUCT_PATH),)
|
|
|
|
def binds(self, var: str) -> bool:
|
|
"""
|
|
Test to see if this pattern binds a given variable
|
|
"""
|
|
return var == self.name
|
|
|
|
def __repr__(self) -> str:
|
|
return self.name
|
|
|
|
@dataclass(frozen=True)
|
|
class IgnorePattern:
|
|
"""
|
|
A pattern which always succeeds to match, but binds nothing
|
|
"""
|
|
|
|
def match_tree(self, location: StructurePath, success_leaf: 'MatchTree[A]') -> 'MatchTree[A]':
|
|
return success_leaf
|
|
|
|
def bindings(self) -> Collection[Tuple[str, StructurePath]]:
|
|
return tuple()
|
|
|
|
def binds(self, var: str) -> bool:
|
|
"""
|
|
Test to see if this pattern binds a given variable
|
|
|
|
For an `IgnorePattern` this is always false
|
|
"""
|
|
return False
|
|
|
|
def __repr__(self) -> str:
|
|
return '_'
|
|
|
|
@dataclass(frozen=True)
|
|
class IntPattern:
|
|
value: int
|
|
|
|
def match_tree(self, location: StructurePath, success_leaf: 'MatchTree[A]') -> 'MatchTree[A]':
|
|
return IntNode(location, {self.value: success_leaf}, LeafNode([]))
|
|
|
|
def bindings(self) -> Collection[Tuple[str, StructurePath]]:
|
|
return tuple()
|
|
|
|
def binds(self, var: str) -> bool:
|
|
"""
|
|
Test to see if this pattern binds a given variable
|
|
|
|
For an `IntPattern` this is always false
|
|
"""
|
|
return False
|
|
|
|
def __repr__(self) -> str:
|
|
return repr(self.value)
|
|
|
|
@dataclass(frozen=True)
|
|
class SPattern:
|
|
pred: Pattern
|
|
|
|
def match_tree(self, location: StructurePath, success_leaf: 'MatchTree[A]') -> 'MatchTree[A]':
|
|
match self.pred.match_tree(StructurePath((*location, 0)), success_leaf):
|
|
case IntNode(child_location, trees, fallback) as child:
|
|
# If the child check is also an int node on pred of our current location:
|
|
# "raise" that node to be at our current level.
|
|
if child_location == (*location, 0):
|
|
return IntNode(location, dict(((0, FAIL_NODE), *((1 + v, mt) for v, mt in trees.items()))), fallback)
|
|
else:
|
|
return IntNode(location, {0: FAIL_NODE}, child)
|
|
case child:
|
|
return IntNode(location, {0: FAIL_NODE}, child)
|
|
|
|
def bindings(self) -> Collection[Tuple[str, StructurePath]]:
|
|
# Prepend each binding path of the child pattern with 0 (i.e. subtract one from an int)
|
|
return tuple((name, StructurePath((0, *path))) for (name, path) in self.pred.bindings())
|
|
|
|
def binds(self, var: str) -> bool:
|
|
"""
|
|
Test to see if this pattern binds a given variable
|
|
"""
|
|
return self.pred.binds(var)
|
|
|
|
def __repr__(self) -> str:
|
|
return 'S ' + repr(self.pred) |