environment decl_attributes::apply(environment env, io_state const & ios, name const & d) const { if (m_is_instance) { if (m_priority) { #if defined(__GNUC__) && !defined(__CLANG__) #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif env = add_instance(env, d, *m_priority, m_persistent); } else { env = add_instance(env, d, m_persistent); } } if (m_is_trans_instance) { if (m_priority) { #if defined(__GNUC__) && !defined(__CLANG__) #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif env = add_trans_instance(env, d, *m_priority, m_persistent); } else { env = add_trans_instance(env, d, m_persistent); } } if (m_is_coercion) env = add_coercion(env, ios, d, m_persistent); auto decl = env.find(d); if (decl && decl->is_definition()) { if (m_is_reducible) env = set_reducible(env, d, reducible_status::Reducible, m_persistent); if (m_is_irreducible) env = set_reducible(env, d, reducible_status::Irreducible, m_persistent); if (m_is_semireducible) env = set_reducible(env, d, reducible_status::Semireducible, m_persistent); if (m_is_quasireducible) env = set_reducible(env, d, reducible_status::Quasireducible, m_persistent); if (m_unfold_hint) env = add_unfold_hint(env, d, m_unfold_hint, m_persistent); if (m_unfold_full_hint) env = add_unfold_full_hint(env, d, m_persistent); } if (m_constructor_hint) env = add_constructor_hint(env, d, m_persistent); if (m_symm) env = add_symm(env, d, m_persistent); if (m_refl) env = add_refl(env, d, m_persistent); if (m_trans) env = add_trans(env, d, m_persistent); if (m_subst) env = add_subst(env, d, m_persistent); if (m_recursor) env = add_user_recursor(env, d, m_recursor_major_pos, m_persistent); if (m_is_class) env = add_class(env, d, m_persistent); if (m_rewrite) env = add_rewrite_rule(env, d, m_persistent); if (m_has_multiple_instances) env = mark_multiple_instances(env, d, m_persistent); return env; }
static std::unique_ptr<Observer> stack_observer(const Function& in, const Function& out, const Function& free) { // special state names std::string n_sink = "sink"; std::string n_make = "output was never input"; std::string n_dupl = "duplicate output"; std::string n_loss = "value loss"; std::string n_lifo = "no lifo"; std::string n_dfree = "double free"; // make states std::vector<std::unique_ptr<State>> states; states.push_back(mk_state(n_sink, false, false)); // ObsMake states.push_back(mk_state("u0", true, false)); states.push_back(mk_state("v0", true, false)); states.push_back(mk_state(n_make, false, true)); // ObsDupl states.push_back(mk_state("u1", true, false)); states.push_back(mk_state("v1", true, false)); states.push_back(mk_state("u2", false, false)); states.push_back(mk_state("v2", false, false)); states.push_back(mk_state("u3", false, false)); states.push_back(mk_state("v3", false, false)); states.push_back(mk_state(n_dupl, false, true)); // ObsLoss states.push_back(mk_state("u4", true, false)); states.push_back(mk_state("v4", true, false)); states.push_back(mk_state("u5", false, false)); states.push_back(mk_state("v5", false, false)); states.push_back(mk_state(n_loss, false, true)); // ObsLifo states.push_back(mk_state("u6", true, false)); states.push_back(mk_state("v6", true, false)); states.push_back(mk_state("u7", false, false)); states.push_back(mk_state("v7", false, false)); states.push_back(mk_state("u8", false, false)); states.push_back(mk_state("v8", false, false)); states.push_back(mk_state(n_lifo, false, true)); // ObsFree states.push_back(mk_state("u9", true, false)); states.push_back(mk_state("v9", true, false)); states.push_back(mk_state("u10", false, false)); states.push_back(mk_state("v10", false, false)); states.push_back(mk_state(n_dfree, false, true)); // get hold of the stats const State& sink = *states[0]; assert(sink.name() == n_sink); State& u0 = *states[1]; assert(u0.name() == "u0"); State& v0 = *states[2]; assert(v0.name() == "v0"); const State& f_make = *states[3]; assert(f_make.name() == n_make); State& u1 = *states[4]; assert(u1.name() == "u1"); State& v1 = *states[5]; assert(v1.name() == "v1"); State& u2 = *states[6]; assert(u2.name() == "u2"); State& v2 = *states[7]; assert(v2.name() == "v2"); State& u3 = *states[8]; assert(u3.name() == "u3"); State& v3 = *states[9]; assert(v3.name() == "v3"); const State& f_dupl = *states[10]; assert(f_dupl.name() == n_dupl); State& u4 = *states[11]; assert(u4.name() == "u4"); State& v4 = *states[12]; assert(v4.name() == "v4"); State& u5 = *states[13]; assert(u5.name() == "u5"); State& v5 = *states[14]; assert(v5.name() == "v5"); const State& f_loss = *states[15]; assert(f_loss.name() == n_loss); State& u6 = *states[16]; assert(u6.name() == "u6"); State& v6 = *states[17]; assert(v6.name() == "v6"); State& u7 = *states[18]; assert(u7.name() == "u7"); State& v7 = *states[19]; assert(v7.name() == "v7"); State& u8 = *states[20]; assert(u8.name() == "u8"); State& v8 = *states[21]; assert(v8.name() == "v8"); const State& f_lifo = *states[22]; assert(f_lifo.name() == n_lifo); State& u9 = *states[23]; assert(u9.name() == "u9"); State& v9 = *states[24]; assert(v9.name() == "v9"); State& u10 = *states[25]; assert(u10.name() == "u10"); State& v10 = *states[26]; assert(v10.name() == "v10"); const State& f_dfree = *states[27]; assert(f_dfree.name() == n_dfree); auto result = std::unique_ptr<Observer>(new Observer(std::move(states), 2)); // add transitions // ObsMake a = 0 [u*] add_trans(u0, f_make, out, 0); add_trans(u0, sink, in, 0); // ObsMake a = 1 [v*] add_trans(v0, f_make, out, 1); add_trans(v0, sink, in, 1); // ObsDupl a = 0 [u*] add_trans(u1, u2, in, 0); add_trans(u1, sink, out, 0); add_trans(u2, u3, out, 0); add_trans(u2, sink, in, 0); add_trans(u3, f_dupl, out, 0); add_trans(u3, sink, in, 0); // ObsDupl a = 1 [v*] add_trans(v1, v2, in, 1); add_trans(v1, sink, out, 1); add_trans(v2, v3, out, 1); add_trans(v2, sink, in, 1); add_trans(v3, f_dupl, out, 1); add_trans(v3, sink, in, 1); // ObsLoss a = 0 [u*] add_trans(u4, u5, in, 0); add_trans(u4, sink, out, 0); add_trans(u5, f_loss, out); add_trans(u5, sink, out, 0); // ObsLoss a = 1 [v*] add_trans(v4, v5, in, 1); add_trans(v4, sink, out, 1); add_trans(v5, f_loss, out); add_trans(v5, sink, out, 1); // ObsLifo a = 0, b = 1 add_trans(u6, u7, in, 0); add_trans(u6, sink, in, 1); add_trans(u6, sink, out, 0); add_trans(u6, sink, out, 1); add_trans(u7, u8, in, 1); add_trans(u7, sink, in, 0); add_trans(u7, sink, out, 0); add_trans(u7, sink, out, 1); add_trans(u8, f_lifo, out, 0); add_trans(u8, sink, out, 1); add_trans(u8, sink, in, 0); add_trans(u8, sink, in, 1); // ObsLifo a = 1, b = 0 add_trans(v6, v7, in, 1); add_trans(v6, sink, in, 0); add_trans(v6, sink, out, 1); add_trans(v6, sink, out, 0); add_trans(v7, v8, in, 0); add_trans(v7, sink, in, 1); add_trans(v7, sink, out, 1); add_trans(v7, sink, out, 0); add_trans(v8, f_lifo, out, 1); add_trans(v8, sink, out, 0); add_trans(v8, sink, in, 1); add_trans(v8, sink, in, 0); // ObsFree a = 0, b = 1 add_trans(u9, u10, free, 0); add_trans(u10, f_dfree, free, 0); // ObsFree a = 1, b = 0 add_trans(v9, v10, free, 1); add_trans(v10, f_dfree, free, 1); // make observer return result; }
/* Attempt to convert a CFG to a FSG. No heuristic simplifcation is performed * here. The conversion will only take place if all expansion rule in the * CFG takes one of the following form * * X -> w0 w1 ... wN Y * X -> w0 w1 ... wN * X -> Y * X -> w0 * X -> nil * * where X, Y are non-terminals, and w0, ..., wN are terminals. If the * conversion is not possible, _fsg is set to NULL and the function returns -1. */ void s3_cfg_convert_to_fsg(s3_cfg_t *_cfg,s2_fsg_t **_fsg) { hash_table_t *item2state=NULL; int num_states=1; /* let 0 be the end state */ int start_state=0; int from_state; int to_state; int i=0,j=0; s3_cfg_id_t id; s3u_vector_t *items=NULL; s3u_vector_t *rules=NULL; s3_cfg_item_t *item=NULL; s3_cfg_rule_t *rule=NULL; s2_fsg_t *fsg=NULL; char *word; item2state=hash_new(S3_CFG_NAME_HASH_SIZE,HASH_CASE_YES); if (item2state==NULL) goto cleanup; fsg=(s2_fsg_t*)ckd_calloc(1,sizeof(s2_fsg_t)); fsg->name=NULL; fsg->trans_list=NULL; items=&_cfg->item_info; for (i=s3u_vec_count(items)-1;i>=0;i--) { if ((item=s3u_vec_get(items,i))==NULL) goto cleanup; rules=&item->rules; if (!s3_cfg_is_terminal(item->id) && (item->nil_rule!=NULL || (rules!=NULL && s3u_vec_count(rules)>0))) hash_enter_bkey(item2state,&item->id,sizeof(s3_cfg_id_t),num_states++); } /* iterate through the CFG's expansion rules and convert them to FSG * transitions. If at any point the conversion fails, do some cleanup * and return. */ rules=&_cfg->rules; for (i=s3u_vec_count(rules)-1;i>=0;i--) { if ((rule=s3u_vec_get(rules,i))==NULL) goto cleanup; hash_lookup_bkey(item2state,&rule->src,sizeof(s3_cfg_id_t),&from_state); /* a NULL production rule means we transition to the end state */ if (rule->len==0) add_trans(fsg,from_state,0,rule->prob_score,NULL); else if (rule->len==1) { id=rule->products[0]; /* a single terminal means we output the terminal and transition to * the end state */ if (s3_cfg_is_terminal(id)) { word=((s3_cfg_item_t*)s3u_vec_get(items,s3_cfg_id2index(id)))->name; add_trans(fsg,from_state,0,rule->prob_score,word); } /* a single non-terminal means we take an epsilon transition */ else { hash_lookup_bkey(item2state,&id,sizeof(s3_cfg_id_t),&to_state); add_trans(fsg,from_state,to_state,rule->prob_score,NULL); } } else { for (j=1;j<rule->len;j++) { /* get the output for the transition */ id=rule->products[j-1]; if (!s3_cfg_is_terminal(id)) goto cleanup; word=((s3_cfg_item_t*)s3u_vec_get(items,s3_cfg_id2index(id)))->name; /* get the target state for the transition */ id=rule->products[j]; if (s3_cfg_is_terminal(id)) to_state=num_states++; else hash_lookup_bkey(item2state,&id,sizeof(s3_cfg_id_t),&to_state); add_trans(fsg,from_state,to_state,j==1?rule->prob_score:1.0,word); from_state=to_state; } } } *_fsg=fsg; return 0; cleanup: if (fsg!=NULL) free_fsg(fsg); return -1; }