/* * Apply s to an offset equality x = y + offset */ static void subst_eq(substitution_t *s, offset_equality_t *e) { offset_pair_t aux1, aux2; aux1.var = e->lhs; aux1.delta = 0; subst_var(s, &aux1); aux2.var = e->rhs; aux2.delta = 0; subst_var(s, &aux2); e->lhs = aux1.var; e->rhs = aux2.var; e->offset -= aux1.delta; e->offset += aux2.delta; }
/* * Apply s to a monomial array mono * - store the result in buffer b */ static void subst_poly(substitution_t *s, poly_buffer_t *b, monomial_t *mono) { offset_pair_t aux; rational_t q; int32_t x; q_init(&q); reset_poly_buffer(b); x = mono->var; while (x != max_idx) { if (x == const_idx) { poly_buffer_add_const(b, &mono->coeff); } else { aux.var = x; aux.delta = 0; subst_var(s, &aux); // aux constains S[x] = y + delta // add a * y + a * delta to b if (aux.var > 0) { poly_buffer_add_monomial(b, aux.var, &mono->coeff); } q_set32(&q, aux.delta); poly_buffer_addmul_monomial(b, const_idx, &mono->coeff, &q); } mono ++; x = mono->var; } normalize_poly_buffer(b); q_clear(&q); }
Expr* subst(Expr* e, const Subst& sub) { switch (e->kind) { case id_expr: return e; case unit_term: return e; case true_term: return e; case false_term: return e; case if_term: return subst_ternary_term(as<If>(e), sub); case int_term: return e; case and_term: return subst_binary_term(as<And>(e), sub); case or_term: return subst_binary_term(as<Or>(e), sub); case equals_term: return subst_binary_term(as<Equals>(e), sub); case less_term: return subst_binary_term(as<Less>(e), sub); case not_term: return subst_unary_term(as<Not>(e), sub); case succ_term: return subst_unary_term(as<Succ>(e), sub); case pred_term: return subst_unary_term(as<Pred>(e), sub); case iszero_term: return subst_unary_term(as<Iszero>(e), sub); case var_term: return subst_var(as<Var>(e), sub); case abs_term: return subst_binary_term(as<Abs>(e), sub); case app_term: return subst_binary_term(as<App>(e), sub); case ref_term: return subst_ref(as<Ref>(e), sub); case mem_term: return subst_mem(as<Mem>(e), sub); case kind_type: return e; case unit_type: return e; case bool_type: return e; case nat_type: return e; case arrow_type: return e; case record_term: return e; default: break; } lang_unreachable(format("substitution into unkown term '{}'", node_name(e))); }