--- /dev/null
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "util.h"
+#include "array.h"
+
+struct array array_null = {.nel=0, .cap=0, .el=NULL};
+
+void array_init(struct array *array, size_t cap)
+{
+ array->nel = 0;
+ array->cap = cap;
+ array->el = xalloc(cap, void *);
+}
+
+struct array array_resize(struct array a, size_t cap)
+{
+ if (cap > a.cap)
+ a.el = xrealloc(a.el, a.cap = cap, void *);
+ return a;
+}
+
+struct array array_append(struct array a, void *x)
+{
+ if (a.nel >= a.cap)
+ a = array_resize(a, a.cap == 0 ? 8 : 2*a.cap);
+ a.el[a.nel++] = x;
+ return a;
+}
+
+//struct array array_insert(struct array a, size_t idx, void *x)
+//{
+// a = array_append(a, NULL);
+// for (size_t i = a.nel; i>idx; i--)
+// a.el[i] = a.el[i-1];
+// a.el[idx] = x;
+// return a;
+//}
+
+void array_free(struct array a, void (*freefun)(void *))
+{
+ array_clean(a, freefun);
+ free(a.el);
+}
+
+struct array array_clean(struct array a, void (*freefun)(void *))
+{
+ if (freefun != NULL)
+ ARRAY_ITERI(i, a)
+ freefun(a.el[i]);
+ a.nel = 0;
+ return a;
+}
--- /dev/null
+#ifndef ARRAY_H
+#define ARRAY_H
+
+#include <stdint.h>
+
+#define ARRAY_EL(type, array, idx)\
+ ((type)(array.el[idx]))
+
+#define ARRAY_ITERI(iter, a)\
+ for (size_t (iter) = 0; (iter)<(a).nel; (iter)++)
+
+#define ARRAY_ITER(type, x, iter, a)\
+ ARRAY_ITERI (iter, a) {\
+ type (x) = ARRAY_EL(type, a, iter);
+#define AIEND }
+
+#define ARRAY_SIZE(a) (a).nel
+#define ARRAY_ELS(type, a) ((type *)(a).el)
+
+
+extern struct array array_null;
+
+struct array {
+ size_t nel;
+ size_t cap;
+ void **el;
+};
+
+//* Initialise an array
+void array_init(struct array *array, size_t cap);
+
+//* Resize an array to hold at least a certain capacity
+struct array array_resize(struct array a, size_t cap);
+
+//* Create an array with the given capacity
+struct array *array_new(size_t cap);
+
+//* Append an item to the array
+struct array array_append(struct array a, void *x);
+
+//* free all elements and free the array
+void array_free(struct array, void (*freefun)(void *));
+
+//* free all element and keep the array
+struct array array_clean(struct array array, void (*freefun)(void *));
+
+#endif
#include <stdio.h>
#include <string.h>
+#include "array.h"
#include "util.h"
#include "ast.h"
#include "type.h"
};
const char *unop_str[] = { [inverse] = "!", [negate] = "-", };
-struct ast *ast(struct list *decls, YYLTYPE l)
+struct ast *ast(struct array decls, YYLTYPE l)
{
struct ast *res = xalloc(1, struct ast);
res->loc = l;
- res->decls = (struct decl **)list_to_array(decls, &res->ndecls, true, 0);
+ res->ndecls = ARRAY_SIZE(decls);
+ res->decls = ARRAY_ELS(struct decl *, decls);
return res;
}
res->expr = expr;
return res;
}
-struct fundecl *fundecl(char *ident, struct list *args, struct list *atypes,
- struct type *rtype, struct list *body, YYLTYPE l)
+
+struct fundecl *fundecl(char *ident, struct array args, struct array atypes,
+ struct type *rtype, struct array body, YYLTYPE l)
{
struct fundecl *res = xalloc(1, struct fundecl);
res->loc = l;
res->ident = ident;
- res->args = (char **)list_to_array(args, &res->nargs, true, 0);
- res->atypes = (struct type **)list_to_array(atypes, &res->natypes, true, 0);
+ res->args = args;
+ res->atypes = atypes;
res->rtype = rtype;
- //Reserve room for an optional extra return inserted by the compiler
- res->body = (struct stmt **)list_to_array(body, &res->nbody, true, 1);
+ res->body = body;
return res;
}
return res;
}
-struct stmt *stmt_assign(char *ident, struct list *fields, struct expr *expr, YYLTYPE l)
+struct stmt *stmt_assign(char *ident, struct array fields, struct expr *expr, YYLTYPE l)
{
struct stmt *res = xalloc(1, struct stmt);
res->loc = l;
res->type = sassign;
res->data.sassign.ident = ident;
- res->data.sassign.fields = (char **)
- list_to_array(fields, &res->data.sassign.nfields, true, 0);
+ res->data.sassign.fields = fields;
res->data.sassign.expr = expr;
return res;
}
-struct stmt *stmt_if(struct expr *pred, struct list *then, struct list *els, YYLTYPE l)
+struct stmt *stmt_if(struct expr *pred, struct array then, struct array els, YYLTYPE l)
{
struct stmt *res = xalloc(1, struct stmt);
res->loc = l;
res->type = sif;
res->data.sif.pred = pred;
- res->data.sif.then = (struct stmt **)
- 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, 0);
+ res->data.sif.then = then;
+ res->data.sif.els = els;
return res;
}
return res;
}
-struct stmt *stmt_while(struct expr *pred, struct list *body, YYLTYPE l)
+struct stmt *stmt_while(struct expr *pred, struct array body, YYLTYPE l)
{
struct stmt *res = xalloc(1, struct stmt);
res->loc = l;
res->type = swhile;
res->data.swhile.pred = pred;
- res->data.swhile.body = (struct stmt **)
- list_to_array(body, &res->data.swhile.nbody, true, 0);
+ res->data.swhile.body = body;
return res;
}
|| strcmp(t, "print") == 0;
}
-struct expr *expr_funcall_real(char *ident, struct list *args, YYLTYPE l)
+struct expr *expr_funcall_real(char *ident, struct array args, YYLTYPE l)
{
struct expr *res = xalloc(1, struct expr);
res->loc = l;
res->type = efuncall;
res->data.efuncall.ident = ident;
- res->data.efuncall.args = (struct expr **)
- list_to_array(args, &res->data.efuncall.nargs, true, 0);
+ res->data.efuncall.args = args;
return res;
}
-static struct expr *expr_apply_fields(struct expr *r, struct list *fields, YYLTYPE l)
+static struct expr *expr_apply_fields(struct expr *r, struct array fields, YYLTYPE l)
{
- FOREACH(field, fields) {
- if (is_valid_field(field->el)) {
- struct list *as = list_cons(r, NULL);
- r = expr_funcall_real(field->el, as, l);
+ ARRAY_ITER(char *, f, i, fields) {
+ if (is_valid_field(f)) {
+ struct array as;
+ array_init(&as, 1);
+ as = array_append(as, r);
+ r = expr_funcall_real(f, as, l);
}
- }
- list_free(fields, NULL);
+ } AIEND
+ array_free(fields, NULL);
return r;
}
-struct expr *expr_funcall(char *ident, struct list *args, struct list *fields, YYLTYPE l)
+struct expr *expr_funcall(char *ident, struct array args, struct array fields, YYLTYPE l)
{
struct expr *res = expr_funcall_real(ident, args, l);
res = expr_apply_fields(res, fields, l);
return res;
}
-struct expr *expr_ident(char *ident, struct list *fields, YYLTYPE l)
+struct expr *expr_ident(char *ident, struct array fields, YYLTYPE l)
{
struct expr *res = xalloc(1, struct expr);
res->loc = l;
void fundecl_print(struct fundecl *decl, FILE *out)
{
safe_fprintf(out, "%s (", decl->ident);
- for (int i = 0; i<decl->nargs; i++) {
- safe_fprintf(out, "%s", decl->args[i]);
- if (i < decl->nargs - 1)
+ ARRAY_ITER(char *, arg, i, decl->args) {
+ safe_fprintf(out, "%s", arg);
+ if (i < ARRAY_SIZE(decl->args) - 1)
safe_fprintf(out, ", ");
- }
+ } AIEND
safe_fprintf(out, ")");
if (decl->rtype != NULL) {
safe_fprintf(out, " :: ");
- for (int i = 0; i<decl->natypes; i++) {
- type_print(decl->atypes[i], out);
+ ARRAY_ITER(struct type *, atype, i, decl->atypes) {
+ type_print(atype, out);
safe_fprintf(out, " ");
- }
+ } AIEND
safe_fprintf(out, "-> ");
type_print(decl->rtype, out);
}
safe_fprintf(out, " {\n");
- for (int i = 0; i<decl->nbody; i++)
- stmt_print(decl->body[i], 1, out);
+ ARRAY_ITER(struct stmt *, stmt, i, decl->body)
+ stmt_print(stmt, 1, out);
+ AIEND
safe_fprintf(out, "}\n");
}
break;
case dcomp:
fprintf(out, "//<<<comp\n");
- for (int i = 0; i<decl->data.dcomp.ndecls; i++)
- fundecl_print(decl->data.dcomp.decls[i], out);
+ ARRAY_ITER(struct fundecl *, d, i, decl->data.dcomp)
+ fundecl_print(d, out);
+ AIEND
fprintf(out, "//>>>comp\n");
break;
default:
case sassign:
pindent(indent, out);
fprintf(out, "%s", stmt->data.sassign.ident);
- for (int i = 0; i<stmt->data.sassign.nfields; i++)
- fprintf(out, ".%s", stmt->data.sassign.fields[i]);
+ ARRAY_ITER(char *, f, i, stmt->data.sassign.fields)
+ fprintf(out, ".%s", f);
+ AIEND
safe_fprintf(out, " = ");
expr_print(stmt->data.sassign.expr, out);
safe_fprintf(out, ";\n");
safe_fprintf(out, "if (");
expr_print(stmt->data.sif.pred, out);
safe_fprintf(out, ") {\n");
- for (int i = 0; i<stmt->data.sif.nthen; i++)
- stmt_print(stmt->data.sif.then[i], indent+1, out);
+ ARRAY_ITER(struct stmt *, s, i, stmt->data.sif.then)
+ stmt_print(s, indent+1, out);
+ AIEND
pindent(indent, out);
safe_fprintf(out, "} else {\n");
- for (int i = 0; i<stmt->data.sif.nels; i++)
- stmt_print(stmt->data.sif.els[i], indent+1, out);
+ ARRAY_ITER(struct stmt *, s, i, stmt->data.sif.els)
+ stmt_print(s, indent+1, out);
+ AIEND
pindent(indent, out);
safe_fprintf(out, "}\n");
break;
safe_fprintf(out, "while (");
expr_print(stmt->data.swhile.pred, out);
safe_fprintf(out, ") {\n");
- for (int i = 0; i<stmt->data.swhile.nbody; i++)
- stmt_print(stmt->data.swhile.body[i], indent+1, out);
+ ARRAY_ITER(struct stmt *, s, i, stmt->data.swhile.body)
+ stmt_print(s, indent+1, out);
+ AIEND
pindent(indent, out);
safe_fprintf(out, "}\n");
break;
break;
case efuncall:
safe_fprintf(out, "%s(", expr->data.efuncall.ident);
- for(int i = 0; i<expr->data.efuncall.nargs; i++) {
- expr_print(expr->data.efuncall.args[i], out);
- if (i+1 < expr->data.efuncall.nargs)
+ ARRAY_ITER(struct expr *, e, i, expr->data.efuncall.args) {
+ expr_print(e, out);
+ if (i+1 < ARRAY_SIZE(expr->data.efuncall.args))
safe_fprintf(out, ", ");
- }
+ } AIEND
safe_fprintf(out, ")");
break;
case eint:
void fundecl_free(struct fundecl *decl)
{
free(decl->ident);
- for (int i = 0; i<decl->nargs; i++)
- free(decl->args[i]);
- free(decl->args);
- for (int i = 0; i<decl->natypes; i++)
- type_free(decl->atypes[i]);
- free(decl->atypes);
+ array_free(decl->args, free);
+ array_free(decl->atypes, (void (*)(void *))type_free);
type_free(decl->rtype);
- for (int i = 0; i<decl->nbody; i++)
- stmt_free(decl->body[i]);
- free(decl->body);
+ array_free(decl->body, (void (*)(void *))stmt_free);
free(decl);
}
return;
switch(decl->type) {
case dcomp:
- for (int i = 0; i<decl->data.dcomp.ndecls; i++)
- fundecl_free(decl->data.dcomp.decls[i]);
- free(decl->data.dcomp.decls);
+ array_free(decl->data.dcomp, (void (*)(void *))fundecl_free);
break;
case dfundecl:
fundecl_free(decl->data.dfun);
switch(stmt->type) {
case sassign:
free(stmt->data.sassign.ident);
- for (int i = 0; i<stmt->data.sassign.nfields; i++)
- free(stmt->data.sassign.fields[i]);
- free(stmt->data.sassign.fields);
+ array_free(stmt->data.sassign.fields, free);
expr_free(stmt->data.sassign.expr);
break;
case sif:
expr_free(stmt->data.sif.pred);
- for (int i = 0; i<stmt->data.sif.nthen; i++)
- stmt_free(stmt->data.sif.then[i]);
- free(stmt->data.sif.then);
- for (int i = 0; i<stmt->data.sif.nels; i++)
- stmt_free(stmt->data.sif.els[i]);
- free(stmt->data.sif.els);
+ array_free(stmt->data.sif.then, (void (*)(void *))stmt_free);
+ array_free(stmt->data.sif.els, (void (*)(void *))stmt_free);
break;
case sreturn:
expr_free(stmt->data.sreturn);
break;
case swhile:
expr_free(stmt->data.swhile.pred);
- for (int i = 0; i<stmt->data.swhile.nbody; i++)
- stmt_free(stmt->data.swhile.body[i]);
- free(stmt->data.swhile.body);
+ array_free(stmt->data.swhile.body, (void (*)(void *))stmt_free);
break;
case svardecl:
vardecl_free(stmt->data.svardecl);
break;
case efuncall:
free(expr->data.efuncall.ident);
- for (int i = 0; i<expr->data.efuncall.nargs; i++)
- expr_free(expr->data.efuncall.args[i]);
- free(expr->data.efuncall.args);
+ array_free(expr->data.efuncall.args, (void (*)(void *))expr_free);
break;
case eint:
break;
#include <stdio.h>
#include <stdbool.h>
+#include "array.h"
#include "util.h"
#include "type.h"
struct ast;
struct fundecl {
YYLTYPE loc;
char *ident;
- int nargs;
- char **args;
- int natypes;
- struct type **atypes;
+ struct array args; // char *
+ struct array atypes; // struct type *
struct type *rtype;
- int nbody;
- struct stmt **body;
+ struct array body; //struct stmt *
};
struct decl {
//NOTE: DON'T CHANGE THIS ORDER
enum {dcomp, dvardecl, dfundecl} type;
union {
- struct {
- int ndecls;
- struct fundecl **decls;
- } dcomp;
+ struct array dcomp; //struct fundecl *
struct fundecl *dfun;
struct vardecl *dvar;
} data;
union {
struct {
char *ident;
- int nfields;
- char **fields;
+ struct array fields; //char *
struct expr *expr;
} sassign;
struct {
struct expr *pred;
- int nthen;
- struct stmt **then;
- int nels;
- struct stmt **els;
+ struct array then; //struct stmt *
+ struct array els; //struct stmt *
} sif;
struct vardecl *svardecl;
struct expr *sreturn;
struct expr *sexpr;
struct {
struct expr *pred;
- int nbody;
- struct stmt **body;
+ struct array body; //struct stmt *
} swhile;
} data;
};
char echar;
struct {
char *ident;
- int nargs;
- struct expr **args;
+ struct array args; // struct expr *
} efuncall;
int eint;
char *eident;
} data;
};
-struct ast *ast(struct list *decls, YYLTYPE l);
+struct ast *ast(struct array decls, YYLTYPE l);
struct vardecl *vardecl(struct type *type, char *ident, struct expr *expr, YYLTYPE l);
-struct fundecl *fundecl(char *ident, struct list *args, struct list *atypes, struct type *rtype, struct list *body, YYLTYPE l);
+struct fundecl *fundecl(char *ident, struct array args, struct array atypes, struct type *rtype, struct array body, YYLTYPE l);
struct decl *decl_fun(struct fundecl *fundecl, YYLTYPE l);
struct decl *decl_var(struct vardecl *vardecl, YYLTYPE l);
-struct stmt *stmt_assign(char *ident, struct list *fields, struct expr *expr, YYLTYPE l);
-struct stmt *stmt_if(struct expr *pred, struct list *then, struct list *els, YYLTYPE l);
+struct stmt *stmt_assign(char *ident, struct array fields, struct expr *expr, YYLTYPE l);
+struct stmt *stmt_if(struct expr *pred, struct array then, struct array els, YYLTYPE l);
struct stmt *stmt_return(struct expr *rtrn, YYLTYPE l);
struct stmt *stmt_expr(struct expr *expr, YYLTYPE l);
struct stmt *stmt_vardecl(struct vardecl *vardecl, YYLTYPE l);
-struct stmt *stmt_while(struct expr *pred, struct list *body, YYLTYPE l);
+struct stmt *stmt_while(struct expr *pred, struct array body, YYLTYPE l);
struct expr *expr_binop(struct expr *left, enum binop op, struct expr *right, YYLTYPE l);
struct expr *expr_bool(bool b, YYLTYPE l);
struct expr *expr_char(char *c, YYLTYPE l);
-struct expr *expr_funcall(char *ident, struct list *args, struct list *fields, YYLTYPE l);
+struct expr *expr_funcall(char *ident, struct array args, struct array fields, YYLTYPE l);
struct expr *expr_int(int integer, YYLTYPE l);
-struct expr *expr_ident(char *ident, struct list *fields, YYLTYPE l);
+struct expr *expr_ident(char *ident, struct array fields, YYLTYPE l);
struct expr *expr_nil(YYLTYPE l);
struct expr *expr_tuple(struct expr *left, struct expr *right, YYLTYPE l);
struct expr *expr_string(char *str, YYLTYPE l);
break;
case efuncall:
safe_fprintf(cout, "%s(", expr->data.efuncall.ident);
- for(int i = 0; i<expr->data.efuncall.nargs; i++) {
- expr_genc(expr->data.efuncall.args[i], cout);
- if (i+1 < expr->data.efuncall.nargs)
+ ARRAY_ITER(struct expr *, e, i, expr->data.efuncall.args) {
+ expr_genc(e, cout);
+ if (i+1 < ARRAY_SIZE(expr->data.efuncall.args))
safe_fprintf(cout, ", ");
- }
+ } AIEND
safe_fprintf(cout, ")");
break;
case eint:
case sassign:
pindent(indent, cout);
fprintf(cout, "%s", stmt->data.sassign.ident);
- for (int i = 0; i<stmt->data.sassign.nfields; i++)
- fprintf(cout, "->%s", stmt->data.sassign.fields[i]);
+ ARRAY_ITER(char *, f, i, stmt->data.sassign.fields)
+ fprintf(cout, "->%s", f);
+ AIEND
safe_fprintf(cout, " = ");
expr_genc(stmt->data.sassign.expr, cout);
safe_fprintf(cout, ";\n");
safe_fprintf(cout, "if (");
expr_genc(stmt->data.sif.pred, cout);
safe_fprintf(cout, ") {\n");
- for (int i = 0; i<stmt->data.sif.nthen; i++)
- stmt_genc(stmt->data.sif.then[i], indent+1, cout);
+ ARRAY_ITER(struct stmt *, s, i, stmt->data.sif.then)
+ stmt_genc(s, indent+1, cout);
+ AIEND
pindent(indent, cout);
safe_fprintf(cout, "} else {\n");
- for (int i = 0; i<stmt->data.sif.nels; i++)
- stmt_genc(stmt->data.sif.els[i], indent+1, cout);
+ ARRAY_ITER(struct stmt *, s, i, stmt->data.sif.els)
+ stmt_genc(s, indent+1, cout);
+ AIEND
pindent(indent, cout);
safe_fprintf(cout, "}\n");
break;
safe_fprintf(cout, "while (");
expr_genc(stmt->data.swhile.pred, cout);
safe_fprintf(cout, ") {\n");
- for (int i = 0; i<stmt->data.swhile.nbody; i++)
- stmt_genc(stmt->data.swhile.body[i], indent+1, cout);
+ ARRAY_ITER(struct stmt *, s, i, stmt->data.swhile.body)
+ stmt_genc(s, indent+1, cout);
+ AIEND
pindent(indent, cout);
safe_fprintf(cout, "}\n");
break;
{
type_genc(decl->rtype, cout);
safe_fprintf(cout, "%s (", decl->ident);
- for (int i = 0; i<decl->nargs; i++) {
- if (i < decl->natypes)
+ ARRAY_ITER(char *, a, i, decl->args) {
+ if (i >= ARRAY_SIZE(decl->atypes))
die("function with unmatched type\n");
- safe_fprintf(cout, "%s", decl->args[i]);
- if (i < decl->nargs - 1)
+ safe_fprintf(cout, "%s", a);
+ if (i < ARRAY_SIZE(decl->args) - 1)
safe_fprintf(cout, ", ");
- }
+ } AIEND
safe_fprintf(cout, ") /*");
if (decl->rtype != NULL) {
safe_fprintf(cout, " :: ");
- for (int i = 0; i<decl->natypes; i++) {
- type_print(decl->atypes[i], cout);
+ ARRAY_ITER(struct type *, t, i, decl->atypes) {
+ type_print(t, cout);
safe_fprintf(cout, " ");
- }
+ } AIEND
safe_fprintf(cout, "-> ");
type_print(decl->rtype, cout);
}
safe_fprintf(cout, "*/ {\n");
- for (int i = 0; i<decl->nbody; i++)
- stmt_genc(decl->body[i], 1, cout);
+ ARRAY_ITER(struct stmt *, s, i, decl->body)
+ stmt_genc(s, 1, cout);
+ AIEND
safe_fprintf(cout, "}\n");
}
switch (decl->type) {
case dcomp:
//TODO generate prototypes?
- for (int i = 0; i<decl->data.dcomp.ndecls; i++)
- fundecl_genc(decl->data.dcomp.decls[i], cout);
+ ARRAY_ITER(struct fundecl *, d, i, decl->data.dcomp)
+ fundecl_genc(d, cout);
+ AIEND
break;
case dfundecl:
fundecl_genc(decl->data.dfun, cout);
%{
#include <stdio.h>
+#include "array.h"
#include "ast.h"
#include "list.h"
#include "parse.h"
//%expect 1
// Tuples and parenthesis
//%expect-rr 1
-%glr-parser
+//%glr-parser
%locations
%parse-param { struct ast **result }
%union {
struct expr *expr;
struct stmt *stmt;
- struct list *list;
+ struct array array;
struct vardecl *vardecl;
struct fundecl *fundecl;
struct type *type;
%type <ast> start
%type <expr> expr tuply
-%type <list> args body decls fargs field fnargs nargs funtype bbody
+%type <array> decls funtype args nargs body bbody fargs fnargs field
%type <stmt> stmt
%type <type> type ftype
%type <vardecl> vardecl
start : decls { *result = ast($1, @$); } ;
decls
- : /* empty */ { $$ = NULL; }
- | decls vardecl { $$ = list_cons(decl_var($2, @2), $1); }
- | decls fundecl { $$ = list_cons(decl_fun($2, @2), $1); }
+ : /* empty */ { $$ = array_null; }
+ | decls vardecl { $$ = array_append($1, decl_var($2, @2)); }
+ | decls fundecl { $$ = array_append($1, decl_fun($2, @2)); }
;
vardecl
: VAR IDENT ASSIGN expr SEMICOLON { $$ = vardecl(NULL, $2, $4, @$); }
| type IDENT ASSIGN expr SEMICOLON { $$ = vardecl($1, $2, $4, @$); }
;
fundecl
- : IDENT BOPEN args BCLOSE COPEN body CCLOSE
- { $$ = fundecl($1, $3, NULL, NULL, $6, @$); }
- | IDENT BOPEN args BCLOSE CONS CONS funtype ARROW ftype COPEN body CCLOSE
- { $$ = fundecl($1, $3, $7, $9, $11, @$); }
+ : IDENT BOPEN args BCLOSE bbody
+ { $$ = fundecl($1, $3, array_null, NULL, $5, @$); }
+ | IDENT BOPEN args BCLOSE CONS CONS funtype ARROW ftype bbody
+ { $$ = fundecl($1, $3, $7, $9, $10, @$); }
;
funtype
- : /* empty */ { $$ = NULL; }
- | funtype ftype { $$ = list_cons($2, $1); }
+ : /* empty */ { $$ = array_null; }
+ | funtype ftype { $$ = array_append($1, $2); }
;
/* don't allow vardecls to be fully polymorph, this complicates parsing a lot */
type
| IDENT { $$ = type_var_str($1); free($1); }
;
args
- : /* empty */ { $$ = NULL; }
+ : /* empty */ { $$ = array_null; }
| nargs
;
nargs
- : nargs COMMA IDENT { $$ = list_cons($3, $1); }
- | IDENT { $$ = list_cons($1, NULL); }
+ : nargs COMMA IDENT { $$ = array_append($1, $3); }
+ | IDENT { array_init(&$$, 8); $$ = array_append($$, $1); }
;
fargs
- : /* empty */ { $$ = NULL; }
+ : /* empty */ { $$ = array_null; }
| fnargs
;
fnargs
- : fnargs COMMA expr { $$ = list_cons($3, $1); }
- | expr { $$ = list_cons($1, NULL); }
+ : fnargs COMMA expr { $$ = array_append($1, $3); }
+ | expr { array_init(&$$, 8); $$ = array_append($$, $1); }
;
body
- : /* empty */ { $$ = NULL; }
- | body stmt { $$ = list_cons($2, $1); }
+ : /* empty */ { $$ = array_null; }
+ | body stmt { $$ = array_append($1, $2); }
;
field
- : /* empty */ { $$ = NULL; }
- | field DOT IDENT { $$ = list_cons($3, $1); }
+ : /* empty */ { $$ = array_null; }
+ | field DOT IDENT { $$ = array_append($1, $3); }
;
bbody
: COPEN body CCLOSE { $$ = $2; }
- | stmt { $$ = list_cons($1, NULL); }
+ | stmt { array_init(&$$, 1); $$ = array_append($$, $1); }
;
stmt
- : IF BOPEN expr BCLOSE bbody { $$ = stmt_if($3, $5, NULL, @$); }
+ : IF BOPEN expr BCLOSE bbody { $$ = stmt_if($3, $5, array_null, @$); }
| IF BOPEN expr BCLOSE bbody ELSE bbody { $$ = stmt_if($3, $5, $7, @$); }
| WHILE BOPEN expr BCLOSE bbody { $$ = stmt_while($3, $5, @$); }
| IDENT field ASSIGN expr SEMICOLON { $$ = stmt_assign($1, $2, $4, @$); }
#include <stdlib.h>
#include <string.h>
+#include <stdint.h>
#include "list.h"
#include "sem/scc.h"
return vardecl;
}
-void type_comp(struct gamma *gamma, int ndecls, struct fundecl **decl)
+void type_comp(struct gamma *gamma, struct array decl)
{
//Create a fresh variable for every function in the component
- struct type **fs = xalloc(ndecls, struct type *);
- for (int i = 0; i<ndecls; i++) {
+ struct type **fs = xalloc(ARRAY_SIZE(decl), struct type *);
+ ARRAY_ITER(struct fundecl *, d, i, decl) {
fs[i] = gamma_fresh(gamma);
- for (int j = 0; j<decl[i]->nargs; j++) {
+ ARRAY_ITERI(j, d->args) {
struct type *a = gamma_fresh(gamma);
fs[i] = type_arrow(a, fs[i]);
}
- gamma_insert(gamma, ident_str(decl[i]->ident), scheme_create(fs[i]));
- }
+ gamma_insert(gamma, ident_str(d->ident), scheme_create(fs[i]));
+ } AIEND
//Infer each function
struct subst *s0 = subst_id();
- for (int i = 0; i<ndecls; i++) {
- struct subst *s1 = infer_fundecl(gamma, decl[i],
+ ARRAY_ITERI(i, decl) {
+ struct subst *s1 = infer_fundecl(gamma,
+ ARRAY_EL(struct fundecl *, decl, i),
subst_apply_t(s0, fs[i]));
s0 = subst_union(s1, s0);
subst_apply_g(s0, gamma);
}
//Generalise all functions and put in gamma
- for (int i = 0; i<ndecls; i++) {
+ ARRAY_ITER(struct fundecl *, d, i, decl) {
struct type *t = subst_apply_t(s0, fs[i]);
//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--) {
- dt = type_arrow(decl[i]->atypes[j], dt);
- }
- struct subst *s1 = unify(decl[i]->loc, dt, t);
+ if (d->rtype != NULL) {
+ struct type *dt = d->rtype;
+ for (int j = (int)ARRAY_SIZE(d->atypes)-1; j>=0; j--)
+ dt = type_arrow(ARRAY_EL(struct type *,
+ d->atypes, j), dt);
+ struct subst *s1 = unify(d->loc, dt, t);
subst_apply_t(s1, fs[i]);
subst_free(s1);
type_free(dt);
}
- gamma_insert(gamma, ident_str(decl[i]->ident), scheme_generalise(gamma, t));
+ gamma_insert(gamma, ident_str(d->ident), scheme_generalise(gamma, t));
//Put the type in the ast
- 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);
- decl[i]->rtype = type_dup(t);
- }
+ d->atypes = array_clean(d->atypes, NULL);
+ d->atypes = array_resize(d->atypes, ARRAY_SIZE(d->args));
+
+ ARRAY_ITERI(j, d->args) {
+ d->atypes = array_append(d->atypes, (void *)type_dup(t->data.tarrow.l));
+ t = t->data.tarrow.r;
+ }
+ d->rtype = type_dup(t);
+ } AIEND
//Free all types
- for (int i = 0; i<ndecls; i++)
+ for (size_t i = 0; i<ARRAY_SIZE(decl); i++)
type_free(fs[i]);
free(fs);
subst_free(s0);
}
bool check_return_stmt(struct stmt *stmt);
-bool check_return_body(int nbody, struct stmt **body)
+bool check_return_body(struct array body)
{
- for (int i = 0; i<nbody; i++)
- if (check_return_stmt(body[i]))
+ ARRAY_ITER(struct stmt *, s, i, body)
+ if (check_return_stmt(s))
return true;
+ AIEND
return false;
}
case sassign:
return false;
case sif:
- return check_return_body(stmt->data.sif.nthen, stmt->data.sif.then)
- && check_return_body(stmt->data.sif.nels, stmt->data.sif.els);
+ return check_return_body(stmt->data.sif.then)
+ && check_return_body(stmt->data.sif.els);
case swhile:
- return check_return_body(stmt->data.swhile.nbody,
- stmt->data.swhile.body);
+ return check_return_body(stmt->data.swhile.body);
case sreturn:
return true;
default:
}
}
-void check_return_comp(int ndecl, struct fundecl **decls)
+void check_return_comp(struct array decl)
{
- for (int i = 0; i<ndecl; i++) {
- if (decls[i]->rtype->type == tbasic &&
- decls[i]->rtype->data.tbasic == btvoid)
+ ARRAY_ITER(struct fundecl *, d, i, decl) {
+ if (d->rtype->type == tbasic && d->rtype->data.tbasic == btvoid)
continue;
- if (!check_return_body(decls[i]->nbody, decls[i]->body))
- type_error(decls[i]->loc, true,
- "%s doesn't return properly", decls[i]->ident);
- }
+ if (!check_return_body(d->body))
+ type_error(d->loc, true,
+ "%s doesn't return properly", d->ident);
+ } AIEND
}
-void add_return_if_none(int ndecl, struct fundecl **decl)
+void add_return_if_none(struct array 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);
- }
- }
+ ARRAY_ITER(struct fundecl *, d, i, decl)
+ if (d->rtype == NULL && !check_return_body(d->body))
+ d->body = array_append(d->body, stmt_return(NULL, d->loc));
+ AIEND
}
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++) {
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);
+ add_return_if_none(decl->data.dcomp);
+ type_comp(gamma, decl->data.dcomp);
+ check_return_comp(decl->data.dcomp);
break;
case dfundecl:
die("fundecls should be gone by now\n");
struct type *t = ft;
struct subst *s0 = subst_id();
//Infer args
- for (int i = 0; i<expr->data.efuncall.nargs; i++) {
+ ARRAY_ITER(struct expr *, a, i, expr->data.efuncall.args) {
if (t->type != tarrow)
type_error(expr->loc, true,
"too many arguments to %s\n",
expr->data.efuncall.ident);
- s1 = infer_expr(gamma,
- expr->data.efuncall.args[i], t->data.tarrow.l);
+ s1 = infer_expr(gamma, a, t->data.tarrow.l);
s0 = subst_union(s1, s0);
t = t->data.tarrow.r;
- }
+ } AIEND
if (t->type == tarrow)
type_error(expr->loc, true,
"not enough arguments to %s\n",
return NULL;
}
-struct subst *infer_body(struct gamma *gamma, int nstmt, struct stmt **stmts, struct type *type)
+struct subst *infer_body(struct gamma *gamma, struct array 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);
+ ARRAY_ITER(struct stmt *, s, i, stmts) {
+ s1 = infer_stmt(gamma, s, type);
s0 = subst_union(s1, s0);
subst_apply_g(s0, gamma);
- }
+ } AIEND
gamma_decrement_scope(gamma);
return s0;
}
s0 = infer_expr(gamma, stmt->data.sif.pred, &tybool);
//subst_apply_g(s0, gamma);
- s0 = subst_union(s0, infer_body(gamma,
- stmt->data.sif.nthen, stmt->data.sif.then, type));
+ s0 = subst_union(s0,
+ infer_body(gamma, stmt->data.sif.then, type));
- s0 = subst_union(s0, infer_body(gamma,
- stmt->data.sif.nels, stmt->data.sif.els, type));
+ s0 = subst_union(s0,
+ infer_body(gamma, stmt->data.sif.els, type));
return s0;
case sreturn:
return stmt->data.sreturn == NULL
s0 = infer_expr(gamma, stmt->data.swhile.pred, &tybool);
//subst_apply_g(s0, gamma);
- s0 = subst_union(s0, infer_body(gamma,
- stmt->data.swhile.nbody, stmt->data.swhile.body, type));
+ s0 = subst_union(s0,
+ infer_body(gamma, stmt->data.swhile.body, type));
return s0;
}
// Put arguments in gamma
gamma_increment_scope(gamma);
struct type *at = ftype;
- for (int i = 0; i<fundecl->nargs; i++) {
+ ARRAY_ITER(char *, a, i, fundecl->args) {
if (at->type != tarrow)
die("malformed ftype\n");
- gamma_insert(gamma, ident_str(fundecl->args[i]),
- scheme_create(at->data.tarrow.l));
+ gamma_insert(gamma, ident_str(a), scheme_create(at->data.tarrow.l));
at = at->data.tarrow.r;
- }
+ } AIEND
if (at->type == tarrow)
die("malformed ftype\n");
struct subst *s = subst_id();
- for (int i = 0; i<fundecl->nbody; i++) {
- struct subst *s1 = infer_stmt(gamma, fundecl->body[i], at);
+ ARRAY_ITER(struct stmt *, st, i, fundecl->body) {
+ struct subst *s1 = infer_stmt(gamma, st, at);
s = subst_union(s1, s);
subst_apply_g(s, gamma);
- }
+ } AIEND
// Remove arguments from gamma
gamma_decrement_scope(gamma);
return type_var_int(gamma->fresh++);
}
-void gamma_print(struct gamma *gamma, FILE *out)
-{
- fprintf(out, "{");
- for (int i = 0; i<gamma->nentries; i++) {
- 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, ", ");
- }
- fprintf(out, "}");
-}
-
+//void gamma_print(struct gamma *gamma, FILE *out)
+//{
+// fprintf(out, "{");
+// for (int i = 0; i<gamma->nentries; i++) {
+// 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, ", ");
+// }
+// fprintf(out, "}");
+//}
+//
void gamma_free(struct gamma *gamma)
{
for (int i = 0; i<gamma->nentries; i++) {
return s;
}
-void scheme_print(struct scheme *scheme, FILE *out)
-{
- if (scheme == NULL) {
- fprintf(out, "NULLSCHEME");
- return;
- }
- if (scheme->nvar > 0) {
- fprintf(out, "A.");
- for (int i = 0; i<scheme->nvar; i++) {
- if (i > 0)
- fprintf(out, " ");
- ident_print(scheme->var[i], stderr);
- }
- fprintf(out, ": ");
- }
- type_print(scheme->type, out);
-}
-
+//void scheme_print(struct scheme *scheme, FILE *out)
+//{
+// if (scheme == NULL) {
+// fprintf(out, "NULLSCHEME");
+// return;
+// }
+// if (scheme->nvar > 0) {
+// fprintf(out, "A.");
+// for (int i = 0; i<scheme->nvar; i++) {
+// if (i > 0)
+// fprintf(out, " ");
+// ident_print(scheme->var[i], stderr);
+// }
+// fprintf(out, ": ");
+// }
+// type_print(scheme->type, out);
+//}
+//
void scheme_free(struct scheme *scheme)
{
type_free(scheme->type);
case echar:
break;
case efuncall:
- for(int i = 0; i<expr->data.efuncall.nargs; i++)
- l = edges_expr(ndecls, decls, parent,
- expr->data.efuncall.args[i], l);
+ ARRAY_ITER(struct expr *, e, i, expr->data.efuncall.args )
+ l = edges_expr(ndecls, decls, parent, e, l);
+ AIEND
bool found = false;
for (int i = 0; i<ndecls && !found; i++) {
if (strcmp(decls[i]->data.dfun->ident,
break;
case sif:
l = edges_expr(ndecls, decls, parent, stmt->data.sif.pred, l);
- for (int i = 0; i<stmt->data.sif.nthen; i++)
- l = edges_stmt(ndecls, decls, parent,
- stmt->data.sif.then[i], l);
- for (int i = 0; i<stmt->data.sif.nels; i++)
- l = edges_stmt(ndecls, decls, parent,
- stmt->data.sif.els[i], l);
+ ARRAY_ITER(struct stmt *, s, i, stmt->data.sif.then)
+ 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);
+ AIEND
break;
case sreturn:
l = edges_expr(ndecls, decls, parent, stmt->data.sreturn, l);
case swhile:
l = edges_expr(ndecls, decls, parent,
stmt->data.swhile.pred, l);
- for (int i = 0; i<stmt->data.swhile.nbody; i++)
- l = edges_stmt(ndecls, decls, parent,
- stmt->data.swhile.body[i], l);
+ ARRAY_ITER(struct stmt *, s, i, stmt->data.swhile.body)
+ l = edges_stmt(ndecls, decls, parent, s, l);
+ AIEND
break;
default:
die("Unsupported stmt node\n");
if (ast->decls[ffun]->type == dfundecl)
break;
//Number of functions
- int nfun = ast->ndecls-ffun;
+ size_t nfun = ast->ndecls-ffun;
//Calculate the edges
struct decl **fundecls = ast->decls+ffun;
struct list *edges = NULL;
- for (int i = 0; i<nfun; i++)
- for (int j = 0; j<fundecls[i]->data.dfun->nbody; j++)
- edges = edges_stmt(nfun, fundecls, fundecls[i],
- fundecls[i]->data.dfun->body[j], edges);
+ 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);
+ AIEND
+ }
int nedges;
struct edge **edata = (struct edge **)
list_to_array(edges, &nedges, false, 0);
for (struct components *c = cs; c != NULL; c = c->next) {
struct decl *d = xalloc(1, struct decl);
d->type = dcomp;
- d->data.dcomp.ndecls = c->nnodes;
- d->data.dcomp.decls = xalloc(c->nnodes, struct fundecl *);
+ array_init(&d->data.dcomp, c->nnodes);
for (int j = 0; j<c->nnodes; j++)
- d->data.dcomp.decls[j] =
- ((struct decl *)c->nodes[j])->data.dfun;
+ d->data.dcomp = array_append(d->data.dcomp,
+ ((struct decl *)c->nodes[j])->data.dfun);
ast->decls[i++] = d;
}
ast->ndecls = i;
//Parse
r = yyparse(&result);
+
if (yyin != stdin)
safe_fclose(yyin);
yylex_destroy();
if (r != 0)
return r;
+ fprintf(stderr, "lexical and syntactical done\n");
if (pparse)
ast_print(result, stdout);
//Typecheck
- if ((result = sem(result)) == NULL) {
+ if ((result = sem(result)) == NULL)
return 1;
- }
+ fprintf(stderr, "semantic analyses done\n");
if (ptype)
ast_print(result, stdout);
free(cfile);
switch(lang) {
case langc:
- genc(result, cout);
+// genc(result, cout);
break;
default:
die("unsupported language\n");
}
safe_fclose(cout);
+ fprintf(stderr, "code generation* done\n");
ast_free(result);
return r;
}