Build, and adjust if needed, a binary expression.
This has a similar purpose to dimb-make/adjust-expr-cast:
see that function's documentation first.
The same kind of incorrect grouping
(prevented by the use of dimb-make/adjust-expr-cast)
may arise with a binary expression
This function assumes that
A mismatch should be possible only if the sub-expression is a binary one, because the only decrease in priority during disambiguation can happen when the lower-priority expression is a binary one. We throw a hard error if that is not the case, which we expect to never happen.
If there is no mismatch, we just build the binary expression.
If only one sub-expression mismatches,
we perform the adjustment by moving up the sub-expression's operator
and redirecting one of its operands to the lowered operator.
For instance, consider the adjustment
from
* + / / A + ---> * C / / B C A B
where the
But note that, in the example above,
If both sub-expressions mismatch,
we compare the priorities of the two sub-expressions,
and we perform the adjustment as if only the lower-priority one mismatches.
For instance, consider
The case in which the two mismatching sub-expressions
have the same priority is handled in the same way as
when the right one has lower priority.
The reason for this asymmetry is that
all the binary operations involved are left-associative.
For instance, consider
Function:
(defun dimb-make/adjust-expr-binary (op arg1 arg2) (declare (xargs :guard (and (binopp op) (exprp arg1) (exprp arg2)))) (declare (xargs :guard (and (expr-unambp arg1) (expr-unambp arg2)))) (let ((__function__ 'dimb-make/adjust-expr-binary)) (declare (ignorable __function__)) (b* (((mv arg1-expected arg2-expected) (binop-expected-priorities op)) (arg1-actual (expr->priority arg1)) (arg2-actual (expr->priority arg2)) (arg1-mismatch (expr-priority-< arg1-actual arg1-expected)) (arg2-mismatch (expr-priority-< arg2-actual arg2-expected)) ((when (and arg1-mismatch (not (expr-case arg1 :binary)))) (raise "Internal error: ~ non-binary expression ~x0 ~ used as left argument of binary operator ~x1." (expr-fix arg1) (binop-fix op)) (expr-binary op arg1 arg2 nil)) ((when (and arg2-mismatch (not (expr-case arg2 :binary)))) (raise "Internal error: ~ non-binary expression ~x0 ~ used as right argument of binary operator ~x1." (expr-fix arg2) (binop-fix op)) (expr-binary op arg1 arg2 nil))) (cond ((and arg1-mismatch (or (not arg2-mismatch) (expr-priority-> arg1-actual arg2-actual))) (b* ((new-op (expr-binary->op arg1)) (new-arg1 (expr-binary->arg1 arg1)) (new-arg2 (dimb-make/adjust-expr-binary op (expr-binary->arg2 arg1) arg2))) (make-expr-binary :op new-op :arg1 new-arg1 :arg2 new-arg2 :info nil))) ((and arg2-mismatch (or (not arg1-mismatch) (expr-priority-<= arg1-actual arg2-actual))) (b* ((new-op (expr-binary->op arg2)) (new-arg1 (dimb-make/adjust-expr-binary op arg1 (expr-binary->arg1 arg2))) (new-arg2 (expr-binary->arg2 arg2))) (make-expr-binary :op new-op :arg1 new-arg1 :arg2 new-arg2 :info nil))) (t (make-expr-binary :op op :arg1 arg1 :arg2 arg2 :info nil))))))
Theorem:
(defthm exprp-of-dimb-make/adjust-expr-binary (b* ((expr (dimb-make/adjust-expr-binary op arg1 arg2))) (exprp expr)) :rule-classes :rewrite)
Theorem:
(defthm expr-unambp-of-dimb-make/adjust-expr-binary (implies (and (expr-unambp arg1) (expr-unambp arg2)) (b* ((?expr (dimb-make/adjust-expr-binary op arg1 arg2))) (expr-unambp expr))))
Theorem:
(defthm dimb-make/adjust-expr-binary-of-binop-fix-op (equal (dimb-make/adjust-expr-binary (binop-fix op) arg1 arg2) (dimb-make/adjust-expr-binary op arg1 arg2)))
Theorem:
(defthm dimb-make/adjust-expr-binary-binop-equiv-congruence-on-op (implies (binop-equiv op op-equiv) (equal (dimb-make/adjust-expr-binary op arg1 arg2) (dimb-make/adjust-expr-binary op-equiv arg1 arg2))) :rule-classes :congruence)
Theorem:
(defthm dimb-make/adjust-expr-binary-of-expr-fix-arg1 (equal (dimb-make/adjust-expr-binary op (expr-fix arg1) arg2) (dimb-make/adjust-expr-binary op arg1 arg2)))
Theorem:
(defthm dimb-make/adjust-expr-binary-expr-equiv-congruence-on-arg1 (implies (expr-equiv arg1 arg1-equiv) (equal (dimb-make/adjust-expr-binary op arg1 arg2) (dimb-make/adjust-expr-binary op arg1-equiv arg2))) :rule-classes :congruence)
Theorem:
(defthm dimb-make/adjust-expr-binary-of-expr-fix-arg2 (equal (dimb-make/adjust-expr-binary op arg1 (expr-fix arg2)) (dimb-make/adjust-expr-binary op arg1 arg2)))
Theorem:
(defthm dimb-make/adjust-expr-binary-expr-equiv-congruence-on-arg2 (implies (expr-equiv arg2 arg2-equiv) (equal (dimb-make/adjust-expr-binary op arg1 arg2) (dimb-make/adjust-expr-binary op arg1 arg2-equiv))) :rule-classes :congruence)