static void pgf_print_productions(GuMapItor* fn, const void* key, void* value, GuExn* err) { PgfPrintFn* clo = (PgfPrintFn*) fn; int fid = *((int *) key); PgfCCat* ccat = *((PgfCCat**) value); GuWriter *wtr = clo->wtr; if (!gu_seq_is_null(ccat->prods)) { size_t n_prods = gu_seq_length(ccat->prods); for (size_t i = 0; i < n_prods; i++) { PgfProduction prod = gu_seq_get(ccat->prods, PgfProduction, i); gu_printf(wtr,err," C%d -> ",fid); GuVariantInfo i = gu_variant_open(prod); switch (i.tag) { case PGF_PRODUCTION_APPLY: { PgfProductionApply* papp = i.data; gu_printf(wtr,err,"F%d[",papp->fun->funid); size_t n_args = gu_seq_length(papp->args); for (size_t j = 0; j < n_args; j++) { if (j > 0) gu_putc(',',wtr,err); PgfPArg arg = gu_seq_get(papp->args, PgfPArg, j); if (arg.hypos != NULL) { size_t n_hypos = gu_list_length(arg.hypos); for (size_t k = 0; k < n_hypos; k++) { if (k > 0) gu_putc(' ',wtr,err); PgfCCat *hypo = gu_list_index(arg.hypos, k); gu_printf(wtr,err,"C%d",hypo->fid); } } gu_printf(wtr,err,"C%d",arg.ccat->fid); } gu_printf(wtr,err,"]\n"); break; } case PGF_PRODUCTION_COERCE: { PgfProductionCoerce* pcoerce = i.data; gu_printf(wtr,err,"_[C%d]\n",pcoerce->coerce->fid); break; } default: gu_impossible(); } } } }
void pgf_print_symbol(PgfSymbol sym, GuWriter *wtr, GuExn *err) { switch (gu_variant_tag(sym)) { case PGF_SYMBOL_CAT: { PgfSymbolCat* scat = gu_variant_data(sym); gu_printf(wtr, err, "<%d,%d>", scat->d, scat->r); break; } case PGF_SYMBOL_KS: { PgfSymbolKS* sks = gu_variant_data(sym); pgf_print_tokens(sks->tokens, wtr, err); break; } case PGF_SYMBOL_KP: { PgfSymbolKP* skp = gu_variant_data(sym); gu_puts("pre {", wtr, err); pgf_print_tokens(skp->default_form, wtr, err); for (size_t i = 0; i < skp->n_forms; i++) { gu_puts("; ", wtr, err); pgf_print_tokens(skp->forms[i].form, wtr, err); gu_puts(" / ", wtr, err); size_t n_prefixes = gu_list_length(skp->forms[i].prefixes); for (size_t j = 0; j < n_prefixes; j++) { if (j > 0) gu_putc(' ', wtr, err); GuString prefix = gu_list_index(skp->forms[i].prefixes, j); gu_putc('"', wtr, err); gu_string_write(prefix, wtr, err); gu_putc('"', wtr, err); } } gu_puts("}", wtr, err); break; } case PGF_SYMBOL_LIT: { PgfSymbolLit *slit = gu_variant_data(sym); gu_printf(wtr, err, "{%d,%d}", slit->d, slit->r); break; } case PGF_SYMBOL_VAR: { PgfSymbolVar *svar = gu_variant_data(sym); gu_printf(wtr, err, "<%d,$%d>", svar->d, svar->r); break; } default: gu_impossible(); } }
static void pgf_metrics_lzn_expr_literal(PgfLinFuncs** funcs, PgfLiteral lit) { PgfMetricsLznState* state = gu_container(funcs, PgfMetricsLznState, funcs); GuVariantInfo i = gu_variant_open(lit); switch (i.tag) { case PGF_LITERAL_STR: { PgfLiteralStr* lstr = i.data; if (state->ps != NULL) { state->ps = pgf_parser_next_state(state->ps, lstr->val, state->pool); } state->pos++; break; } case PGF_LITERAL_INT: { PgfLiteralInt* lint = i.data; if (state->ps != NULL) { GuString tok = gu_format_string(state->pool, "%d", lint->val); state->ps = pgf_parser_next_state(state->ps, tok, state->pool); } state->pos++; break; } case PGF_LITERAL_FLT: { PgfLiteralFlt* lflt = i.data; if (state->ps != NULL) { GuString tok = gu_format_string(state->pool, "%f", lflt->val); state->ps = pgf_parser_next_state(state->ps, tok, state->pool); } state->pos++; break; } default: gu_impossible(); } }
static bool gu_map_lookup(GuMap* map, const void* key, size_t* idx_out) { size_t n = map->data.n_entries; switch (map->kind) { case GU_MAP_GENERIC: { GuHasher* hasher = map->hasher; GuEquality* eq = (GuEquality*) hasher; GuHash hash = hasher->hash(hasher, key); size_t idx = hash % n; size_t offset = (hash % (n - 2)) + 1; size_t key_size = map->key_size; while (true) { void* entry_key = &map->data.keys[idx * key_size]; if (gu_map_buf_is_zero(entry_key, key_size) && map->data.zero_idx != idx) { *idx_out = idx; return false; } else if (eq->is_equal(eq, key, entry_key)) { *idx_out = idx; return true; } idx = (idx + offset) % n; } gu_impossible(); break; } case GU_MAP_ADDR: { GuHash hash = (GuHash) key; size_t idx = hash % n; size_t offset = (hash % (n - 2)) + 1; while (true) { const void* entry_key = ((const void**)map->data.keys)[idx]; if (entry_key == NULL && map->data.zero_idx != idx) { *idx_out = idx; return false; } else if (entry_key == key) { *idx_out = idx; return true; } idx = (idx + offset) % n; } gu_impossible(); break; } case GU_MAP_WORD: { GuWord w = *(const GuWord*)key; GuHash hash = (GuHash) w; size_t idx = hash % n; size_t offset = (hash % (n - 2)) + 1; while (true) { GuWord entry_key = ((GuWord*)map->data.keys)[idx]; if (entry_key == 0 && map->data.zero_idx != idx) { *idx_out = idx; return false; } else if (entry_key == w) { *idx_out = idx; return true; } idx = (idx + offset) % n; } gu_impossible(); break; } case GU_MAP_STRING: { GuHasher* hasher = map->hasher; GuEquality* eq = (GuEquality*) hasher; GuHash hash = hasher->hash(hasher, key); size_t idx = hash % n; size_t offset = (hash % (n - 2)) + 1; while (true) { GuString entry_key = ((GuString*)map->data.keys)[idx]; if (entry_key == NULL && map->data.zero_idx != idx) { *idx_out = idx; return false; } else if (eq->is_equal(eq, key, entry_key)) { *idx_out = idx; return true; } idx = (idx + offset) % n; } gu_impossible(); break; } default: gu_impossible(); } gu_impossible(); return false; }
static void gu_map_resize(GuMap* map) { GuMapData* data = &map->data; GuMapData old_data = *data; size_t req_entries = gu_twin_prime_sup(GU_MAX(11, map->data.n_occupied * 4 / 3 + 1)); size_t key_size = map->key_size; size_t key_alloc = 0; data->keys = gu_mem_buf_alloc(req_entries * key_size, &key_alloc); size_t value_size = map->value_size; size_t value_alloc = 0; if (value_size) { data->values = gu_mem_buf_alloc(req_entries * value_size, &value_alloc); memset(data->values, 0, value_alloc); } data->n_entries = gu_twin_prime_inf(value_size ? GU_MIN(key_alloc / key_size, value_alloc / value_size) : key_alloc / key_size); switch (map->kind) { case GU_MAP_GENERIC: case GU_MAP_WORD: memset(data->keys, 0, key_alloc); break; case GU_MAP_ADDR: for (size_t i = 0; i < data->n_entries; i++) { ((const void**)data->keys)[i] = NULL; } break; case GU_MAP_STRING: for (size_t i = 0; i < data->n_entries; i++) { ((GuString*)data->keys)[i] = NULL; } break; default: gu_impossible(); } gu_assert(data->n_entries > data->n_occupied); data->n_occupied = 0; data->zero_idx = SIZE_MAX; for (size_t i = 0; i < old_data.n_entries; i++) { if (gu_map_entry_is_free(map, &old_data, i)) { continue; } void* old_key = &old_data.keys[i * key_size]; if (map->kind == GU_MAP_ADDR) { old_key = *(void**)old_key; } else if (map->kind == GU_MAP_STRING) { old_key = (void*) *(GuString*)old_key; } void* old_value = &old_data.values[i * value_size]; memcpy(gu_map_insert(map, old_key), old_value, map->value_size); } gu_mem_buf_free(old_data.keys); if (value_size) { gu_mem_buf_free(old_data.values); } }
PgfClosure* pgf_evaluate_expr_thunk(PgfReasoner* rs, PgfExprThunk* thunk) { PgfEnv* env = thunk->env; PgfExpr expr = thunk->expr; size_t n_args = 0; PgfClosure** args = NULL; PgfClosure* res = NULL; repeat:; GuVariantInfo ei = gu_variant_open(expr); switch (ei.tag) { case PGF_EXPR_ABS: { PgfExprAbs* eabs = ei.data; if (n_args > 0) { PgfEnv* new_env = gu_new(PgfEnv, rs->pool); new_env->next = env; new_env->closure = args[--n_args]; env = new_env; expr = eabs->body; goto repeat; } else { thunk->header.code = rs->eval_gates->evaluate_value_lambda; thunk->expr = eabs->body; res = &thunk->header; } break; } case PGF_EXPR_APP: { PgfExprApp* eapp = ei.data; PgfExprThunk* thunk = gu_new(PgfExprThunk, rs->pool); thunk->header.code = rs->eval_gates->evaluate_expr_thunk; thunk->env = env; thunk->expr = eapp->arg; if (n_args % PGF_ARGS_DELTA == 0) { args = realloc(args, n_args + PGF_ARGS_DELTA); } args[n_args++] = &thunk->header; expr = eapp->fun; goto repeat; } case PGF_EXPR_LIT: { PgfExprLit* elit = ei.data; PgfValueLit* val = (PgfValueLit*) thunk; val->header.code = rs->eval_gates->evaluate_value_lit; val->lit = elit->lit; res = &val->header; break; } case PGF_EXPR_META: { PgfExprMeta* emeta = ei.data; PgfValueMeta* val = gu_new(PgfValueMeta, rs->pool); val->header.code = rs->eval_gates->evaluate_meta; val->env = env; val->id = emeta->id; res = pgf_mk_pap(rs, &val->header, n_args, args); break; } case PGF_EXPR_FUN: { PgfExprFun* efun = ei.data; PgfAbsFun* absfun = gu_seq_binsearch(rs->abstract->funs, pgf_absfun_order, PgfAbsFun, efun->fun); gu_assert(absfun != NULL); if (absfun->closure.code != NULL) { res = pgf_mk_pap(rs, (PgfClosure*) &absfun->closure, n_args, args); } else { size_t arity = absfun->arity; if (n_args == arity) { PgfValue* val = gu_new_flex(rs->pool, PgfValue, args, arity); val->header.code = rs->eval_gates->evaluate_value; val->con = (PgfClosure*) &absfun->closure; for (size_t i = 0; i < arity; i++) { val->args[i] = args[--n_args]; } res = &val->header; } else { gu_assert(n_args < arity); PgfExprThunk* lambda = gu_new(PgfExprThunk, rs->pool); lambda->header.code = rs->eval_gates->evaluate_value_lambda; lambda->env = NULL; res = pgf_mk_pap(rs, &lambda->header, n_args, args); for (size_t i = 0; i < arity; i++) { PgfExpr new_expr, arg; PgfExprVar *evar = gu_new_variant(PGF_EXPR_VAR, PgfExprVar, &arg, rs->pool); evar->var = arity-i-1; PgfExprApp *eapp = gu_new_variant(PGF_EXPR_APP, PgfExprApp, &new_expr, rs->pool); eapp->fun = expr; eapp->arg = arg; expr = new_expr; } for (size_t i = 0; i < arity-1; i++) { PgfExpr new_expr; PgfExprAbs *eabs = gu_new_variant(PGF_EXPR_ABS, PgfExprAbs, &new_expr, rs->pool); eabs->bind_type = PGF_BIND_TYPE_EXPLICIT; eabs->id = "_"; eabs->body = expr; expr = new_expr; } lambda->expr = expr; } } break; } case PGF_EXPR_VAR: { PgfExprVar* evar = ei.data; PgfEnv* tmp_env = env; size_t i = evar->var; while (i > 0) { tmp_env = tmp_env->next; if (tmp_env == NULL) { GuExnData* err_data = gu_raise(rs->err, PgfExn); if (err_data) { err_data->data = "invalid de Bruijn index"; } return NULL; } i--; } res = pgf_mk_pap(rs, tmp_env->closure, n_args, args); break; } case PGF_EXPR_TYPED: { PgfExprTyped* etyped = ei.data; expr = etyped->expr; goto repeat; } case PGF_EXPR_IMPL_ARG: { PgfExprImplArg* eimpl = ei.data; expr = eimpl->expr; goto repeat; } default: gu_impossible(); } free(args); return res; }
static PgfExpr pgf_value2expr(PgfReasoner* rs, int level, PgfClosure* clos) { clos = rs->eval_gates->enter(rs, clos); if (clos == NULL) return gu_null_variant; PgfExpr expr = gu_null_variant; size_t n_args = 0; PgfClosure** args; if (clos->code == rs->eval_gates->evaluate_value) { PgfValue* val = (PgfValue*) clos; PgfAbsFun* absfun = gu_container(val->con, PgfAbsFun, closure); expr = absfun->ep.expr; n_args = absfun->arity; args = val->args; } else if (clos->code == rs->eval_gates->evaluate_value_lit) { PgfValueLit* val = (PgfValueLit*) clos; PgfExprLit *elit = gu_new_variant(PGF_EXPR_LIT, PgfExprLit, &expr, rs->out_pool); GuVariantInfo i = gu_variant_open(val->lit); switch (i.tag) { case PGF_LITERAL_STR: { PgfLiteralStr* lstr = i.data; PgfLiteralStr* new_lstr = gu_new_flex_variant(PGF_LITERAL_STR, PgfLiteralStr, val, strlen(lstr->val)+1, &elit->lit, rs->out_pool); strcpy(new_lstr->val, lstr->val); break; } case PGF_LITERAL_INT: { PgfLiteralInt* lint = i.data; PgfLiteralInt* new_lint = gu_new_variant(PGF_LITERAL_INT, PgfLiteralInt, &elit->lit, rs->out_pool); new_lint->val = lint->val; break; } case PGF_LITERAL_FLT: { PgfLiteralFlt* lflt = i.data; PgfLiteralFlt* new_lflt = gu_new_variant(PGF_LITERAL_FLT, PgfLiteralFlt, &elit->lit, rs->out_pool); new_lflt->val = lflt->val; break; } default: gu_impossible(); } } else if (clos->code == rs->eval_gates->evaluate_value_pap) { PgfValuePAP *pap = (PgfValuePAP*) clos; PgfValueGen* gen = gu_new(PgfValueGen, rs->pool); gen->header.code = rs->eval_gates->evaluate_gen; gen->level = level; size_t n_args = pap->n_args/sizeof(PgfClosure*); PgfValuePAP* new_pap = gu_new_flex(rs->pool, PgfValuePAP, args, n_args+1); new_pap->header.code = rs->eval_gates->evaluate_value_pap; new_pap->fun = pap->fun; new_pap->n_args = pap->n_args+sizeof(PgfClosure*); new_pap->args[0] = &gen->header; for (size_t i = 0; i < n_args; i++) { new_pap->args[i+1] = pap->args[i]; } PgfExprAbs *eabs = gu_new_variant(PGF_EXPR_ABS, PgfExprAbs, &expr, rs->out_pool); eabs->bind_type = PGF_BIND_TYPE_EXPLICIT; eabs->id = gu_format_string(rs->out_pool, "v%d", level); eabs->body = pgf_value2expr(rs, level+1, &new_pap->header); } else if (clos->code == rs->eval_gates->evaluate_value_const) { PgfValuePAP* val = (PgfValuePAP*) clos; if (val->fun->code == rs->eval_gates->evaluate_meta) { PgfValueMeta* fun = (PgfValueMeta*) val->fun; PgfExprMeta *emeta = gu_new_variant(PGF_EXPR_META, PgfExprMeta, &expr, rs->out_pool); emeta->id = fun->id; } else if (val->fun->code == rs->eval_gates->evaluate_gen) { PgfValueGen* fun = (PgfValueGen*) val->fun; PgfExprVar *evar = gu_new_variant(PGF_EXPR_VAR, PgfExprVar, &expr, rs->out_pool); evar->var = level - fun->level - 1; } else if (val->fun->code == rs->eval_gates->evaluate_sum) { PgfValueSum* sum = (PgfValueSum*) val->fun; PgfExpr e1,e2; PgfExprFun *efun = gu_new_flex_variant(PGF_EXPR_FUN, PgfExprFun, fun, 2, &e1, rs->out_pool); strcpy(efun->fun, "+"); PgfExprLit *elit = gu_new_variant(PGF_EXPR_LIT, PgfExprLit, &e2, rs->out_pool); elit->lit = sum->lit; PgfExprApp* eapp = gu_new_variant(PGF_EXPR_APP, PgfExprApp, &expr, rs->out_pool); eapp->fun = e1; eapp->arg = e2; size_t n_consts = gu_buf_length(sum->consts); for (size_t i = 0; i < n_consts; i++) { PgfClosure* con = gu_buf_get(sum->consts, PgfClosure*, i); PgfExpr fun = expr; PgfExpr arg = pgf_value2expr(rs, level, con); if (gu_variant_is_null(arg)) return gu_null_variant; PgfExprApp* e = gu_new_variant(PGF_EXPR_APP, PgfExprApp, &expr, rs->out_pool); e->fun = fun; e->arg = arg; } } else {
static void pgf_read_tag_error(PgfReader* rdr) { gu_impossible(); }