def rewrite_arbitrary_arity_and_or(syn_ctx, sol): import functools apps = exprs.find_all_applications(sol, 'and') for app in apps: if len(app.children) == 2: continue elif len(app.children) == 1: new_app = syn_ctx.make_function_expr('and', app.children[0], app.children[0]) else: new_app = functools.reduce( lambda a, b: syn_ctx.make_function_expr('and', a, b), app.children) sol = exprs.substitute(sol, app, new_app) new_apps = exprs.find_all_applications(sol, 'and') assert all([len(new_app.children) == 2 for new_app in new_apps]) apps = exprs.find_all_applications(sol, 'or') for app in apps: if len(app.children) == 2: continue elif len(app.children) == 1: new_app = syn_ctx.make_function_expr('or', app.children[0], app.children[0]) else: new_app = functools.reduce( lambda a, b: syn_ctx.make_function_expr('or', a, b), app.children) sol = exprs.substitute(sol, app, new_app) new_apps = exprs.find_all_applications(sol, 'or') assert all([len(new_app.children) == 2 for new_app in new_apps]) return sol
def get_applications(self): applications = {} for sf in self.synth_funs: sf_name = sf.function_name apps = exprs.find_all_applications(self.spec_expr, sf_name) applications[sf] = apps return applications
def apply(constraints, uf_instantiator, syn_ctx): import random conds = [] all_apps = set() for uf_name, uf_info in uf_instantiator.get_functions().items(): uf_apps = set() for c in constraints: uf_apps |= set(exprs.find_all_applications(c, uf_name)) all_apps |= uf_apps while len(uf_apps) > 0: uf_app1 = uf_apps.pop() for uf_app2 in uf_apps: app1_args, app2_args = uf_app1.children, uf_app2.children args_eq_expr = [ syn_ctx.make_function_expr('=', a1, a2) for (a1, a2) in zip(app1_args, app2_args) ] output_neq_expr = syn_ctx.make_function_expr( 'ne', uf_app1, uf_app2) cond = syn_ctx.make_function_expr('and', output_neq_expr, *args_eq_expr) conds.append(cond) if len(conds) > 0: constraints = [ syn_ctx.make_function_expr('or', *conds, constraint) for constraint in constraints ] for app in sorted(all_apps, key=exprs.get_expression_size): var = syn_ctx.make_variable_expr( app.function_info.range_type, 'ufcall_' + app.function_info.function_name + '_' + str(random.randint(1, 1000000))) constraints = [ exprs.substitute(constraint, app, var) for constraint in constraints ] return constraints
def decompose(self, macro_instantiator): start_nt = self.start reverse_mapping = [] term_productions = [] pred_productions = [] for rewrite in self.rules[start_nt]: ph_vars, nts, orig_expr_template = rewrite.to_template_expr() ph_var_nt_map = dict(zip(ph_vars, nts)) expr_template = macro_instantiator.instantiate_all( orig_expr_template) ifs = exprs.find_all_applications(expr_template, 'ite') # Either there are no ifs or it is an concrete expression if len(ifs) == 0 or len(nts) == 0: term_productions.append(rewrite) continue elif len(ifs) > 1 and ifs[0] != expr_template: return None [cond, thent, elset] = ifs[0].children cond_ph_vars = exprs.get_all_variables(cond) & set(ph_vars) then_ph_vars = exprs.get_all_variables(thent) & set(ph_vars) else_ph_vars = exprs.get_all_variables(elset) & set(ph_vars) if (len(cond_ph_vars & then_ph_vars) > 0 or len(cond_ph_vars & else_ph_vars) > 0 or len(else_ph_vars & then_ph_vars) > 0): return None if ( thent not in ph_vars or \ elset not in ph_vars or \ ph_var_nt_map[thent] != start_nt or \ ph_var_nt_map[elset] != start_nt): return None cond_rewrite = expr_template_to_rewrite(cond, ph_var_nt_map, self) # Make dummy function to recognize predicate arg_var = exprs.VariableExpression( exprs.VariableInfo(exprtypes.BoolType(), 'd', 0)) dummy_macro_func = semantics_types.MacroFunction( 'dummy_pred_id_' + str(random.randint(1, 1000000)), 1, (exprtypes.BoolType(), ), exprtypes.BoolType(), arg_var, [arg_var]) pred_production = FunctionRewrite(dummy_macro_func, cond_rewrite) pred_productions.append(pred_production) reverse_mapping.append( (dummy_macro_func, cond, orig_expr_template, expr_template)) if len(pred_productions) == 0: return None # Non-terminals [term_start, pred_start] = [x + start_nt for x in ['Term', 'Pred']] [term_nts, pred_nts ] = [self.non_terminals + [x] for x in [term_start, pred_start]] term_nts.remove(start_nt) pred_nts.remove(start_nt) # Non-terminal types term_nt_type, pred_nt_type = self.nt_type.copy(), self.nt_type.copy() term_nt_type.pop(start_nt) term_nt_type[term_start] = self.nt_type[start_nt] pred_nt_type.pop(start_nt) pred_nt_type[pred_start] = exprtypes.BoolType() # Rules term_rules = {} term_rules[term_start] = [ rew.rename_nt(start_nt, term_start) for rew in term_productions ] for nt in self.non_terminals: if nt != start_nt: term_rules[nt] = [ rew.rename_nt(start_nt, term_start) for rew in self.rules[nt] ] pred_rules = {} pred_rules[pred_start] = [ rew.rename_nt(start_nt, term_start) for rew in pred_productions ] for nt in self.non_terminals: if nt != start_nt: pred_rules[nt] = [ rew.rename_nt(start_nt, term_start) for rew in self.rules[nt] ] # pred_rules[term_start] = term_rules[term_start] # pred_nt_type[term_start] = term_nt_type[term_start] pred_rules = {**term_rules, **pred_rules} pred_nt_type = {**term_nt_type, **pred_nt_type} term_grammar = Grammar(term_nts, term_nt_type, term_rules, term_start) pred_grammar = Grammar(pred_nts + [term_start], pred_nt_type, pred_rules, pred_start) # print(pred_grammar) return term_grammar, pred_grammar, reverse_mapping