// Copyright (c) 2023, Marvin Borner // SPDX-License-Identifier: MIT #include #include #include #include #include static int max_depth = 0; static struct term *new_term(term_type_t type, hash_t hash, int depth) { struct term *term = malloc(sizeof(*term)); if (!term) fatal("out of memory!\n"); term->type = type; term->refs = 1; term->hash = hash; term->depth = depth; return term; } static hash_t abs_blc(char **term, int depth) { term_type_t res_type = ABS; hash_t inner_hash = parse_blc(term, depth + 1); hash_t res = hash((uint8_t *)&res_type, sizeof(res_type), inner_hash); struct term *res_term; if ((res_term = map_get(res))) { res_term->refs++; res_term->depth = (res_term->depth + depth) / 2; } else { res_term = new_term(res_type, res, depth); res_term->u.abs.term = inner_hash; map_set(res_term, res); } return res; } static hash_t app_blc(char **term, int depth) { term_type_t res_type = APP; hash_t lhs_hash = parse_blc(term, depth + 1); hash_t rhs_hash = parse_blc(term, depth + 1); hash_t res = hash((uint8_t *)&res_type, sizeof(res_type), lhs_hash); res = hash((uint8_t *)&res, sizeof(res), rhs_hash); struct term *res_term; if ((res_term = map_get(res))) { res_term->refs++; res_term->depth = (res_term->depth + depth) / 2; } else { res_term = new_term(res_type, res, depth); res_term->u.app.lhs = lhs_hash; res_term->u.app.rhs = rhs_hash; map_set(res_term, res); } return res; } static hash_t var_blc(int index, int depth) { term_type_t res_type = VAR; hash_t res = hash((uint8_t *)&res_type, sizeof(res_type), index); struct term *res_term; if ((res_term = map_get(res))) { res_term->refs++; res_term->depth = (res_term->depth + depth) / 2; } else { res_term = new_term(res_type, res, depth); res_term->u.var.index = index; map_set(res_term, res); } return res; } int parse_get_max_depth(void) { return max_depth; } // TODO: bit parse_bblc // TODO: BLoC support (needs entry reference index sth two passes) hash_t parse_blc(char **term, int depth) { if (depth > max_depth) max_depth = depth; if (!**term) { fatal("invalid parsing state!\n"); } else if (**term == '0' && *(*term + 1) == '0') { (*term) += 2; return abs_blc(term, depth); } else if (**term == '0' && *(*term + 1) == '1') { (*term) += 2; return app_blc(term, depth); } else if (**term == '1') { const char *cur = *term; while (**term == '1') (*term)++; int index = *term - cur - 1; (*term)++; return var_blc(index, depth); } else { (*term)++; return parse_blc(term, depth); } }