Пример #1
0
def test_different_constraints_on_commutative_operation():
    c1 = CustomConstraint(lambda x: len(str(x)) > 1)
    c2 = CustomConstraint(lambda x: len(str(x)) == 1)
    pattern1 = Pattern(f_c(x_), c1)
    pattern2 = Pattern(f_c(x_), c2)
    pattern3 = Pattern(f_c(x_, b), c1)
    pattern4 = Pattern(f_c(x_, b), c2)
    matcher = ManyToOneMatcher(pattern1, pattern2, pattern3, pattern4)

    subject = f_c(a)
    results = list(matcher.match(subject))
    assert len(results) == 1
    assert results[0][0] == pattern2
    assert results[0][1] == {'x': a}

    subject = f_c(Symbol('longer'), b)
    results = sorted(matcher.match(subject))
    assert len(results) == 1
    assert results[0][0] == pattern3
    assert results[0][1] == {'x': Symbol('longer')}

    subject = f_c(a, b)
    results = list(matcher.match(subject))
    assert len(results) == 1
    assert results[0][0] == pattern4
    assert results[0][1] == {'x': a}
Пример #2
0
def test_add_duplicate_pattern():
    pattern = Pattern(f(a))
    matcher = ManyToOneMatcher()

    matcher.add(pattern)
    matcher.add(pattern)

    assert len(matcher.patterns) == 1
Пример #3
0
def test_add_duplicate_pattern_with_different_constraint():
    pattern1 = Pattern(f(a))
    pattern2 = Pattern(f(a), MockConstraint(False))
    matcher = ManyToOneMatcher()

    matcher.add(pattern1)
    matcher.add(pattern2)

    assert len(matcher.patterns) == 2
Пример #4
0
def test_different_constraints_no_match_on_operation():
    c1 = CustomConstraint(lambda x: x == a)
    c2 = CustomConstraint(lambda x: x == b)
    pattern1 = Pattern(f(x_), c1)
    pattern2 = Pattern(f(x_), c2)
    matcher = ManyToOneMatcher(pattern1, pattern2)

    subject = f(c)
    results = list(matcher.match(subject))
    assert len(results) == 0
Пример #5
0
def test_same_pattern_different_label():
    pattern = Pattern(a)
    matcher = ManyToOneMatcher()
    matcher.add(pattern, 42)
    matcher.add(pattern, 23)

    result = sorted(
        (l, sorted(map(tuple, s.items()))) for l, s in matcher.match(a))

    assert result == [(23, []), (42, [])]
Пример #6
0
def test_same_commutative_but_different_pattern():
    pattern1 = Pattern(f(f_c(x_), a))
    pattern2 = Pattern(f(f_c(x_), b))
    matcher = ManyToOneMatcher(pattern1, pattern2)

    subject = f(f_c(a), a)
    result = list(matcher.match(subject))
    assert result == [(pattern1, {'x': a})]

    subject = f(f_c(a), b)
    result = list(matcher.match(subject))
    assert result == [(pattern2, {'x': a})]
Пример #7
0
def match_many_to_one(expression, *patterns):
    try:
        pattern = patterns[0]
        commutative = next(
            p for p in preorder_iter(pattern.expression) if isinstance(p, CommutativeOperation)
        )
        next(wc for wc in preorder_iter(commutative) if isinstance(wc, Wildcard) and wc.min_count > 1)
    except StopIteration:
        pass
    else:
        pytest.xfail('Matcher does not support fixed wildcards with length != 1 in commutative operations')
    matcher = ManyToOneMatcher(*patterns)
    for _, substitution in matcher.match(expression):
        yield substitution
Пример #8
0
def test_code_generation_many_to_one(subject, patterns):
    patterns = [Pattern(p) for p in patterns]
    matcher = ManyToOneMatcher(*patterns)

    generator = CodeGenerator(matcher)
    gc, code = generator.generate_code()
    code = GENERATED_TEMPLATE.format(gc, code)
    compiled = compile(code, '', 'exec')
    module = ModuleType('generated_code')
    print('=' * 80)
    print(code)
    print('=' * 80)
    exec(compiled, module.__dict__)

    for pattern in patterns:
        print(pattern)

    matches = list(module.match_root(subject))

    for i, pattern in enumerate(patterns):
        expected_matches = PARAM_MATCHES[subject, pattern.expression]
        for expected_match in expected_matches:
            assert (
                i, expected_match
            ) in matches, "Subject {!s} and pattern {!s} did not yield the match {!s} but were supposed to".format(
                subject, pattern, expected_match)
            while (i, expected_match) in matches:
                matches.remove((i, expected_match))

    assert matches == [], "Subject {!s} and pattern {!s} yielded unexpected matches".format(
        subject, pattern)
Пример #9
0
def test_many_to_one(subject, patterns):
    patterns = [Pattern(p) for p in patterns]
    matcher = ManyToOneMatcher(*patterns)
    matches = list(matcher.match(subject))

    for pattern in patterns:
        expected_matches = PARAM_MATCHES[subject, pattern.expression]
        for expected_match in expected_matches:
            assert (
                pattern, expected_match
            ) in matches, "Subject {!s} and pattern {!s} did not yield the match {!s} but were supposed to".format(
                subject, pattern, expected_match)
            while (pattern, expected_match) in matches:
                matches.remove((pattern, expected_match))

    assert matches == [], "Subject {!s} and pattern {!s} yielded unexpected matches".format(
        subject, pattern)
Пример #10
0
def test_grouped():
    pattern1 = Pattern(a, MockConstraint(True))
    pattern2 = Pattern(a, MockConstraint(True))
    pattern3 = Pattern(x_, MockConstraint(True))
    matcher = ManyToOneMatcher(pattern1, pattern2, pattern3)

    result = [[p for p, _ in ps] for ps in matcher.match(a).grouped()]

    assert len(result) == 2
    for res in result:
        if len(res) == 2:
            assert pattern1 in res
            assert pattern2 in res
        elif len(res) == 1:
            assert pattern3 in res
        else:
            assert False, "Wrong number of grouped matches"
Пример #11
0
def test_different_pattern_same_constraint(c1, c2):
    constr1 = CustomConstraint(lambda x: c1)
    constr2 = CustomConstraint(lambda x: c2)
    constr3 = CustomConstraint(lambda x: True)
    patterns = [
        Pattern(f2(x_, a), constr3),
        Pattern(f(a, a, x_), constr3),
        Pattern(f(a, x_), constr1),
        Pattern(f(x_, a), constr2),
        Pattern(f(a, x_, b), constr1),
        Pattern(f(x_, a, b), constr1),
    ]
    subject = f(a, a)

    matcher = ManyToOneMatcher(*patterns)
    results = list(matcher.match(subject))

    assert len(results) == int(c1) + int(c2)
Пример #12
0
def test_different_pattern_different_label():
    matcher = ManyToOneMatcher()
    matcher.add(Pattern(a), 42)
    matcher.add(Pattern(x_), 23)

    result = sorted(
        (l, sorted(map(tuple, s.items()))) for l, s in matcher.match(a))

    assert result == [(23, [('x', a)]), (42, [])]
Пример #13
0
def match_generated(expression, pattern):
    matcher = ManyToOneMatcher(pattern)
    generator = CodeGenerator(matcher)
    gc, code = generator.generate_code()
    code = GENERATED_TEMPLATE.format(gc, code)
    compiled = compile(code, '', 'exec')
    module = ModuleType("generated_code")
    print(code)
    exec(compiled, module.__dict__)
    for _, substitution in module.match_root(expression):
        yield substitution
Пример #14
0
def test_one_identity_optional_commutativity():
    Int = Operation.new('Int', Arity.binary)
    Add = Operation.new('+',
                        Arity.variadic,
                        'Add',
                        infix=True,
                        associative=True,
                        commutative=True,
                        one_identity=True)
    Mul = Operation.new('*',
                        Arity.variadic,
                        'Mul',
                        infix=True,
                        associative=True,
                        commutative=True,
                        one_identity=True)
    Pow = Operation.new('^', Arity.binary, 'Pow', infix=True)

    class Integer(Symbol):
        def __init__(self, value):
            super().__init__(str(value))

    i0 = Integer(0)
    i1 = Integer(1)
    i2 = Integer(2)

    x_, m_, a_ = map(Wildcard.dot, 'xma')
    x, m = map(Symbol, 'xm')
    a0_ = Wildcard.optional('a', i0)
    b1_ = Wildcard.optional('b', i1)
    c0_ = Wildcard.optional('c', i0)
    d1_ = Wildcard.optional('d', i1)
    m1_ = Wildcard.optional('m', i1)
    n1_ = Wildcard.optional('n', i1)

    pattern22 = Pattern(
        Int(
            Mul(Pow(Add(a0_, Mul(b1_, x_)), m1_),
                Pow(Add(c0_, Mul(d1_, x_)), n1_)), x_))
    pattern23 = Pattern(
        Int(
            Mul(Pow(Add(a_, Mul(b1_, x_)), m1_),
                Pow(Add(c0_, Mul(d1_, x_)), n1_)), x_))

    matcher = ManyToOneMatcher()
    matcher.add(pattern22, 22)
    matcher.add(pattern23, 23)

    subject = Int(Mul(Pow(Add(Mul(b, x), a), i2), Pow(x, i2)), x)

    result = sorted(
        (l, sorted(map(tuple, s.items()))) for l, s in matcher.match(subject))

    assert result == [
        (22, [('a', i0), ('b', i1), ('c', a), ('d', b), ('m', i2), ('n', i2),
              ('x', x)]),
        (22, [('a', a), ('b', b), ('c', i0), ('d', i1), ('m', i2), ('n', i2),
              ('x', x)]),
        (23, [('a', a), ('b', b), ('c', i0), ('d', i1), ('m', i2), ('n', i2),
              ('x', x)]),
    ]