Skip to content

Commit e612e38

Browse files
committed
Use any primitive
Not sure if this is faster than a for loop. Also fix typing. Uses inplace update of unified var dicts
1 parent 718da31 commit e612e38

2 files changed

Lines changed: 31 additions & 25 deletions

File tree

src/arch/zx48k/peephole/pattern.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -69,22 +69,24 @@ class LinePattern(BasicLinePattern):
6969
push af
7070
and bounds $1 to 'af'
7171
Note that $$ matches against the $ sign
72+
73+
Returns whether the pattern matched (True) or not.
74+
If it matched, the vars_ dictionary will be updated with unified vars.
7275
"""
7376
__slots__ = 'line', 'vars', 're_pattern', 're', 'output'
7477

75-
def match(self, line: str, vars_: Optional[Dict[str, re.Pattern]] = None) -> Optional[Dict[str, re.Pattern]]:
78+
def match(self, line: str, vars_: Dict[str, str]) -> bool:
7679
match = self.re.match(line)
7780
if match is None:
78-
return None
81+
return False
7982

80-
vars__ = {'_%s' % k[1:]: v for k, v in (vars_ or {}).items()}
81-
for k, v in vars__.items():
82-
if match.groupdict().get(k, v) != v:
83-
return None
83+
vars__ = {'_' + k[1:]: v for k, v in (vars_ or {}).items()}
84+
mdict = match.groupdict()
85+
if any(mdict.get(k, v) != v for k, v in vars__.items()):
86+
return False
8487

85-
result = dict(vars_ or {})
86-
result.update({'$' + k[1:]: v for k, v in match.groupdict().items()})
87-
return result
88+
vars_.update({'$' + k[1:]: v for k, v in match.groupdict().items()})
89+
return True
8890

8991
def __repr__(self):
9092
return repr(self.re)
@@ -104,7 +106,7 @@ def __init__(self, lines: List[str]):
104106
def __len__(self):
105107
return len(self.lines)
106108

107-
def match(self, instructions: List[str], start: int = 0) -> Optional[Dict[str, re.Pattern]]:
109+
def match(self, instructions: List[str], start: int = 0) -> Optional[Dict[str, str]]:
108110
""" Given a list of instructions and a starting point,
109111
returns whether this pattern matches or not from such point
110112
onwards.
@@ -121,10 +123,9 @@ def match(self, instructions: List[str], start: int = 0) -> Optional[Dict[str, r
121123
if len(self) > len(lines):
122124
return None
123125

124-
univars: Optional[Dict[str, re.Pattern]] = {}
126+
univars: Dict[str, str] = {}
125127
for patt, line in zip(self.patterns, lines):
126-
univars = patt.match(line, vars_=univars)
127-
if univars is None:
128+
if not patt.match(line, vars_=univars):
128129
return None
129130

130131
return univars

tests/arch/zx48k/peephole/test_pattern.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import unittest
44

5+
from typing import Dict
6+
57
from src.arch.zx48k.peephole import pattern
68

79

@@ -38,35 +40,38 @@ def test_parse_comma_correctly(self):
3840

3941

4042
class TestLinePattern(unittest.TestCase):
43+
def setUp(self) -> None:
44+
self.vars: Dict[str, str] = {}
45+
4146
def test_matches_parsed(self):
4247
patt = pattern.LinePattern('push $1')
43-
match = patt.match('push af')
44-
self.assertEqual(match, {'$1': 'af'})
48+
self.assertTrue(patt.match('push af', self.vars))
49+
self.assertEqual({'$1': 'af'}, self.vars)
4550

4651
def test_no_match(self):
4752
patt = pattern.LinePattern('push $1')
48-
match = patt.match('pop af')
49-
self.assertIsNone(match)
53+
self.assertFalse(patt.match('pop af', self.vars))
54+
self.assertEqual({}, self.vars)
5055

5156
def test_double_match(self):
5257
patt = pattern.LinePattern('push $1 $1') # three spaces
53-
match = patt.match('push af af') # only two spaces
54-
self.assertEqual(match, {'$1': 'af'})
58+
self.assertTrue(patt.match('push af af', self.vars)) # only two spaces
59+
self.assertEqual({'$1': 'af'}, self.vars)
5560

5661
def test_match_two_patterns(self):
5762
patt = pattern.LinePattern('$2 $1')
58-
match = patt.match('push af')
59-
self.assertEqual(match, {'$1': 'af', '$2': 'push'})
63+
self.assertTrue(patt.match('push af', self.vars))
64+
self.assertEqual({'$1': 'af', '$2': 'push'}, self.vars)
6065

6166
def test_match_two_patterns_twice(self):
6267
patt = pattern.LinePattern('$2 $1 $2 $1')
63-
match = patt.match('push af push af')
64-
self.assertEqual(match, {'$1': 'af', '$2': 'push'})
68+
self.assertTrue(patt.match('push af push af', self.vars))
69+
self.assertEqual({'$1': 'af', '$2': 'push'}, self.vars)
6570

6671
def test_matches_empty_novars(self):
6772
patt = pattern.LinePattern('push af')
68-
match = patt.match('push af')
69-
self.assertEqual(match, {})
73+
self.assertTrue(patt.match('push af', self.vars))
74+
self.assertEqual({}, self.vars)
7075

7176

7277
class TestBlockPattern(unittest.TestCase):

0 commit comments

Comments
 (0)