-
Notifications
You must be signed in to change notification settings - Fork 0
/
infer.c
59 lines (49 loc) · 1.24 KB
/
infer.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <stdlib.h>
#include "stlc.h"
static type_t find(type_t *, type_t);
static bool unify(const term_t *, type_t *, type_t, type_t);
static bool occurs(const term_t *, type_t *, type_t, type_t);
/* Attempts to infer a simple typing for a term. */
type_t *
infer(const term_t *term)
{
long len = term[0];
type_t *type = calloc(len, sizeof *type);
if (!type)
return NULL;
for (type_t t = ROOT; t < len; t++) {
if (ISAPP(t) && !unify(term, type, TYPEOF(LEFT(t)), t)) {
free(type);
return NULL;
}
}
return type;
}
type_t
find(type_t *type, type_t x)
{
if (ISATOM(x) && VALUE(x) != NIL)
return VALUE(x) = find(type, VALUE(x)); // path compression
else
return x;
}
bool
unify(const term_t *term, type_t *type, type_t x, type_t y)
{
for (; (x = find(type, x)) != (y = find(type, y)); x = COD(x), y = COD(y))
if (ISATOM(x))
return !occurs(term, type, x, y) && (VALUE(x) = y, true);
else if (ISATOM(y))
return !occurs(term, type, y, x) && (VALUE(y) = x, true);
else if (!unify(term, type, DOM(x), DOM(y)))
return false;
return true;
}
bool
occurs(const term_t *term, type_t *type, type_t a, type_t x)
{
for (; !ISATOM(x); x = SUB(x))
if (occurs(term, type, a, find(type, ATOM(x))))
return true;
return x == a;
}