summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-01-27 11:12:16 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-01-27 11:12:16 -0500
commit730469c7a96a26ecba362db39c67e97bd07bf157 (patch)
tree65603b6d164132d0e7dc125ebbb3a93989b9a94f
parentabfea518adf24b5f2a6245ba37e068bfe97152ce (diff)
#include
-rw-r--r--abbrevs.txt1
-rw-r--r--cgen.c10
-rw-r--r--copy.c11
-rw-r--r--decls_cgen.c5
-rw-r--r--eval.c5
-rw-r--r--incstuff.toc8
-rw-r--r--main.c41
-rw-r--r--package.c20
-rw-r--r--parse.c28
-rw-r--r--sdecls_cgen.c5
-rw-r--r--test.toc8
-rw-r--r--toc.c32
-rw-r--r--tokenizer.c2
-rw-r--r--types.c39
-rw-r--r--types.h12
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
diff --git a/cgen.c b/cgen.c
index d0ebedd..f11a94a 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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;
}
diff --git a/copy.c b/copy.c
index 8b3db68..0a034f6 100644
--- a/copy.c
+++ b/copy.c
@@ -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;
}
diff --git a/eval.c b/eval.c
index 3d6cde6..32804e0 100644
--- a/eval.c
+++ b/eval.c
@@ -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
diff --git a/main.c b/main.c
index 3b58f8f..6d0ae5c 100644
--- a/main.c
+++ b/main.c
@@ -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;
diff --git a/package.c b/package.c
index 4483e45..a102a47 100644
--- a/package.c
+++ b/package.c
@@ -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)
diff --git a/parse.c b/parse.c
index 5e22103..50ebdee 100644
--- a/parse.c
+++ b/parse.c
@@ -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;
}
diff --git a/test.toc b/test.toc
index 2b645bd..9e82451 100644
--- a/test.toc
+++ b/test.toc
@@ -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';
diff --git a/toc.c b/toc.c
index 57c67b5..9bb497e 100644
--- a/toc.c
+++ b/toc.c
@@ -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 */
diff --git a/types.c b/types.c
index a84bf30..c5f0d47 100644
--- a/types.c
+++ b/types.c
@@ -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;
diff --git a/types.h b/types.h
index e7a1503..25ddad6 100644
--- a/types.h
+++ b/types.h
@@ -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 {