actual recursive unification for transforms

Still stops at the first solution but that's not too bad.
This commit is contained in:
Lephenixnoir 2021-12-26 10:40:52 +01:00
parent 71563fcf33
commit 3680b56765
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
3 changed files with 40 additions and 15 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
test/

14
Makefile Normal file
View File

@ -0,0 +1,14 @@
#! /usr/bin/env make -f
py = g35pe2_ml_patch.py
src = $(filter-out $(wildcard test/*-E2.g1a),$(wildcard test/*.g1a))
out = $(src:.g1a=-E2.g1a)
test: $(out)
test/%-E2.g1a: test/%.g1a $(py)
@echo -e "\n\e[33;1mPatching $<...\x1b[0m"
@ python $(py) $< $@
# Always redo all the tests
.PHONY: test

View File

@ -104,29 +104,39 @@ class Transform:
self.insn = [(make_pattern(p), make_pattern(repl))
for p, repl in patterns]
def match_transform_recursive(insn, vars, offsets, data, start, end):
if not insn:
return (vars, offsets)
p, repl = insn[0]
n = len(p.nibbles) // 2
insn = insn[1:]
# Try all matching offsets
for offset in range(start, end, 2):
d = data[offset:offset+n]
v = match_pattern(p, d, vars)
if v != False:
o = offsets + [offset]
v2, o2 = match_transform_recursive(insn, v, o, data, start, end)
if v2 != False:
# TODO: Yield here to explore all options
return (v2, o2)
return (False, [])
def match_transform(tr, base_vars, data, start, end):
"""Matches all instructions from <tr> in <data> between <start> and <end>,
returning either (False, []) or a pair (<vars>, [<offset>...])
indicating where instructions matched and with what variables."""
indicating where instructions matched and with what variables. Only the
first solution found to the unification problem is returned."""
start, end = align(start, end, 2)
vars = base_vars.copy()
offsets = []
for p, repl in tr.insn:
n = len(p.nibbles) // 2
for offset in range(start, end, 2):
d = data[offset:offset+n]
v = match_pattern(p, d, vars)
if v != False:
offsets.append(offset)
vars = v
break
else:
return (False, [])
return (vars, offsets)
return match_transform_recursive(tr.insn, vars, offsets, data, start, end)
def apply_transform(tr, vars, offsets, data):
"""Apply replacements from <tr> on <data> in-place, using the <offsets> and