scoping
authorMart Lubbers <mart@martlubbers.net>
Tue, 2 Mar 2021 14:23:36 +0000 (15:23 +0100)
committerMart Lubbers <mart@martlubbers.net>
Tue, 2 Mar 2021 14:23:36 +0000 (15:23 +0100)
13 files changed:
ast.c
list.c
list.h
sem.c
sem/hm.c
sem/hm.h
sem/hm/gamma.c
sem/hm/gamma.h
sem/hm/scheme.c
sem/hm/subst.c
sem/hm/subst.h
sem/scc.c
util.c

diff --git a/ast.c b/ast.c
index 3f1c97d..e4c45a3 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -22,7 +22,7 @@ struct ast *ast(struct list *decls, YYLTYPE l)
 {
        struct ast *res = safe_malloc(sizeof(struct ast));
        res->loc = l;
-       res->decls = (struct decl **)list_to_array(decls, &res->ndecls, true);
+       res->decls = (struct decl **)list_to_array(decls, &res->ndecls, true, 0);
        return res;
 }
 
@@ -41,10 +41,11 @@ struct fundecl *fundecl(char *ident, struct list *args, struct list *atypes,
        struct fundecl *res = safe_malloc(sizeof(struct fundecl));
        res->loc = l;
        res->ident = ident;
-       res->args = (char **)list_to_array(args, &res->nargs, true);
-       res->atypes = (struct type **)list_to_array(atypes, &res->natypes, true);
+       res->args = (char **)list_to_array(args, &res->nargs, true, 0);
+       res->atypes = (struct type **)list_to_array(atypes, &res->natypes, true, 0);
        res->rtype = rtype;
-       res->body = (struct stmt **)list_to_array(body, &res->nbody, true);
+       //Reserve room for an optional extra return inserted by the compiler
+       res->body = (struct stmt **)list_to_array(body, &res->nbody, true, 1);
        return res;
 }
 
@@ -75,7 +76,7 @@ struct stmt *stmt_assign(char *ident, struct list *fields, struct expr *expr, YY
        res->type = sassign;
        res->data.sassign.ident = ident;
        res->data.sassign.fields = (char **)
-               list_to_array(fields, &res->data.sassign.nfields, true);
+               list_to_array(fields, &res->data.sassign.nfields, true, 0);
        res->data.sassign.expr = expr;
        return res;
 }
@@ -87,9 +88,9 @@ struct stmt *stmt_if(struct expr *pred, struct list *then, struct list *els, YYL
        res->type = sif;
        res->data.sif.pred = pred;
        res->data.sif.then = (struct stmt **)
-               list_to_array(then, &res->data.sif.nthen, true);
+               list_to_array(then, &res->data.sif.nthen, true, 0);
        res->data.sif.els = (struct stmt **)
-               list_to_array(els, &res->data.sif.nels, true);
+               list_to_array(els, &res->data.sif.nels, true, 0);
        return res;
 }
 
@@ -127,7 +128,7 @@ struct stmt *stmt_while(struct expr *pred, struct list *body, YYLTYPE l)
        res->type = swhile;
        res->data.swhile.pred = pred;
        res->data.swhile.body = (struct stmt **)
-               list_to_array(body, &res->data.swhile.nbody, true);
+               list_to_array(body, &res->data.swhile.nbody, true, 0);
        return res;
 }
 
@@ -187,7 +188,7 @@ struct expr *expr_funcall_real(char *ident, struct list *args, YYLTYPE l)
        res->type = efuncall;
        res->data.efuncall.ident = ident;
        res->data.efuncall.args = (struct expr **)
-               list_to_array(args, &res->data.efuncall.nargs, true);
+               list_to_array(args, &res->data.efuncall.nargs, true, 0);
        return res;
 }
 
diff --git a/list.c b/list.c
index 62af95e..a18850b 100644 (file)
--- a/list.c
+++ b/list.c
@@ -34,11 +34,11 @@ void list_free(struct list *head, void (*freefun)(void *))
        }
 }
 
-void **list_to_array(struct list *list, int *num, bool reverse)
+void **list_to_array(struct list *list, int *num, bool reverse, int extra)
 {
        int i = list_length(list);
        *num = i;
-       void **ptr = safe_malloc(i*sizeof(void *));
+       void **ptr = safe_malloc((i+extra)*sizeof(void *));
 
        struct list *r = list;
        while(i > 0) {
diff --git a/list.h b/list.h
index 1cc3fb2..979e101 100644 (file)
--- a/list.h
+++ b/list.h
@@ -13,7 +13,7 @@ struct list {
 struct list *list_append(void *el, struct list *head);
 struct list *list_cons(void *el, struct list *tail);
 void list_free(struct list *head, void (*freefun)(void *));
-void **list_to_array(struct list *list, int *num, bool reverse);
+void **list_to_array(struct list *list, int *num, bool reverse, int extra);
 int list_length(struct list *head);
 
 #endif
diff --git a/sem.c b/sem.c
index f856b97..6fe9385 100644 (file)
--- a/sem.c
+++ b/sem.c
@@ -91,21 +91,20 @@ void type_comp(struct gamma *gamma, int ndecls, struct fundecl **decl)
                //unify against given type specification
                if (decl[i]->rtype != NULL) {
                        struct type *dt = decl[i]->rtype;
-                       for (int j = decl[i]->natypes-1; j>=0; j--)
+                       for (int j = decl[i]->natypes-1; j>=0; j--) {
                                dt = type_arrow(decl[i]->atypes[j], dt);
-                       unify(decl[i]->loc, dt, t);
-                       //Free the old types if there were any
-                       for (int j = 0; j<decl[i]->natypes; j++)
-                               type_free(decl[i]->atypes[j]);
-                       free(decl[i]->atypes);
-                       type_free(decl[i]->rtype);
+                       }
+                       struct subst *s1 = unify(decl[i]->loc, dt, t);
+                       subst_apply_t(s1, fs[i]);
+                       subst_free(s1);
+                       type_free(dt);
                }
 
                gamma_insert(gamma, decl[i]->ident, scheme_generalise(gamma, t));
 
-
                //Put the type in the ast
-               decl[i]->atypes = safe_malloc(decl[i]->nargs*sizeof(struct type *));
+               decl[i]->atypes = safe_realloc(decl[i]->atypes,
+                       decl[i]->nargs*sizeof(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);
@@ -182,7 +181,8 @@ bool check_return_stmt(struct stmt *stmt)
 void check_return_comp(int ndecl, struct fundecl **decls)
 {
        for (int i = 0; i<ndecl; i++) {
-               if (decls[i]->rtype->type == tbasic && decls[i]->rtype->data.tbasic == btvoid)
+               if (decls[i]->rtype->type == tbasic &&
+                               decls[i]->rtype->data.tbasic == btvoid)
                        continue;
                if (!check_return_body(decls[i]->nbody, decls[i]->body))
                        type_error(decls[i]->loc, true,
@@ -190,6 +190,18 @@ void check_return_comp(int ndecl, struct fundecl **decls)
        }
 }
 
+void add_return_if_none(int ndecl, struct fundecl **decl)
+{
+       for (int i = 0; i<ndecl; i++) {
+               if (decl[i]->rtype == NULL && !check_return_body(
+                               decl[i]->nbody, decl[i]->body)) {
+                       //Room for this was reserved in ast.c
+                       decl[i]->body[decl[i]->nbody++] =
+                               stmt_return(NULL, decl[i]->loc);
+               }
+       }
+}
+
 struct ast *sem(struct ast *ast)
 {
        //Break up into strongly connected components
@@ -197,6 +209,9 @@ struct ast *sem(struct ast *ast)
 
        struct gamma *gamma = gamma_init();
        gamma_preamble(gamma);
+       fprintf(stderr, "start with gamma: ");
+       gamma_print(gamma, stderr);
+       fprintf(stderr, "\n");
 
        //Check all vardecls
        for (int i = 0; i<ast->ndecls; i++) {
@@ -208,17 +223,17 @@ struct ast *sem(struct ast *ast)
                        //Infer if necessary
                        type_vardecl(gamma, decl->data.dvar);
                        break;
-               case dfundecl:
-                       //Infer function as singleton component
-                       type_comp(gamma, 1, &decl->data.dfun);
-//                     check_return_comp(1, &decl->data.dfun);
-                       break;
                case dcomp:
                        //Infer function as singleton component
+                       add_return_if_none(decl->data.dcomp.ndecls,
+                               decl->data.dcomp.decls);
                        type_comp(gamma, decl->data.dcomp.ndecls,
                                decl->data.dcomp.decls);
-//                     check_return_comp(decl->data.dcomp.ndecls,
-//                             decl->data.dcomp.decls);
+                       check_return_comp(decl->data.dcomp.ndecls,
+                               decl->data.dcomp.decls);
+                       break;
+               case dfundecl:
+                       die("fundecls should be gone by now\n");
                        break;
                }
        }
index 6e4ca9d..d81902a 100644 (file)
--- a/sem/hm.c
+++ b/sem/hm.c
@@ -196,6 +196,19 @@ struct subst *infer_expr(struct gamma *gamma, struct expr *expr, struct type *ty
        return NULL;
 }
 
+struct subst *infer_body(struct gamma *gamma, int nstmt, struct stmt **stmts, struct type *type)
+{
+       gamma_increment_scope(gamma);
+       struct subst *s0 = subst_id(), *s1;
+       for (int i = 0; i<nstmt; i++) {
+               s1 = infer_stmt(gamma, stmts[i], type);
+               s0 = subst_union(s1, s0);
+               subst_apply_g(s0, gamma);
+       }
+       gamma_decrement_scope(gamma);
+       return s0;
+}
+
 struct subst *infer_stmt(struct gamma *gamma, struct stmt *stmt, struct type *type)
 {
        struct subst *s0, *s1;
@@ -205,19 +218,13 @@ struct subst *infer_stmt(struct gamma *gamma, struct stmt *stmt, struct type *ty
                break;
        case sif:
                s0 = infer_expr(gamma, stmt->data.sif.pred, &tybool);
-               subst_apply_g(s0, gamma);
+               //subst_apply_g(s0, gamma);
 
-               for (int i = 0; i<stmt->data.sif.nthen; i++) {
-                       s1 = infer_stmt(gamma, stmt->data.sif.then[i], type);
-                       s0 = subst_union(s1, s0);
-                       subst_apply_g(s0, gamma);
-               }
+               s0 = subst_union(s0, infer_body(gamma,
+                       stmt->data.sif.nthen, stmt->data.sif.then, type));
 
-               for (int i = 0; i<stmt->data.sif.nels; i++) {
-                       s1 = infer_stmt(gamma, stmt->data.sif.els[i], type);
-                       s0 = subst_union(s1, s0);
-                       subst_apply_g(s0, gamma);
-               }
+               s0 = subst_union(s0, infer_body(gamma,
+                       stmt->data.sif.nels, stmt->data.sif.els, type));
                return s0;
        case sreturn:
                return stmt->data.sreturn == NULL
@@ -238,17 +245,16 @@ struct subst *infer_stmt(struct gamma *gamma, struct stmt *stmt, struct type *ty
                s0 = subst_union(s1, s0);
                //TODO fielsd
                //TODO
-               gamma_insert(gamma, stmt->data.svardecl->ident, scheme_create(subst_apply_t(s0, f1)));
+               gamma_insert(gamma, stmt->data.svardecl->ident,
+                       scheme_create(subst_apply_t(s0, f1)));
+               type_free(f1);
                return s0;
        case swhile:
                s0 = infer_expr(gamma, stmt->data.swhile.pred, &tybool);
-               subst_apply_g(s0, gamma);
+               //subst_apply_g(s0, gamma);
 
-               for (int i = 0; i<stmt->data.swhile.nbody; i++) {
-                       s1 = infer_stmt(gamma, stmt->data.swhile.body[i], type);
-                       s0 = subst_union(s1, s0);
-                       subst_apply_g(s0, gamma);
-               }
+               s0 = subst_union(s0, infer_body(gamma,
+                       stmt->data.swhile.nbody, stmt->data.swhile.body, type));
 
                return s0;
        }
@@ -258,6 +264,7 @@ struct subst *infer_stmt(struct gamma *gamma, struct stmt *stmt, struct type *ty
 struct subst *infer_fundecl(struct gamma *gamma, struct fundecl *fundecl, struct type *ftype)
 {
        // Put arguments in gamma
+       gamma_increment_scope(gamma);
        struct type *at = ftype;
        for (int i = 0; i<fundecl->nargs; i++) {
                if (at->type != tarrow)
@@ -277,10 +284,6 @@ struct subst *infer_fundecl(struct gamma *gamma, struct fundecl *fundecl, struct
        }
 
        // Remove arguments from gamma
-       at = ftype;
-       for (int i = 0; i<fundecl->nargs; i++) {
-               gamma_remove(gamma, fundecl->args[i]);
-               at = at->data.tarrow.r;
-       }
+       gamma_decrement_scope(gamma);
        return s;
 }
index 0a92475..932e508 100644 (file)
--- a/sem/hm.h
+++ b/sem/hm.h
@@ -7,6 +7,8 @@
 #include "hm/scheme.h"
 
 struct ast *infer(struct ast *ast);
+
+bool occurs_check(char *var, 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);
index c5ad9eb..93de4ec 100644 (file)
@@ -3,63 +3,78 @@
 
 #include "../hm.h"
 
-#define IN_CAP 25
+#define IN_CAP 50
 
 struct gamma *gamma_init()
 {
        struct gamma *gamma = safe_malloc(sizeof(struct gamma));
        gamma->capacity = IN_CAP;
        gamma->fresh = 0;
-       gamma->nschemes = 0;
-       gamma->vars = safe_malloc(IN_CAP*sizeof(char *));
-       gamma->schemes = safe_malloc(IN_CAP*sizeof(struct scheme *));
+       gamma->nentries = 0;
+       gamma->scope = 0;
+       gamma->entries = safe_malloc(IN_CAP*sizeof(struct gamma_entry));
        return gamma;
 }
 
 void gamma_insert(struct gamma *gamma, char *ident, struct scheme *scheme)
 {
-       for (int i = 0; i<gamma->nschemes; i++) {
-               if(strcmp(gamma->vars[i], ident) == 0) {
-                       scheme_free(gamma->schemes[i]);
-                       gamma->schemes[i] = scheme;
+       for (int i = 0; i<gamma->nentries; i++) {
+               if(strcmp(gamma->entries[i].var, ident) == 0
+                               && gamma->entries[i].scope == gamma->scope) {
+                       scheme_free(gamma->entries[i].scheme);
+                       gamma->entries[i].scheme = scheme;
                        return;
                }
        }
-       gamma->nschemes++;
-       if (gamma->nschemes >= gamma->capacity) {
+       gamma->nentries++;
+       if (gamma->nentries >= gamma->capacity) {
                gamma->capacity += gamma->capacity;
-               gamma->vars = safe_realloc(gamma->vars,
-                       gamma->capacity*sizeof(char *));
-               gamma->schemes = safe_realloc(gamma->schemes,
-                       gamma->capacity*sizeof(struct scheme *));
+               gamma->entries = safe_realloc(gamma->entries,
+                       gamma->capacity*sizeof(struct gamma_entry));
        }
-       gamma->vars[gamma->nschemes-1] = safe_strdup(ident);
-       gamma->schemes[gamma->nschemes-1] = scheme;
+       gamma->entries[gamma->nentries-1].scope = gamma->scope;
+       gamma->entries[gamma->nentries-1].var = safe_strdup(ident);
+       gamma->entries[gamma->nentries-1].scheme = scheme;
 }
 
-void gamma_remove(struct gamma *gamma, char *ident)
+void gamma_increment_scope(struct gamma *gamma)
 {
+       gamma->scope++;
+}
+
+void gamma_decrement_scope(struct gamma *gamma)
+{
+       if (gamma->scope == 0)
+               die("scope cannot be decrement to a negative scope\n");
+
        int i = 0;
-       for (i = 0; i<gamma->nschemes; i++) {
-               if (strcmp(gamma->vars[i], ident) == 0) {
-                       scheme_free(gamma->schemes[i]);
-                       free(gamma->vars[i]);
-                       break;
+       while (i<gamma->nentries) {
+               if (gamma->entries[i].scope == gamma->scope) {
+                       scheme_free(gamma->entries[i].scheme);
+                       free(gamma->entries[i].var);
+                       for (int j = i+1; j<gamma->nentries; j++)
+                               gamma->entries[j-1] = gamma->entries[j];
+                       gamma->nentries--;
+               } else {
+                       i++;
                }
        }
-       for (i++; i<gamma->nschemes; i++) {
-               gamma->vars[i-1] = gamma->vars[i];
-               gamma->schemes[i-1] = gamma->schemes[i];
-       }
-       gamma->nschemes--;
+       gamma->scope--;
 }
 
 struct scheme *gamma_lookup(struct gamma *gamma, char *ident)
 {
-       for (int i = 0; i<gamma->nschemes; i++)
-               if (strcmp(ident, gamma->vars[i]) == 0)
-                       return gamma->schemes[i];
-       return NULL;
+       struct scheme *res = NULL;
+       int maxscope = 0;
+       for (int i = 0; i<gamma->nentries; i++) {
+               if (strcmp(ident, gamma->entries[i].var) == 0) {
+                       if (gamma->entries[i].scope >= maxscope) {
+                               maxscope = gamma->entries[i].scope;
+                               res = gamma->entries[i].scheme;
+                       }
+               }
+       }
+       return res;
 }
 
 struct type *gamma_fresh(struct gamma *gamma)
@@ -72,10 +87,11 @@ struct type *gamma_fresh(struct gamma *gamma)
 void gamma_print(struct gamma *gamma, FILE *out)
 {
        fprintf(out, "{");
-       for (int i = 0; i<gamma->nschemes; i++) {
-               fprintf(out, "%s=", gamma->vars[i]);
-               scheme_print(gamma->schemes[i], out);
-               if (i + 1 < gamma->nschemes)
+       for (int i = 0; i<gamma->nentries; i++) {
+               fprintf(out, "%s(%d) = ", gamma->entries[i].var,
+                       gamma->entries[i].scope);
+               scheme_print(gamma->entries[i].scheme, out);
+               if (i + 1 < gamma->nentries)
                        fprintf(out, ", ");
        }
        fprintf(out, "}");
@@ -83,11 +99,10 @@ void gamma_print(struct gamma *gamma, FILE *out)
 
 void gamma_free(struct gamma *gamma)
 {
-       for (int i = 0; i<gamma->nschemes; i++) {
-               free(gamma->vars[i]);
-               scheme_free(gamma->schemes[i]);
+       for (int i = 0; i<gamma->nentries; i++) {
+               free(gamma->entries[i].var);
+               scheme_free(gamma->entries[i].scheme);
        }
-       free(gamma->vars);
-       free(gamma->schemes);
+       free(gamma->entries);
        free(gamma);
 }
index f146621..9641dcc 100644 (file)
@@ -8,14 +8,19 @@
 struct gamma {
        int capacity;
        int fresh;
-       int nschemes;
-       char **vars;
-       struct scheme **schemes;
+       int scope;
+       int nentries;
+       struct gamma_entry {
+               int scope;
+               char *var;
+               struct scheme *scheme;
+       } *entries;
 };
 
 struct gamma *gamma_init();
 void gamma_insert(struct gamma *gamma, char *ident, struct scheme *scheme);
-void gamma_remove(struct gamma *gamma, char *ident);
+void gamma_increment_scope(struct gamma *gamma);
+void gamma_decrement_scope(struct gamma *gamma);
 
 struct scheme *gamma_lookup(struct gamma *gamma, char *ident);
 struct type *gamma_fresh(struct gamma *gamma);
index b9b9861..5715837 100644 (file)
@@ -39,8 +39,8 @@ struct scheme *scheme_generalise(struct gamma *gamma, struct type *t)
        s->var = safe_malloc(nftv*sizeof(char *));
        for (int i = 0; i<nftv; i++) {
                bool skip = false;
-               for (int j = 0; j<gamma->nschemes; j++)
-                       if (strcmp(gamma->vars[j], ftv[i]) == 0)
+               for (int j = 0; j<gamma->nentries; j++)
+                       if (strcmp(gamma->entries[j].var, ftv[i]) == 0)
                                skip = true;
                if (skip)
                        continue;
index 1fcfbbc..6725fc7 100644 (file)
@@ -1,42 +1,42 @@
 #include <string.h>
 #include <stdlib.h>
 
+#include <search.h>
+
 #include "../hm.h"
 
-#define INCAP 25
+#define INCAP 50
 
 struct subst *subst_id()
 {
        struct subst *res = safe_malloc(sizeof(struct subst));
-       res->nvar = 0;
        res->capacity = INCAP;
-       res->vars = safe_malloc(INCAP*sizeof(char *));
-       res->types = safe_malloc(INCAP*sizeof(struct type *));
+       res->nvar = 0;
+       res->entries = safe_malloc(INCAP*sizeof(struct subst_entry));
        return res;
 }
 
 struct subst *subst_insert(struct subst *s, char *ident, struct type *t)
 {
-
        int i = 0;
        while (i < s->nvar) {
-               if (strcmp(s->vars[i], ident) == 0) {
-                       free(s->vars[i]);
-                       s->vars[i] = safe_strdup(ident);
-                       type_free(s->types[i]);
-                       s->types[i] = type_dup(t);
+               if (strcmp(s->entries[i].var, ident) == 0) {
+       //              free(s->entries[i].var);
+       //              s->entries[i].var = safe_strdup(ident);
+                       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->vars = safe_realloc(s->vars, s->capacity*sizeof(char *));
-               s->types = safe_realloc(s->types, s->capacity*sizeof(struct type *));
+               s->entries = safe_realloc(s->entries,
+                       s->capacity*sizeof(struct subst_entry));
        }
-       s->nvar ++;
-       s->vars[i] = safe_strdup(ident);
-       s->types[i] = type_dup(t);
+       s->nvar++;
+       s->entries[i].var = safe_strdup(ident);
+       s->entries[i].type = type_dup(t);
        return s;
 }
 
@@ -49,10 +49,10 @@ struct subst *subst_union(struct subst *s1, struct subst *s2)
 {
        //Apply s1 on s2
        for (int i = 0; i<s2->nvar; i++)
-               s2->types[i] = subst_apply_t(s1, s2->types[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++)
-               subst_insert(s2, s1->vars[i], s1->types[i]);
+               subst_insert(s2, s1->entries[i].var, s1->entries[i].type);
        subst_free(s1);
        return s2;
 }
@@ -77,9 +77,10 @@ struct type *subst_apply_t(struct subst *subst, struct type *l)
                break;
        case tvar:
                for (int i = 0; i<subst->nvar; i++) {
-                       if (strcmp(subst->vars[i], l->data.tvar) == 0) {
+                       if (strcmp(subst->entries[i].var, l->data.tvar) == 0) {
                                free(l->data.tvar);
-                               struct type *r = type_dup(subst->types[i]);
+                               struct type *r =
+                                       type_dup(subst->entries[i].type);
                                *l = *r;
                                free(r);
                                break;
@@ -97,12 +98,13 @@ struct scheme *subst_apply_s(struct subst *subst, struct scheme *scheme)
        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->vars[j]) == 0) {
+                       if (strcmp(scheme->var[i], subst->entries[j].var) == 0) {
                                found = true;
                        }
                }
                if (!found)
-                       subst_insert(s, subst->vars[j], subst->types[j]);
+                       subst_insert(s, subst->entries[j].var,
+                               subst->entries[j].type);
        }
        scheme->type = subst_apply_t(s, scheme->type);
        subst_free(s);
@@ -111,8 +113,8 @@ struct scheme *subst_apply_s(struct subst *subst, struct scheme *scheme)
 
 struct gamma *subst_apply_g(struct subst *subst, struct gamma *gamma)
 {
-       for (int i = 0; i<gamma->nschemes; i++)
-               subst_apply_s(subst, gamma->schemes[i]);
+       for (int i = 0; i<gamma->nentries; i++)
+               subst_apply_s(subst, gamma->entries[i].scheme);
        return gamma;
 }
 
@@ -123,8 +125,8 @@ void subst_print(struct subst *s, FILE *out)
        } else {
                fprintf(out, "[");
                for (int i = 0; i<s->nvar; i++) {
-                       fprintf(out, "%s->", s->vars[i]);
-                       type_print(s->types[i], out);
+                       fprintf(out, "%s->", s->entries[i].var);
+                       type_print(s->entries[i].type, out);
                        if (i + 1 < s->nvar)
                                fprintf(out, ", ");
                }
@@ -136,11 +138,10 @@ void subst_free(struct subst *s)
 {
        if (s != NULL) {
                for (int i = 0; i<s->nvar; i++) {
-                       free(s->vars[i]);
-                       type_free(s->types[i]);
+                       free(s->entries[i].var);
+                       type_free(s->entries[i].type);
                }
-               free(s->vars);
-               free(s->types);
+               free(s->entries);
                free(s);
        }
 }
index ff9e71f..d3661c2 100644 (file)
@@ -7,8 +7,11 @@
 struct subst {
        int nvar;
        int capacity;
-       char **vars;
-       struct type **types;
+       struct subst_entry *entries;
+};
+struct subst_entry {
+       char *var;
+       struct type *type;
 };
 
 struct subst *subst_id();
index 29a3bee..dd25ee7 100644 (file)
--- a/sem/scc.c
+++ b/sem/scc.c
@@ -274,28 +274,21 @@ struct ast *ast_scc(struct ast *ast)
                                fundecls[i]->data.dfun->body[j], edges);
        int nedges;
        struct edge **edata = (struct edge **)
-               list_to_array(edges, &nedges, false);
+               list_to_array(edges, &nedges, false, 0);
 
        // Do tarjan's and convert back into the declaration list
        struct components *cs = tarjans(nfun, (void **)fundecls, nedges, edata);
-//     if (cs == NULL)
-//             die("malformed edges in tarjan's????");
 
        int i = ffun;
        for (struct components *c = cs; c != NULL; c = c->next) {
                struct decl *d = safe_malloc(sizeof(struct decl));
-               if (c->nnodes > 1) {
-                       d->type = dcomp;
-                       d->data.dcomp.ndecls = c->nnodes;
-                       d->data.dcomp.decls = safe_malloc(
-                               c->nnodes*sizeof(struct fundecl *));
-                       for (int i = 0; i<c->nnodes; i++)
-                               d->data.dcomp.decls[i] =
-                                       ((struct decl *)c->nodes[i])->data.dfun;
-               } else {
-                       d->type = dfundecl;
-                       d->data.dfun = ((struct decl *)c->nodes[0])->data.dfun;
-               }
+               d->type = dcomp;
+               d->data.dcomp.ndecls = c->nnodes;
+               d->data.dcomp.decls = safe_malloc(
+                       c->nnodes*sizeof(struct fundecl *));
+               for (int j = 0; j<c->nnodes; j++)
+                       d->data.dcomp.decls[j] =
+                               ((struct decl *)c->nodes[j])->data.dfun;
                ast->decls[i++] = d;
        }
        ast->ndecls = i;
diff --git a/util.c b/util.c
index 6c70c63..1653cad 100644 (file)
--- a/util.c
+++ b/util.c
@@ -155,7 +155,7 @@ void *safe_malloc(size_t size)
 void *safe_realloc(void *ptr, size_t size)
 {
        void *res = realloc(ptr, size);
-       if (res == NULL)
+       if (size > 0 && res == NULL)
                pdie("realloc");
        return res;
 }