-CFLAGS+=-Wall -Wextra -std=c99 -pedantic -ggdb
+CFLAGS+=-Wall -Wextra -Werror -std=c99 -pedantic -ggdb
YFLAGS+=-d --locations -v --defines=parse.h
LFLAGS+=--header-file=scan.h
-OBJECTS:=scan.o parse.o ast.o type.o util.o list.o sem.o genc.o \
+OBJECTS:=scan.o parse.o ast.o type.o util.o list.o sem.o genc.o ident.o\
$(addprefix sem,.o /scc.o $(addprefix /hm, .o /gamma.o /subst.o /scheme.o))
all: splc
struct ast *ast(struct list *decls, YYLTYPE l)
{
- struct ast *res = safe_malloc(sizeof(struct ast));
+ struct ast *res = xalloc(1, struct ast);
res->loc = l;
res->decls = (struct decl **)list_to_array(decls, &res->ndecls, true, 0);
return res;
struct vardecl *vardecl(struct type *type, char *ident, struct expr *expr, YYLTYPE l)
{
- struct vardecl *res = safe_malloc(sizeof(struct vardecl));
+ struct vardecl *res = xalloc(1, struct vardecl);
res->loc = l;
res->type = type;
res->ident = ident;
struct fundecl *fundecl(char *ident, struct list *args, struct list *atypes,
struct type *rtype, struct list *body, YYLTYPE l)
{
- struct fundecl *res = safe_malloc(sizeof(struct fundecl));
+ struct fundecl *res = xalloc(1, struct fundecl);
res->loc = l;
res->ident = ident;
res->args = (char **)list_to_array(args, &res->nargs, true, 0);
struct decl *decl_fun(struct fundecl *fundecl, YYLTYPE l)
{
- struct decl *res = safe_malloc(sizeof(struct decl));
+ struct decl *res = xalloc(1, struct decl);
res->loc = l;
res->loc = l;
res->type = dfundecl;
struct decl *decl_var(struct vardecl *vardecl, YYLTYPE l)
{
- struct decl *res = safe_malloc(sizeof(struct decl));
+ struct decl *res = xalloc(1, struct decl);
res->loc = l;
res->loc = l;
res->type = dvardecl;
struct stmt *stmt_assign(char *ident, struct list *fields, struct expr *expr, YYLTYPE l)
{
- struct stmt *res = safe_malloc(sizeof(struct stmt));
+ struct stmt *res = xalloc(1, struct stmt);
res->loc = l;
res->type = sassign;
res->data.sassign.ident = ident;
struct stmt *stmt_if(struct expr *pred, struct list *then, struct list *els, YYLTYPE l)
{
- struct stmt *res = safe_malloc(sizeof(struct stmt));
+ struct stmt *res = xalloc(1, struct stmt);
res->loc = l;
res->type = sif;
res->data.sif.pred = pred;
struct stmt *stmt_return(struct expr *rtrn, YYLTYPE l)
{
- struct stmt *res = safe_malloc(sizeof(struct stmt));
+ struct stmt *res = xalloc(1, struct stmt);
res->loc = l;
res->type = sreturn;
res->data.sreturn = rtrn;
struct stmt *stmt_expr(struct expr *expr, YYLTYPE l)
{
- struct stmt *res = safe_malloc(sizeof(struct stmt));
+ struct stmt *res = xalloc(1, struct stmt);
res->loc = l;
res->type = sexpr;
res->data.sexpr = expr;
struct stmt *stmt_vardecl(struct vardecl *vardecl, YYLTYPE l)
{
- struct stmt *res = safe_malloc(sizeof(struct stmt));
+ struct stmt *res = xalloc(1, struct stmt);
res->loc = l;
res->type = svardecl;
res->data.svardecl = vardecl;
struct stmt *stmt_while(struct expr *pred, struct list *body, YYLTYPE l)
{
- struct stmt *res = safe_malloc(sizeof(struct stmt));
+ struct stmt *res = xalloc(1, struct stmt);
res->loc = l;
res->type = swhile;
res->data.swhile.pred = pred;
struct expr *expr_binop(struct expr *left, enum binop op, struct expr *right, YYLTYPE l)
{
- struct expr *res = safe_malloc(sizeof(struct expr));
+ struct expr *res = xalloc(1, struct expr);
res->loc = l;
res->type = ebinop;
res->data.ebinop.l = left;
struct expr *expr_bool(bool b, YYLTYPE l)
{
- struct expr *res = safe_malloc(sizeof(struct expr));
+ struct expr *res = xalloc(1, struct expr);
res->loc = l;
res->type = ebool;
res->data.ebool = b;
struct expr *expr_char(char *c, YYLTYPE l)
{
- struct expr *res = safe_malloc(sizeof(struct expr));
+ struct expr *res = xalloc(1, struct expr);
res->loc = l;
res->type = echar;
res->data.echar = unescape_char(c)[0];
struct expr *expr_funcall_real(char *ident, struct list *args, YYLTYPE l)
{
- struct expr *res = safe_malloc(sizeof(struct expr));
+ struct expr *res = xalloc(1, struct expr);
res->loc = l;
res->type = efuncall;
res->data.efuncall.ident = ident;
struct expr *expr_int(int integer, YYLTYPE l)
{
- struct expr *res = safe_malloc(sizeof(struct expr));
+ struct expr *res = xalloc(1, struct expr);
res->loc = l;
res->type = eint;
res->data.eint = integer;
struct expr *expr_ident(char *ident, struct list *fields, YYLTYPE l)
{
- struct expr *res = safe_malloc(sizeof(struct expr));
+ struct expr *res = xalloc(1, struct expr);
res->loc = l;
res->type = eident;
res->data.eident = ident;
struct expr *expr_nil(YYLTYPE l)
{
- struct expr *res = safe_malloc(sizeof(struct expr));
+ struct expr *res = xalloc(1, struct expr);
res->loc = l;
res->type = enil;
return res;
struct expr *expr_tuple(struct expr *left, struct expr *right, YYLTYPE l)
{
- struct expr *res = safe_malloc(sizeof(struct expr));
+ struct expr *res = xalloc(1, struct expr);
res->loc = l;
res->type = etuple;
res->data.etuple.left = left;
struct expr *expr_string(char *str, YYLTYPE l)
{
- struct expr *res = safe_malloc(sizeof(struct expr));
+ struct expr *res = xalloc(1, struct expr);
res->loc = l;
res->type = estring;
res->data.estring.nchars = 0;
- res->data.estring.chars = safe_malloc(strlen(str)+1);
+ res->data.estring.chars = xalloc(strlen(str)+1, char);
res->loc = l;
char *p = res->data.estring.chars;
while(*str != '\0') {
struct expr *expr_unop(enum unop op, struct expr *e, YYLTYPE l)
{
- struct expr *res = safe_malloc(sizeof(struct expr));
+ struct expr *res = xalloc(1, struct expr);
res->loc = l;
res->type = eunop;
res->data.eunop.op = op;
extern const char *fieldspec_str[];
extern const char *binop_str[];
extern const char *unop_str[];
+
struct ast {
YYLTYPE loc;
int ndecls;
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "util.h"
+#include "ident.h"
+
+struct ident ident_str(char *s)
+{
+ return (struct ident) {.type=istr, .data={.istr=s}};
+}
+
+struct ident ident_int(int i)
+{
+ return (struct ident) {.type=iint, .data={.iint=i}};
+}
+
+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 ident_cmpv(void *l, void *r)
+{
+ return ident_cmp(*(struct ident *)l, *(struct ident *)r);
+}
+
+int ident_stricmp(char *l, struct ident r)
+{
+ return ident_cmp((struct ident){.type=istr, .data={.istr=l}}, r);
+}
+
+int ident_stricmpv(void *l, void *r)
+{
+ return ident_stricmp((char *)l, *(struct ident *)r);
+}
+
+int ident_istrcmp(struct ident l, char *r)
+{
+ return ident_cmp(l, (struct ident){.type=istr, .data={.istr=r}});
+}
+
+int ident_istrcmpv(void *l, void *r)
+{
+ return ident_istrcmp(*(struct ident *)l, (char *)r);
+}
+
+struct ident ident_dup(struct ident i)
+{
+ if (i.type == istr)
+ i.data.istr = safe_strdup(i.data.istr);
+ return i;
+}
+
+char *ident_tostr(struct ident i)
+{
+ if (i.type == istr)
+ return i.data.istr;
+ char buf[10] = {0};
+ sprintf(buf, "%d", i.data.iint);
+ return safe_strdup(buf);
+}
+
+void ident_print(struct ident i, FILE *out)
+{
+ if (i.type == istr)
+ fprintf(out, "%s", i.data.istr);
+ else
+ fprintf(out, "%d", i.data.iint);
+}
+
+void ident_free(struct ident i)
+{
+ if (i.type == istr)
+ free(i.data.istr);
+ (void)i;
+}
--- /dev/null
+#ifndef IDENT_H
+#define IDENT_H
+
+#include <stdio.h>
+
+struct ident {
+ enum {istr, iint} type;
+ union {
+ int iint;
+ char *istr;
+ } data;
+};
+
+struct ident ident_str(char *istr);
+struct ident ident_int(int iint);
+
+int ident_cmp(struct ident, struct ident);
+int ident_cmpv(void *, void *);
+int ident_stricmp(char *, struct ident);
+int ident_stricmpv(void *, void *);
+int ident_istrcmp(struct ident, char *);
+int ident_istrcmpv(void *, void *);
+
+struct ident ident_dup(struct ident);
+char *ident_tostr(struct ident);
+void ident_print(struct ident, FILE *);
+void ident_free(struct ident);
+
+#endif
struct list *list_cons(void *el, struct list *tail)
{
- struct list *res = safe_malloc(sizeof(struct list));
+ struct list *res = xalloc(1, struct list);
res->el = el;
res->tail = tail;
return res;
{
int i = list_length(list);
*num = i;
- void **ptr = safe_malloc((i+extra)*sizeof(void *));
+ void **ptr = xalloc(i+extra, void *);
struct list *r = list;
while(i > 0) {
;
ftype
: type
- | IDENT { $$ = type_var($1); }
+ | IDENT { $$ = type_var_str($1); free($1); }
;
args
: /* empty */ { $$ = NULL; }
struct subst *s = infer_expr(gamma, vardecl->expr, t);
vardecl->type = subst_apply_t(s, t);
- gamma_insert(gamma, vardecl->ident, scheme_create(vardecl->type));
+ gamma_insert(gamma, ident_str(vardecl->ident), scheme_create(vardecl->type));
subst_free(s);
struct subst *s1 = infer_fundecl(gamma, decl, f1);
f1 = subst_apply_t(s1, f1);
- gamma_insert(gamma, decl->ident, scheme_generalise(gamma, f1));
+ gamma_insert(gamma, ident_str(decl->ident), scheme_generalise(gamma, f1));
subst_free(s1);
type_free(f1);
}
void type_comp(struct gamma *gamma, int ndecls, struct fundecl **decl)
{
//Create a fresh variable for every function in the component
- struct type **fs = safe_malloc(ndecls*sizeof(struct type *));
+ struct type **fs = xalloc(ndecls, struct type *);
for (int i = 0; i<ndecls; i++) {
fs[i] = gamma_fresh(gamma);
for (int j = 0; j<decl[i]->nargs; j++) {
struct type *a = gamma_fresh(gamma);
fs[i] = type_arrow(a, fs[i]);
}
- gamma_insert(gamma, decl[i]->ident, scheme_create(fs[i]));
+ gamma_insert(gamma, ident_str(decl[i]->ident), scheme_create(fs[i]));
}
//Infer each function
type_free(dt);
}
- gamma_insert(gamma, decl[i]->ident, scheme_generalise(gamma, t));
+ gamma_insert(gamma, ident_str(decl[i]->ident), scheme_generalise(gamma, t));
//Put the type in the ast
- decl[i]->atypes = safe_realloc(decl[i]->atypes,
- decl[i]->nargs*sizeof(struct type *));
+ decl[i]->atypes = xrealloc(decl[i]->atypes,
+ decl[i]->nargs, struct type *);
decl[i]->natypes = decl[i]->nargs;
for (int j = 0; j<decl[i]->nargs; j++, t = t->data.tarrow.r)
decl[i]->atypes[j] = type_dup(t->data.tarrow.l);
void gamma_preamble(struct gamma *gamma)
{
- struct type *t = type_arrow(type_tuple(type_var(safe_strdup("a"))
- , type_var(safe_strdup("b"))) ,type_var(safe_strdup("a")));
- gamma_insert(gamma, "fst", scheme_generalise(gamma, t));
+ struct type *t = type_arrow(type_tuple(type_var_str("a")
+ , type_var_str("b")) ,type_var_str("a"));
+ gamma_insert(gamma, ident_str("fst"), scheme_generalise(gamma, t));
type_free(t);
- t = type_arrow(type_tuple(type_var(safe_strdup("a"))
- , type_var(safe_strdup("b"))) ,type_var(safe_strdup("b")));
- gamma_insert(gamma, "snd", scheme_generalise(gamma, t));
+ t = type_arrow(type_tuple(type_var_str("a")
+ , type_var_str("b")) ,type_var_str("b"));
+ gamma_insert(gamma, ident_str("snd"), scheme_generalise(gamma, t));
type_free(t);
- t = type_arrow(type_list(type_var(safe_strdup("a"))),
- type_var(safe_strdup("a")));
- gamma_insert(gamma, "hd", scheme_generalise(gamma, t));
+ t = type_arrow(type_list(type_var_str("a")),
+ type_var_str("a"));
+ gamma_insert(gamma, ident_str("hd"), scheme_generalise(gamma, t));
type_free(t);
- t = type_arrow(type_list(type_var(safe_strdup("a"))),
- type_list(type_var(safe_strdup("a"))));
- gamma_insert(gamma, "tl", scheme_generalise(gamma, t));
+ t = type_arrow(type_list(type_var_str("a")),
+ type_list(type_var_str("a")));
+ gamma_insert(gamma, ident_str("tl"), scheme_generalise(gamma, t));
type_free(t);
- t = type_arrow(type_list(type_var(safe_strdup("a"))),
+ t = type_arrow(type_list(type_var_str("a")),
type_basic(btbool));
- gamma_insert(gamma, "isEmpty", scheme_generalise(gamma, t));
+ gamma_insert(gamma, ident_str("isEmpty"), scheme_generalise(gamma, t));
type_free(t);
- t = type_arrow(type_var(safe_strdup("a")), type_basic(btvoid));
- gamma_insert(gamma, "print", scheme_generalise(gamma, t));
+ t = type_arrow(type_var_str("a"), type_basic(btvoid));
+ gamma_insert(gamma, ident_str("print"), scheme_generalise(gamma, t));
type_free(t);
}
}
}
gamma_free(gamma);
+ subst_free_queue();
return ast;
}
#include "../sem.h"
#include "../ast.h"
-bool occurs_check(char *var, struct type *r)
+bool occurs_check(struct ident ident, struct type *r)
{
int nftv = 0;
- char **ftv = NULL;
+ struct ident *ftv = NULL;
bool res = false;
type_ftv(r, &nftv, &ftv);
for (int i = 0; i<nftv; i++) {
- if (strcmp(ftv[i], var) == 0) {
+ if (ident_cmp(ftv[i], ident) == 0) {
res = true;
break;
}
subst_apply_t(s1, r->data.ttuple.r));
return subst_union(s2, s1);
} else if (l->type == tvar) {
- if (r->type == tvar && strcmp(l->data.tvar, r->data.tvar) == 0)
+ if (r->type == tvar && ident_cmp(l->data.tvar, r->data.tvar) == 0)
return subst_id();
else if (occurs_check(l->data.tvar, r))
type_error(loc, true, "Infinite type %s\n",
case echar:
return unify(expr->loc, &tychar, type);
case efuncall:
- if ((s = gamma_lookup(gamma, expr->data.efuncall.ident)) == NULL)
+ if ((s = gamma_lookup(gamma, ident_str(expr->data.efuncall.ident))) == NULL)
type_error(expr->loc, true, "Unbound function: %s\n"
, expr->data.efuncall.ident);
struct type *ft = scheme_instantiate(gamma, s);
case eint:
return unify(expr->loc, &tyint, type);
case eident:
- if ((s = gamma_lookup(gamma, expr->data.eident)) == NULL)
+ if ((s = gamma_lookup(gamma, ident_str(expr->data.eident))) == NULL)
type_error(expr->loc, true, "Unbound variable: %s\n"
, expr->data.eident);
f1 = scheme_instantiate(gamma, s);
s0 = subst_union(s1, s0);
//TODO fielsd
//TODO
- gamma_insert(gamma, stmt->data.svardecl->ident,
+ gamma_insert(gamma, ident_str(stmt->data.svardecl->ident),
scheme_create(subst_apply_t(s0, f1)));
type_free(f1);
return s0;
for (int i = 0; i<fundecl->nargs; i++) {
if (at->type != tarrow)
die("malformed ftype\n");
- gamma_insert(gamma, fundecl->args[i],
+ gamma_insert(gamma, ident_str(fundecl->args[i]),
scheme_create(at->data.tarrow.l));
at = at->data.tarrow.r;
}
#include "hm/gamma.h"
#include "hm/subst.h"
#include "hm/scheme.h"
+#include "../ident.h"
struct ast *infer(struct ast *ast);
-bool occurs_check(char *var, struct type *r);
+bool occurs_check(struct ident ident, struct type *r);
struct subst *unify(YYLTYPE loc, struct type *l, struct type *r);
struct subst *infer_expr(struct gamma *gamma, struct expr *expr, struct type *type);
struct subst *infer_stmt(struct gamma *gamma, struct stmt *stmt, struct type *type);
struct gamma *gamma_init()
{
- struct gamma *gamma = safe_malloc(sizeof(struct gamma));
+ struct gamma *gamma = xalloc(1, struct gamma);
gamma->capacity = IN_CAP;
gamma->fresh = 0;
gamma->nentries = 0;
gamma->scope = 0;
- gamma->entries = safe_malloc(IN_CAP*sizeof(struct gamma_entry));
+ gamma->entries = xalloc(IN_CAP, struct gamma_entry);
return gamma;
}
-void gamma_insert(struct gamma *gamma, char *ident, struct scheme *scheme)
+void gamma_insert(struct gamma *gamma, struct ident ident, struct scheme *scheme)
{
for (int i = 0; i<gamma->nentries; i++) {
- if(strcmp(gamma->entries[i].var, ident) == 0
+ if(ident_cmp(gamma->entries[i].var, ident) == 0
&& gamma->entries[i].scope == gamma->scope) {
scheme_free(gamma->entries[i].scheme);
gamma->entries[i].scheme = scheme;
gamma->nentries++;
if (gamma->nentries >= gamma->capacity) {
gamma->capacity += gamma->capacity;
- gamma->entries = safe_realloc(gamma->entries,
- gamma->capacity*sizeof(struct gamma_entry));
+ gamma->entries = xrealloc(gamma->entries,
+ gamma->capacity, struct gamma_entry);
}
gamma->entries[gamma->nentries-1].scope = gamma->scope;
- gamma->entries[gamma->nentries-1].var = safe_strdup(ident);
+ gamma->entries[gamma->nentries-1].var = ident_dup(ident);
gamma->entries[gamma->nentries-1].scheme = scheme;
}
while (i<gamma->nentries) {
if (gamma->entries[i].scope == gamma->scope) {
scheme_free(gamma->entries[i].scheme);
- free(gamma->entries[i].var);
+ ident_free(gamma->entries[i].var);
for (int j = i+1; j<gamma->nentries; j++)
gamma->entries[j-1] = gamma->entries[j];
gamma->nentries--;
gamma->scope--;
}
-struct scheme *gamma_lookup(struct gamma *gamma, char *ident)
+struct scheme *gamma_lookup(struct gamma *gamma, struct ident ident)
{
struct scheme *res = NULL;
int maxscope = 0;
for (int i = 0; i<gamma->nentries; i++) {
- if (strcmp(ident, gamma->entries[i].var) == 0) {
+ if (ident_cmp(ident, gamma->entries[i].var) == 0) {
if (gamma->entries[i].scope >= maxscope) {
maxscope = gamma->entries[i].scope;
res = gamma->entries[i].scheme;
{
char buf[10] = {0};
sprintf(buf, "%d", gamma->fresh++);
- return type_var(safe_strdup(buf));
+ return type_var_int(gamma->fresh++);
}
void gamma_print(struct gamma *gamma, FILE *out)
{
fprintf(out, "{");
for (int i = 0; i<gamma->nentries; i++) {
- fprintf(out, "%s(%d) = ", gamma->entries[i].var,
- gamma->entries[i].scope);
+ ident_print(gamma->entries[i].var, out);
+ fprintf(out, "(%d) = ", gamma->entries[i].scope);
scheme_print(gamma->entries[i].scheme, out);
if (i + 1 < gamma->nentries)
fprintf(out, ", ");
void gamma_free(struct gamma *gamma)
{
for (int i = 0; i<gamma->nentries; i++) {
- free(gamma->entries[i].var);
+ ident_free(gamma->entries[i].var);
scheme_free(gamma->entries[i].scheme);
}
free(gamma->entries);
#include <stdlib.h>
#include "../hm.h"
+#include "../../ident.h"
struct gamma {
int capacity;
int nentries;
struct gamma_entry {
int scope;
- char *var;
+ struct ident var;
struct scheme *scheme;
} *entries;
};
struct gamma *gamma_init();
-void gamma_insert(struct gamma *gamma, char *ident, struct scheme *scheme);
+void gamma_insert(struct gamma *gamma, struct ident ident, struct scheme *scheme);
void gamma_increment_scope(struct gamma *gamma);
void gamma_decrement_scope(struct gamma *gamma);
-struct scheme *gamma_lookup(struct gamma *gamma, char *ident);
+struct scheme *gamma_lookup(struct gamma *gamma, struct ident ident);
struct type *gamma_fresh(struct gamma *gamma);
void gamma_print(struct gamma *gamma, FILE *out);
struct scheme *scheme_create(struct type *t)
{
- struct scheme *s = safe_malloc(sizeof(struct scheme));
+ struct scheme *s = xalloc(1, struct scheme);
s->type = type_dup(t);
s->nvar = 0;
s->var = NULL;
struct scheme *scheme_generalise(struct gamma *gamma, struct type *t)
{
- struct scheme *s = safe_malloc(sizeof(struct scheme));
+ struct scheme *s = xalloc(1, struct scheme);
int nftv = 0;
- char **ftv = NULL;
+ struct ident *ftv = NULL;
type_ftv(t, &nftv, &ftv);
s->type = type_dup(t);
s->nvar = 0;
- s->var = safe_malloc(nftv*sizeof(char *));
+ s->var = xalloc(nftv, struct ident);
for (int i = 0; i<nftv; i++) {
bool skip = false;
for (int j = 0; j<gamma->nentries; j++)
- if (strcmp(gamma->entries[j].var, ftv[i]) == 0)
+ if (ident_cmp(gamma->entries[j].var, ftv[i]) == 0)
skip = true;
if (skip)
continue;
s->nvar++;
- s->var[i] = safe_strdup(ftv[i]);
+ s->var[i] = ident_dup(ftv[i]);
}
free(ftv);
return s;
for (int i = 0; i<scheme->nvar; i++) {
if (i > 0)
fprintf(out, " ");
- fprintf(out, "%s", scheme->var[i]);
+ ident_print(scheme->var[i], stderr);
}
fprintf(out, ": ");
}
{
type_free(scheme->type);
for (int i = 0; i<scheme->nvar; i++)
- free(scheme->var[i]);
+ ident_free(scheme->var[i]);
free(scheme->var);
free(scheme);
}
#define SEM_HM_SCHEME_H
#include "../hm.h"
+#include "../../ident.h"
struct scheme {
struct type *type;
int nvar;
- char **var;
+ struct ident *var;
};
struct type *scheme_instantiate(struct gamma *gamma, struct scheme *s);
#include <string.h>
#include <stdlib.h>
-#include <search.h>
-
#include "../hm.h"
+#include "../../list.h"
#define INCAP 50
+#define KEEP_LIST
+
+#ifdef KEEP_LIST
+#define BUFCAP 100
+struct subst *buf[BUFCAP] = {NULL};
+int bufi = 0;
+#endif
+
struct subst *subst_id()
{
- struct subst *res = safe_malloc(sizeof(struct subst));
- res->capacity = INCAP;
- res->nvar = 0;
- res->entries = safe_malloc(INCAP*sizeof(struct subst_entry));
+ struct subst *res;
+
+#ifdef KEEP_LIST
+ if (bufi == 0 || bufi >= BUFCAP) {
+#endif
+ res = xalloc(1, struct subst);
+ res->capacity = INCAP;
+ res->nvar = 0;
+ res->entries = xalloc(INCAP, struct subst_entry);
+#ifdef KEEP_LIST
+ } else {
+ res = buf[--bufi];
+ res->nvar = 0;
+ }
+#endif
return res;
}
-struct subst *subst_insert(struct subst *s, char *ident, struct type *t)
+struct subst *subst_insert(struct subst *s, struct ident ident, struct type *t)
{
int i = 0;
while (i < s->nvar) {
- if (strcmp(s->entries[i].var, ident) == 0) {
- // free(s->entries[i].var);
- // s->entries[i].var = safe_strdup(ident);
+ if (ident_cmp(s->entries[i].var, ident) == 0) {
type_free(s->entries[i].type);
s->entries[i].type = type_dup(t);
return s;
}
if (s->nvar >= s->capacity) {
s->capacity += s->capacity;
- s->entries = safe_realloc(s->entries,
- s->capacity*sizeof(struct subst_entry));
+ s->entries = xrealloc(s->entries,
+ s->capacity, struct subst_entry);
}
s->nvar++;
- s->entries[i].var = safe_strdup(ident);
+ s->entries[i].var = ident_dup(ident);
s->entries[i].type = type_dup(t);
return s;
}
-struct subst *subst_singleton(char *ident, struct type *t)
+struct subst *subst_singleton(struct ident ident, struct type *t)
{
return subst_insert(subst_id(), ident, t);
}
break;
case tvar:
for (int i = 0; i<subst->nvar; i++) {
- if (strcmp(subst->entries[i].var, l->data.tvar) == 0) {
- free(l->data.tvar);
+ 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;
struct subst *s = subst_id();
for (int j = 0; j<subst->nvar; j++) {
bool found = false;
- for (int i = 0; i<scheme->nvar; i++) {
- if (strcmp(scheme->var[i], subst->entries[j].var) == 0) {
+ for (int i = 0; i<scheme->nvar; i++)
+ if (ident_cmp(scheme->var[i], subst->entries[j].var) == 0)
found = true;
- }
- }
if (!found)
subst_insert(s, subst->entries[j].var,
subst->entries[j].type);
} else {
fprintf(out, "[");
for (int i = 0; i<s->nvar; i++) {
- fprintf(out, "%s->", s->entries[i].var);
+ ident_print(s->entries[i].var, out);
+ fprintf(out, "->");
type_print(s->entries[i].type, out);
if (i + 1 < s->nvar)
fprintf(out, ", ");
}
}
-void subst_free(struct subst *s)
+static void subst_really_free(void *sp)
{
+ struct subst *s = (struct subst *)sp;
if (s != NULL) {
- for (int i = 0; i<s->nvar; i++) {
- free(s->entries[i].var);
- type_free(s->entries[i].type);
- }
free(s->entries);
free(s);
}
}
+
+void subst_free(struct subst *s)
+{
+ for (int i = 0; i<s->nvar; i++) {
+ ident_free(s->entries[i].var);
+ type_free(s->entries[i].type);
+ }
+#ifdef KEEP_LIST
+ if (bufi < BUFCAP) {
+ buf[bufi++] = s;
+ } else {
+ subst_really_free(s);
+ }
+#else
+ subst_really_free(s);
+#endif
+}
+
+void subst_free_queue()
+{
+#ifdef KEEP_LIST
+ while (--bufi >= 0) {
+ free(buf[bufi]->entries);
+ free(buf[bufi]);
+ }
+#endif
+}
#include "../../ast.h"
#include "../hm.h"
+#include "../../ident.h"
struct subst {
int nvar;
struct subst_entry *entries;
};
struct subst_entry {
- char *var;
+ struct ident var;
struct type *type;
};
struct subst *subst_id();
-struct subst *subst_insert(struct subst *s, char *ident, struct type *t);
-struct subst *subst_singleton(char *ident, struct type *t);
+struct subst *subst_insert(struct subst *s, struct ident ident, struct type *t);
+struct subst *subst_singleton(struct ident ident, struct type *t);
struct subst *subst_union(struct subst *l, struct subst *r);
struct type *subst_apply_t(struct subst *subst, struct type *l);
void subst_print(struct subst *s, FILE *out);
void subst_free(struct subst *s);
+void subst_free_queue();
#endif
/* If v is a root node, pop the stack and generate an SCC */
if (v->lowlink == v->index) {
- struct components *ng = safe_malloc(sizeof(struct components));
+ struct components *ng = xalloc(1, struct components);
if (tj->tail == NULL)
tj->head = ng;
else
w->onStack = false;
ng->nnodes++;
} while (w != v);
- ng->nodes = safe_malloc(ng->nnodes*sizeof(void *));
+ ng->nodes = xalloc(ng->nnodes, void *);
for (int i = 0; i<ng->nnodes; i++)
ng->nodes[i] = tj->stack[tj->sp+i]->data;
}
for (int i = 0; i<ndecls && !found; i++) {
if (strcmp(decls[i]->data.dfun->ident,
expr->data.efuncall.ident) == 0) {
- struct edge *edge = safe_malloc(sizeof(struct edge));
+ struct edge *edge = xalloc(1, struct edge);
edge->from = parent;
edge->to = (void *)decls[i];
l = list_cons(edge, l);
int i = ffun;
for (struct components *c = cs; c != NULL; c = c->next) {
- struct decl *d = safe_malloc(sizeof(struct decl));
+ struct decl *d = xalloc(1, struct decl);
d->type = dcomp;
d->data.dcomp.ndecls = c->nnodes;
- d->data.dcomp.decls = safe_malloc(
- c->nnodes*sizeof(struct fundecl *));
+ d->data.dcomp.decls = xalloc(c->nnodes, struct fundecl *);
for (int j = 0; j<c->nnodes; j++)
d->data.dcomp.decls[j] =
((struct decl *)c->nodes[j])->data.dfun;
//Generate code
if (cfile == NULL)
- sprintf(cfile = safe_malloc(10), "a.%s", suffix[lang]);
+ sprintf(cfile = xalloc(10, char), "a.%s", suffix[lang]);
cout = safe_fopen(cfile, "w+");
free(cfile);
switch(lang) {
char **var = malloc(sizeof(char *));
var[0] = safe_strdup("a");
- struct scheme scheme = {.type=type_var("a"), .nvar=1, .var=var};
+ struct scheme scheme = {.type=type_var_str("a"), .nvar=1, .var=var};
struct type *t = scheme_instantiate(gamma, &scheme);
ck_assert(t->type == tvar);
#include "util.h"
#include "type.h"
+#include "ident.h"
static const char *basictype_str[] = {
[btbool] = "Bool", [btchar] = "Char", [btint] = "Int",
struct type *type_arrow(struct type *l, struct type *r)
{
- struct type *res = safe_malloc(sizeof(struct type));
+ struct type *res = xalloc(1, struct type);
res->type = tarrow;
res->data.tarrow.l = l;
res->data.tarrow.r = r;
struct type *type_basic(enum basictype type)
{
- struct type *res = safe_malloc(sizeof(struct type));
+ struct type *res = xalloc(1, struct type);
res->type = tbasic;
res->data.tbasic = type;
return res;
struct type *type_list(struct type *type)
{
- struct type *res = safe_malloc(sizeof(struct type));
+ struct type *res = xalloc(1, struct type);
res->type = tlist;
res->data.tlist = type;
return res;
struct type *type_tuple(struct type *l, struct type *r)
{
- struct type *res = safe_malloc(sizeof(struct type));
+ struct type *res = xalloc(1, struct type);
res->type = ttuple;
res->data.ttuple.l = l;
res->data.ttuple.r = r;
return res;
}
-struct type *type_var(char *ident)
+struct type *type_var_str(char *s)
{
- struct type *res = safe_malloc(sizeof(struct type));
- if (strcmp(ident, "Int") == 0) {
+ return type_var((struct ident){.type=istr, .data={.istr=s}});
+}
+
+struct type *type_var_int(int i)
+{
+ return type_var((struct ident){.type=iint, .data={.iint=i}});
+}
+
+struct type *type_var(struct ident ident)
+{
+ struct type *res = xalloc(1, struct type);
+ if (ident_istrcmp(ident, "Int") == 0) {
res->type = tbasic;
res->data.tbasic = btint;
- free(ident);
- } else if (strcmp(ident, "Char") == 0) {
+ ident_free(ident);
+ } else if (ident_istrcmp(ident, "Char") == 0) {
res->type = tbasic;
res->data.tbasic = btchar;
- free(ident);
- } else if (strcmp(ident, "Bool") == 0) {
+ ident_free(ident);
+ } else if (ident_istrcmp(ident, "Bool") == 0) {
res->type = tbasic;
res->data.tbasic = btbool;
- free(ident);
- } else if (strcmp(ident, "Void") == 0) {
+ ident_free(ident);
+ } else if (ident_istrcmp(ident, "Void") == 0) {
res->type = tbasic;
res->data.tbasic = btvoid;
- free(ident);
+ ident_free(ident);
} else {
res->type = tvar;
- res->data.tvar = ident;
+ res->data.tvar = ident_dup(ident);
}
return res;
}
safe_fprintf(out, ")");
break;
case tvar:
- safe_fprintf(out, "%s", type->data.tvar);
+ ident_print(type->data.tvar, out);
break;
default:
die("Unsupported type node: %d\n", type->type);
type_free(type->data.ttuple.r);
break;
case tvar:
- free(type->data.tvar);
+ ident_free(type->data.tvar);
break;
default:
die("Unsupported type node: %d\n", type->type);
struct type *type_dup(struct type *r)
{
- struct type *res = safe_malloc(sizeof(struct type));
+ struct type *res = xalloc(1, struct type);
*res = *r;
switch (r->type) {
case tarrow:
res->data.ttuple.r = type_dup(r->data.ttuple.r);
break;
case tvar:
- res->data.tvar = safe_strdup(r->data.tvar);
+ res->data.tvar = ident_dup(r->data.tvar);
break;
default:
die("Unsupported type node: %d\n", r->type);
return res;
}
-void type_ftv(struct type *r, int *nftv, char ***ftv)
+void type_ftv(struct type *r, int *nftv, struct ident **ftv)
{
switch (r->type) {
case tarrow:
break;
case tvar:
for (int i = 0; i<*nftv; i++)
- if (strcmp((*ftv)[i], r->data.tvar) == 0)
+ if (ident_cmp((*ftv)[i], r->data.tvar) == 0)
return;
- *ftv = safe_realloc(*ftv, (*nftv+1)*sizeof(char *));
+ *ftv = xrealloc(*ftv, *nftv+1, struct ident);
(*ftv)[(*nftv)++] = r->data.tvar;
break;
default:
#include <stdio.h>
#include "ast.h"
+#include "ident.h"
enum basictype {btbool, btchar, btint, btvoid};
struct type {
struct type *l;
struct type *r;
} ttuple;
- char *tvar;
+ struct ident tvar;
} data;
};
struct type *type_basic(enum basictype type);
struct type *type_list(struct type *type);
struct type *type_tuple(struct type *left, struct type *right);
-struct type *type_var(char *ident);
+struct type *type_var(struct ident ident);
+struct type *type_var_str(char *s);
+struct type *type_var_int(int i);
-void type_print(struct type *type, FILE *out);
+void type_print(struct type *type, FILE *stream);
void type_free(struct type *type);
struct type *type_dup(struct type *t);
-void type_ftv(struct type *r, int *nftv, char ***ftv);
+void type_ftv(struct type *r, int *nftv, struct ident **ftv);
#endif
char *escape_char(char c, char *buf, bool str)
{
- buf = buf == NULL ? safe_malloc(10) : buf;
+ buf = buf == NULL ? xalloc(10, char) : buf;
switch (c) {
case '\0': strcpy(buf, "\\0"); break;
case '\a': strcpy(buf, "\\a"); break;
void safe_fprintf(FILE *out, const char *msg, ...);
void *safe_malloc(size_t size);
+#define xalloc(nmemb, type) ((type *)safe_malloc((nmemb)*sizeof(type)))
void *safe_realloc(void *ptr, size_t size);
+#define xrealloc(ptr, nmemb, type) ((type *)safe_realloc(ptr, (nmemb)*sizeof(type)))
void *safe_strdup(const char *c);
FILE *safe_fopen(const char *path, const char *mode);
void safe_fclose(FILE *file);