def test_pattern_match():

    r = match(assemble("$"), assemble("$"))
    assert r == {}

    r = match(assemble("($ . size)"), assemble("200"))
    assert r == {"size": assemble("200")}

    r = match(assemble("(: . size)"), assemble("200"))
    assert r == {"size": assemble("200")}

    r = match(assemble("($ . size)"), assemble("(I like cheese)"))
    assert r is None

    r = match(assemble("(: . size)"), assemble("(I like cheese)"))
    assert r == {"size": assemble("(I like cheese)")}

    r = match(assemble("(= (f (r (a))) ($ . pubkey))"),
              assemble("(= (f (r (a))) 50000)"))
    assert r == {"pubkey": assemble("50000")}

    r = match(assemble("(= (f (r (a))) ($ . pubkey1) ($ . pubkey2))"),
              assemble("(= (f (r (a))) 50000 60000)"))
    assert r == {"pubkey1": assemble("50000"), "pubkey2": assemble("60000")}

    r = match(assemble("(= (f (r (a))) ($ . pubkey1) ($ . pubkey1))"),
              assemble("(= (f (r (a))) 50000 60000)"))
    assert r is None

    r = match(assemble("(= (f (r (a))) ($ . pubkey1) ($ . pubkey1))"),
              assemble("(= (f (r (a))) 50000 50000)"))
    assert r == {"pubkey1": assemble("50000")}
예제 #2
0
def cons_optimizer(r, eval):
    """
    This applies the transform
    (f (c A B)) => A
    and
    (r (c A B)) => B
    """
    t1 = match(CONS_OPTIMIZER_PATTERN_FIRST, r)
    if t1:
        return t1["first"]
    t1 = match(CONS_OPTIMIZER_PATTERN_REST, r)
    if t1:
        return t1["rest"]
    return r
예제 #3
0
def var_change_optimizer_cons_eval(r, eval):
    """
    This applies the transform
    ((c (q (op SEXP1...)) (ARGS))) => (q RET_VAL) where ARGS != @
    via
    (op ((c SEXP1 (ARGS)) ...)) (ARGS)) and then "children_optimizer" of this.
    In some cases, this can result in a constant in some of the children.

    If we end up needing to push the "change of variables" to only one child, keep
    the optimization. Otherwise discard it.
    """

    t1 = match(VAR_CHANGE_OPTIMIZER_CONS_EVAL_PATTERN, r)

    if t1 is None:
        return r

    original_args = t1["args"]

    if is_args_call(original_args):
        return r

    original_call = t1["sexp"]

    new_eval_sexp_args = sub_args(original_call, original_args)

    new_operands = list(new_eval_sexp_args.as_iter())
    opt_operands = [optimize_sexp(_, eval) for _ in new_operands]
    non_constant_count = sum(1 if _.listp() and _.first() != QUOTE_KW else 0
                             for _ in opt_operands)
    if non_constant_count < 1:
        final_sexp = r.to(opt_operands)
        return final_sexp
    return r
예제 #4
0
def cons_q_a_optimizer(r, eval):
    """
    This applies the transform
    (a (q . SEXP) @) => SEXP
    """
    t1 = match(CONS_Q_A_OPTIMIZER_PATTERN, r)
    if t1 and is_args_call(t1["args"]):
        return t1["sexp"]
    return r
예제 #5
0
def apply_null_optimizer(r, eval):
    """
    This applies the transform `(a 0 ARGS)` => `0`
    """
    t1 = match(APPLY_NULL_PATTERN_1, r)
    if t1 is not None:
        return r.to(0)

    return r
예제 #6
0
def quote_null_optimizer(r, eval):
    """
    This applies the transform `(q . 0)` => `0`
    """
    t1 = match(QUOTE_PATTERN_1, r)
    if t1 is not None:
        return r.to(0)

    return r
예제 #7
0
def path_optimizer(r, eval):
    """
    This applies the transform
    (f N) => A
    and
    (r N) => B
    """

    t1 = match(FIRST_ATOM_PATTERN, r)
    if t1 and non_nil(t1["atom"]):
        node = NodePath(t1["atom"].as_int())
        node = node + LEFT
        return r.to(node.as_short_path())

    t1 = match(REST_ATOM_PATTERN, r)
    if t1 and non_nil(t1["atom"]):
        node = NodePath(t1["atom"].as_int())
        node = node + RIGHT
        return r.to(node.as_short_path())
    return r
예제 #8
0
def path_optimizer(r, eval):
    """
    This applies the transform
    (a) => 1
    and
    (f N) => A
    and
    (r N) => B
    """
    if is_args_call(r):
        return r.to(1)

    t1 = match(FIRST_ATOM_PATTERN, r)
    if t1:
        node = NodePath(t1["atom"].as_int())
        node = node + LEFT
        return r.to(node.as_short_path())

    t1 = match(REST_ATOM_PATTERN, r)
    if t1:
        node = NodePath(t1["atom"].as_int())
        node = node + RIGHT
        return r.to(node.as_short_path())
    return r
예제 #9
0
def cons_r(args):
    t = match(CONS_PATTERN, args)
    if t:
        return t["rest"]
    return args.to([REST_KW, args])
예제 #10
0
def cons_f(args):
    t = match(CONS_PATTERN, args)
    if t:
        return t["first"]
    return args.to([FIRST_KW, args])