diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-01-27 11:12:16 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-01-27 11:12:16 -0500 |
commit | 730469c7a96a26ecba362db39c67e97bd07bf157 (patch) | |
tree | 65603b6d164132d0e7dc125ebbb3a93989b9a94f | |
parent | abfea518adf24b5f2a6245ba37e068bfe97152ce (diff) |
#include
-rw-r--r-- | abbrevs.txt | 1 | ||||
-rw-r--r-- | cgen.c | 10 | ||||
-rw-r--r-- | copy.c | 11 | ||||
-rw-r--r-- | decls_cgen.c | 5 | ||||
-rw-r--r-- | eval.c | 5 | ||||
-rw-r--r-- | incstuff.toc | 8 | ||||
-rw-r--r-- | main.c | 41 | ||||
-rw-r--r-- | package.c | 20 | ||||
-rw-r--r-- | parse.c | 28 | ||||
-rw-r--r-- | sdecls_cgen.c | 5 | ||||
-rw-r--r-- | test.toc | 8 | ||||
-rw-r--r-- | toc.c | 32 | ||||
-rw-r--r-- | tokenizer.c | 2 | ||||
-rw-r--r-- | types.c | 39 | ||||
-rw-r--r-- | types.h | 12 |
15 files changed, 181 insertions, 46 deletions
diff --git a/abbrevs.txt b/abbrevs.txt index 643d89b..2449533 100644 --- a/abbrevs.txt +++ b/abbrevs.txt @@ -16,6 +16,7 @@ exptr - exporter fn - function ident - identifier imptr - importer +inc - include kw - keyword len - length num - number @@ -2028,6 +2028,11 @@ static bool cgen_stmt(CGenerator *g, Statement *s) { if (!cgen_ret(g, has_expr ? &s->ret.expr : NULL)) return false; } break; + case STMT_INCLUDE: + arr_foreach(s->inc.stmts, Statement, sub) + if (!cgen_stmt(g, sub)) + return false; + break; } return true; } @@ -2110,6 +2115,11 @@ static bool cgen_defs_stmt(CGenerator *g, Statement *s) { if (!cgen_defs_expr(g, &s->ret.expr)) return false; break; + case STMT_INCLUDE: + arr_foreach(s->inc.stmts, Statement, sub) + if (!cgen_defs_stmt(g, sub)) + return false; + break; } return true; } @@ -304,6 +304,17 @@ static void copy_stmt(Copier *c, Statement *out, Statement *in) { if (in->ret.flags & RET_HAS_EXPR) copy_expr(c, &out->ret.expr, &in->ret.expr); break; + case STMT_INCLUDE: + if (in->flags & STMT_TYPED) { + size_t nstmts = arr_len(in->inc.stmts); + arr_set_lena(&out->inc.stmts, nstmts, c->allocr); + for (size_t i = 0; i < nstmts; ++i) { + copy_stmt(c, &out->inc.stmts[i], &in->inc.stmts[i]); + } + } else { + copy_expr(c, &out->inc.filename, &in->inc.filename); + } + break; case STMT_EXPR: copy_expr(c, &out->expr, &in->expr); break; diff --git a/decls_cgen.c b/decls_cgen.c index 99ae190..b0382b5 100644 --- a/decls_cgen.c +++ b/decls_cgen.c @@ -291,6 +291,11 @@ static bool cgen_decls_stmt(CGenerator *g, Statement *s) { if (!cgen_decls_expr(g, &s->ret.expr)) return false; break; + case STMT_INCLUDE: + arr_foreach(s->inc.stmts, Statement, sub) + if (!cgen_decls_stmt(g, sub)) + return false; + break; } return true; } @@ -1668,6 +1668,11 @@ static bool eval_stmt(Evaluator *ev, Statement *stmt) { return false; copy_val(NULL, &ev->ret_val, &r, &stmt->ret.expr.type); } break; + case STMT_INCLUDE: + arr_foreach(stmt->inc.stmts, Statement, sub) + if (!eval_stmt(ev, sub)) + return false; + return false; } return true; } diff --git a/incstuff.toc b/incstuff.toc new file mode 100644 index 0000000..c192e06 --- /dev/null +++ b/incstuff.toc @@ -0,0 +1,8 @@ + + x : arr.Arr(char); + arr.arr_add(&x, 'H'); + arr.arr_add(&x, 'e'); + arr.arr_add(&x, 'l'); + arr.arr_add(&x, 'l'); + arr.arr_add(&x, 'o'); + arr.arr_add(&x, '!');
\ No newline at end of file @@ -18,13 +18,8 @@ /* TODO: -#builtin("sizeof int") -#builtin("target sizeof int") -etc. - -allow any global declaration to be used before itself - #include +nested packages constants in structs #if @@ -64,40 +59,16 @@ int main(int argc, char **argv) { if (strs_equal(argv[i], "-o")) out_filename = argv[i+1]; } - - FILE *in = fopen(in_filename, "r"); - if (!in) { - fprintf(stderr, "Could not open file: %s.\n", in_filename); - return EXIT_FAILURE; - } - - char *contents = err_malloc(4096); - contents[0] = 0; /* put 0 byte at the start of the file. see err.c:err_print_location_text to find out why */ - contents[1] = 0; /* if fgets fails the first time */ - long contents_cap = 4095; - long contents_len = 1; - while (fgets(contents + contents_len, (int)(contents_cap - contents_len), in)) { - contents_len += (long)strlen(contents + contents_len); - - if (contents_len >= (long)contents_cap - 1024) { - contents_cap *= 2; - contents = err_realloc(contents, (size_t)contents_cap + 1); - } - } - ++contents; - if (ferror(in)) { - fprintf(stderr, "Error reading input file: %s.\n", in_filename); - return EXIT_FAILURE; - } - fclose(in); - Identifiers idents; - idents_create(&idents); - Tokenizer t; Allocator main_allocr; allocr_create(&main_allocr); ErrCtx err_ctx = {0}; err_ctx.enabled = true; err_ctx.color_enabled = true; + char *contents = read_entire_file(&main_allocr, &err_ctx, in_filename); + + Identifiers idents; + idents_create(&idents); + Tokenizer t; File file = {0}; file.filename = in_filename; file.contents = contents; @@ -1053,6 +1053,17 @@ static bool export_stmt(Exporter *ex, Statement *s) { if (!export_expr(ex, &s->ret.expr)) return false; } break; + case STMT_INCLUDE: + if (s->flags & STMT_TYPED) { + export_len(ex, arr_len(s->inc.stmts)); + arr_foreach(s->inc.stmts, Statement, sub) + if (!export_stmt(ex, sub)) + return false; + } else { + if (!export_expr(ex, &s->inc.filename)) + return false; + } + break; } return true; } @@ -1068,6 +1079,15 @@ static void import_stmt(Importer *im, Statement *s) { case STMT_DECL: import_decl(im, &s->decl); break; + case STMT_INCLUDE: + if (s->flags & STMT_TYPED) { + import_arr(im, &s->inc.stmts); + arr_foreach(s->inc.stmts, Statement, sub) + import_stmt(im, sub); + } else { + import_expr(im, &s->inc.filename); + } + break; case STMT_RET: s->ret.flags = import_u8(im); if (s->ret.flags & RET_HAS_EXPR) @@ -1724,6 +1724,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { break; case DIRECT_FOREIGN: case DIRECT_EXPORT: + case DIRECT_INCLUDE: tokr_err(t, "Unrecognized expression."); return false; case DIRECT_COUNT: assert(0); break; @@ -2057,6 +2058,23 @@ static bool parse_stmt(Parser *p, Statement *s, bool *was_a_statement) { } default: break; } + } else if (t->token->kind == TOKEN_DIRECT) { + switch (t->token->direct) { + case DIRECT_INCLUDE: { + ++t->token; + s->kind = STMT_INCLUDE; + if (!parse_expr(p, &s->inc.filename, expr_find_end(p, 0))) + return false; + if (!token_is_kw(t->token, KW_SEMICOLON)) { + tokr_err(t, "Expected ; after #include directive"); + return false; + } + ++t->token; + return true; + } break; + default: + break; + } } if (is_decl(t)) { s->kind = STMT_DECL; @@ -2396,6 +2414,16 @@ static void fprint_stmt(FILE *out, Statement *s) { fprint_expr(out, &s->ret.expr); fprintf(out, ";\n"); break; + case STMT_INCLUDE: + if (s->flags & STMT_TYPED) { + arr_foreach(s->inc.stmts, Statement, sub) + fprint_stmt(out, sub); + } else { + fprintf(out, "#include "); + fprint_expr(out, &s->inc.filename); + fprintf(out, ";\n"); + } + break; } } diff --git a/sdecls_cgen.c b/sdecls_cgen.c index 2bd71a0..966b22e 100644 --- a/sdecls_cgen.c +++ b/sdecls_cgen.c @@ -108,6 +108,11 @@ static bool cgen_sdecls_stmt(CGenerator *g, Statement *s) { if (!cgen_sdecls_expr(g, &s->ret.expr)) return false; break; + case STMT_INCLUDE: + arr_foreach(s->inc.stmts, Statement, sub) + if (!cgen_sdecls_stmt(g, sub)) + return false; + break; } return true; } @@ -1,13 +1,7 @@ arr ::= pkg "std/arr"; io ::= pkg "std/io"; main ::= fn() { - x : arr.Arr(char); - arr.arr_add(&x, 'H'); - arr.arr_add(&x, 'e'); - arr.arr_add(&x, 'l'); - arr.arr_add(&x, 'l'); - arr.arr_add(&x, 'o'); - arr.arr_add(&x, '!'); +#include "incstuff.toc"; s : [1]char; s[0] = (arr.arr_len(x) as char) + '0'; @@ -84,6 +84,38 @@ static size_t compiler_sizeof(Type *t); #include "copy.c" #include "binfile.c" +/* returns NULL on error */ +static char *read_entire_file(Allocator *a, ErrCtx *ectx, const char *filename) { + FILE *in = fopen(filename, "r"); + + if (!in) { + Location where = {0}; + File file = {0}; + file.ctx = ectx; + file.filename = filename; + where.file = &file; + err_print(where, "Could not open file: %s.", filename); + return NULL; + } + char *contents = allocr_malloc(a, 4096); + contents[0] = 0; /* put 0 byte at the start of the file. see err.c:err_print_location_text to find out why */ + contents[1] = 0; /* if fgets fails the first time */ + long contents_cap = 4095; + long contents_len = 1; + while (fgets(contents + contents_len, (int)(contents_cap - contents_len), in)) { + contents_len += (long)strlen(contents + contents_len); + + if (contents_len >= (long)contents_cap - 1024) { + size_t prev = (size_t)contents_cap + 1; + contents_cap *= 2; + contents = allocr_realloc(a, contents, prev, (size_t)contents_cap + 1); + } + } + ++contents; + return contents; +} + + #include "identifiers.c" #include "tokenizer.c" diff --git a/tokenizer.c b/tokenizer.c index 98c0d13..dc194ca 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -20,7 +20,7 @@ static const char *const keywords[KW_COUNT] = static inline const char *kw_to_str(Keyword k) { return keywords[k]; } static const char *directives[DIRECT_COUNT] = - {"C", "sizeof", "alignof", "export", "foreign", "builtin"}; + {"C", "sizeof", "alignof", "export", "foreign", "builtin", "include"}; /* Returns KW_COUNT if it's not a keyword */ /* OPTIM: don't use strncmp so much */ @@ -2249,10 +2249,13 @@ static bool types_block(Typer *tr, Block *b) { bool success = true; if (!typer_block_enter(tr, b)) return false; + arr_foreach(b->stmts, Statement, s) { - if (!types_stmt(tr, s)) + if (!types_stmt(tr, s)) { success = false; - else if (s->kind == STMT_EXPR && (s->flags & STMT_EXPR_NO_SEMICOLON)) { + continue; + } + if (s->kind == STMT_EXPR && (s->flags & STMT_EXPR_NO_SEMICOLON)) { /* not voided */ Expression *e = &s->expr; if (e->type.kind == TYPE_VOID) { @@ -2489,6 +2492,36 @@ static bool types_stmt(Typer *tr, Statement *s) { } } break; + case STMT_INCLUDE: { + char *filename = eval_expr_as_cstr(tr, &s->inc.filename, "import filename"); + if (!filename) + return false; + char *contents = read_entire_file(tr->allocr, tr->err_ctx, filename); + Tokenizer tokr; + tokr_create(&tokr, tr->idents, tr->err_ctx, tr->allocr); + File *file = typer_calloc(tr, 1, sizeof *file); + file->filename = filename; + file->contents = contents; + file->ctx = tr->err_ctx; + if (!tokenize_file(&tokr, file)) + return false; + Parser parser; + parser_create(&parser, &tokr, tr->allocr); + ParsedFile parsed_file; + if (!parse_file(&parser, &parsed_file)) { + return false; + } + Statement *stmts_inc = parsed_file.stmts; + s->inc.stmts = stmts_inc; + arr_foreach(stmts_inc, Statement, s_incd) { + if (!types_stmt(tr, s_incd)) + return false; + if (s_incd->kind == STMT_DECL) { + if (!add_ident_decls(tr->block, &s_incd->decl, SCOPE_CHECK_REDECL)) + return false; + } + } + } break; } return true; } @@ -2513,6 +2546,7 @@ static void typer_create(Typer *tr, Evaluator *ev, ErrCtx *err_ctx, Allocator *a static bool types_file(Typer *tr, ParsedFile *f) { bool ret = true; FILE *pkg_fp = NULL; + tr->parsed_file = f; if (f->pkg_name) { Value pkg_name; if (!types_expr(tr, f->pkg_name)) @@ -2548,6 +2582,7 @@ static bool types_file(Typer *tr, ParsedFile *f) { exptr_create(tr->exptr, pkg_fp, pkg_file_name, tr->err_ctx); exptr_start(tr->exptr, pkg_name_str, pkg_name_len); } + arr_foreach(f->stmts, Statement, s) { if (!types_stmt(tr, s)) { ret = false; @@ -240,6 +240,7 @@ typedef enum { DIRECT_EXPORT, DIRECT_FOREIGN, DIRECT_BUILTIN, + DIRECT_INCLUDE, DIRECT_COUNT } Directive; @@ -820,7 +821,8 @@ typedef struct Declaration { typedef enum { STMT_DECL, STMT_EXPR, - STMT_RET + STMT_RET, + STMT_INCLUDE } StatementKind; enum { @@ -833,7 +835,13 @@ typedef struct Return { enum { STMT_EXPR_NO_SEMICOLON = 0x01, + STMT_TYPED = 0x02 }; +typedef union { + Expression filename; /* before typing */ + struct Statement *stmts; /* after typing */ +} Include; + typedef struct Statement { Location where; StatementKind kind; @@ -842,6 +850,7 @@ typedef struct Statement { Declaration decl; Expression expr; Return ret; + Include inc; }; } Statement; @@ -912,6 +921,7 @@ typedef struct Typer { /* for checking for problematic struct circular dependencies */ bool *is_reference_stack; Package *pkgs; /* all packages which have been imported */ + ParsedFile *parsed_file; } Typer; typedef struct Exporter { |