int ident_cmp(struct ident l, struct ident r)
{
- //int bigger than str
- if (l.type == iint)
- return r.type == iint ? l.data.iint - r.data.iint : 1;
- else
- return r.type == istr
- ? strcmp(l.data.istr, r.data.istr) : -1;
+ //int > buf == str
+ switch (l.type) {
+ case iint:
+ switch (r.type) {
+ case iint:
+ return l.data.iint - r.data.iint;
+ default:
+ return 1;
+ }
+ break;
+ case istr:
+ switch (r.type) {
+ case iint:
+ return -1;
+ case istr:
+ return strcmp(l.data.istr, r.data.istr);
+ }
+ break;
+ }
+ return 0;
}
-int ident_cmpv(void *l, void *r)
+int ident_cmpv(const void *l, const void *r)
{
return ident_cmp(*(struct ident *)l, *(struct ident *)r);
}
return ident_cmp((struct ident){.type=istr, .data={.istr=l}}, r);
}
-int ident_stricmpv(void *l, void *r)
+int ident_stricmpv(const void *l, const void *r)
{
return ident_stricmp((char *)l, *(struct ident *)r);
}
return ident_cmp(l, (struct ident){.type=istr, .data={.istr=r}});
}
-int ident_istrcmpv(void *l, void *r)
+int ident_istrcmpv(const void *l, const void *r)
{
return ident_istrcmp(*(struct ident *)l, (char *)r);
}
{
if (i.type == istr)
free(i.data.istr);
- (void)i;
}
struct ident ident_int(int iint);
int ident_cmp(struct ident, struct ident);
-int ident_cmpv(void *, void *);
+int ident_cmpv(const void *, const void *);
int ident_stricmp(char *, struct ident);
-int ident_stricmpv(void *, void *);
+int ident_stricmpv(const void *, const void *);
int ident_istrcmp(struct ident, char *);
-int ident_istrcmpv(void *, void *);
+int ident_istrcmpv(const void *, const void *);
struct ident ident_dup(struct ident);
char *ident_tostr(struct ident);
#include <string.h>
#include <stdlib.h>
+#include <stdint.h>
#include "../hm.h"
#include "../../list.h"
return res;
}
-struct subst *subst_insert(struct subst *s, struct ident ident, struct type *t)
+
+static inline void subst_increase_cap(struct subst *s)
{
- int i = 0;
- while (i < s->nvar) {
- if (ident_cmp(s->entries[i].var, ident) == 0) {
- type_free(s->entries[i].type);
- s->entries[i].type = type_dup(t);
- return s;
- }
- i++;
- }
if (s->nvar >= s->capacity) {
s->capacity += s->capacity;
s->entries = xrealloc(s->entries,
s->capacity, struct subst_entry);
}
+}
+
+static const void *bsearchfail;
+int idententrycmp(const void *l, const void *r)
+{
+ bsearchfail = r;
+ return ident_cmp(*(struct ident *)l, ((struct subst_entry *)r)->var);
+}
+
+struct subst *subst_insert(struct subst *s, struct ident ident, struct type *t)
+{
+ size_t idx;
+ //Shortcut, substitution is still empty
+ if (s->nvar == 0) {
+ idx = 0;
+ //Shortcut, ident is the biggest
+ } else if (ident_cmp(ident, s->entries[s->nvar-1].var) > 0) {
+ idx = s->nvar;
+ subst_increase_cap(s);
+ } else {
+ //See if it is already in here
+ bsearchfail = NULL;
+ struct subst_entry *e = bsearch(&ident, s->entries, s->nvar,
+ sizeof(struct subst_entry), idententrycmp);
+ if (e != NULL) {
+ type_free(e->type);
+ e->type = type_dup(t);
+ return s;
+ }
+ idx = ((intptr_t)s->entries-(intptr_t)bsearchfail)
+ /sizeof(struct subst_entry);
+ //check if it is smaller than the smallest
+ if (idx == 0) {
+ if (ident_cmp(ident, s->entries[0].var) > 0)
+ idx++;
+ } else if (idx >= s->nvar)
+ idx = s->nvar;
+
+ subst_increase_cap(s);
+ for (size_t i = s->nvar; i>idx; i--)
+ s->entries[i] = s->entries[i-1];
+ }
+ s->entries[idx].var = ident_dup(ident);
+ s->entries[idx].type = type_dup(t);
s->nvar++;
- s->entries[i].var = ident_dup(ident);
- s->entries[i].type = type_dup(t);
return s;
}
struct subst *subst_union(struct subst *s1, struct subst *s2)
{
//Apply s1 on s2
- for (int i = 0; i<s2->nvar; i++)
+ for (size_t i = 0; i<s2->nvar; i++)
s2->entries[i].type = subst_apply_t(s1, s2->entries[i].type);
//Insert s1 into s2
- for (int i = 0; i<s1->nvar; i++)
+ for (size_t i = 0; i<s1->nvar; i++)
subst_insert(s2, s1->entries[i].var, s1->entries[i].type);
subst_free(s1);
return s2;
l->data.ttuple.l = subst_apply_t(subst, l->data.ttuple.l);
l->data.ttuple.r = subst_apply_t(subst, l->data.ttuple.r);
break;
- case tvar:
- for (int i = 0; i<subst->nvar; i++) {
- if (ident_cmp(subst->entries[i].var, l->data.tvar) == 0) {
- ident_free(l->data.tvar);
- struct type *r =
- type_dup(subst->entries[i].type);
- *l = *r;
- free(r);
- break;
- }
+ case tvar: {
+ struct subst_entry *e = bsearch(&l->data.tvar, subst->entries,
+ subst->nvar, sizeof(struct subst_entry), ident_cmpv);
+ if (e != NULL) {
+ ident_free(l->data.tvar);
+ struct type *r = type_dup(e->type);
+ *l = *r;
+ free(r);
}
break;
- }
+ }}
return l;
}
{
//remove the quantified ones from the subst
struct subst *s = subst_id();
- for (int j = 0; j<subst->nvar; j++) {
+ for (size_t j = 0; j<subst->nvar; j++) {
bool found = false;
for (int i = 0; i<scheme->nvar; i++)
if (ident_cmp(scheme->var[i], subst->entries[j].var) == 0)
fprintf(out, "(nil)");
} else {
fprintf(out, "[");
- for (int i = 0; i<s->nvar; i++) {
+ for (size_t i = 0; i<s->nvar; i++) {
ident_print(s->entries[i].var, out);
fprintf(out, "->");
type_print(s->entries[i].type, out);
void subst_free(struct subst *s)
{
- for (int i = 0; i<s->nvar; i++) {
+ for (size_t i = 0; i<s->nvar; i++) {
ident_free(s->entries[i].var);
type_free(s->entries[i].type);
}