forked from GitHub/gf-core
hash function for abstract syntax trees
This commit is contained in:
@@ -367,15 +367,15 @@ gu_string_is_prefix(GuString s1, GuString s2)
|
||||
return true;
|
||||
}
|
||||
|
||||
GuWord
|
||||
gu_string_hash(GuString s)
|
||||
GuHash
|
||||
gu_string_hash(GuHash h, GuString s)
|
||||
{
|
||||
if (s.w_ & 1) {
|
||||
return s.w_;
|
||||
return h*101 + s.w_;
|
||||
}
|
||||
size_t len = gu_string_length(s);
|
||||
uint8_t* data = gu_string_long_data(s);
|
||||
return gu_hash_bytes(0, data, len);
|
||||
return gu_hash_bytes(h, data, len);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -403,7 +403,7 @@ gu_string_hasher_hash(GuHasher* self, const void* p)
|
||||
{
|
||||
(void) self;
|
||||
const GuString* sp = p;
|
||||
return gu_string_hash(*sp);
|
||||
return gu_string_hash(0, *sp);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
||||
@@ -78,8 +78,8 @@ gu_string_is_prefix(GuString s1, GuString s2);
|
||||
#if defined(GU_HASH_H_) && !defined(GU_STRING_H_HASH_)
|
||||
#define GU_STRING_H_HASH_
|
||||
|
||||
uintptr_t
|
||||
gu_string_hash(GuString s);
|
||||
GuHash
|
||||
gu_string_hash(GuHash h, GuString s);
|
||||
|
||||
extern GuHasher gu_string_hasher[1];
|
||||
|
||||
|
||||
@@ -830,6 +830,86 @@ pgf_expr_eq(PgfExpr e1, PgfExpr e2)
|
||||
return false;
|
||||
}
|
||||
|
||||
GuHash
|
||||
pgf_literal_hash(GuHash h, PgfLiteral lit)
|
||||
{
|
||||
GuVariantInfo i = gu_variant_open(lit);
|
||||
|
||||
switch (i.tag) {
|
||||
case PGF_LITERAL_STR: {
|
||||
PgfLiteralStr* lit = i.data;
|
||||
h = gu_string_hash(h, lit->val);
|
||||
break;
|
||||
}
|
||||
case PGF_LITERAL_INT: {
|
||||
PgfLiteralInt* lit = i.data;
|
||||
h = gu_hash_byte(h, lit->val);
|
||||
break;
|
||||
}
|
||||
case PGF_LITERAL_FLT: {
|
||||
PgfLiteralFlt* lit = i.data;
|
||||
h = gu_hash_byte(h, lit->val);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
gu_impossible();
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
GuHash
|
||||
pgf_expr_hash(GuHash h, PgfExpr e)
|
||||
{
|
||||
GuVariantInfo ei = gu_variant_open(e);
|
||||
switch (ei.tag) {
|
||||
case PGF_EXPR_ABS: {
|
||||
PgfExprAbs* abs = ei.data;
|
||||
h = gu_string_hash(h, abs->id);
|
||||
h = pgf_expr_hash(h, abs->body);
|
||||
break;
|
||||
}
|
||||
case PGF_EXPR_APP: {
|
||||
PgfExprApp* app = ei.data;
|
||||
h = pgf_expr_hash(h, app->fun);
|
||||
h = pgf_expr_hash(h, app->arg);
|
||||
break;
|
||||
}
|
||||
case PGF_EXPR_LIT: {
|
||||
PgfExprLit* lit = ei.data;
|
||||
h = pgf_literal_hash(h, lit->lit);
|
||||
break;
|
||||
}
|
||||
case PGF_EXPR_META:
|
||||
h = gu_hash_byte(h, '?');
|
||||
break;
|
||||
case PGF_EXPR_FUN: {
|
||||
PgfExprFun* fun = ei.data;
|
||||
h = gu_string_hash(h, fun->fun);
|
||||
break;
|
||||
}
|
||||
case PGF_EXPR_VAR: {
|
||||
PgfExprVar* evar = ei.data;
|
||||
|
||||
h = gu_hash_byte(h, evar->var);
|
||||
break;
|
||||
}
|
||||
case PGF_EXPR_TYPED: {
|
||||
PgfExprTyped* typed = ei.data;
|
||||
h = pgf_expr_hash(h, typed->expr);
|
||||
break;
|
||||
}
|
||||
case PGF_EXPR_IMPL_ARG: {
|
||||
PgfExprImplArg* impl = ei.data;
|
||||
h = pgf_expr_hash(h, impl->expr);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
gu_impossible();
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
void
|
||||
pgf_print_literal(PgfLiteral lit,
|
||||
GuWriter* wtr, GuExn* err)
|
||||
|
||||
@@ -166,6 +166,12 @@ pgf_expr_eq(PgfExpr e1, PgfExpr e2);
|
||||
bool
|
||||
pgf_type_eq(PgfType* t1, PgfType* t2);
|
||||
|
||||
GuHash
|
||||
pgf_literal_hash(GuHash h, PgfLiteral lit);
|
||||
|
||||
GuHash
|
||||
pgf_expr_hash(GuHash h, PgfExpr e);
|
||||
|
||||
typedef struct PgfPrintContext PgfPrintContext;
|
||||
|
||||
struct PgfPrintContext {
|
||||
|
||||
Reference in New Issue
Block a user