framework for typechecking and code generation
authorMart Lubbers <mart@martlubbers.net>
Tue, 9 Feb 2021 15:39:53 +0000 (16:39 +0100)
committerMart Lubbers <mart@martlubbers.net>
Tue, 9 Feb 2021 15:39:53 +0000 (16:39 +0100)
Makefile
ast.c
ast.h
gen.c [new file with mode: 0644]
gen.h [new file with mode: 0644]
splc.c
type.c [new file with mode: 0644]
type.h [new file with mode: 0644]

index 05c5649..245e79f 100644 (file)
--- 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 (file)
--- 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; i<stmt->data.sassign.nfield; i++)
+               for (int i = 0; i<stmt->data.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; i<expr->data.estring.nchar; i++)
+               for (int i = 0; i<expr->data.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; i<stmt->data.sassign.nfield; i++)
+               for (int i = 0; i<stmt->data.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 (file)
--- 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 (file)
index 0000000..ab6b6d3
--- /dev/null
+++ b/gen.c
@@ -0,0 +1,9 @@
+#include <stdbool.h>
+
+#include "ast.h"
+
+bool gen(struct ast *res)
+{
+       (void)res;
+       return true;
+}
diff --git a/gen.h b/gen.h
new file mode 100644 (file)
index 0000000..ca695a4
--- /dev/null
+++ b/gen.h
@@ -0,0 +1,10 @@
+#ifndef GEN_H
+#define GEN_H
+
+#include <stdbool.h>
+
+#include "ast.h"
+
+bool gen(struct ast *res);
+
+#endif
diff --git a/splc.c b/splc.c
index 8d7174c..6b23b49 100644 (file)
--- a/splc.c
+++ b/splc.c
@@ -3,8 +3,10 @@
 #include <getopt.h>
 
 #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 (file)
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; i<ast->ndecls; i++)
+               ast->decls[i] = type_decl(ast->decls[i]);
+       return ast;
+}
diff --git a/type.h b/type.h
new file mode 100644 (file)
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