From a857bf42f629f82547a845c98ab2bb2653781051 Mon Sep 17 00:00:00 2001 From: Mart Lubbers Date: Tue, 9 Feb 2021 16:39:53 +0100 Subject: [PATCH] framework for typechecking and code generation --- Makefile | 2 +- ast.c | 12 ++++++------ ast.h | 4 ++-- gen.c | 9 +++++++++ gen.h | 10 ++++++++++ splc.c | 34 +++++++++++++++++++--------------- type.c | 26 ++++++++++++++++++++++++++ type.h | 8 ++++++++ 8 files changed, 81 insertions(+), 24 deletions(-) create mode 100644 gen.c create mode 100644 gen.h create mode 100644 type.c create mode 100644 type.h diff --git a/Makefile b/Makefile index 05c5649..245e79f 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CFLAGS+=-Wall -Wextra -std=c99 -pedantic -D_XOPEN_SOURCE=700 -ggdb YFLAGS+=-d --locations -v --defines=parse.h LFLAGS+=--header-file=scan.h -OBJECTS:=scan.o parse.o ast.o util.o +OBJECTS:=scan.o parse.o ast.o util.o gen.o type.o all: splc splc: $(OBJECTS) diff --git a/ast.c b/ast.c index 372234e..29141e4 100644 --- a/ast.c +++ b/ast.c @@ -66,7 +66,7 @@ struct stmt *stmt_assign(char *ident, struct list *fields, struct expr *expr) res->type = sassign; res->data.sassign.ident = ident; res->data.sassign.fields = (char **) - list_to_array(fields, &res->data.sassign.nfield, true); + list_to_array(fields, &res->data.sassign.nfields, true); res->data.sassign.expr = expr; return res; } @@ -212,13 +212,13 @@ struct expr *expr_string(char *str) { struct expr *res = safe_malloc(sizeof(struct expr)); res->type = estring; - res->data.estring.nchar = 0; + res->data.estring.nchars = 0; res->data.estring.chars = safe_malloc(strlen(str)+1); char *p = res->data.estring.chars; while(*str != '\0') { str = unescape_char(str); *p++ = *str++; - res->data.estring.nchar++; + res->data.estring.nchars++; } *p = '\0'; return res; @@ -349,7 +349,7 @@ void stmt_print(struct stmt *stmt, int indent, FILE *out) case sassign: pindent(indent, out); fprintf(out, "%s", stmt->data.sassign.ident); - for (int i = 0; idata.sassign.nfield; i++) + for (int i = 0; idata.sassign.nfields; i++) fprintf(out, ".%s", stmt->data.sassign.fields[i]); safe_fprintf(out, " = "); expr_print(stmt->data.sassign.expr, out); @@ -452,7 +452,7 @@ void expr_print(struct expr *expr, FILE *out) break; case estring: safe_fprintf(out, "\""); - for (int i = 0; idata.estring.nchar; i++) + for (int i = 0; idata.estring.nchars; i++) safe_fprintf(out, "%s", escape_char( expr->data.estring.chars[i], buf, true)); safe_fprintf(out, "\""); @@ -547,7 +547,7 @@ void stmt_free(struct stmt *stmt) switch(stmt->type) { case sassign: free(stmt->data.sassign.ident); - for (int i = 0; idata.sassign.nfield; i++) + for (int i = 0; idata.sassign.nfields; i++) free(stmt->data.sassign.fields[i]); free(stmt->data.sassign.fields); expr_free(stmt->data.sassign.expr); diff --git a/ast.h b/ast.h index f84f08b..a8e98bb 100644 --- a/ast.h +++ b/ast.h @@ -55,7 +55,7 @@ struct stmt { union { struct { char *ident; - int nfield; + int nfields; char **fields; struct expr *expr; } sassign; @@ -112,7 +112,7 @@ struct expr { struct expr *right; } etuple; struct { - int nchar; + int nchars; char *chars; } estring; struct { diff --git a/gen.c b/gen.c new file mode 100644 index 0000000..ab6b6d3 --- /dev/null +++ b/gen.c @@ -0,0 +1,9 @@ +#include + +#include "ast.h" + +bool gen(struct ast *res) +{ + (void)res; + return true; +} diff --git a/gen.h b/gen.h new file mode 100644 index 0000000..ca695a4 --- /dev/null +++ b/gen.h @@ -0,0 +1,10 @@ +#ifndef GEN_H +#define GEN_H + +#include + +#include "ast.h" + +bool gen(struct ast *res); + +#endif diff --git a/splc.c b/splc.c index 8d7174c..6b23b49 100644 --- a/splc.c +++ b/splc.c @@ -3,8 +3,10 @@ #include #include "ast.h" +#include "gen.h" #include "parse.h" #include "scan.h" +#include "type.h" extern int yylex_destroy(void); void usage(FILE *out, char *arg0) @@ -15,30 +17,24 @@ void usage(FILE *out, char *arg0) "Compile an spl file. If FILE is not specified stdin is used.\n" "\n" "Options:\n" - "\t-p\tJust parse and pretty print\n" - "\t-t\tJust parse and typecheck\n" - "\t-c\tparse, typecheck and compile (default)\n" + "\t-p\tPretty print the parsed abstract syntax tree\n" + "\t-t\tPretty print the typed abstract syntax tree\n" "\t-h\tShow this help\n" , arg0); } -enum mode {parse,type,compile}; - int main(int argc, char *argv[]) { int opt; - enum mode mode = compile; + bool pparse = false, ptype = false; - while ((opt = getopt(argc, argv, "hptc")) != -1) { + while ((opt = getopt(argc, argv, "hpt")) != -1) { switch (opt) { case 'p': - mode = parse; + pparse = true; break; case 't': - mode = type; - break; - case 'c': - mode = compile; + ptype = true; break; case 'h': usage(stdout, argv[0]); @@ -57,14 +53,22 @@ int main(int argc, char *argv[]) if (r != 0) return 1; yylex_destroy(); - if (mode == parse) { + if (pparse) ast_print(result, stdout); + if ((result = type(result)) == NULL) { + r = 1; + goto end; + } + if (ptype) + ast_print(result, stdout); + if (!gen(result)) { + r = 1; goto end; } -end: ast_free(result); +end: if (yyin == stdin) if (fclose(yyin) == -1) perror("fclose"); - return 0; + return r; } diff --git a/type.c b/type.c new file mode 100644 index 0000000..3ced0eb --- /dev/null +++ b/type.c @@ -0,0 +1,26 @@ +#include "ast.h" + +struct vardecl *type_vardecl(struct vardecl *vardecl) +{ + return vardecl; +} + +struct decl *type_decl(struct decl *decl) +{ + switch (decl->type) { + case dfundecl: + fprintf(stderr, "type_decl:fundecl unsupported\n"); + break; + case dvardecl: + decl->data.dvar = type_vardecl(decl->data.dvar); + break; + } + return decl; +} + +struct ast *type(struct ast *ast) +{ + for (int i = 0; indecls; i++) + ast->decls[i] = type_decl(ast->decls[i]); + return ast; +} diff --git a/type.h b/type.h new file mode 100644 index 0000000..2cdaca7 --- /dev/null +++ b/type.h @@ -0,0 +1,8 @@ +#ifndef TYPE_H +#define TYPE_H + +#include "ast.h" + +struct ast *type(struct ast *ast); + +#endif -- 2.20.1