reorder variable declarations
authorMart Lubbers <mart@martlubbers.net>
Wed, 17 Mar 2021 14:02:32 +0000 (15:02 +0100)
committerMart Lubbers <mart@martlubbers.net>
Wed, 17 Mar 2021 14:02:32 +0000 (15:02 +0100)
array.c
array.h
ast.c
gen.c
gen/c.c
gen/ssm.c
sem/hm/subst.c
sem/hm/subst.h
sem/scc.c
sem/vardecl.c
splc.c

diff --git a/array.c b/array.c
index 6b7d313..2905f0d 100644 (file)
--- a/array.c
+++ b/array.c
@@ -33,12 +33,30 @@ void array_append(struct array *a, void *x)
        a->el[a->nel++] = x;
 }
 
+void array_remove(struct array *a, size_t idx)
+{
+       for (size_t i = idx; i<a->nel-1; i++)
+               a[i] = a[i+1];
+       a->nel--;
+}
+
 void array_insert(struct array *a, size_t idx, void *x)
 {
-       array_append(a, NULL);
-       for (size_t i = a->nel-1; i>idx; i--)
-               a->el[i] = a->el[i-1];
-       a->el[idx] = x;
+       array_append(a, x);
+       array_move(a, a->nel-1, idx);
+}
+
+void array_move(struct array *a, size_t from, size_t to)
+{
+       void *t = a->el[from];
+       if (from < to) {
+               for (size_t i = from; i<to-1; i++)
+                       a->el[i] = a->el[i+1];
+       } else if (from > to) {
+               for (size_t i = from; i>to; i--)
+                       a->el[i] = a->el[i-1];
+       }
+       a->el[to] = t;
 }
 
 void array_free(struct array *a, void (*freefun)(void *))
diff --git a/array.h b/array.h
index e53698a..0f8fb28 100644 (file)
--- a/array.h
+++ b/array.h
@@ -46,6 +46,15 @@ void array_free(struct array *a, void (*freefun)(void *));
 //* free all element and keep the array
 void array_clean(struct array *a, void (*freefun)(void *));
 
+//* insert an item in a specific place, moving the other items
+void array_insert(struct array *a, size_t idx, void *x);
+
+//* remove an item from an array
+void array_remove(struct array *a, size_t idx);
+
+//* move an item from a position to another
+void array_move(struct array *a, size_t from, size_t to);
+
 //* insert an item in a sorted array
 void array_binsert(void *key, struct array *a, int (*cmp)(const void *, const void *));
 
diff --git a/ast.c b/ast.c
index ccc7a46..5ae01f2 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -287,8 +287,11 @@ void vardecl_print(struct vardecl *decl, int indent, FILE *out)
                safe_fprintf(out, "var");
        else
                type_print(decl->type, out);
-       safe_fprintf(out, " %s = ", decl->ident);
-       expr_print(decl->expr, out);
+       safe_fprintf(out, " %s", decl->ident);
+       if (decl->expr != NULL) {
+               safe_fprintf(out, "  = ");
+               expr_print(decl->expr, out);
+       }
        safe_fprintf(out, ";\n");
 }
 
@@ -468,7 +471,7 @@ static void expr_print2(struct expr *expr, FILE *out, struct ctx ctx)
                        safe_fprintf(out, ")");
                break;
        case ebool:
-               safe_fprintf(out, "%s", expr->data.ebool ? "true" : "false");
+               safe_fprintf(out, "%s", expr->data.ebool ? "True" : "False");
                break;
        case echar:
                safe_fprintf(out, "'%s'",
@@ -544,7 +547,8 @@ void vardecl_free(struct vardecl *decl)
 {
        type_free(decl->type);
        free(decl->ident);
-       expr_free(decl->expr);
+       if (decl->expr != NULL)
+               expr_free(decl->expr);
        free(decl);
 }
 
diff --git a/gen.c b/gen.c
index dfacb2b..a115b3a 100644 (file)
--- a/gen.c
+++ b/gen.c
@@ -100,7 +100,8 @@ static void ol_stmt(struct overload *st, struct stmt *stmt)
                ol_expr(st, stmt->data.sexpr);
                break;
        case svardecl:
-               ol_expr(st, stmt->data.svardecl->expr);
+               if (stmt->data.svardecl->expr != NULL)
+                       ol_expr(st, stmt->data.svardecl->expr);
                break;
        case swhile:
                ol_expr(st, stmt->data.swhile.pred);
diff --git a/gen/c.c b/gen/c.c
index 663dbde..889bf53 100644 (file)
--- a/gen/c.c
+++ b/gen/c.c
@@ -134,8 +134,11 @@ static void vardecl_genc(struct vardecl *vardecl, int indent, FILE *cout)
                return;
        pindent(indent, cout);
        type_genc(vardecl->type, cout);
-       safe_fprintf(cout, "%s = ", vardecl->ident);
-       expr_genc(vardecl->expr, cout);
+       safe_fprintf(cout, "%s", vardecl->ident);
+       if (vardecl->expr != NULL) {
+               safe_fprintf(cout, " = ", vardecl->ident);
+               expr_genc(vardecl->expr, cout);
+       }
        safe_fprintf(cout, ";\n");
 }
 
index 2e37d57..0a94702 100644 (file)
--- a/gen/ssm.c
+++ b/gen/ssm.c
@@ -366,7 +366,10 @@ static void stmt_genssm(struct genssmst *st, struct stmt *stmt, FILE *cout)
                safe_fprintf(cout, "ajs -1\n");
                break;
        case svardecl:
-               expr_genssm(st, stmt->data.svardecl->expr, cout);
+               if (stmt->data.svardecl->expr != NULL)
+                       expr_genssm(st, stmt->data.svardecl->expr, cout);
+               else
+                       safe_fprintf(cout, "ldc 0\n");
                add_vref(st, stmt->data.svardecl->ident, local, st->vdecl++);
                break;
        case swhile:
index fdea48d..c46756f 100644 (file)
@@ -5,9 +5,17 @@
 #include "../hm.h"
 #include "../../list.h"
 
-#define INCAP 50
+struct subst {
+       size_t nvar;
+       size_t capacity;
+       struct subst_entry *entries;
+};
+struct subst_entry {
+       struct ident var;
+       struct type *type;
+};
 
-#define KEEP_LIST
+#define INCAP 50
 
 struct subst *subst_id()
 {
index 1e3cb8e..11d7c98 100644 (file)
@@ -5,15 +5,7 @@
 #include "../hm.h"
 #include "../../ident.h"
 
-struct subst {
-       size_t nvar;
-       size_t capacity;
-       struct subst_entry *entries;
-};
-struct subst_entry {
-       struct ident var;
-       struct type *type;
-};
+struct subst;
 
 struct subst *subst_id();
 struct subst *subst_insert(struct subst *s, struct ident ident, struct type *t);
index 10681c0..93327a9 100644 (file)
--- a/sem/scc.c
+++ b/sem/scc.c
@@ -147,15 +147,15 @@ struct components *tarjans(
        return tj.head;
 }
 
-struct array edges_expr(int ndecls, struct decl **decls, void *parent,
-       struct expr *expr, struct array l)
+void edges_expr(int ndecls, struct decl **decls, void *parent,
+       struct expr *expr, struct array *l)
 {
        if (expr == NULL)
-               return l;
+               return;
        switch(expr->type) {
        case ebinop:
-               l = edges_expr(ndecls, decls, parent, expr->data.ebinop.l, l);
-               l = edges_expr(ndecls, decls, parent, expr->data.ebinop.r, l);
+               edges_expr(ndecls, decls, parent, expr->data.ebinop.l, l);
+               edges_expr(ndecls, decls, parent, expr->data.ebinop.r, l);
                break;
        case ebool:
                break;
@@ -163,7 +163,7 @@ struct array edges_expr(int ndecls, struct decl **decls, void *parent,
                break;
        case efuncall:
                ARRAY_ITER(struct expr *, e, i, &expr->data.efuncall.args )
-                       l = edges_expr(ndecls, decls, parent, e, l);
+                       edges_expr(ndecls, decls, parent, e, l);
                AIEND
                bool found = false;
                for (int i = 0; i<ndecls && !found; i++) {
@@ -172,7 +172,7 @@ struct array edges_expr(int ndecls, struct decl **decls, void *parent,
                                struct edge *edge = xalloc(1, struct edge);
                                edge->from = parent;
                                edge->to = (void *)decls[i];
-                               array_append(&l, edge);
+                               array_append(l, edge);
                                found = true;
                        }
                }
@@ -187,59 +187,53 @@ struct array edges_expr(int ndecls, struct decl **decls, void *parent,
        case enil:
                break;
        case etuple:
-               l = edges_expr(ndecls, decls, parent,
-                       expr->data.etuple.left, l);
-               l = edges_expr(ndecls, decls, parent,
-                       expr->data.etuple.right, l);
+               edges_expr(ndecls, decls, parent, expr->data.etuple.left, l);
+               edges_expr(ndecls, decls, parent, expr->data.etuple.right, l);
                break;
        case estring:
                break;
        case eunop:
-               return edges_expr(ndecls, decls, parent, expr->data.eunop.l, l);
+               edges_expr(ndecls, decls, parent, expr->data.eunop.l, l);
+               break;
        default:
                die("Unsupported expr node\n");
        }
-       return l;
 }
 
-struct array edges_stmt(int ndecls, struct decl **decls, void *parent,
-               struct stmt *stmt, struct array l)
+void edges_stmt(int ndecls, struct decl **decls, void *parent,
+               struct stmt *stmt, struct array *l)
 {
        switch(stmt->type) {
        case sassign:
-               l = edges_expr(ndecls, decls, parent,
-                       stmt->data.sassign.expr, l);
+               edges_expr(ndecls, decls, parent, stmt->data.sassign.expr, l);
                break;
        case sif:
-               l = edges_expr(ndecls, decls, parent, stmt->data.sif.pred, l);
+               edges_expr(ndecls, decls, parent, stmt->data.sif.pred, l);
                ARRAY_ITER(struct stmt *, s, i, &stmt->data.sif.then)
-                       l = edges_stmt(ndecls, decls, parent, s, l);
+                       edges_stmt(ndecls, decls, parent, s, l);
                AIEND
                ARRAY_ITER(struct stmt *, s, i, &stmt->data.sif.els)
-                       l = edges_stmt(ndecls, decls, parent, s, l);
+                       edges_stmt(ndecls, decls, parent, s, l);
                AIEND
                break;
        case sreturn:
-               l = edges_expr(ndecls, decls, parent, stmt->data.sreturn, l);
+               edges_expr(ndecls, decls, parent, stmt->data.sreturn, l);
                break;
        case sexpr:
-               l = edges_expr(ndecls, decls, parent, stmt->data.sexpr, l);
+               edges_expr(ndecls, decls, parent, stmt->data.sexpr, l);
                break;
        case svardecl:
-               l = edges_expr(ndecls, decls, parent,
-                       stmt->data.svardecl->expr, l);
+               edges_expr(ndecls, decls, parent, stmt->data.svardecl->expr, l);
                break;
        case swhile:
-               l = edges_expr(ndecls, decls, parent,
-                       stmt->data.swhile.pred, l);
+               edges_expr(ndecls, decls, parent, stmt->data.swhile.pred, l);
                ARRAY_ITER(struct stmt *, s, i, &stmt->data.swhile.body)
-                       l = edges_stmt(ndecls, decls, parent, s, l);
+                       edges_stmt(ndecls, decls, parent, s, l);
                AIEND
                break;
        default:
                die("Unsupported stmt node\n");
        }
-       return l;
 }
 
 int declcmp(const void *l, const void *r)
@@ -265,7 +259,7 @@ void sem_check_scc(struct ast *ast)
        array_init(&edges, nfun*2);
        for (size_t i = 0; i<nfun; i++) {
                ARRAY_ITER(struct stmt *, s, j, &fundecls[i]->data.dfun->body)
-                       edges = edges_stmt(nfun, fundecls, fundecls[i], s, edges);
+                       edges_stmt(nfun, fundecls, fundecls[i], s, &edges);
                AIEND
        }
 
index a1215c2..48005b9 100644 (file)
+#include <stdio.h>
+#include <string.h>
 #include "../ast.h"
 
-void fix_vars_fun(struct fundecl *d)
+static inline void var_refactor_ident(char **torep, char *from, size_t idx)
 {
-       (void)d;
+       char *t = *torep;
+       //This limits scopedepth to 9999
+       *torep = xalloc(strlen(from)+5, char);
+       sprintf(*torep, "_%s%lu", from, idx);
+       free(t);
+}
+
+static void var_refactor(struct array *body, size_t ifrom, char *from, size_t rescope, size_t scope);
+
+static void var_refactor_expr(struct expr *expr, char *from, size_t idx)
+{
+       switch (expr->type) {
+       case ebinop:
+               var_refactor_expr(expr->data.ebinop.l, from, idx);
+               var_refactor_expr(expr->data.ebinop.r, from, idx);
+               break;
+       case efuncall:
+               ARRAY_ITER(struct expr *, e, i, &expr->data.efuncall.args) {
+                       var_refactor_expr(e, from, idx);
+               } AIEND
+               break;
+       case eident:
+               if (strcmp(from, expr->data.eident) == 0)
+                       var_refactor_ident(&expr->data.eident, from, idx);
+               break;
+       case etuple:
+               var_refactor_expr(expr->data.etuple.left, from, idx);
+               var_refactor_expr(expr->data.etuple.right, from, idx);
+               break;
+       case eunop:
+               var_refactor_expr(expr->data.eunop.l, from, idx);
+               break;
+       default:
+               break;
+       }
+}
+
+static void var_refactor(struct array *body, size_t ifrom, char *from, size_t rescope, size_t scope)
+{
+       ARRAY_ITER(struct stmt *, s, i, body) {
+               if (i < ifrom)
+                       continue;
+               switch (s->type) {
+               case sassign:
+                       if (strcmp(s->data.sassign.ident, from) == 0)
+                               var_refactor_ident(&s->data.sassign.ident, from, rescope);
+                       var_refactor_expr(s->data.sassign.expr, from, rescope);
+                       break;
+               case svardecl:
+                       var_refactor_expr(s->data.svardecl->expr, from, rescope);
+                       if (s->data.svardecl->ident[0] != '_') {
+                               var_refactor(body, i+1, s->data.svardecl->ident, scope, scope);
+                               var_refactor_ident(&s->data.svardecl->ident, s->data.svardecl->ident, scope);
+                       }
+                       break;
+               case sexpr:
+                       var_refactor_expr(s->data.sexpr, from, rescope);
+                       break;
+               case sreturn:
+                       if (s->data.sreturn != NULL)
+                               var_refactor_expr(s->data.sreturn, from, rescope);
+                       break;
+               case swhile:
+                       var_refactor_expr(s->data.swhile.pred, from, rescope);
+                       var_refactor(&s->data.swhile.body, 0, from, rescope, scope+1);
+                       break;
+               case sif:
+                       var_refactor_expr(s->data.sif.pred, from, rescope);
+                       var_refactor(&s->data.sif.then, 0, from, rescope, scope+1);
+                       var_refactor(&s->data.sif.els, 0, from, rescope, scope+1);
+                       break;
+               default:
+                       break;
+               }
+       } AIEND
+
+}
+
+static void var_reorder(struct array *lp, struct array stmts, size_t *idx, bool top)
+{
+       ARRAY_ITER(struct stmt *, s, i, &stmts) {
+               switch(s->type) {
+               case svardecl:
+                       if (top) {
+                               array_move(lp, i, (*idx)++);
+                       } else {
+                               stmts.el[i] = stmt_assign(
+                                       safe_strdup(s->data.svardecl->ident),
+                                       array_null, s->data.svardecl->expr, s->loc);
+                               s->data.svardecl->expr = NULL;
+                               bool found = false;
+                               ARRAY_ITER(struct stmt *, s1, j, lp) {
+                                       if (s1->type == svardecl && strcmp(s1->data.svardecl->ident, s->data.svardecl->ident) == 0) {
+                                               found = true;
+                                               break;
+                                       }
+                               }AIEND
+                               if (!found)
+                                       array_insert(lp, (*idx)++, s);
+                               else
+                                       stmt_free(s);
+                       }
+                       break;
+               case swhile:
+                       var_reorder(lp, s->data.swhile.body, idx, false);
+                       break;
+               case sif:
+                       var_reorder(lp, s->data.sif.then, idx, false);
+                       var_reorder(lp, s->data.sif.els, idx, false);
+                       break;
+               default:
+                       break;
+               }
+       } AIEND
 }
 
 void sem_check_vardecls(struct ast *ast)
 {
        for (int i = 0; i<ast->ndecls; i++) {
                if (ast->decls[i]->type == dcomp) {
-                       ARRAY_ITER(struct fundecl *, d, i, &ast->decls[i]->data.dcomp)
-                               fix_vars_fun(d);
+                       ARRAY_ITER(struct fundecl *, d, j, &ast->decls[i]->data.dcomp)
+                               var_refactor(&d->body, 0, "", 0, 0);
+                               size_t idx = 0;
+                               var_reorder(&d->body, d->body, &idx, true);
                        AIEND
                }
        }
diff --git a/splc.c b/splc.c
index 8a4f1f3..48311c8 100644 (file)
--- a/splc.c
+++ b/splc.c
@@ -96,7 +96,7 @@ int main(int argc, char *argv[])
        cout = safe_fopen(cfile, "w+");
        free(cfile);
 
-//     gen(result, lang, cout);
+       gen(result, lang, cout);
 
        safe_fclose(cout);
        safe_fprintf(stderr, "code generation done\n");