10 bool occurs_check(char *var
, struct type
*r
)
14 type_ftv(r
, &nftv
, &ftv
);
15 for (int i
= 0; i
<nftv
; i
++)
16 if (strcmp(ftv
[i
], var
) == 0)
21 struct subst
*unify(struct type
*l
, struct type
*r
)
23 if (l
== NULL
|| r
== NULL
)
25 if (r
->type
== tvar
&& l
->type
!= tvar
)
27 struct subst
*s1
, *s2
;
30 if (r
->type
== tarrow
) {
31 s1
= unify(l
->data
.tarrow
.l
, r
->data
.tarrow
.l
);
32 s2
= unify(subst_apply_t(s1
, l
->data
.tarrow
.l
),
33 subst_apply_t(s1
, r
->data
.tarrow
.l
));
34 return subst_union(s1
, s2
);
38 if (r
->type
== tbasic
&& l
->data
.tbasic
== r
->data
.tbasic
)
43 return unify(l
->data
.tlist
, r
->data
.tlist
);
46 if (r
->type
== ttuple
) {
47 s1
= unify(l
->data
.ttuple
.l
, r
->data
.ttuple
.l
);
48 s2
= unify(subst_apply_t(s1
, l
->data
.ttuple
.l
),
49 subst_apply_t(s1
, r
->data
.ttuple
.l
));
50 return subst_union(s1
, s2
);
54 if (r
->type
== tvar
&& strcmp(l
->data
.tvar
, r
->data
.tvar
) == 0)
56 else if (occurs_check(l
->data
.tvar
, r
))
57 fprintf(stderr
, "Infinite type %s\n", l
->data
.tvar
);
59 return subst_singleton(l
->data
.tvar
, r
);
62 fprintf(stderr
, "cannot unify ");
63 type_print(l
, stderr
);
64 fprintf(stderr
, " with ");
65 type_print(r
, stderr
);
66 fprintf(stderr
, "\n");
70 struct subst
*infer_expr(struct gamma
*gamma
, struct expr
*expr
, struct type
*type
)
72 fprintf(stderr
, "infer expr: ");
73 expr_print(expr
, stderr
);
74 fprintf(stderr
, "\ngamma: ");
75 gamma_print(gamma
, stderr
);
76 fprintf(stderr
, "\ntype: ");
77 type_print(type
, stderr
);
78 fprintf(stderr
, "\n");
80 #define infbop(l, r, a1, a2, rt, sigma) {\
81 s1 = infer_expr(gamma, l, a1);\
82 s2 = subst_union(s1, infer_expr(subst_apply_g(s1, gamma), r, a2));\
83 return subst_union(s2, unify(subst_apply_t(s2, sigma), rt));\
85 #define infbinop(e, a1, a2, rt, sigma)\
86 infbop(e->data.ebinop.l, e->data.ebinop.r, a1, a2, rt, sigma)
87 struct subst
*s1
, *s2
;
92 return unify(type_basic(btbool
), type
);
94 switch (expr
->data
.ebinop
.op
) {
97 infbinop(expr
, type_basic(btbool
), type_basic(btbool
),
98 type_basic(btbool
), type
);
105 f1
= gamma_fresh(gamma
);
106 infbinop(expr
, f1
, f1
, type_basic(btbool
), type
);
108 f1
= gamma_fresh(gamma
);
109 infbinop(expr
, f1
, type_list(f1
), type_list(f1
), type
);
116 infbinop(expr
, type_basic(btint
), type_basic(btint
),
117 type_basic(btint
), type
);
121 return unify(type_basic(btchar
), type
);
123 if ((s
= gamma_lookup(gamma
, expr
->data
.efuncall
.ident
)) == NULL
)
124 die("Unbound function: %s\n", expr
->data
.efuncall
.ident
);
129 return unify(type_basic(btint
), type
);
131 if ((s
= gamma_lookup(gamma
, expr
->data
.eident
.ident
)) == NULL
)
132 die("Unbound variable: %s\n", expr
->data
.eident
.ident
);
134 return unify(scheme_instantiate(gamma
, s
), type
);
136 f1
= gamma_fresh(gamma
);
137 return unify(type_list(f1
), type
);
139 f1
= gamma_fresh(gamma
);
140 f2
= gamma_fresh(gamma
);
141 infbop(expr
->data
.etuple
.left
, expr
->data
.etuple
.right
,
142 f1
, f2
, type_tuple(f1
, f2
), type
);
144 return unify(type_list(type_basic(btchar
)), type
);
146 switch(expr
->data
.eunop
.op
) {
148 s1
= infer_expr(gamma
,
149 expr
->data
.eunop
.l
, type_basic(btint
));
152 return subst_union(s1
,
153 unify(subst_apply_t(s1
, type
),
156 s1
= infer_expr(gamma
,
157 expr
->data
.eunop
.l
, type_basic(btbool
));
158 return subst_union(s1
,
159 unify(subst_apply_t(s1
, type
),
160 type_basic(btbool
)));