#pragma once
#include<utility>
#include "ast/ast.h"
#include "util/hashtable.h"
#include "util/map.h"
#include "util/obj_pair_hashtable.h"
#include "util/ref_vector.h"
#include "util/vector.h"
#include "muz/rel/dl_base.h"
#include "muz/base/dl_context.h"
#include "muz/rel/dl_instruction.h"
namespace datalog {
class compiler {
typedef instruction::reg_idx reg_idx;
typedef hashtable<unsigned, u_hash, u_eq> int_set;
typedef u_map<unsigned> int2int;
typedef u_map<unsigned_vector> int2ints;
typedef obj_map<func_decl, reg_idx> pred2idx;
typedef unsigned_vector var_vector;
typedef ptr_vector<func_decl> func_decl_vector;
enum assembling_column_kind {
ACK_BOUND_VAR,
ACK_UNBOUND_VAR,
ACK_CONSTANT
};
struct assembling_column_info {
relation_sort domain; assembling_column_kind kind; union {
unsigned source_column; unsigned var_index; relation_element constant; };
};
class instruction_observer : public instruction_block::instruction_observer {
compiler & m_parent;
rule * m_current;
public:
instruction_observer(compiler & parent) : m_parent(parent), m_current(nullptr) {}
void start_rule(rule * r) { SASSERT(!m_current); m_current=r; }
void finish_rule() { m_current = nullptr; }
void notify(instruction * i) override {
if(m_current) {
i->set_accounting_parent_object(m_parent.m_context, m_current);
}
}
};
context & m_context;
rule_set const & m_rule_set;
instruction_block & m_top_level_code;
pred2idx m_pred_regs;
vector<relation_signature> m_reg_signatures;
obj_pair_map<sort, app, reg_idx> m_constant_registers;
obj_pair_map<sort, decl, reg_idx> m_total_registers;
obj_map<decl, reg_idx> m_empty_tables_registers;
instruction_observer m_instruction_observer;
expr_free_vars m_free_vars;
bool all_or_nothing_deltas() const { return m_context.all_or_nothing_deltas(); }
bool compile_with_widening() const { return m_context.compile_with_widening(); }
reg_idx get_fresh_register(const relation_signature & sig);
reg_idx get_register(const relation_signature & sig, bool reuse, reg_idx r);
reg_idx get_single_column_register(const relation_sort s);
void get_fresh_registers(const func_decl_set & preds, pred2idx & regs);
void make_join(reg_idx t1, reg_idx t2, const variable_intersection & vars, reg_idx & result,
bool reuse_t1, instruction_block & acc);
void make_min(reg_idx source, reg_idx & target, const unsigned_vector & group_by_cols,
unsigned min_col, instruction_block & acc);
void make_join_project(reg_idx t1, reg_idx t2, const variable_intersection & vars,
const unsigned_vector & removed_cols, reg_idx & result, bool reuse_t1, instruction_block & acc);
void make_filter_interpreted_and_project(reg_idx src, app_ref & cond,
const unsigned_vector & removed_cols, reg_idx & result, bool reuse, instruction_block & acc);
void make_select_equal_and_project(reg_idx src, const relation_element val, unsigned col,
reg_idx & result, bool reuse, instruction_block & acc);
void make_union(reg_idx src, reg_idx tgt, reg_idx delta, bool widening, instruction_block & acc);
void make_projection(reg_idx src, unsigned col_cnt, const unsigned * removed_cols,
reg_idx & result, bool reuse, instruction_block & acc);
void make_rename(reg_idx src, unsigned cycle_len, const unsigned * permutation_cycle,
reg_idx & result, bool reuse, instruction_block & acc);
void make_clone(reg_idx src, reg_idx & result, instruction_block & acc);
void make_assembling_code(rule* compiled_rule, func_decl* head_pred, reg_idx src, const svector<assembling_column_info> & acis0,
reg_idx & result, bool & dealloc, instruction_block & acc);
void make_dealloc_non_void(reg_idx r, instruction_block & acc);
void make_add_constant_column(func_decl* pred, reg_idx src, const relation_sort s, const relation_element val,
reg_idx & result, bool & dealloc, instruction_block & acc);
void make_add_unbound_column(rule* compiled_rule, unsigned col_idx, func_decl* pred, reg_idx src, const relation_sort& s, reg_idx & result,
bool & dealloc, instruction_block & acc);
void make_full_relation(func_decl* pred, const relation_signature & sig, reg_idx & result,
instruction_block & acc);
void add_unbound_columns_for_negation(rule* compiled_rule, func_decl* pred, reg_idx& single_res, expr_ref_vector& single_res_expr,
bool & dealloc, instruction_block& acc);
void make_duplicate_column(reg_idx src, unsigned col, reg_idx & result, bool reuse, instruction_block & acc);
void ensure_predicate_loaded(func_decl * pred, instruction_block & acc);
void get_local_indexes_for_projection(rule * r, unsigned_vector & res);
void get_local_indexes_for_projection(app * t, var_counter & globals, unsigned ofs,
unsigned_vector & res);
void compile_rule_evaluation_run(rule * r, reg_idx head_reg, const reg_idx * tail_regs,
reg_idx delta_reg, bool use_widening, instruction_block & acc);
void compile_rule_evaluation(rule * r, const pred2idx * input_deltas, reg_idx output_delta,
bool use_widening, instruction_block & acc);
void compile_preds(const func_decl_vector & head_preds, const func_decl_set & widened_preds,
const pred2idx * input_deltas, const pred2idx & output_deltas, instruction_block & acc);
void compile_preds_init(const func_decl_vector & head_preds, const func_decl_set & widened_preds,
const pred2idx * input_deltas, const pred2idx & output_deltas, instruction_block & acc);
void make_inloop_delta_transition(const pred2idx & global_head_deltas,
const pred2idx & global_tail_deltas, const pred2idx & local_deltas, instruction_block & acc);
void compile_loop(const func_decl_vector & head_preds, const func_decl_set & widened_preds,
const pred2idx & global_head_deltas, const pred2idx & global_tail_deltas,
const pred2idx & local_deltas, instruction_block & acc);
void compile_dependent_rules(const func_decl_set & head_preds,
const pred2idx * input_deltas, const pred2idx & output_deltas,
bool add_saturation_marks, instruction_block & acc);
void detect_chains(const func_decl_set & preds, func_decl_vector & ordered_preds,
func_decl_set & global_deltas);
bool is_nonrecursive_stratum(const func_decl_set & preds) const;
void compile_nonrecursive_stratum(const func_decl_set & preds,
const pred2idx * input_deltas, const pred2idx & output_deltas,
bool add_saturation_marks, instruction_block & acc);
void compile_strats(const rule_stratifier & stratifier,
const pred2idx * input_deltas, const pred2idx & output_deltas,
bool add_saturation_marks, instruction_block & acc);
bool all_saturated(const func_decl_set & preds) const;
void reset();
explicit compiler(context & ctx, rule_set const & rules, instruction_block & top_level_code)
: m_context(ctx),
m_rule_set(rules),
m_top_level_code(top_level_code),
m_instruction_observer(*this) {}
void do_compilation(instruction_block & execution_code,
instruction_block & termination_code);
public:
static void compile(context & ctx, rule_set const & rules, instruction_block & execution_code,
instruction_block & termination_code) {
compiler(ctx, rules, execution_code)
.do_compilation(execution_code, termination_code);
}
};
}